Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Side by Side Diff: content/browser/renderer_host/media/video_capture_device_client.cc

Issue 967793002: Linux Video Capture: Add V4L2VideoCaptureDelegate{Single,Multi}Plane. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: posciak@ comments on PS5. Minor rebase of video_capture_controller_unittest.cc and BUILD.gn Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698