| 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 "media/capture/video/video_capture_device_client.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "content/browser/renderer_host/media/video_capture_buffer_handle.h" | |
| 18 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | |
| 19 #include "content/browser/renderer_host/media/video_capture_controller.h" | |
| 20 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" | |
| 21 #include "media/base/bind_to_current_loop.h" | 17 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/media_switches.h" | 18 #include "media/base/media_switches.h" |
| 23 #include "media/base/video_capture_types.h" | 19 #include "media/base/video_capture_types.h" |
| 24 #include "media/base/video_frame.h" | 20 #include "media/base/video_frame.h" |
| 21 #include "media/capture/video/video_capture_buffer_pool.h" |
| 22 #include "media/capture/video/video_capture_jpeg_decoder.h" |
| 23 #include "media/capture/video/video_frame_receiver.h" |
| 25 #include "third_party/libyuv/include/libyuv.h" | 24 #include "third_party/libyuv/include/libyuv.h" |
| 26 | 25 |
| 27 using media::VideoCaptureFormat; | 26 using media::VideoCaptureFormat; |
| 28 using media::VideoFrame; | 27 using media::VideoFrame; |
| 29 using media::VideoFrameMetadata; | 28 using media::VideoFrameMetadata; |
| 30 | 29 |
| 31 namespace content { | 30 namespace media { |
| 32 | 31 |
| 33 // Class combining a Client::Buffer interface implementation and a pool buffer | 32 // Class combining a Client::Buffer interface implementation and a pool buffer |
| 34 // implementation to guarantee proper cleanup on destruction on our side. | 33 // implementation to guarantee proper cleanup on destruction on our side. |
| 35 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { | 34 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| 36 public: | 35 public: |
| 37 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 36 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, |
| 38 int buffer_id) | 37 int buffer_id) |
| 39 : id_(buffer_id), | 38 : id_(buffer_id), |
| 40 pool_(pool), | 39 pool_(pool), |
| 41 buffer_handle_(pool_->GetBufferHandle(buffer_id)) { | 40 buffer_handle_(pool_->GetBufferHandle(buffer_id)) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 const int chopped_width = frame_format.frame_size.width() & 1; | 110 const int chopped_width = frame_format.frame_size.width() & 1; |
| 112 const int chopped_height = frame_format.frame_size.height() & 1; | 111 const int chopped_height = frame_format.frame_size.height() & 1; |
| 113 const int new_unrotated_width = frame_format.frame_size.width() & ~1; | 112 const int new_unrotated_width = frame_format.frame_size.width() & ~1; |
| 114 const int new_unrotated_height = frame_format.frame_size.height() & ~1; | 113 const int new_unrotated_height = frame_format.frame_size.height() & ~1; |
| 115 | 114 |
| 116 int destination_width = new_unrotated_width; | 115 int destination_width = new_unrotated_width; |
| 117 int destination_height = new_unrotated_height; | 116 int destination_height = new_unrotated_height; |
| 118 if (rotation == 90 || rotation == 270) | 117 if (rotation == 90 || rotation == 270) |
| 119 std::swap(destination_width, destination_height); | 118 std::swap(destination_width, destination_height); |
| 120 | 119 |
| 121 DCHECK_EQ(0, rotation % 90) | 120 DCHECK_EQ(0, rotation % 90) << " Rotation must be a multiple of 90, now: " |
| 122 << " Rotation must be a multiple of 90, now: " << rotation; | 121 << rotation; |
| 123 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | 122 libyuv::RotationMode rotation_mode = libyuv::kRotate0; |
| 124 if (rotation == 90) | 123 if (rotation == 90) |
| 125 rotation_mode = libyuv::kRotate90; | 124 rotation_mode = libyuv::kRotate90; |
| 126 else if (rotation == 180) | 125 else if (rotation == 180) |
| 127 rotation_mode = libyuv::kRotate180; | 126 rotation_mode = libyuv::kRotate180; |
| 128 else if (rotation == 270) | 127 else if (rotation == 270) |
| 129 rotation_mode = libyuv::kRotate270; | 128 rotation_mode = libyuv::kRotate270; |
| 130 | 129 |
| 131 const gfx::Size dimensions(destination_width, destination_height); | 130 const gfx::Size dimensions(destination_width, destination_height); |
| 132 const media::VideoPixelStorage output_pixel_storage = | 131 const media::VideoPixelStorage output_pixel_storage = |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 break; | 172 break; |
| 174 case media::PIXEL_FORMAT_YUY2: | 173 case media::PIXEL_FORMAT_YUY2: |
| 175 DCHECK(!chopped_width && !chopped_height); | 174 DCHECK(!chopped_width && !chopped_height); |
| 176 origin_colorspace = libyuv::FOURCC_YUY2; | 175 origin_colorspace = libyuv::FOURCC_YUY2; |
| 177 break; | 176 break; |
| 178 case media::PIXEL_FORMAT_UYVY: | 177 case media::PIXEL_FORMAT_UYVY: |
| 179 DCHECK(!chopped_width && !chopped_height); | 178 DCHECK(!chopped_width && !chopped_height); |
| 180 origin_colorspace = libyuv::FOURCC_UYVY; | 179 origin_colorspace = libyuv::FOURCC_UYVY; |
| 181 break; | 180 break; |
| 182 case media::PIXEL_FORMAT_RGB24: | 181 case media::PIXEL_FORMAT_RGB24: |
| 183 // Linux RGB24 defines red at lowest byte address, | 182 // Linux RGB24 defines red at lowest byte address, |
| 184 // see http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html. | 183 // see http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html. |
| 185 // Windows RGB24 defines blue at lowest byte, | 184 // Windows RGB24 defines blue at lowest byte, |
| 186 // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd407253 | 185 // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd407253 |
| 187 #if defined(OS_LINUX) | 186 #if defined(OS_LINUX) |
| 188 origin_colorspace = libyuv::FOURCC_RAW; | 187 origin_colorspace = libyuv::FOURCC_RAW; |
| 189 #elif defined(OS_WIN) | 188 #elif defined(OS_WIN) |
| 190 origin_colorspace = libyuv::FOURCC_24BG; | 189 origin_colorspace = libyuv::FOURCC_24BG; |
| 191 #else | 190 #else |
| 192 NOTREACHED() << "RGB24 is only available in Linux and Windows platforms"; | 191 NOTREACHED() << "RGB24 is only available in Linux and Windows platforms"; |
| 193 #endif | 192 #endif |
| 194 #if defined(OS_WIN) | 193 #if defined(OS_WIN) |
| 195 // TODO(wjia): Currently, for RGB24 on WIN, capture device always passes | 194 // TODO(wjia): Currently, for RGB24 on WIN, capture device always passes |
| 196 // in positive src_width and src_height. Remove this hardcoded value when | 195 // in positive src_width and src_height. Remove this hardcoded value when |
| (...skipping 16 matching lines...) Expand all Loading... |
| 213 break; | 212 break; |
| 214 default: | 213 default: |
| 215 NOTREACHED(); | 214 NOTREACHED(); |
| 216 } | 215 } |
| 217 | 216 |
| 218 // The input |length| can be greater than the required buffer size because of | 217 // The input |length| can be greater than the required buffer size because of |
| 219 // paddings and/or alignments, but it cannot be smaller. | 218 // paddings and/or alignments, but it cannot be smaller. |
| 220 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); | 219 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); |
| 221 | 220 |
| 222 if (external_jpeg_decoder_) { | 221 if (external_jpeg_decoder_) { |
| 223 const VideoCaptureGpuJpegDecoder::STATUS status = | 222 const VideoCaptureJpegDecoder::STATUS status = |
| 224 external_jpeg_decoder_->GetStatus(); | 223 external_jpeg_decoder_->GetStatus(); |
| 225 if (status == VideoCaptureGpuJpegDecoder::FAILED) { | 224 if (status == VideoCaptureJpegDecoder::FAILED) { |
| 226 external_jpeg_decoder_.reset(); | 225 external_jpeg_decoder_.reset(); |
| 227 } else if (status == VideoCaptureGpuJpegDecoder::INIT_PASSED && | 226 } else if (status == VideoCaptureJpegDecoder::INIT_PASSED && |
| 228 frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && | 227 frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && |
| 229 rotation == 0 && !flip) { | 228 rotation == 0 && !flip) { |
| 230 external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format, | 229 external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format, |
| 231 reference_time, timestamp, | 230 reference_time, timestamp, |
| 232 std::move(buffer)); | 231 std::move(buffer)); |
| 233 return; | 232 return; |
| 234 } | 233 } |
| 235 } | 234 } |
| 236 | 235 |
| 237 if (libyuv::ConvertToI420(data, | 236 if (libyuv::ConvertToI420(data, length, y_plane_data, yplane_stride, |
| 238 length, | 237 u_plane_data, uv_plane_stride, v_plane_data, |
| 239 y_plane_data, | 238 uv_plane_stride, crop_x, crop_y, |
| 240 yplane_stride, | |
| 241 u_plane_data, | |
| 242 uv_plane_stride, | |
| 243 v_plane_data, | |
| 244 uv_plane_stride, | |
| 245 crop_x, | |
| 246 crop_y, | |
| 247 frame_format.frame_size.width(), | 239 frame_format.frame_size.width(), |
| 248 (flip ? -1 : 1) * frame_format.frame_size.height(), | 240 (flip ? -1 : 1) * frame_format.frame_size.height(), |
| 249 new_unrotated_width, | 241 new_unrotated_width, new_unrotated_height, |
| 250 new_unrotated_height, | 242 rotation_mode, origin_colorspace) != 0) { |
| 251 rotation_mode, | |
| 252 origin_colorspace) != 0) { | |
| 253 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " | 243 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " |
| 254 << media::VideoPixelFormatToString(frame_format.pixel_format); | 244 << media::VideoPixelFormatToString(frame_format.pixel_format); |
| 255 return; | 245 return; |
| 256 } | 246 } |
| 257 | 247 |
| 258 const VideoCaptureFormat output_format = VideoCaptureFormat( | 248 const VideoCaptureFormat output_format = |
| 259 dimensions, frame_format.frame_rate, | 249 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
| 260 media::PIXEL_FORMAT_I420, output_pixel_storage); | 250 media::PIXEL_FORMAT_I420, output_pixel_storage); |
| 261 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 251 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 262 timestamp); | 252 timestamp); |
| 263 } | 253 } |
| 264 | 254 |
| 265 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 255 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 266 VideoCaptureDeviceClient::ReserveOutputBuffer( | 256 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 267 const gfx::Size& frame_size, | 257 const gfx::Size& frame_size, |
| 268 media::VideoPixelFormat pixel_format, | 258 media::VideoPixelFormat pixel_format, |
| 269 media::VideoPixelStorage pixel_storage) { | 259 media::VideoPixelStorage pixel_storage) { |
| 270 DCHECK_GT(frame_size.width(), 0); | 260 DCHECK_GT(frame_size.width(), 0); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 const std::string log_message = base::StringPrintf( | 341 const std::string log_message = base::StringPrintf( |
| 352 "error@ %s, %s, OS message: %s", from_here.ToString().c_str(), | 342 "error@ %s, %s, OS message: %s", from_here.ToString().c_str(), |
| 353 reason.c_str(), | 343 reason.c_str(), |
| 354 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode()) | 344 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode()) |
| 355 .c_str()); | 345 .c_str()); |
| 356 DLOG(ERROR) << log_message; | 346 DLOG(ERROR) << log_message; |
| 357 OnLog(log_message); | 347 OnLog(log_message); |
| 358 receiver_->OnError(); | 348 receiver_->OnError(); |
| 359 } | 349 } |
| 360 | 350 |
| 361 void VideoCaptureDeviceClient::OnLog( | 351 void VideoCaptureDeviceClient::OnLog(const std::string& message) { |
| 362 const std::string& message) { | |
| 363 receiver_->OnLog(message); | 352 receiver_->OnLog(message); |
| 364 } | 353 } |
| 365 | 354 |
| 366 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { | 355 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { |
| 367 return buffer_pool_->GetBufferPoolUtilization(); | 356 return buffer_pool_->GetBufferPoolUtilization(); |
| 368 } | 357 } |
| 369 | 358 |
| 370 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 359 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 371 VideoCaptureDeviceClient::ReserveI420OutputBuffer( | 360 VideoCaptureDeviceClient::ReserveI420OutputBuffer( |
| 372 const gfx::Size& dimensions, | 361 const gfx::Size& dimensions, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 *u_plane_data = | 394 *u_plane_data = |
| 406 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); | 395 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); |
| 407 *v_plane_data = | 396 *v_plane_data = |
| 408 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); | 397 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); |
| 409 return buffer; | 398 return buffer; |
| 410 } | 399 } |
| 411 NOTREACHED(); | 400 NOTREACHED(); |
| 412 return std::unique_ptr<Buffer>(); | 401 return std::unique_ptr<Buffer>(); |
| 413 } | 402 } |
| 414 | 403 |
| 415 } // namespace content | 404 } // namespace media |
| OLD | NEW |