OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/browser/renderer_host/media/video_capture_device_client.h" | 5 #include "content/browser/renderer_host/media/video_capture_device_client.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 10 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 | 66 |
67 if (last_captured_pixel_format_ != frame_format.pixel_format) { | 67 if (last_captured_pixel_format_ != frame_format.pixel_format) { |
68 OnLog("Pixel format: " + media::VideoCaptureFormat::PixelFormatToString( | 68 OnLog("Pixel format: " + media::VideoCaptureFormat::PixelFormatToString( |
69 frame_format.pixel_format)); | 69 frame_format.pixel_format)); |
70 last_captured_pixel_format_ = frame_format.pixel_format; | 70 last_captured_pixel_format_ = frame_format.pixel_format; |
71 } | 71 } |
72 | 72 |
73 if (!frame_format.IsValid()) | 73 if (!frame_format.IsValid()) |
74 return; | 74 return; |
75 | 75 |
76 // Chopped pixels in width/height in case video capture device has odd | 76 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
77 // numbers for width/height. | 77 // bit decomposition of {width, height}, grabbing the odd and even parts. |
78 int chopped_width = 0; | 78 const int chopped_width = frame_format.frame_size.width() & 1; |
79 int chopped_height = 0; | 79 const int chopped_height = frame_format.frame_size.height() & 1; |
80 int new_unrotated_width = frame_format.frame_size.width(); | 80 const int new_unrotated_width = frame_format.frame_size.width() & ~1; |
81 int new_unrotated_height = frame_format.frame_size.height(); | 81 const int new_unrotated_height = frame_format.frame_size.height() & ~1; |
82 | |
83 if (new_unrotated_width & 1) { | |
84 --new_unrotated_width; | |
85 chopped_width = 1; | |
86 } | |
87 if (new_unrotated_height & 1) { | |
88 --new_unrotated_height; | |
89 chopped_height = 1; | |
90 } | |
91 | 82 |
92 int destination_width = new_unrotated_width; | 83 int destination_width = new_unrotated_width; |
93 int destination_height = new_unrotated_height; | 84 int destination_height = new_unrotated_height; |
94 if (rotation == 90 || rotation == 270) { | 85 if (rotation == 90 || rotation == 270) { |
95 destination_width = new_unrotated_height; | 86 destination_width = new_unrotated_height; |
96 destination_height = new_unrotated_width; | 87 destination_height = new_unrotated_width; |
97 } | 88 } |
89 | |
90 DLOG_IF(WARNING, (rotation % 90)) | |
perkj_chrome
2015/03/19 20:38:17
nit: dcheck this
mcasas
2015/03/19 22:57:00
Done.
| |
91 << " Rotation must be a multiple of 90 and is " << rotation; | |
92 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | |
93 if (rotation == 90) | |
94 rotation_mode = libyuv::kRotate90; | |
95 else if (rotation == 180) | |
96 rotation_mode = libyuv::kRotate180; | |
97 else if (rotation == 270) | |
98 rotation_mode = libyuv::kRotate270; | |
99 | |
98 const gfx::Size dimensions(destination_width, destination_height); | 100 const gfx::Size dimensions(destination_width, destination_height); |
99 if (!VideoFrame::IsValidConfig(VideoFrame::I420, | 101 if (!VideoFrame::IsValidConfig(VideoFrame::I420, |
100 dimensions, | 102 dimensions, |
101 gfx::Rect(dimensions), | 103 gfx::Rect(dimensions), |
102 dimensions)) { | 104 dimensions)) { |
103 return; | 105 return; |
104 } | 106 } |
105 | 107 |
106 scoped_refptr<Buffer> buffer = ReserveOutputBuffer(VideoFrame::I420, | 108 scoped_refptr<Buffer> buffer = ReserveOutputBuffer(VideoFrame::I420, |
107 dimensions); | 109 dimensions); |
108 if (!buffer.get()) | 110 if (!buffer.get()) |
109 return; | 111 return; |
110 | 112 |
111 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); | 113 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); |
112 uint8* const uplane = | 114 uint8* const uplane = |
113 yplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, | 115 yplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, |
114 VideoFrame::kYPlane, dimensions); | 116 VideoFrame::kYPlane, dimensions); |
115 uint8* const vplane = | 117 uint8* const vplane = |
116 uplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, | 118 uplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, |
117 VideoFrame::kUPlane, dimensions); | 119 VideoFrame::kUPlane, dimensions); |
118 int yplane_stride = dimensions.width(); | 120 int yplane_stride = dimensions.width(); |
119 int uv_plane_stride = yplane_stride / 2; | 121 int uv_plane_stride = yplane_stride / 2; |
120 int crop_x = 0; | 122 int crop_x = 0; |
121 int crop_y = 0; | 123 int crop_y = 0; |
122 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; | 124 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; |
123 | 125 |
124 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | |
125 if (rotation == 90) | |
126 rotation_mode = libyuv::kRotate90; | |
127 else if (rotation == 180) | |
128 rotation_mode = libyuv::kRotate180; | |
129 else if (rotation == 270) | |
130 rotation_mode = libyuv::kRotate270; | |
131 | |
132 bool flip = false; | 126 bool flip = false; |
133 switch (frame_format.pixel_format) { | 127 switch (frame_format.pixel_format) { |
134 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. | 128 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. |
135 break; | 129 break; |
136 case media::PIXEL_FORMAT_I420: | 130 case media::PIXEL_FORMAT_I420: |
137 DCHECK(!chopped_width && !chopped_height); | 131 DCHECK(!chopped_width && !chopped_height); |
138 origin_colorspace = libyuv::FOURCC_I420; | 132 origin_colorspace = libyuv::FOURCC_I420; |
139 break; | 133 break; |
140 case media::PIXEL_FORMAT_YV12: | 134 case media::PIXEL_FORMAT_YV12: |
141 DCHECK(!chopped_width && !chopped_height); | 135 DCHECK(!chopped_width && !chopped_height); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 BrowserThread::IO, | 216 BrowserThread::IO, |
223 FROM_HERE, | 217 FROM_HERE, |
224 base::Bind( | 218 base::Bind( |
225 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | 219 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
226 controller_, | 220 controller_, |
227 buffer, | 221 buffer, |
228 frame, | 222 frame, |
229 timestamp)); | 223 timestamp)); |
230 } | 224 } |
231 | 225 |
226 void | |
227 VideoCaptureDeviceClient::OnIncomingCapturedYuvData( | |
228 const uint8* y_data, | |
229 const uint8* u_data, | |
230 const uint8* v_data, | |
231 int y_length, | |
232 int u_length, | |
233 int v_length, | |
234 const VideoCaptureFormat& frame_format, | |
235 int clockwise_rotation, | |
236 const base::TimeTicks& timestamp) { | |
237 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedYuvData"); | |
238 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); | |
239 DCHECK_EQ(clockwise_rotation, 0) << "Rotation not supported"; | |
240 DCHECK_GE(static_cast<size_t>(y_length + u_length + v_length), | |
241 frame_format.ImageAllocationSize()); | |
242 | |
243 scoped_refptr<Buffer> buffer = ReserveOutputBuffer(VideoFrame::I420, | |
244 frame_format.frame_size); | |
245 if (!buffer.get()) | |
246 return; | |
247 | |
248 // Blit (copy) here from y,u,v into buffer.data()). Needed so we can return | |
249 // the parameter buffer synchronously to the driver. | |
250 const size_t y_stride = y_length / frame_format.frame_size.height(); | |
251 const size_t u_stride = u_length / frame_format.frame_size.height() / 2; | |
magjed_chromium
2015/03/19 18:13:29
You need parenthesis around height() / 2, now it's
perkj_chrome
2015/03/19 20:38:17
Why dont you have y_stride u_stride etc as input p
mcasas
2015/03/19 22:57:00
Done.
mcasas
2015/03/19 22:57:00
Done.
| |
252 const size_t v_stride = v_length / frame_format.frame_size.height() / 2; | |
253 const size_t y_plane_size = VideoFrame::PlaneAllocationSize(VideoFrame::I420, | |
254 VideoFrame::kYPlane, frame_format.frame_size); | |
255 const size_t u_plane_size = VideoFrame::PlaneAllocationSize(VideoFrame::I420, | |
256 VideoFrame::kUPlane, frame_format.frame_size); | |
257 uint8* const dst_y = reinterpret_cast<uint8*>(buffer->data()); | |
258 uint8* const dst_u = dst_y + y_plane_size; | |
259 uint8* const dst_v = dst_u + u_plane_size; | |
260 | |
261 if (libyuv::I420Copy(y_data, y_stride, | |
perkj_chrome
2015/03/19 20:38:17
So actually holding the buffer in the driver did n
mcasas
2015/03/19 22:57:00
After much discussion with posciak@ we decided not
| |
262 u_data, u_stride, | |
263 v_data, v_stride, | |
264 dst_y, y_stride, | |
265 dst_u, u_stride, | |
266 dst_v, v_stride, | |
267 frame_format.frame_size.width(), | |
268 frame_format.frame_size.height())) { | |
269 DLOG(WARNING) << "Failed to copy buffer"; | |
270 return; | |
271 } | |
272 | |
273 scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData( | |
274 VideoFrame::I420, frame_format.frame_size, | |
275 gfx::Rect(frame_format.frame_size), frame_format.frame_size, y_stride, | |
276 u_stride, v_stride, dst_y, dst_u, dst_v, base::TimeDelta(), | |
277 base::Closure()); | |
278 DCHECK(video_frame.get()); | |
279 | |
280 BrowserThread::PostTask( | |
281 BrowserThread::IO, | |
282 FROM_HERE, | |
283 base::Bind( | |
284 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | |
285 controller_, | |
286 buffer, | |
287 video_frame, | |
288 timestamp)); | |
289 }; | |
290 | |
232 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> | 291 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> |
233 VideoCaptureDeviceClient::ReserveOutputBuffer(VideoFrame::Format format, | 292 VideoCaptureDeviceClient::ReserveOutputBuffer(VideoFrame::Format format, |
234 const gfx::Size& dimensions) { | 293 const gfx::Size& dimensions) { |
235 const size_t frame_bytes = VideoFrame::AllocationSize(format, dimensions); | 294 const size_t frame_bytes = VideoFrame::AllocationSize(format, dimensions); |
236 if (format == VideoFrame::NATIVE_TEXTURE) { | 295 if (format == VideoFrame::NATIVE_TEXTURE) { |
237 DCHECK_EQ(dimensions.width(), 0); | 296 DCHECK_EQ(dimensions.width(), 0); |
238 DCHECK_EQ(dimensions.height(), 0); | 297 DCHECK_EQ(dimensions.height(), 0); |
239 } else { | 298 } else { |
240 DLOG_IF(ERROR, frame_bytes == 0) << "Error calculating allocation size"; | 299 DLOG_IF(ERROR, frame_bytes == 0) << "Error calculating allocation size"; |
241 } | 300 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 } | 352 } |
294 | 353 |
295 void VideoCaptureDeviceClient::OnLog( | 354 void VideoCaptureDeviceClient::OnLog( |
296 const std::string& message) { | 355 const std::string& message) { |
297 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 356 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
298 base::Bind(&VideoCaptureController::DoLogOnIOThread, | 357 base::Bind(&VideoCaptureController::DoLogOnIOThread, |
299 controller_, message)); | 358 controller_, message)); |
300 } | 359 } |
301 | 360 |
302 } // namespace content | 361 } // namespace content |
OLD | NEW |