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 a change in endianness, we try to determine it from the data. |
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 // Note that we only do this if endian_ is still UNKNOWN. |
164 frame_size.width(), frame_size.height()); | 175 for (int y = 0; y < height && endian_ == UNKNOWN; ++y) { |
| 176 for (int x = 0; x < width; ++x) { |
| 177 if (row_ptr[x * 4 + 0] != 255) { // First byte is not Alpha => XXXA. |
| 178 endian_ = XXXA; |
| 179 break; |
| 180 } |
| 181 if (row_ptr[x * 4 + 3] != 255) { // Fourth byte is not Alpha => AXXX. |
| 182 endian_ = AXXX; |
| 183 break; |
| 184 } |
| 185 } |
| 186 row_ptr += stride; |
| 187 } |
| 188 if (endian_ == UNKNOWN) { |
| 189 LOG(WARNING) << "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO - " |
| 190 << "Could not determine endianness."; |
| 191 } |
| 192 // libyuv specifies fourcc/channel ordering the same as webrtc. That is why |
| 193 // the naming is reversed compared to PixelEndian and PP_ImageDataFormat which |
| 194 // describes the memory layout from the lowest address to the highest. |
| 195 const auto* xxxxToI420 = |
| 196 (endian_ == AXXX) ? &libyuv::BGRAToI420 : &libyuv::ARGBToI420; |
| 197 xxxxToI420(data, |
| 198 stride, |
| 199 new_frame->data(media::VideoFrame::kYPlane), |
| 200 new_frame->stride(media::VideoFrame::kYPlane), |
| 201 new_frame->data(media::VideoFrame::kUPlane), |
| 202 new_frame->stride(media::VideoFrame::kUPlane), |
| 203 new_frame->data(media::VideoFrame::kVPlane), |
| 204 new_frame->stride(media::VideoFrame::kVPlane), |
| 205 width, |
| 206 height); |
165 | 207 |
166 // The local time when this frame is generated is unknown so give a null | 208 // The local time when this frame is generated is unknown so give a null |
167 // value to |estimated_capture_time|. | 209 // value to |estimated_capture_time|. |
168 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); | 210 new_frame_callback_.Run(new_frame, format, base::TimeTicks()); |
169 } | 211 } |
170 | 212 |
171 PpFrameWriter::PpFrameWriter() { | 213 PpFrameWriter::PpFrameWriter() { |
172 DVLOG(3) << "PpFrameWriter ctor"; | 214 DVLOG(3) << "PpFrameWriter ctor"; |
173 delegate_ = new FrameWriterDelegate(io_message_loop()); | 215 delegate_ = new FrameWriterDelegate(io_message_loop()); |
174 } | 216 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 bool track_enabled = true; | 295 bool track_enabled = true; |
254 | 296 |
255 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( | 297 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( |
256 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), | 298 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), |
257 track_enabled)); | 299 track_enabled)); |
258 | 300 |
259 return true; | 301 return true; |
260 } | 302 } |
261 | 303 |
262 } // namespace content | 304 } // namespace content |
OLD | NEW |