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 enum PixelEndian { | |
| 45 UNKNOWN, | |
| 46 AXXX, | |
| 47 XXXA, | |
| 48 }; | |
| 49 | |
| 44 virtual ~FrameWriterDelegate(); | 50 virtual ~FrameWriterDelegate(); |
| 45 | 51 |
| 46 void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback); | 52 void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback); |
| 47 void StopDeliverOnIO(); | 53 void StopDeliverOnIO(); |
| 48 | 54 |
| 49 void DeliverFrameOnIO(uint8* data, int stride, int width, int height, | 55 void DeliverFrameOnIO(uint8* data, int stride, int width, int height, |
| 50 int64 time_stamp_ns); | 56 int64 time_stamp_ns); |
| 51 void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data); | 57 void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data); |
| 52 | 58 |
| 53 scoped_refptr<base::MessageLoopProxy> io_message_loop_; | 59 scoped_refptr<base::MessageLoopProxy> io_message_loop_; |
| 54 | 60 |
| 55 // |frame_pool_| and |new_frame_callback_| are only used on the IO-thread. | 61 // |frame_pool_|, |new_frame_callback_| and |endian_| are only used on the |
| 62 // IO-thread. | |
| 56 media::VideoFramePool frame_pool_; | 63 media::VideoFramePool frame_pool_; |
| 57 VideoCaptureDeliverFrameCB new_frame_callback_; | 64 VideoCaptureDeliverFrameCB new_frame_callback_; |
| 65 PixelEndian endian_; | |
| 58 | 66 |
| 59 // Used to DCHECK that we are called on the main render thread. | 67 // Used to DCHECK that we are called on the main render thread. |
| 60 base::ThreadChecker thread_checker_; | 68 base::ThreadChecker thread_checker_; |
| 61 }; | 69 }; |
| 62 | 70 |
| 63 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate( | 71 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate( |
| 64 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 72 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) |
| 65 : io_message_loop_(io_message_loop_proxy) { | 73 : io_message_loop_(io_message_loop_proxy), endian_(UNKNOWN) { |
| 66 } | 74 } |
| 67 | 75 |
| 68 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() { | 76 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() { |
| 69 } | 77 } |
| 70 | 78 |
| 71 void PpFrameWriter::FrameWriterDelegate::StartDeliver( | 79 void PpFrameWriter::FrameWriterDelegate::StartDeliver( |
| 72 const VideoCaptureDeliverFrameCB& frame_callback) { | 80 const VideoCaptureDeliverFrameCB& frame_callback) { |
| 73 DCHECK(thread_checker_.CalledOnValidThread()); | 81 DCHECK(thread_checker_.CalledOnValidThread()); |
| 74 io_message_loop_->PostTask( | 82 io_message_loop_->PostTask( |
| 75 FROM_HERE, | 83 FROM_HERE, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 94 << "The image could not be mapped and is unusable."; | 102 << "The image could not be mapped and is unusable."; |
| 95 return; | 103 return; |
| 96 } | 104 } |
| 97 | 105 |
| 98 const SkBitmap* bitmap = image_data->GetMappedBitmap(); | 106 const SkBitmap* bitmap = image_data->GetMappedBitmap(); |
| 99 if (!bitmap) { | 107 if (!bitmap) { |
| 100 LOG(ERROR) << "PpFrameWriter::PutFrame - " | 108 LOG(ERROR) << "PpFrameWriter::PutFrame - " |
| 101 << "The image_data's mapped bitmap is NULL."; | 109 << "The image_data's mapped bitmap is NULL."; |
| 102 return; | 110 return; |
| 103 } | 111 } |
| 112 // We only support PP_IMAGEDATAFORMAT_BGRA_PREMUL at the moment. | |
| 113 DCHECK(image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL); | |
| 104 io_message_loop_->PostTaskAndReply( | 114 io_message_loop_->PostTaskAndReply( |
| 105 FROM_HERE, | 115 FROM_HERE, |
| 106 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this, | 116 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this, |
| 107 static_cast<uint8*>(bitmap->getPixels()), | 117 static_cast<uint8*>(bitmap->getPixels()), |
| 108 bitmap->rowBytes(), | 118 bitmap->rowBytes(), |
| 109 bitmap->width(), | 119 bitmap->width(), |
| 110 bitmap->height(), | 120 bitmap->height(), |
| 111 time_stamp_ns), | 121 time_stamp_ns), |
| 112 base::Bind(&FrameWriterDelegate::FrameDelivered, this, | 122 base::Bind(&FrameWriterDelegate::FrameDelivered, this, |
| 113 image_data)); | 123 image_data)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle. | 156 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle. |
| 147 // crbug/359587. | 157 // crbug/359587. |
| 148 scoped_refptr<media::VideoFrame> new_frame = | 158 scoped_refptr<media::VideoFrame> new_frame = |
| 149 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size, | 159 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size, |
| 150 gfx::Rect(frame_size), frame_size, timestamp); | 160 gfx::Rect(frame_size), frame_size, timestamp); |
| 151 media::VideoCaptureFormat format( | 161 media::VideoCaptureFormat format( |
| 152 frame_size, | 162 frame_size, |
| 153 MediaStreamVideoSource::kUnknownFrameRate, | 163 MediaStreamVideoSource::kUnknownFrameRate, |
| 154 media::PIXEL_FORMAT_YV12); | 164 media::PIXEL_FORMAT_YV12); |
| 155 | 165 |
| 156 libyuv::BGRAToI420(data, | 166 // TODO(magjed): Remove this and always use libyuv::ARGBToI420 when |
| 157 stride, | 167 // crbug/426020 is fixed. |
| 158 new_frame->data(media::VideoFrame::kYPlane), | 168 // Due to confusion about endianness, we try to determine it from the data. |
| 159 new_frame->stride(media::VideoFrame::kYPlane), | 169 // The alpha channel is always 255. It is unlikely for other color channels to |
| 160 new_frame->data(media::VideoFrame::kUPlane), | 170 // be 255, so we will most likely break on the first few pixels in the first |
| 161 new_frame->stride(media::VideoFrame::kUPlane), | 171 // frame. |
| 162 new_frame->data(media::VideoFrame::kVPlane), | 172 uint8* row_ptr = data; |
| 163 new_frame->stride(media::VideoFrame::kVPlane), | 173 for (int y = 0; y < height && endian_ == UNKNOWN; ++y) { |
| 164 frame_size.width(), frame_size.height()); | 174 for (int x = 0; x < width; ++x) { |
| 175 if (row_ptr[x * 4 + 0] != 255) { | |
| 176 endian_ = XXXA; | |
| 177 break; | |
| 178 } | |
| 179 if (row_ptr[x * 4 + 3] != 255) { | |
| 180 endian_ = AXXX; | |
| 181 break; | |
| 182 } | |
| 183 } | |
| 184 row_ptr += stride; | |
| 185 } | |
| 186 if (endian_ == UNKNOWN) { | |
| 187 LOG(WARNING) << "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO - " | |
| 188 << "Could not determine endianness."; | |
| 189 } | |
| 190 const auto xxxxToI420 = | |
| 191 (endian_ == AXXX) ? libyuv::BGRAToI420 : libyuv::ARGBToI420; | |
|
brucedawson
2014/10/22 17:58:41
This reads very strangely. If endian_ is AXXX then
magjed_chromium
2014/10/22 18:18:14
I agree that it looks strange, but AXXX/XXXA is in
| |
| 192 xxxxToI420(data, | |
| 193 stride, | |
| 194 new_frame->data(media::VideoFrame::kYPlane), | |
| 195 new_frame->stride(media::VideoFrame::kYPlane), | |
| 196 new_frame->data(media::VideoFrame::kUPlane), | |
| 197 new_frame->stride(media::VideoFrame::kUPlane), | |
| 198 new_frame->data(media::VideoFrame::kVPlane), | |
| 199 new_frame->stride(media::VideoFrame::kVPlane), | |
| 200 width, | |
| 201 height); | |
| 165 | 202 |
| 166 // The local time when this frame is generated is unknown so give a null | 203 // The local time when this frame is generated is unknown so give a null |
| 167 // value to |estimated_capture_time|. | 204 // value to |estimated_capture_time|. |
| 168 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); | 205 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); |
| 169 } | 206 } |
| 170 | 207 |
| 171 PpFrameWriter::PpFrameWriter() { | 208 PpFrameWriter::PpFrameWriter() { |
| 172 DVLOG(3) << "PpFrameWriter ctor"; | 209 DVLOG(3) << "PpFrameWriter ctor"; |
| 173 delegate_ = new FrameWriterDelegate(io_message_loop()); | 210 delegate_ = new FrameWriterDelegate(io_message_loop()); |
| 174 } | 211 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 bool track_enabled = true; | 290 bool track_enabled = true; |
| 254 | 291 |
| 255 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( | 292 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( |
| 256 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), | 293 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), |
| 257 track_enabled)); | 294 track_enabled)); |
| 258 | 295 |
| 259 return true; | 296 return true; |
| 260 } | 297 } |
| 261 | 298 |
| 262 } // namespace content | 299 } // namespace content |
| OLD | NEW |