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