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..3671c7fa63fc39b316b78f200292214bc4cdfe2f 100644 |
--- a/media/capture/video/video_capture_device_client.cc |
+++ b/media/capture/video/video_capture_device_client.cc |
@@ -38,43 +38,31 @@ 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 BufferPoolBufferAccessProvider : public BufferAccessProvider { |
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()); |
+ BufferPoolBufferAccessProvider( |
+ 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 |
+ // 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(); |
+ |
+ ~BufferPoolBufferAccessProvider() override { |
+ buffer_pool_->RelinquishProducerReservation(buffer_id_); |
} |
-#endif |
- bool IsBackedByVideoFrame() const override { |
- return buffer_handle_->IsBackedByVideoFrame(); |
+ |
+ // Implementation of BufferAccessProvider: |
+ mojo::ScopedSharedBufferHandle GetHandleForTransit() override { |
+ return buffer_pool_->GetHandleForTransit(buffer_id_); |
} |
- scoped_refptr<VideoFrame> GetVideoFrame() override { |
- return buffer_handle_->GetVideoFrame(); |
+ std::unique_ptr<VideoCaptureBufferHandle> GetReadWriteAccess() override { |
+ return buffer_pool_->GetReadWriteAccess(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 +136,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.access_provider->GetReadWriteAccess(); |
+ 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 +259,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 +269,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 +276,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 +291,13 @@ 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_->GetHandleForTransit(buffer.id()); |
base::SharedMemoryHandle memory_handle; |
size_t memory_size = 0; |
bool read_only_flag = false; |
@@ -319,17 +306,18 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( |
&read_only_flag); |
DCHECK_EQ(MOJO_RESULT_OK, unwrap_result_code); |
+ auto buffer_access = buffer.access_provider->GetReadWriteAccess(); |
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 +327,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 +336,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 +361,35 @@ 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<BufferPoolBufferAccessProvider>(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 +399,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.access_provider->GetReadWriteAccess(); |
+ 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); |