diff options
21 files changed, 185 insertions, 102 deletions
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index 2000a13..75a2adb 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc @@ -282,7 +282,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( static void ReturnTexture(const scoped_refptr<media::VideoFrame>& frame, uint32 sync_point, bool lost_resource) { - frame->mailbox_holder()->sync_point = sync_point; + frame->AppendReleaseSyncPoint(sync_point); } VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( @@ -296,7 +296,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( if (!context_provider_) return VideoFrameExternalResources(); - gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); + const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); VideoFrameExternalResources external_resources; switch (mailbox_holder->texture_target) { case GL_TEXTURE_2D: diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index fb1ff7a..9c70806 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc @@ -251,7 +251,7 @@ void VideoCaptureController::ReturnBuffer( const VideoCaptureControllerID& id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - uint32 sync_point) { + const std::vector<uint32>& sync_points) { DCHECK_CURRENTLY_ON(BrowserThread::IO); ControllerClient* client = FindClient(id, event_handler, controller_clients_); @@ -267,8 +267,10 @@ void VideoCaptureController::ReturnBuffer( scoped_refptr<media::VideoFrame> frame = iter->second; client->active_buffers.erase(iter); - if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) - frame->mailbox_holder()->sync_point = sync_point; + if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { + for (size_t i = 0; i < sync_points.size(); i++) + frame->AppendReleaseSyncPoint(sync_points[i]); + } buffer_pool_->RelinquishConsumerHold(buffer_id, 1); } diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h index c0c3bed..9b82870 100644 --- a/content/browser/renderer_host/media/video_capture_controller.h +++ b/content/browser/renderer_host/media/video_capture_controller.h @@ -105,7 +105,7 @@ class CONTENT_EXPORT VideoCaptureController { void ReturnBuffer(const VideoCaptureControllerID& id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - uint32 sync_point); + const std::vector<uint32>& sync_points); const media::VideoCaptureFormat& GetVideoCaptureFormat() const; diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index 5fbb515..f650397 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc @@ -70,7 +70,7 @@ class MockVideoCaptureControllerEventHandler id, this, buffer_id, - 0)); + std::vector<uint32>())); } virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id, int buffer_id, @@ -79,7 +79,8 @@ class MockVideoCaptureControllerEventHandler base::TimeTicks timestamp) OVERRIDE { DoMailboxBufferReady(id); // Use a very different syncpoint value when returning a new syncpoint. - const uint32 new_sync_point = ~mailbox_holder.sync_point; + std::vector<uint32> release_sync_points; + release_sync_points.push_back(~mailbox_holder.sync_point); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer, @@ -87,7 +88,7 @@ class MockVideoCaptureControllerEventHandler id, this, buffer_id, - new_sync_point)); + release_sync_points)); } virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE { DoEnded(id); @@ -262,9 +263,11 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) { << "Client count should return to zero after all clients are gone."; } -static void CacheSyncPoint(uint32* sync_value, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { - *sync_value = mailbox_holder->sync_point; +static void CacheSyncPoint(std::vector<uint32>* called_release_sync_points, + const std::vector<uint32>& release_sync_points) { + DCHECK(called_release_sync_points->empty()); + called_release_sync_points->assign(release_sync_points.begin(), + release_sync_points.end()); } // This test will connect and disconnect several clients while simulating an @@ -481,7 +484,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) { buffer = NULL; } std::vector<uint32> mailbox_syncpoints(mailbox_buffers); - std::vector<uint32> mailbox_syncpoints_new(mailbox_buffers); + std::vector<std::vector<uint32> > release_syncpoint_vectors(mailbox_buffers); for (int i = 0; i < mailbox_buffers; ++i) { buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, gfx::Size(0, 0)); @@ -496,7 +499,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) { buffer, make_scoped_ptr(new gpu::MailboxHolder( gpu::Mailbox(), 0, mailbox_syncpoints[i])), - base::Bind(&CacheSyncPoint, &mailbox_syncpoints_new[i]), + base::Bind(&CacheSyncPoint, &release_syncpoint_vectors[i]), capture_resolution), base::TimeTicks()); buffer = NULL; @@ -513,7 +516,8 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) { base::RunLoop().RunUntilIdle(); for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) { // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() - ASSERT_EQ(mailbox_syncpoints[i], ~mailbox_syncpoints_new[i]); + ASSERT_EQ(1u, release_syncpoint_vectors[i].size()); + ASSERT_EQ(mailbox_syncpoints[i], ~release_syncpoint_vectors[i][0]); } Mock::VerifyAndClearExpectations(client_b_.get()); } diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index 43bc404..14ab5d4 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc @@ -295,9 +295,10 @@ void VideoCaptureHost::OnPauseCapture(int device_id) { Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); } -void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, - int buffer_id, - uint32 sync_point) { +void VideoCaptureHost::OnReceiveEmptyBuffer( + int device_id, + int buffer_id, + const std::vector<uint32>& sync_points) { DCHECK_CURRENTLY_ON(BrowserThread::IO); VideoCaptureControllerID controller_id(device_id); @@ -305,7 +306,7 @@ void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, if (it != entries_.end()) { const base::WeakPtr<VideoCaptureController>& controller = it->second; if (controller) - controller->ReturnBuffer(controller_id, this, buffer_id, sync_point); + controller->ReturnBuffer(controller_id, this, buffer_id, sync_points); } } diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index 89dd1d6..25d6947 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h @@ -125,7 +125,9 @@ class CONTENT_EXPORT VideoCaptureHost // IPC message: Receive an empty buffer from renderer. Send it to device // referenced by |device_id|. - void OnReceiveEmptyBuffer(int device_id, int buffer_id, uint32 sync_point); + void OnReceiveEmptyBuffer(int device_id, + int buffer_id, + const std::vector<uint32>& sync_points); // IPC message: Get supported formats referenced by |capture_session_id|. // |device_id| is needed for message back-routing purposes. diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index 48a3563..171d300 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc @@ -151,7 +151,7 @@ class MockVideoCaptureHost : public VideoCaptureHost { void ReturnReceivedDibs(int device_id) { int handle = GetReceivedDib(); while (handle) { - this->OnReceiveEmptyBuffer(device_id, handle, 0); + this->OnReceiveEmptyBuffer(device_id, handle, std::vector<uint32>()); handle = GetReceivedDib(); } } @@ -239,7 +239,8 @@ class MockVideoCaptureHost : public VideoCaptureHost { OnBufferFilled(device_id, buffer_id, frame_format, timestamp); if (return_buffers_) { - VideoCaptureHost::OnReceiveEmptyBuffer(device_id, buffer_id, 0); + VideoCaptureHost::OnReceiveEmptyBuffer( + device_id, buffer_id, std::vector<uint32>()); } } @@ -252,7 +253,7 @@ class MockVideoCaptureHost : public VideoCaptureHost { device_id, buffer_id, mailbox_holder, format, timestamp); if (return_buffers_) { VideoCaptureHost::OnReceiveEmptyBuffer( - device_id, buffer_id, mailbox_holder.sync_point); + device_id, buffer_id, std::vector<uint32>()); } } diff --git a/content/common/media/video_capture_messages.h b/content/common/media/video_capture_messages.h index abfc46c..c3970df 100644 --- a/content/common/media/video_capture_messages.h +++ b/content/common/media/video_capture_messages.h @@ -92,7 +92,7 @@ IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Stop, IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_BufferReady, int /* device_id */, int /* buffer_id */, - uint32 /* syncpoint */) + std::vector<uint32> /* syncpoints */) // Get the formats supported by a device referenced by |capture_session_id|. IPC_MESSAGE_CONTROL2(VideoCaptureHostMsg_GetDeviceSupportedFormats, diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc index a725840..c8c8ae4 100644 --- a/content/renderer/media/android/webmediaplayer_android.cc +++ b/content/renderer/media/android/webmediaplayer_android.cc @@ -71,10 +71,10 @@ const char* kMediaEme = "Media.EME."; void OnReleaseTexture( const scoped_refptr<content::StreamTextureFactory>& factories, uint32 texture_id, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { + const std::vector<uint32>& release_sync_points) { GLES2Interface* gl = factories->ContextGL(); - if (mailbox_holder->sync_point) - gl->WaitSyncPointCHROMIUM(mailbox_holder->sync_point); + for (size_t i = 0; i < release_sync_points.size(); i++) + gl->WaitSyncPointCHROMIUM(release_sync_points[i]); gl->DeleteTextures(1, &texture_id); } } // namespace @@ -468,7 +468,7 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( if (!video_frame || video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) return false; - gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); + const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); DCHECK((!is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) || (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D)); @@ -516,6 +516,7 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( web_graphics_context->bindTexture(GL_TEXTURE_2D, texture); web_graphics_context->deleteTexture(source_texture); web_graphics_context->flush(); + video_frame->AppendReleaseSyncPoint(web_graphics_context->insertSyncPoint()); return true; } diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc index 81ca813..3987767 100644 --- a/content/renderer/media/rtc_video_decoder.cc +++ b/content/renderer/media/rtc_video_decoder.cc @@ -639,9 +639,11 @@ void RTCVideoDecoder::ReleaseMailbox( const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, int64 picture_buffer_id, uint32 texture_id, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { + const std::vector<uint32>& release_sync_points) { DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); - factories->WaitSyncPoint(mailbox_holder->sync_point); + + for (size_t i = 0; i < release_sync_points.size(); i++) + factories->WaitSyncPoint(release_sync_points[i]); if (decoder) { decoder->ReusePictureBuffer(picture_buffer_id); diff --git a/content/renderer/media/rtc_video_decoder.h b/content/renderer/media/rtc_video_decoder.h index e0070b7..d1a04e5 100644 --- a/content/renderer/media/rtc_video_decoder.h +++ b/content/renderer/media/rtc_video_decoder.h @@ -28,10 +28,6 @@ class WaitableEvent; class MessageLoopProxy; }; -namespace gpu { -struct MailboxHolder; -} - namespace media { class DecoderBuffer; class GpuVideoAcceleratorFactories; @@ -156,7 +152,7 @@ class CONTENT_EXPORT RTCVideoDecoder const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, int64 picture_buffer_id, uint32 texture_id, - scoped_ptr<gpu::MailboxHolder> mailbox_holder); + const std::vector<uint32>& release_sync_points); // Tells VDA that a picture buffer can be recycled. void ReusePictureBuffer(int64 picture_buffer_id); diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc index bda203a..465c9fe 100644 --- a/content/renderer/media/video_capture_impl.cc +++ b/content/renderer/media/video_capture_impl.cc @@ -214,7 +214,8 @@ void VideoCaptureImpl::OnBufferReceived(int buffer_id, DCHECK_EQ(format.pixel_format, media::PIXEL_FORMAT_I420); if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { - Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0)); + Send(new VideoCaptureHostMsg_BufferReady( + device_id_, buffer_id, std::vector<uint32>())); return; } @@ -242,12 +243,12 @@ void VideoCaptureImpl::OnBufferReceived(int buffer_id, buffer->buffer_size, buffer->buffer->handle(), timestamp - first_frame_timestamp_, - media::BindToCurrentLoop(base::Bind( - &VideoCaptureImpl::OnClientBufferFinished, - weak_factory_.GetWeakPtr(), - buffer_id, - buffer, - base::Passed(scoped_ptr<gpu::MailboxHolder>().Pass())))); + media::BindToCurrentLoop( + base::Bind(&VideoCaptureImpl::OnClientBufferFinished, + weak_factory_.GetWeakPtr(), + buffer_id, + buffer, + std::vector<uint32>()))); for (ClientInfoMap::iterator it = clients_.begin(); it != clients_.end(); ++it) { @@ -266,7 +267,7 @@ void VideoCaptureImpl::OnMailboxBufferReceived( if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { Send(new VideoCaptureHostMsg_BufferReady( - device_id_, buffer_id, mailbox_holder.sync_point)); + device_id_, buffer_id, std::vector<uint32>())); return; } @@ -296,10 +297,10 @@ void VideoCaptureImpl::OnMailboxBufferReceived( void VideoCaptureImpl::OnClientBufferFinished( int buffer_id, const scoped_refptr<ClientBuffer>& /* ignored_buffer */, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { + const std::vector<uint32>& release_sync_points) { DCHECK(thread_checker_.CalledOnValidThread()); - const uint32 sync_point = (mailbox_holder ? mailbox_holder->sync_point : 0); - Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, sync_point)); + Send(new VideoCaptureHostMsg_BufferReady( + device_id_, buffer_id, release_sync_points)); } void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h index 66c393c..872bfd6 100644 --- a/content/renderer/media/video_capture_impl.h +++ b/content/renderer/media/video_capture_impl.h @@ -129,7 +129,7 @@ class CONTENT_EXPORT VideoCaptureImpl // buffer. void OnClientBufferFinished(int buffer_id, const scoped_refptr<ClientBuffer>& buffer, - scoped_ptr<gpu::MailboxHolder> mailbox_holder); + const std::vector<uint32>& release_sync_points); void StopDevice(); void RestartCapture(); diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc index 13c71af..1f54b76 100644 --- a/content/renderer/media/video_capture_impl_unittest.cc +++ b/content/renderer/media/video_capture_impl_unittest.cc @@ -80,7 +80,7 @@ class VideoCaptureImplTest : public ::testing::Test { void DeviceReceiveEmptyBuffer(int device_id, int buffer_id, - uint32 sync_point) {} + const std::vector<uint32>& sync_points) {} void DeviceGetSupportedFormats(int device_id, media::VideoCaptureSessionId session_id) { diff --git a/content/renderer/media/video_capture_message_filter.cc b/content/renderer/media/video_capture_message_filter.cc index 78d25e7..f58347b 100644 --- a/content/renderer/media/video_capture_message_filter.cc +++ b/content/renderer/media/video_capture_message_filter.cc @@ -114,7 +114,8 @@ void VideoCaptureMessageFilter::OnBufferCreated( // Send the buffer back to Host in case it's waiting for all buffers // to be returned. base::SharedMemory::CloseHandle(handle); - Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0)); + Send(new VideoCaptureHostMsg_BufferReady( + device_id, buffer_id, std::vector<uint32>())); return; } @@ -133,7 +134,8 @@ void VideoCaptureMessageFilter::OnBufferReceived( // Send the buffer back to Host in case it's waiting for all buffers // to be returned. - Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0)); + Send(new VideoCaptureHostMsg_BufferReady( + device_id, buffer_id, std::vector<uint32>())); return; } @@ -154,7 +156,8 @@ void VideoCaptureMessageFilter::OnMailboxBufferReceived( // Send the buffer back to Host in case it's waiting for all buffers // to be returned. - Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0)); + Send(new VideoCaptureHostMsg_BufferReady( + device_id, buffer_id, std::vector<uint32>())); return; } diff --git a/content/renderer/media/webmediaplayer_impl.cc b/content/renderer/media/webmediaplayer_impl.cc index fa12b0f..75c1e7a 100644 --- a/content/renderer/media/webmediaplayer_impl.cc +++ b/content/renderer/media/webmediaplayer_impl.cc @@ -635,7 +635,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) return false; - gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); + const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); if (mailbox_holder->texture_target != GL_TEXTURE_2D) return false; @@ -682,6 +682,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( web_graphics_context->deleteTexture(source_texture); web_graphics_context->flush(); + video_frame->AppendReleaseSyncPoint(web_graphics_context->insertSyncPoint()); return true; } diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 8776665..3d01455 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc @@ -50,8 +50,14 @@ scoped_refptr<VideoFrame> VideoFrame::CreateFrame( return NULL; } DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); - scoped_refptr<VideoFrame> frame(new VideoFrame( - format, new_coded_size, visible_rect, natural_size, timestamp, false)); + scoped_refptr<VideoFrame> frame( + new VideoFrame(format, + new_coded_size, + visible_rect, + natural_size, + scoped_ptr<gpu::MailboxHolder>(), + timestamp, + false)); frame->AllocateYUV(); return frame; } @@ -145,9 +151,9 @@ scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( coded_size, visible_rect, natural_size, + mailbox_holder.Pass(), timestamp, false)); - frame->mailbox_holder_ = mailbox_holder.Pass(); frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb; frame->read_pixels_cb_ = read_pixels_cb; @@ -178,8 +184,14 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory( switch (format) { case I420: { - scoped_refptr<VideoFrame> frame(new VideoFrame( - format, coded_size, visible_rect, natural_size, timestamp, false)); + scoped_refptr<VideoFrame> frame( + new VideoFrame(format, + coded_size, + visible_rect, + natural_size, + scoped_ptr<gpu::MailboxHolder>(), + timestamp, + false)); frame->shared_memory_handle_ = handle; frame->strides_[kYPlane] = coded_size.width(); frame->strides_[kUPlane] = coded_size.width() / 2; @@ -213,8 +225,14 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) return NULL; - scoped_refptr<VideoFrame> frame(new VideoFrame( - format, coded_size, visible_rect, natural_size, timestamp, false)); + scoped_refptr<VideoFrame> frame( + new VideoFrame(format, + coded_size, + visible_rect, + natural_size, + scoped_ptr<gpu::MailboxHolder>(), + timestamp, + false)); frame->strides_[kYPlane] = y_stride; frame->strides_[kUPlane] = u_stride; frame->strides_[kVPlane] = v_stride; @@ -236,9 +254,14 @@ scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( CHECK(frame->format() != NATIVE_TEXTURE); DCHECK(frame->visible_rect().Contains(visible_rect)); - scoped_refptr<VideoFrame> wrapped_frame(new VideoFrame( - frame->format(), frame->coded_size(), visible_rect, natural_size, - frame->timestamp(), frame->end_of_stream())); + scoped_refptr<VideoFrame> wrapped_frame( + new VideoFrame(frame->format(), + frame->coded_size(), + visible_rect, + natural_size, + scoped_ptr<gpu::MailboxHolder>(), + frame->timestamp(), + frame->end_of_stream())); for (size_t i = 0; i < NumPlanes(frame->format()); ++i) { wrapped_frame->strides_[i] = frame->stride(i); @@ -255,6 +278,7 @@ scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { gfx::Size(), gfx::Rect(), gfx::Size(), + scoped_ptr<gpu::MailboxHolder>(), kNoTimestamp(), true); } @@ -290,8 +314,14 @@ scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) { scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( const gfx::Size& size) { DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); - scoped_refptr<VideoFrame> frame(new VideoFrame( - VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta(), false)); + scoped_refptr<VideoFrame> frame( + new VideoFrame(VideoFrame::HOLE, + size, + gfx::Rect(size), + size, + scoped_ptr<gpu::MailboxHolder>(), + base::TimeDelta(), + false)); return frame; } #endif // defined(VIDEO_HOLE) @@ -453,12 +483,14 @@ VideoFrame::VideoFrame(VideoFrame::Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, const gfx::Size& natural_size, + scoped_ptr<gpu::MailboxHolder> mailbox_holder, base::TimeDelta timestamp, bool end_of_stream) : format_(format), coded_size_(coded_size), visible_rect_(visible_rect), natural_size_(natural_size), + mailbox_holder_(mailbox_holder.Pass()), shared_memory_handle_(base::SharedMemory::NULLHandle()), timestamp_(timestamp), end_of_stream_(end_of_stream) { @@ -470,8 +502,12 @@ VideoFrame::VideoFrame(VideoFrame::Format format, VideoFrame::~VideoFrame() { if (!mailbox_holder_release_cb_.is_null()) { - base::ResetAndReturn(&mailbox_holder_release_cb_) - .Run(mailbox_holder_.Pass()); + std::vector<uint32> release_sync_points; + { + base::AutoLock locker(release_sync_point_lock_); + release_sync_points_.swap(release_sync_points); + } + base::ResetAndReturn(&mailbox_holder_release_cb_).Run(release_sync_points); } if (!no_longer_needed_cb_.is_null()) base::ResetAndReturn(&no_longer_needed_cb_).Run(); @@ -543,7 +579,7 @@ uint8* VideoFrame::data(size_t plane) const { return data_[plane]; } -gpu::MailboxHolder* VideoFrame::mailbox_holder() const { +const gpu::MailboxHolder* VideoFrame::mailbox_holder() const { DCHECK_EQ(format_, NATIVE_TEXTURE); return mailbox_holder_.get(); } @@ -552,6 +588,14 @@ base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { return shared_memory_handle_; } +void VideoFrame::AppendReleaseSyncPoint(uint32 sync_point) { + DCHECK_EQ(format_, NATIVE_TEXTURE); + if (!sync_point) + return; + base::AutoLock locker(release_sync_point_lock_); + release_sync_points_.push_back(sync_point); +} + void VideoFrame::HashFrameForTesting(base::MD5Context* context) { for (int plane = 0; plane < kMaxPlanes; ++plane) { if (!IsValidPlane(plane)) diff --git a/media/base/video_frame.h b/media/base/video_frame.h index 8106a27..024cb4c 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -5,9 +5,12 @@ #ifndef MEDIA_BASE_VIDEO_FRAME_H_ #define MEDIA_BASE_VIDEO_FRAME_H_ +#include <vector> + #include "base/callback.h" #include "base/md5.h" #include "base/memory/shared_memory.h" +#include "base/synchronization/lock.h" #include "media/base/buffers.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -80,7 +83,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { // CB to be called on the mailbox backing this frame when the frame is // destroyed. - typedef base::Callback<void(scoped_ptr<gpu::MailboxHolder>)> ReleaseMailboxCB; + typedef base::Callback<void(const std::vector<uint32>&)> ReleaseMailboxCB; // Wraps a native texture of the given parameters with a VideoFrame. The // backing of the VideoFrame is held in the mailbox held by |mailbox_holder|, @@ -204,7 +207,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { // Returns the mailbox holder of the native texture wrapped by this frame. // Only valid to call if this is a NATIVE_TEXTURE frame. Before using the // mailbox, the caller must wait for the included sync point. - gpu::MailboxHolder* mailbox_holder() const; + const gpu::MailboxHolder* mailbox_holder() const; // Returns the shared-memory handle, if present base::SharedMemoryHandle shared_memory_handle() const; @@ -219,6 +222,13 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { timestamp_ = timestamp; } + // Append |sync_point| into |release_sync_points_| which will be passed to + // the video decoder when |mailbox_holder_release_cb_| is called so that + // the video decoder waits for the sync points before reusing the mailbox. + // Multiple clients can append multiple sync points on one frame. + // This method is thread safe. Both blink and compositor threads can call it. + void AppendReleaseSyncPoint(uint32 sync_point); + // Used to keep a running hash of seen frames. Expects an initialized MD5 // context. Calls MD5Update with the context and the contents of the frame. void HashFrameForTesting(base::MD5Context* context); @@ -230,6 +240,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { const gfx::Size& coded_size, const gfx::Rect& visible_rect, const gfx::Size& natural_size, + scoped_ptr<gpu::MailboxHolder> mailbox_holder, base::TimeDelta timestamp, bool end_of_stream); virtual ~VideoFrame(); @@ -267,7 +278,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { uint8* data_[kMaxPlanes]; // Native texture mailbox, if this is a NATIVE_TEXTURE frame. - scoped_ptr<gpu::MailboxHolder> mailbox_holder_; + const scoped_ptr<gpu::MailboxHolder> mailbox_holder_; ReleaseMailboxCB mailbox_holder_release_cb_; ReadPixelsCB read_pixels_cb_; @@ -278,6 +289,9 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { base::TimeDelta timestamp_; + base::Lock release_sync_point_lock_; + std::vector<uint32> release_sync_points_; + const bool end_of_stream_; DISALLOW_IMPLICIT_CONSTRUCTORS(VideoFrame); diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index 8e7ce8f..618d68f 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc @@ -240,63 +240,72 @@ TEST(VideoFrame, CheckFrameExtents) { ExpectFrameExtents(VideoFrame::YV16, "cce408a044b212db42a10dfec304b3ef"); } -static void TextureCallback(uint32* called_sync_point, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { - *called_sync_point = mailbox_holder->sync_point; +static void TextureCallback(std::vector<uint32>* called_sync_point, + const std::vector<uint32>& release_sync_points) { + called_sync_point->assign(release_sync_points.begin(), + release_sync_points.end()); } // Verify the gpu::MailboxHolder::ReleaseCallback is called when VideoFrame is -// destroyed with the original sync point. +// destroyed with the default release sync points. TEST(VideoFrame, TextureNoLongerNeededCallbackIsCalled) { - uint32 sync_point = 7; - uint32 called_sync_point = 0; + std::vector<uint32> called_sync_points; + called_sync_points.push_back(1); { scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture( - make_scoped_ptr(new gpu::MailboxHolder(gpu::Mailbox(), 5, sync_point)), - base::Bind(&TextureCallback, &called_sync_point), - gfx::Size(10, 10), // coded_size - gfx::Rect(10, 10), // visible_rect - gfx::Size(10, 10), // natural_size - base::TimeDelta(), // timestamp - base::Callback<void(const SkBitmap&)>()); // read_pixels_cb - - EXPECT_EQ(0u, called_sync_point); + make_scoped_ptr( + new gpu::MailboxHolder(gpu::Mailbox(), 5, 0 /* sync_point */)), + base::Bind(&TextureCallback, &called_sync_points), + gfx::Size(10, 10), // coded_size + gfx::Rect(10, 10), // visible_rect + gfx::Size(10, 10), // natural_size + base::TimeDelta(), // timestamp + VideoFrame::ReadPixelsCB()); // read_pixels_cb + + EXPECT_EQ(1u, called_sync_points.size()); } - EXPECT_EQ(sync_point, called_sync_point); + EXPECT_TRUE(called_sync_points.empty()); } // Verify the gpu::MailboxHolder::ReleaseCallback is called when VideoFrame is -// destroyed with the new sync point, when the mailbox is accessed by a caller. +// destroyed with the release sync points, which was updated by clients. +// (i.e. the compositor, webgl). TEST(VideoFrame, TextureNoLongerNeededCallbackAfterTakingAndReleasingMailbox) { - uint32 called_sync_point = 0; + std::vector<uint32> called_sync_points; gpu::Mailbox mailbox; mailbox.name[0] = 50; uint32 sync_point = 7; uint32 target = 9; + std::vector<uint32> release_sync_points; + release_sync_points.push_back(1); + release_sync_points.push_back(2); + release_sync_points.push_back(3); { scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture( make_scoped_ptr(new gpu::MailboxHolder(mailbox, target, sync_point)), - base::Bind(&TextureCallback, &called_sync_point), - gfx::Size(10, 10), // coded_size - gfx::Rect(10, 10), // visible_rect - gfx::Size(10, 10), // natural_size - base::TimeDelta(), // timestamp - base::Callback<void(const SkBitmap&)>()); // read_pixels_cb + base::Bind(&TextureCallback, &called_sync_points), + gfx::Size(10, 10), // coded_size + gfx::Rect(10, 10), // visible_rect + gfx::Size(10, 10), // natural_size + base::TimeDelta(), // timestamp + VideoFrame::ReadPixelsCB()); // read_pixels_cb + EXPECT_TRUE(called_sync_points.empty()); - gpu::MailboxHolder* mailbox_holder = frame->mailbox_holder(); + const gpu::MailboxHolder* mailbox_holder = frame->mailbox_holder(); EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox.name[0]); EXPECT_EQ(target, mailbox_holder->texture_target); EXPECT_EQ(sync_point, mailbox_holder->sync_point); - // Finish using the mailbox_holder and drop our reference. - sync_point = 10; - mailbox_holder->sync_point = sync_point; + frame->AppendReleaseSyncPoint(release_sync_points[0]); + frame->AppendReleaseSyncPoint(release_sync_points[1]); + frame->AppendReleaseSyncPoint(release_sync_points[2]); + EXPECT_EQ(sync_point, mailbox_holder->sync_point); } - EXPECT_EQ(sync_point, called_sync_point); + EXPECT_EQ(release_sync_points, called_sync_points); } } // namespace media diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index 392448d6..7a179e3 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc @@ -501,9 +501,11 @@ void GpuVideoDecoder::ReleaseMailbox( const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, int64 picture_buffer_id, uint32 texture_id, - scoped_ptr<gpu::MailboxHolder> mailbox_holder) { + const std::vector<uint32>& release_sync_points) { DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); - factories->WaitSyncPoint(mailbox_holder->sync_point); + + for (size_t i = 0; i < release_sync_points.size(); i++) + factories->WaitSyncPoint(release_sync_points[i]); if (decoder) { decoder->ReusePictureBuffer(picture_buffer_id); diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index e8f5f75..1d905cd 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h @@ -108,7 +108,7 @@ class MEDIA_EXPORT GpuVideoDecoder const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, int64 picture_buffer_id, uint32 texture_id, - scoped_ptr<gpu::MailboxHolder> mailbox_holder); + const std::vector<uint32>& release_sync_points); // Indicate the picture buffer can be reused by the decoder. void ReusePictureBuffer(int64 picture_buffer_id); |