Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/webrtc/video_destination_handler.h" | 5 #include "content/renderer/media/webrtc/video_destination_handler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 // Starts forwarding frames to |frame_callback| on the IO-thread that are | 34 // Starts forwarding frames to |frame_callback| on the IO-thread that are |
| 35 // delivered to this class by calling DeliverFrame on the main render thread. | 35 // delivered to this class by calling DeliverFrame on the main render thread. |
| 36 void StartDeliver(const VideoCaptureDeliverFrameCB& frame_callback); | 36 void StartDeliver(const VideoCaptureDeliverFrameCB& frame_callback); |
| 37 void StopDeliver(); | 37 void StopDeliver(); |
| 38 | 38 |
| 39 void DeliverFrame(const scoped_refptr<PPB_ImageData_Impl>& image_data, | 39 void DeliverFrame(const scoped_refptr<PPB_ImageData_Impl>& image_data, |
| 40 int64 time_stamp_ns); | 40 int64 time_stamp_ns); |
| 41 | 41 |
| 42 private: | 42 private: |
| 43 friend class base::RefCountedThreadSafe<FrameWriterDelegate>; | 43 friend class base::RefCountedThreadSafe<FrameWriterDelegate>; |
| 44 // Endian in memory order, e.g. AXXX stands for uint8 pixel[4] = {A, x, x, x}; | |
| 45 enum PixelEndian { | |
| 46 UNKNOWN, | |
| 47 AXXX, | |
| 48 XXXA, | |
| 49 }; | |
| 50 | |
| 44 virtual ~FrameWriterDelegate(); | 51 virtual ~FrameWriterDelegate(); |
| 45 | 52 |
| 46 void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback); | 53 void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback); |
| 47 void StopDeliverOnIO(); | 54 void StopDeliverOnIO(); |
| 48 | 55 |
| 49 void DeliverFrameOnIO(uint8* data, int stride, int width, int height, | 56 void DeliverFrameOnIO(uint8* data, int stride, int width, int height, |
| 50 int64 time_stamp_ns); | 57 int64 time_stamp_ns); |
| 51 void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data); | 58 void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data); |
| 52 | 59 |
| 53 scoped_refptr<base::MessageLoopProxy> io_message_loop_; | 60 scoped_refptr<base::MessageLoopProxy> io_message_loop_; |
| 54 | 61 |
| 55 // |frame_pool_| and |new_frame_callback_| are only used on the IO-thread. | 62 // |frame_pool_|, |new_frame_callback_| and |endian_| are only used on the |
| 63 // IO-thread. | |
| 56 media::VideoFramePool frame_pool_; | 64 media::VideoFramePool frame_pool_; |
| 57 VideoCaptureDeliverFrameCB new_frame_callback_; | 65 VideoCaptureDeliverFrameCB new_frame_callback_; |
| 66 PixelEndian endian_; | |
| 58 | 67 |
| 59 // Used to DCHECK that we are called on the main render thread. | 68 // Used to DCHECK that we are called on the main render thread. |
| 60 base::ThreadChecker thread_checker_; | 69 base::ThreadChecker thread_checker_; |
| 61 }; | 70 }; |
| 62 | 71 |
| 63 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate( | 72 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate( |
| 64 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 73 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) |
| 65 : io_message_loop_(io_message_loop_proxy) { | 74 : io_message_loop_(io_message_loop_proxy), endian_(UNKNOWN) { |
| 66 } | 75 } |
| 67 | 76 |
| 68 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() { | 77 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() { |
| 69 } | 78 } |
| 70 | 79 |
| 71 void PpFrameWriter::FrameWriterDelegate::StartDeliver( | 80 void PpFrameWriter::FrameWriterDelegate::StartDeliver( |
| 72 const VideoCaptureDeliverFrameCB& frame_callback) { | 81 const VideoCaptureDeliverFrameCB& frame_callback) { |
| 73 DCHECK(thread_checker_.CalledOnValidThread()); | 82 DCHECK(thread_checker_.CalledOnValidThread()); |
| 74 io_message_loop_->PostTask( | 83 io_message_loop_->PostTask( |
| 75 FROM_HERE, | 84 FROM_HERE, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 94 << "The image could not be mapped and is unusable."; | 103 << "The image could not be mapped and is unusable."; |
| 95 return; | 104 return; |
| 96 } | 105 } |
| 97 | 106 |
| 98 const SkBitmap* bitmap = image_data->GetMappedBitmap(); | 107 const SkBitmap* bitmap = image_data->GetMappedBitmap(); |
| 99 if (!bitmap) { | 108 if (!bitmap) { |
| 100 LOG(ERROR) << "PpFrameWriter::PutFrame - " | 109 LOG(ERROR) << "PpFrameWriter::PutFrame - " |
| 101 << "The image_data's mapped bitmap is NULL."; | 110 << "The image_data's mapped bitmap is NULL."; |
| 102 return; | 111 return; |
| 103 } | 112 } |
| 113 // We only support PP_IMAGEDATAFORMAT_BGRA_PREMUL at the moment. | |
| 114 DCHECK(image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL); | |
| 104 io_message_loop_->PostTaskAndReply( | 115 io_message_loop_->PostTaskAndReply( |
| 105 FROM_HERE, | 116 FROM_HERE, |
| 106 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this, | 117 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this, |
| 107 static_cast<uint8*>(bitmap->getPixels()), | 118 static_cast<uint8*>(bitmap->getPixels()), |
| 108 bitmap->rowBytes(), | 119 bitmap->rowBytes(), |
| 109 bitmap->width(), | 120 bitmap->width(), |
| 110 bitmap->height(), | 121 bitmap->height(), |
| 111 time_stamp_ns), | 122 time_stamp_ns), |
| 112 base::Bind(&FrameWriterDelegate::FrameDelivered, this, | 123 base::Bind(&FrameWriterDelegate::FrameDelivered, this, |
| 113 image_data)); | 124 image_data)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle. | 157 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle. |
| 147 // crbug/359587. | 158 // crbug/359587. |
| 148 scoped_refptr<media::VideoFrame> new_frame = | 159 scoped_refptr<media::VideoFrame> new_frame = |
| 149 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size, | 160 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size, |
| 150 gfx::Rect(frame_size), frame_size, timestamp); | 161 gfx::Rect(frame_size), frame_size, timestamp); |
| 151 media::VideoCaptureFormat format( | 162 media::VideoCaptureFormat format( |
| 152 frame_size, | 163 frame_size, |
| 153 MediaStreamVideoSource::kUnknownFrameRate, | 164 MediaStreamVideoSource::kUnknownFrameRate, |
| 154 media::PIXEL_FORMAT_YV12); | 165 media::PIXEL_FORMAT_YV12); |
| 155 | 166 |
| 156 libyuv::BGRAToI420(data, | 167 // TODO(magjed): Remove this and always use libyuv::ARGBToI420 when |
| 157 stride, | 168 // crbug/426020 is fixed. |
| 158 new_frame->data(media::VideoFrame::kYPlane), | 169 // Due to confusion about endianness, we try to determine it from the data. |
|
fbarchard
2014/10/22 21:47:43
I'm not aware of any 'confusion'. Pepper original
magjed_chromium
2014/10/23 10:59:35
I removed 'confusion' from the comment. Something
| |
| 159 new_frame->stride(media::VideoFrame::kYPlane), | 170 // The alpha channel is always 255. It is unlikely for other color channels to |
| 160 new_frame->data(media::VideoFrame::kUPlane), | 171 // be 255, so we will most likely break on the first few pixels in the first |
| 161 new_frame->stride(media::VideoFrame::kUPlane), | 172 // frame. |
| 162 new_frame->data(media::VideoFrame::kVPlane), | 173 uint8* row_ptr = data; |
| 163 new_frame->stride(media::VideoFrame::kVPlane), | 174 for (int y = 0; y < height && endian_ == UNKNOWN; ++y) { |
|
fbarchard
2014/10/22 21:47:43
consider making endian_ static so it detects once.
magjed_chromium
2014/10/23 10:59:35
I prefer to keep it per stream. static variables f
| |
| 164 frame_size.width(), frame_size.height()); | 175 for (int x = 0; x < width; ++x) { |
| 176 if (row_ptr[x * 4 + 0] != 255) { // First byte is not Alpha => XXXA. | |
| 177 endian_ = XXXA; | |
| 178 break; | |
| 179 } | |
| 180 if (row_ptr[x * 4 + 3] != 255) { // Fourth byte is not Alpha => AXXX. | |
| 181 endian_ = AXXX; | |
| 182 break; | |
| 183 } | |
| 184 } | |
| 185 row_ptr += stride; | |
| 186 } | |
| 187 if (endian_ == UNKNOWN) { | |
| 188 LOG(WARNING) << "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO - " | |
| 189 << "Could not determine endianness."; | |
| 190 } | |
| 191 // libyuv uses reversed memory byte order, that is why the naming is reversed. | |
|
fbarchard
2014/10/22 21:47:43
comment misleading. libyuv specifies fourcc/chann
magjed_chromium
2014/10/23 10:59:36
Done.
| |
| 192 const auto xxxxToI420 = | |
| 193 (endian_ == AXXX) ? libyuv::BGRAToI420 : libyuv::ARGBToI420; | |
| 194 xxxxToI420(data, | |
|
fbarchard
2014/10/22 21:47:43
consider using ConvertToI420, which takes the four
magjed_chromium
2014/10/23 10:59:36
I can't pass the src stride to ConvertToI420 - it
| |
| 195 stride, | |
| 196 new_frame->data(media::VideoFrame::kYPlane), | |
| 197 new_frame->stride(media::VideoFrame::kYPlane), | |
| 198 new_frame->data(media::VideoFrame::kUPlane), | |
| 199 new_frame->stride(media::VideoFrame::kUPlane), | |
| 200 new_frame->data(media::VideoFrame::kVPlane), | |
| 201 new_frame->stride(media::VideoFrame::kVPlane), | |
| 202 width, | |
| 203 height); | |
| 165 | 204 |
| 166 // The local time when this frame is generated is unknown so give a null | 205 // The local time when this frame is generated is unknown so give a null |
| 167 // value to |estimated_capture_time|. | 206 // value to |estimated_capture_time|. |
| 168 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); | 207 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); |
| 169 } | 208 } |
| 170 | 209 |
| 171 PpFrameWriter::PpFrameWriter() { | 210 PpFrameWriter::PpFrameWriter() { |
| 172 DVLOG(3) << "PpFrameWriter ctor"; | 211 DVLOG(3) << "PpFrameWriter ctor"; |
| 173 delegate_ = new FrameWriterDelegate(io_message_loop()); | 212 delegate_ = new FrameWriterDelegate(io_message_loop()); |
| 174 } | 213 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 bool track_enabled = true; | 292 bool track_enabled = true; |
| 254 | 293 |
| 255 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( | 294 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( |
| 256 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), | 295 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), |
| 257 track_enabled)); | 296 track_enabled)); |
| 258 | 297 |
| 259 return true; | 298 return true; |
| 260 } | 299 } |
| 261 | 300 |
| 262 } // namespace content | 301 } // namespace content |
| OLD | NEW |