Chromium Code Reviews| Index: media/capture/video/video_capture_device_client.cc |
| diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc |
| index c7a92be1266eadf4e43246ebc05e6883a4a165ec..43340223ddc689bae4f6bd97ad9f9bafa67cbc0d 100644 |
| --- a/media/capture/video/video_capture_device_client.cc |
| +++ b/media/capture/video/video_capture_device_client.cc |
| @@ -38,43 +38,46 @@ bool IsFormatSupported(media::VideoPixelFormat pixel_format) { |
| namespace media { |
| -// Class combining a Client::Buffer interface implementation and a pool buffer |
| -// implementation to guarantee proper cleanup on destruction on our side. |
| -class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| +class BufferPoolProducerReservation |
| + : public VideoCaptureDevice::Client::Buffer::ScopedAccessPermission { |
| public: |
| - AutoReleaseBuffer(scoped_refptr<VideoCaptureBufferPool> pool, |
| - int buffer_id, |
| - int frame_feedback_id) |
| - : pool_(std::move(pool)), |
| - id_(buffer_id), |
| - frame_feedback_id_(frame_feedback_id), |
| - buffer_handle_(pool_->GetBufferHandle(buffer_id)) { |
| - DCHECK(pool_.get()); |
| + BufferPoolProducerReservation( |
| + scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
| + int buffer_id) |
| + : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) { |
| + // The code invoking this contstructor is supposed to have already made a |
|
mcasas
2017/01/05 20:37:02
s/contstructor/constructor/
would there be a way
chfremer
2017/01/05 22:44:48
Hmm, not without changing the public API of VideoC
|
| + // producer reservation on the buffer from pool. |
| } |
| - int id() const override { return id_; } |
| - int frame_feedback_id() const override { return frame_feedback_id_; } |
| - gfx::Size dimensions() const override { return buffer_handle_->dimensions(); } |
| - size_t mapped_size() const override { return buffer_handle_->mapped_size(); } |
| - void* data(int plane) override { return buffer_handle_->data(plane); } |
| -#if defined(OS_POSIX) && !defined(OS_MACOSX) |
| - base::FileDescriptor AsPlatformFile() override { |
| - return buffer_handle_->AsPlatformFile(); |
| + |
| + ~BufferPoolProducerReservation() override { |
| + buffer_pool_->RelinquishProducerReservation(buffer_id_); |
| } |
| -#endif |
| - bool IsBackedByVideoFrame() const override { |
| - return buffer_handle_->IsBackedByVideoFrame(); |
| + |
| + private: |
| + const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; |
| + const int buffer_id_; |
| +}; |
| + |
| +class BufferPoolBufferHandleProvider |
| + : public VideoCaptureDevice::Client::Buffer::HandleProvider { |
| + public: |
| + BufferPoolBufferHandleProvider( |
| + scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
| + int buffer_id) |
| + : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) {} |
| + |
| + // Implementation of HandleProvider: |
| + mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit() override { |
| + return buffer_pool_->GetHandleForInterProcessTransit(buffer_id_); |
| } |
| - scoped_refptr<VideoFrame> GetVideoFrame() override { |
| - return buffer_handle_->GetVideoFrame(); |
| + std::unique_ptr<VideoCaptureBufferHandle> GetHandleForInProcessAccess() |
| + override { |
| + return buffer_pool_->GetHandleForInProcessAccess(buffer_id_); |
| } |
| private: |
| - ~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); } |
| - |
| - const scoped_refptr<VideoCaptureBufferPool> pool_; |
| - const int id_; |
| - const int frame_feedback_id_; |
| - const std::unique_ptr<VideoCaptureBufferHandle> buffer_handle_; |
| + const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; |
| + const int buffer_id_; |
| }; |
| VideoCaptureDeviceClient::VideoCaptureDeviceClient( |
| @@ -148,19 +151,23 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| rotation_mode = libyuv::kRotate270; |
| const gfx::Size dimensions(destination_width, destination_height); |
| - uint8_t *y_plane_data, *u_plane_data, *v_plane_data; |
| - std::unique_ptr<Buffer> buffer(ReserveI420OutputBuffer( |
| - dimensions, media::PIXEL_STORAGE_CPU, frame_feedback_id, &y_plane_data, |
| - &u_plane_data, &v_plane_data)); |
| + Buffer buffer = |
| + ReserveOutputBuffer(dimensions, media::PIXEL_FORMAT_I420, |
| + media::PIXEL_STORAGE_CPU, frame_feedback_id); |
| #if DCHECK_IS_ON() |
| - dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
| + dropped_frame_counter_ = buffer.is_valid() ? 0 : dropped_frame_counter_ + 1; |
| if (dropped_frame_counter_ >= kMaxDroppedFrames) |
| OnError(FROM_HERE, "Too many frames dropped"); |
| #endif |
| // Failed to reserve I420 output buffer, so drop the frame. |
| - if (!buffer.get()) |
| + if (!buffer.is_valid()) |
| return; |
| + auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); |
| + uint8_t *y_plane_data, *u_plane_data, *v_plane_data; |
| + InitializeI420PlanePointers(dimensions, buffer_access->data(), &y_plane_data, |
| + &u_plane_data, &v_plane_data); |
| + |
| const int yplane_stride = dimensions.width(); |
| const int uv_plane_stride = yplane_stride / 2; |
| int crop_x = 0; |
| @@ -267,7 +274,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| timestamp); |
| } |
| -std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| +media::VideoCaptureDevice::Client::Buffer |
| VideoCaptureDeviceClient::ReserveOutputBuffer( |
| const gfx::Size& frame_size, |
| media::VideoPixelFormat pixel_format, |
| @@ -277,8 +284,6 @@ VideoCaptureDeviceClient::ReserveOutputBuffer( |
| DCHECK_GT(frame_size.height(), 0); |
| DCHECK(IsFormatSupported(pixel_format)); |
| - // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
| - // it's a ShMem GMB or a DmaBuf GMB. |
| int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| const int buffer_id = |
| buffer_pool_->ReserveForProducer(frame_size, pixel_format, pixel_storage, |
| @@ -286,13 +291,12 @@ VideoCaptureDeviceClient::ReserveOutputBuffer( |
| if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) |
| receiver_->OnBufferDestroyed(buffer_id_to_drop); |
| if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| - return nullptr; |
| - return base::WrapUnique<Buffer>( |
| - new AutoReleaseBuffer(buffer_pool_, buffer_id, frame_feedback_id)); |
| + return Buffer(); |
| + return MakeBufferStruct(buffer_pool_, buffer_id, frame_feedback_id); |
| } |
| void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| - std::unique_ptr<Buffer> buffer, |
| + Buffer buffer, |
| const VideoCaptureFormat& format, |
| base::TimeTicks reference_time, |
| base::TimeDelta timestamp) { |
| @@ -302,15 +306,14 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| } |
| void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( |
| - std::unique_ptr<Buffer> buffer, |
| + Buffer buffer, |
| const VideoCaptureFormat& format, |
| base::TimeTicks reference_time, |
| base::TimeDelta timestamp, |
| gfx::Rect visible_rect, |
| const VideoFrameMetadata& additional_metadata) { |
| - const int buffer_id = buffer->id(); |
| - |
| - auto buffer_mojo_handle = buffer_pool_->GetHandleForTransit(buffer_id); |
| + auto buffer_mojo_handle = |
| + buffer_pool_->GetHandleForInterProcessTransit(buffer.id()); |
| base::SharedMemoryHandle memory_handle; |
| size_t memory_size = 0; |
| bool read_only_flag = false; |
| @@ -319,17 +322,18 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( |
| &read_only_flag); |
| DCHECK_EQ(MOJO_RESULT_OK, unwrap_result_code); |
| + auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); |
| scoped_refptr<media::VideoFrame> frame = |
| media::VideoFrame::WrapExternalSharedMemory( |
| - format.pixel_format, // format |
| - format.frame_size, // coded_size |
| - visible_rect, // visible_rect |
| - format.frame_size, // natural_size |
| - static_cast<uint8_t*>(buffer->data()), // data |
| - buffer->mapped_size(), // data_size |
| - memory_handle, // handle |
| - 0, // shared_memory_offset |
| - timestamp); // timestamp |
| + format.pixel_format, // format |
| + format.frame_size, // coded_size |
| + visible_rect, // visible_rect |
| + format.frame_size, // natural_size |
| + buffer_access->data(), // data |
| + buffer_access->mapped_size(), // data_size |
| + memory_handle, // handle |
| + 0, // shared_memory_offset |
| + timestamp); // timestamp |
| frame->metadata()->MergeMetadataFrom(&additional_metadata); |
| frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| format.frame_rate); |
| @@ -339,7 +343,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( |
| receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); |
| } |
| -std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| +media::VideoCaptureDevice::Client::Buffer |
| VideoCaptureDeviceClient::ResurrectLastOutputBuffer( |
| const gfx::Size& dimensions, |
| media::VideoPixelFormat format, |
| @@ -348,9 +352,8 @@ VideoCaptureDeviceClient::ResurrectLastOutputBuffer( |
| const int buffer_id = |
| buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); |
| if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| - return nullptr; |
| - return base::WrapUnique<Buffer>( |
| - new AutoReleaseBuffer(buffer_pool_, buffer_id, new_frame_feedback_id)); |
| + return Buffer(); |
| + return MakeBufferStruct(buffer_pool_, buffer_id, new_frame_feedback_id); |
| } |
| void VideoCaptureDeviceClient::OnError( |
| @@ -374,33 +377,36 @@ double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { |
| return buffer_pool_->GetBufferPoolUtilization(); |
| } |
| -std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| -VideoCaptureDeviceClient::ReserveI420OutputBuffer( |
| +// static |
| +VideoCaptureDevice::Client::Buffer VideoCaptureDeviceClient::MakeBufferStruct( |
| + scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
| + int buffer_id, |
| + int frame_feedback_id) { |
| + return Buffer( |
| + buffer_id, frame_feedback_id, |
| + base::MakeUnique<BufferPoolBufferHandleProvider>(buffer_pool, buffer_id), |
| + base::MakeUnique<BufferPoolProducerReservation>(buffer_pool, buffer_id)); |
| +} |
| + |
| +void VideoCaptureDeviceClient::InitializeI420PlanePointers( |
| const gfx::Size& dimensions, |
| - media::VideoPixelStorage storage, |
| - int frame_feedback_id, |
| + uint8_t* const data, |
| uint8_t** y_plane_data, |
| uint8_t** u_plane_data, |
| uint8_t** v_plane_data) { |
| - DCHECK(storage == media::PIXEL_STORAGE_CPU); |
| DCHECK(dimensions.height()); |
| DCHECK(dimensions.width()); |
| const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420; |
| - std::unique_ptr<Buffer> buffer(ReserveOutputBuffer( |
| - dimensions, media::PIXEL_FORMAT_I420, storage, frame_feedback_id)); |
| - if (!buffer) |
| - return std::unique_ptr<Buffer>(); |
| // TODO(emircan): See http://crbug.com/521068, move this pointer |
| // arithmetic inside Buffer::data() when this bug is resolved. |
| - *y_plane_data = reinterpret_cast<uint8_t*>(buffer->data()); |
| + *y_plane_data = data; |
| *u_plane_data = |
| *y_plane_data + |
| VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions).GetArea(); |
| *v_plane_data = |
| *u_plane_data + |
| VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); |
| - return buffer; |
| } |
| void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( |
| @@ -410,21 +416,22 @@ void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( |
| base::TimeTicks reference_time, |
| base::TimeDelta timestamp, |
| int frame_feedback_id) { |
| - std::unique_ptr<Buffer> buffer( |
| + Buffer buffer = |
| ReserveOutputBuffer(format.frame_size, media::PIXEL_FORMAT_Y16, |
| - media::PIXEL_STORAGE_CPU, frame_feedback_id)); |
| + media::PIXEL_STORAGE_CPU, frame_feedback_id); |
| // The input |length| can be greater than the required buffer size because of |
| // paddings and/or alignments, but it cannot be smaller. |
| DCHECK_GE(static_cast<size_t>(length), format.ImageAllocationSize()); |
| #if DCHECK_IS_ON() |
| - dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
| + dropped_frame_counter_ = buffer.is_valid() ? 0 : dropped_frame_counter_ + 1; |
| if (dropped_frame_counter_ >= kMaxDroppedFrames) |
| OnError(FROM_HERE, "Too many frames dropped"); |
| #endif |
| // Failed to reserve output buffer, so drop the frame. |
| - if (!buffer.get()) |
| + if (!buffer.is_valid()) |
| return; |
| - memcpy(buffer->data(), data, length); |
| + auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); |
| + memcpy(buffer_access->data(), data, length); |
| const VideoCaptureFormat output_format = |
| VideoCaptureFormat(format.frame_size, format.frame_rate, |
| media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); |