diff options
44 files changed, 173 insertions, 1120 deletions
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index de42351..7be8df8 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -112,16 +112,16 @@ void GpuVideoDecodeAccelerator::Initialize( DCHECK(!video_decode_accelerator_.get()); DCHECK(!init_done_msg_); DCHECK(init_done_msg); - init_done_msg_ = init_done_msg; #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) DCHECK(stub_ && stub_->decoder()); + init_done_msg_ = init_done_msg; OmxVideoDecodeAccelerator* omx_decoder = new OmxVideoDecodeAccelerator(this); omx_decoder->SetEglState( gfx::GLSurfaceEGL::GetHardwareDisplay(), stub_->decoder()->GetGLContext()->GetHandle()); video_decode_accelerator_ = omx_decoder; video_decode_accelerator_->Initialize(profile); -#else // Update RenderViewImpl::createMediaPlayer when adding clauses. +#else NOTIMPLEMENTED() << "HW video decode acceleration not available."; NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); #endif // defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc index 0c96b9c..53fc535 100644 --- a/content/common/gpu/media/omx_video_decode_accelerator.cc +++ b/content/common/gpu/media/omx_video_decode_accelerator.cc @@ -50,25 +50,25 @@ static bool AreOMXFunctionPointersInitialized() { // Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values. static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) { switch (profile) { - case media::H264PROFILE_BASELINE: + case media::VideoDecodeAccelerator::H264PROFILE_BASELINE: return OMX_VIDEO_AVCProfileBaseline; - case media::H264PROFILE_MAIN: + case media::VideoDecodeAccelerator::H264PROFILE_MAIN: return OMX_VIDEO_AVCProfileMain; - case media::H264PROFILE_EXTENDED: + case media::VideoDecodeAccelerator::H264PROFILE_EXTENDED: return OMX_VIDEO_AVCProfileExtended; - case media::H264PROFILE_HIGH: + case media::VideoDecodeAccelerator::H264PROFILE_HIGH: return OMX_VIDEO_AVCProfileHigh; - case media::H264PROFILE_HIGH10PROFILE: + case media::VideoDecodeAccelerator::H264PROFILE_HIGH10PROFILE: return OMX_VIDEO_AVCProfileHigh10; - case media::H264PROFILE_HIGH422PROFILE: + case media::VideoDecodeAccelerator::H264PROFILE_HIGH422PROFILE: return OMX_VIDEO_AVCProfileHigh422; - case media::H264PROFILE_HIGH444PREDICTIVEPROFILE: + case media::VideoDecodeAccelerator::H264PROFILE_HIGH444PREDICTIVEPROFILE: return OMX_VIDEO_AVCProfileHigh444; // Below enums don't have equivalent enum in Openmax. - case media::H264PROFILE_SCALABLEBASELINE: - case media::H264PROFILE_SCALABLEHIGH: - case media::H264PROFILE_STEREOHIGH: - case media::H264PROFILE_MULTIVIEWHIGH: + case media::VideoDecodeAccelerator::H264PROFILE_SCALABLEBASELINE: + case media::VideoDecodeAccelerator::H264PROFILE_SCALABLEHIGH: + case media::VideoDecodeAccelerator::H264PROFILE_STEREOHIGH: + case media::VideoDecodeAccelerator::H264PROFILE_MULTIVIEWHIGH: // Nvidia OMX video decoder requires the same resources (as that of the // High profile) in every profile higher to the Main profile. return OMX_VIDEO_AVCProfileHigh444; @@ -144,8 +144,7 @@ static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { bool OmxVideoDecodeAccelerator::Initialize(Profile profile) { DCHECK_EQ(message_loop_, MessageLoop::current()); - RETURN_ON_FAILURE((profile >= media::H264PROFILE_MIN && - profile <= media::H264PROFILE_MAX), + RETURN_ON_FAILURE(profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX, "Only h264 supported", INVALID_ARGUMENT, false); profile_ = MapH264ProfileToOMXAVCProfile(profile); RETURN_ON_FAILURE(profile_ != OMX_VIDEO_AVCProfileMax, @@ -769,8 +768,7 @@ void OmxVideoDecodeAccelerator::FillBufferDoneTask( --output_buffers_at_component_; if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { - size_t erased = fake_output_buffers_.erase(buffer); - DCHECK_EQ(erased, 1U); + DCHECK_EQ(fake_output_buffers_.erase(buffer), 1U); OMX_ERRORTYPE result = OMX_FreeBuffer(component_handle_, output_port_, buffer); RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", PLATFORM_FAILURE,); diff --git a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc index 727b7fe..a259b31 100644 --- a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc @@ -576,7 +576,8 @@ void EglRenderingVDAClient::CreateDecoder() { return; // Configure the decoder. - media::VideoDecodeAccelerator::Profile profile = media::H264PROFILE_BASELINE; + media::VideoDecodeAccelerator::Profile profile = + media::VideoDecodeAccelerator::H264PROFILE_BASELINE; if (profile_ != -1) profile = static_cast<media::VideoDecodeAccelerator::Profile>(profile_); CHECK(decoder_->Initialize(profile)); @@ -802,10 +803,9 @@ static void AssertWaitForStateOrDeleted(ClientStateNotification* note, << ", instead of " << expected_state; } -// We assert a minimal number of concurrent decoders we expect to succeed. -// Different platforms can support more concurrent decoders, so we don't assert -// failure above this. -enum { kMinSupportedNumConcurrentDecoders = 3 }; +// We assert the exact number of concurrent decoders we expect to succeed and +// that one more than that fails initialization. +enum { kMaxSupportedNumConcurrentDecoders = 3 }; // Test the most straightforward case possible: data is decoded from a single // chunk and rendered to the screen. @@ -889,7 +889,7 @@ TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { // We expect initialization to fail only when more than the supported // number of decoders is instantiated. Assert here that something else // didn't trigger failure. - ASSERT_GT(num_concurrent_decoders, kMinSupportedNumConcurrentDecoders); + ASSERT_GT(num_concurrent_decoders, kMaxSupportedNumConcurrentDecoders); continue; } ASSERT_EQ(state, CS_INITIALIZED); @@ -908,6 +908,9 @@ TEST_P(OmxVideoDecodeAcceleratorTest, TestSimpleDecode) { ASSERT_NO_FATAL_FAILURE( AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); } + ASSERT_EQ(saw_init_failure, + num_concurrent_decoders > kMaxSupportedNumConcurrentDecoders) + << num_concurrent_decoders; // Finally assert that decoding went as expected. for (size_t i = 0; i < num_concurrent_decoders && !saw_init_failure; ++i) { // We can only make performance/correctness assertions if the decoder was @@ -994,9 +997,9 @@ INSTANTIATE_TEST_CASE_P( ResourceExhaustion, OmxVideoDecodeAcceleratorTest, ::testing::Values( // +0 hack below to promote enum to int. - MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, + MakeTuple(1, kMaxSupportedNumConcurrentDecoders + 0, 1, END_OF_STREAM_RESET, CS_RESET), - MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, + MakeTuple(1, kMaxSupportedNumConcurrentDecoders + 1, 1, END_OF_STREAM_RESET, CS_RESET))); // TODO(fischman, vrk): add more tests! In particular: diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 67535f9..f5c75e3 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -149,8 +149,6 @@ 'renderer/renderer_accessibility.h', 'renderer/renderer_clipboard_client.cc', 'renderer/renderer_clipboard_client.h', - 'renderer/renderer_gpu_video_decoder_factories.cc', - 'renderer/renderer_gpu_video_decoder_factories.h', 'renderer/renderer_main.cc', 'renderer/renderer_main_platform_delegate.h', 'renderer/renderer_main_platform_delegate_linux.cc', diff --git a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc index 02eec34..c9c6d59 100644 --- a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc +++ b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc @@ -26,12 +26,12 @@ GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost( client_(client) { DCHECK(channel_); DCHECK(client_); + DCHECK(RenderThreadImpl::current()); } GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {} void GpuVideoDecodeAcceleratorHost::OnChannelError() { - OnErrorNotification(PLATFORM_FAILURE); channel_ = NULL; } diff --git a/content/renderer/media/audio_renderer_impl.cc b/content/renderer/media/audio_renderer_impl.cc index 9bdc981..768142ad 100644 --- a/content/renderer/media/audio_renderer_impl.cc +++ b/content/renderer/media/audio_renderer_impl.cc @@ -202,6 +202,9 @@ void AudioRendererImpl::Render(const std::vector<float*>& audio_data, return; } + // Adjust the playback delay. + base::Time current_time = base::Time::Now(); + base::TimeDelta request_delay = base::TimeDelta::FromMilliseconds(audio_delay_milliseconds); diff --git a/content/renderer/media/capture_video_decoder.cc b/content/renderer/media/capture_video_decoder.cc index 3b0b358..5d9ef9f 100644 --- a/content/renderer/media/capture_video_decoder.cc +++ b/content/renderer/media/capture_video_decoder.cc @@ -33,7 +33,7 @@ CaptureVideoDecoder::~CaptureVideoDecoder() {} void CaptureVideoDecoder::Initialize( media::DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const media::StatisticsCallback& stat_callback) { message_loop_proxy_->PostTask( FROM_HERE, @@ -134,7 +134,7 @@ void CaptureVideoDecoder::OnDeviceInfoReceived( void CaptureVideoDecoder::InitializeOnDecoderThread( media::DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const media::StatisticsCallback& stat_callback) { DVLOG(1) << "InitializeOnDecoderThread"; DCHECK(message_loop_proxy_->BelongsToCurrentThread()); @@ -142,7 +142,7 @@ void CaptureVideoDecoder::InitializeOnDecoderThread( capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); statistics_callback_ = stat_callback; - filter_callback.Run(media::PIPELINE_OK); + filter_callback.Run(); state_ = kNormal; } diff --git a/content/renderer/media/capture_video_decoder.h b/content/renderer/media/capture_video_decoder.h index 5a2a84d6..3d16785 100644 --- a/content/renderer/media/capture_video_decoder.h +++ b/content/renderer/media/capture_video_decoder.h @@ -9,7 +9,6 @@ #include "content/common/content_export.h" #include "media/base/demuxer_stream.h" #include "media/base/filters.h" -#include "media/base/pipeline_status.h" #include "media/base/video_frame.h" #include "media/video/capture/video_capture.h" @@ -42,7 +41,7 @@ class CONTENT_EXPORT CaptureVideoDecoder // Decoder implementation. virtual void Initialize( media::DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const media::StatisticsCallback& stat_callback) OVERRIDE; virtual void Read(const ReadCB& callback) OVERRIDE; virtual const gfx::Size& natural_size() OVERRIDE; @@ -79,7 +78,7 @@ class CONTENT_EXPORT CaptureVideoDecoder void InitializeOnDecoderThread( media::DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const media::StatisticsCallback& stat_callback); void ReadOnDecoderThread(const ReadCB& callback); diff --git a/content/renderer/media/capture_video_decoder_unittest.cc b/content/renderer/media/capture_video_decoder_unittest.cc index 33396a5..5cfc9f5d 100644 --- a/content/renderer/media/capture_video_decoder_unittest.cc +++ b/content/renderer/media/capture_video_decoder_unittest.cc @@ -122,7 +122,7 @@ class CaptureVideoDecoderTest : public ::testing::Test { EXPECT_CALL(*vc_manager_, AddDevice(_, _)) .WillOnce(Return(vc_impl_.get())); decoder_->Initialize(NULL, - media::NewExpectedStatusCB(media::PIPELINE_OK), + media::NewExpectedClosure(), NewStatisticsCallback()); message_loop_->RunAllPending(); } diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc index 75293a8..4f418a5 100644 --- a/content/renderer/media/rtc_video_decoder.cc +++ b/content/renderer/media/rtc_video_decoder.cc @@ -38,7 +38,7 @@ RTCVideoDecoder::RTCVideoDecoder(MessageLoop* message_loop, RTCVideoDecoder::~RTCVideoDecoder() {} void RTCVideoDecoder::Initialize(DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const StatisticsCallback& stat_callback) { if (MessageLoop::current() != message_loop_) { message_loop_->PostTask( @@ -51,7 +51,7 @@ void RTCVideoDecoder::Initialize(DemuxerStream* demuxer_stream, DCHECK_EQ(MessageLoop::current(), message_loop_); state_ = kNormal; - filter_callback.Run(PIPELINE_OK); + filter_callback.Run(); // TODO(acolwell): Implement stats. } diff --git a/content/renderer/media/rtc_video_decoder.h b/content/renderer/media/rtc_video_decoder.h index 35ec744..398ea8c 100644 --- a/content/renderer/media/rtc_video_decoder.h +++ b/content/renderer/media/rtc_video_decoder.h @@ -41,7 +41,7 @@ class CONTENT_EXPORT RTCVideoDecoder // Decoder implementation. virtual void Initialize( media::DemuxerStream* demuxer_stream, - const media::PipelineStatusCB& filter_callback, + const base::Closure& filter_callback, const media::StatisticsCallback& stat_callback) OVERRIDE; virtual void Read(const ReadCB& callback) OVERRIDE; virtual const gfx::Size& natural_size() OVERRIDE; diff --git a/content/renderer/media/rtc_video_decoder_unittest.cc b/content/renderer/media/rtc_video_decoder_unittest.cc index 039fc94..73d2bb4 100644 --- a/content/renderer/media/rtc_video_decoder_unittest.cc +++ b/content/renderer/media/rtc_video_decoder_unittest.cc @@ -34,7 +34,6 @@ using media::MockStatisticsCallback; using media::MockVideoRenderer; using media::MockFilterHost; using media::NewExpectedClosure; -using media::NewExpectedStatusCB; using media::PipelineStatistics; using media::PIPELINE_OK; using media::StatisticsCallback; @@ -133,8 +132,8 @@ class RTCVideoDecoderTest : public testing::Test { void InitializeDecoderSuccessfully() { // Test successful initialization. - decoder_->Initialize( - NULL, NewExpectedStatusCB(PIPELINE_OK), NewStatisticsCallback()); + decoder_->Initialize(NULL, + NewExpectedClosure(), NewStatisticsCallback()); message_loop_.RunAllPending(); } diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 627ecc39..c635162 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -69,7 +69,6 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_accessibility.h" -#include "content/renderer/renderer_gpu_video_decoder_factories.h" #include "content/renderer/renderer_webapplicationcachehost_impl.h" #include "content/renderer/renderer_webstoragenamespace_impl.h" #include "content/renderer/speech_input_dispatcher.h" @@ -81,7 +80,6 @@ #include "media/base/filter_collection.h" #include "media/base/media_switches.h" #include "media/base/message_loop_factory_impl.h" -#include "media/filters/gpu_video_decoder.h" #include "net/base/escape.h" #include "net/base/net_errors.h" #include "net/http/http_util.h" @@ -149,6 +147,7 @@ #include "webkit/glue/webkit_constants.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/weburlloader_impl.h" +#include "webkit/media/video_renderer_impl.h" #include "webkit/media/webmediaplayer_impl.h" #include "webkit/plugins/npapi/plugin_list.h" #include "webkit/plugins/npapi/webplugin_delegate.h" @@ -1944,25 +1943,6 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer( collection->AddAudioRenderer(new AudioRendererImpl()); } -#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) - // Currently only cros/arm has any HW video decode support in - // GpuVideoDecodeAccelerator so we don't even try to use it on other - // platforms. This is a startup-time optimization. When new VDA - // implementations are added, relax the #if above. - WebKit::WebGraphicsContext3D* wk_context3d = webview()->graphicsContext3D(); - if (wk_context3d) { - WebGraphicsContext3DCommandBufferImpl* context3d = - static_cast<WebGraphicsContext3DCommandBufferImpl*>(wk_context3d); - GpuChannelHost* gpu_channel_host = - RenderThreadImpl::current()->EstablishGpuChannelSync( - content::CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE); - collection->AddVideoDecoder(new media::GpuVideoDecoder( - MessageLoop::current(), - new RendererGpuVideoDecoderFactories( - gpu_channel_host, context3d->context()->AsWeakPtr()))); - } -#endif - webkit_media::WebMediaPlayerImpl* result_ptr; if (!content::GetContentClient()->renderer()->OverrideCreateWebMediaPlayer( this, client, AsWeakPtr(), collection, message_loop_factory, diff --git a/content/renderer/renderer_gpu_video_decoder_factories.cc b/content/renderer/renderer_gpu_video_decoder_factories.cc deleted file mode 100644 index 8867f48..0000000 --- a/content/renderer/renderer_gpu_video_decoder_factories.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/renderer_gpu_video_decoder_factories.h" - -#include "content/common/child_thread.h" -#include "content/renderer/gpu/command_buffer_proxy.h" -#include "content/renderer/gpu/gpu_channel_host.h" -#include "content/renderer/gpu/renderer_gl_context.h" -#include "gpu/command_buffer/client/gles2_implementation.h" - -RendererGpuVideoDecoderFactories::~RendererGpuVideoDecoderFactories() {} -RendererGpuVideoDecoderFactories::RendererGpuVideoDecoderFactories( - GpuChannelHost* gpu_channel_host, base::WeakPtr<RendererGLContext> context) - : gpu_channel_host_(gpu_channel_host), context_(context) { -} - -media::VideoDecodeAccelerator* -RendererGpuVideoDecoderFactories::CreateVideoDecodeAccelerator( - media::VideoDecodeAccelerator::Profile profile, - media::VideoDecodeAccelerator::Client* client) { - if (!context_) - return NULL; - return gpu_channel_host_->CreateVideoDecoder( - context_->GetCommandBufferProxy()->route_id(), profile, client); -} - -bool RendererGpuVideoDecoderFactories::CreateTextures( - int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids) { - if (!context_) - return false; - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); - texture_ids->resize(count); - gles2->GenTextures(count, &texture_ids->at(0)); - for (int i = 0; i < count; ++i) { - gles2->ActiveTexture(GL_TEXTURE0); - uint32 texture_id = texture_ids->at(i); - gles2->BindTexture(GL_TEXTURE_2D, texture_id); - gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gles2->TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gles2->TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gles2->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } - DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - return true; -} - -bool RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) { - if (!context_) - return false; - gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation(); - gles2->DeleteTextures(1, &texture_id); - DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - return true; -} - -base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory( - size_t size) { - return ChildThread::current()->AllocateSharedMemory(size); -} diff --git a/content/renderer/renderer_gpu_video_decoder_factories.h b/content/renderer/renderer_gpu_video_decoder_factories.h deleted file mode 100644 index 2b8400f..0000000 --- a/content/renderer/renderer_gpu_video_decoder_factories.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_RENDERER_GPU_VIDEO_DECODER_FACTORIES_H_ -#define CONTENT_RENDERER_RENDERER_GPU_VIDEO_DECODER_FACTORIES_H_ -#pragma once - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "media/filters/gpu_video_decoder.h" -#include "ui/gfx/size.h" - -class GpuChannelHost; -class RendererGLContext; - -// Glue code to expose functionality needed by media::GpuVideoDecoder to -// RenderViewImpl. This class is entirely an implementation detail of -// RenderViewImpl and only has its own header to allow extraction of its -// implementation from render_view_impl.cc which is already far too large. -class RendererGpuVideoDecoderFactories - : public media::GpuVideoDecoder::Factories { - public: - // Takes a ref on |gpu_channel_host| and tests |context| for NULL before each - // use. - RendererGpuVideoDecoderFactories(GpuChannelHost* gpu_channel_host, - base::WeakPtr<RendererGLContext> context); - - virtual ~RendererGpuVideoDecoderFactories(); - - media::VideoDecodeAccelerator* CreateVideoDecodeAccelerator( - media::VideoDecodeAccelerator::Profile profile, - media::VideoDecodeAccelerator::Client* client) OVERRIDE; - - virtual bool CreateTextures(int32 count, const gfx::Size& size, - std::vector<uint32>* texture_ids) OVERRIDE; - - virtual bool DeleteTexture(uint32 texture_id) OVERRIDE; - - virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; - - private: - scoped_refptr<GpuChannelHost> gpu_channel_host_; - base::WeakPtr<RendererGLContext> context_; - DISALLOW_IMPLICIT_CONSTRUCTORS(RendererGpuVideoDecoderFactories); -}; - -#endif // CONTENT_RENDERER_RENDERER_GPU_VIDEO_DECODER_FACTORIES_H_ diff --git a/media/base/composite_filter.cc b/media/base/composite_filter.cc index d6e45df..5c4b1c5 100644 --- a/media/base/composite_filter.cc +++ b/media/base/composite_filter.cc @@ -57,8 +57,6 @@ CompositeFilter::~CompositeFilter() { } bool CompositeFilter::AddFilter(scoped_refptr<Filter> filter) { - // TODO(fischman,scherkus): s/bool/void/ the return type and CHECK on failure - // of the sanity-checks that return false today. DCHECK_EQ(message_loop_, MessageLoop::current()); if (!filter.get() || state_ != kCreated || !host()) return false; @@ -69,23 +67,6 @@ bool CompositeFilter::AddFilter(scoped_refptr<Filter> filter) { return true; } -void CompositeFilter::RemoveFilter(scoped_refptr<Filter> filter) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - if (!filter.get() || state_ != kCreated || !host()) - LOG(FATAL) << "Unknown filter, or in unexpected state."; - - bool found = false; - for (FilterVector::iterator it = filters_.begin(); - it != filters_.end() && !found; ++it) { - if (it->get() == filter.get()) { - filters_.erase(it); - found = true; - } - } - filter->clear_host(); - CHECK(found); -} - void CompositeFilter::set_host(FilterHost* host) { DCHECK_EQ(message_loop_, MessageLoop::current()); DCHECK(host); @@ -356,6 +337,7 @@ void CompositeFilter::SerialCallback() { DispatchPendingCallback(status_); return; } + if (!filters_.empty()) sequence_index_++; @@ -393,6 +375,7 @@ void CompositeFilter::ParallelCallback() { void CompositeFilter::OnCallSequenceDone() { State next_state = GetNextState(state_); + if (next_state == kInvalid) { // We somehow got into an unexpected state. ChangeState(kError); diff --git a/media/base/composite_filter.h b/media/base/composite_filter.h index 9821d03f..4b35be3 100644 --- a/media/base/composite_filter.h +++ b/media/base/composite_filter.h @@ -27,9 +27,6 @@ class MEDIA_EXPORT CompositeFilter : public Filter { // because the composite is in the wrong state. bool AddFilter(scoped_refptr<Filter> filter); - // Undoes AddFilter's actions. CHECK-fails if |filter| is unknown. - void RemoveFilter(scoped_refptr<Filter> filter); - // media::Filter methods. virtual void set_host(FilterHost* host) OVERRIDE; virtual FilterHost* host() OVERRIDE; diff --git a/media/base/composite_filter_unittest.cc b/media/base/composite_filter_unittest.cc index 36ea0b8..23b7f56 100644 --- a/media/base/composite_filter_unittest.cc +++ b/media/base/composite_filter_unittest.cc @@ -379,8 +379,8 @@ TEST_F(CompositeFilterTest, TestAddFilterFailCases) { EXPECT_FALSE(composite_->AddFilter(filter)); } -// Test successful {Add,Remove}Filter() cases. -TEST_F(CompositeFilterTest, TestAddRemoveFilter) { +// Test successful AddFilter() cases. +TEST_F(CompositeFilterTest, TestAddFilter) { composite_->set_host(mock_filter_host_.get()); // Add a filter. @@ -388,20 +388,8 @@ TEST_F(CompositeFilterTest, TestAddRemoveFilter) { EXPECT_EQ(NULL, filter->host()); EXPECT_TRUE(composite_->AddFilter(filter)); - EXPECT_TRUE(filter->host() != NULL); - - composite_->RemoveFilter(filter); - EXPECT_TRUE(filter->host() == NULL); -} - -class CompositeFilterDeathTest : public CompositeFilterTest {}; -// Test failure of RemoveFilter() on an unknown filter. -TEST_F(CompositeFilterDeathTest, TestRemoveUnknownFilter) { - composite_->set_host(mock_filter_host_.get()); - // Remove unknown filter. - scoped_refptr<StrictMock<MockFilter> > filter = new StrictMock<MockFilter>(); - EXPECT_DEATH(composite_->RemoveFilter(filter), ""); + EXPECT_TRUE(filter->host() != NULL); } TEST_F(CompositeFilterTest, TestPlay) { diff --git a/media/base/filter_collection.h b/media/base/filter_collection.h index edf6b29..97e7232 100644 --- a/media/base/filter_collection.h +++ b/media/base/filter_collection.h @@ -40,7 +40,6 @@ class MEDIA_EXPORT FilterCollection { // Selects a filter of the specified type from the collection. // If the required filter cannot be found, NULL is returned. // If a filter is returned it is removed from the collection. - // Filters are selected in FIFO order. void SelectVideoDecoder(scoped_refptr<VideoDecoder>* filter_out); void SelectAudioDecoder(scoped_refptr<AudioDecoder>* filter_out); void SelectVideoRenderer(scoped_refptr<VideoRenderer>* filter_out); diff --git a/media/base/filters.cc b/media/base/filters.cc index ace7d4e..877f391 100644 --- a/media/base/filters.cc +++ b/media/base/filters.cc @@ -29,11 +29,6 @@ Filter::Filter() : host_(NULL) {} Filter::~Filter() {} -void Filter::clear_host() { - DCHECK(host_); - host_ = NULL; -} - void Filter::set_host(FilterHost* host) { DCHECK(host); DCHECK(!host_); diff --git a/media/base/filters.h b/media/base/filters.h index 5cd4cf8..e464202 100644 --- a/media/base/filters.h +++ b/media/base/filters.h @@ -62,8 +62,8 @@ enum Preload { // Used for completing asynchronous methods. typedef base::Callback<void(PipelineStatus)> FilterStatusCB; -// These functions copy |*cb|, call Reset() on |*cb|, and then call Run() -// on the copy. This is used in the common case where you need to clear +// This function copies |*cb|, calls Reset() on |*cb|, and then calls Run() +// on the copy. This is used in the common case where you need to clear // a callback member variable before running the callback. MEDIA_EXPORT void ResetAndRunCB(FilterStatusCB* cb, PipelineStatus status); MEDIA_EXPORT void ResetAndRunCB(base::Closure* cb); @@ -81,10 +81,6 @@ class MEDIA_EXPORT Filter : public base::RefCountedThreadSafe<Filter> { // to be released before the host object is destroyed by the pipeline. virtual void set_host(FilterHost* host); - // Clear |host_| to signal abandonment. Must be called after set_host() and - // before any state-changing method below. - virtual void clear_host(); - virtual FilterHost* host(); // The pipeline has resumed playback. Filters can continue requesting reads. @@ -168,8 +164,9 @@ class MEDIA_EXPORT VideoDecoder : public Filter { // Initialize a VideoDecoder with the given DemuxerStream, executing the // callback upon completion. // stats_callback is used to update global pipeline statistics. - virtual void Initialize(DemuxerStream* stream, - const PipelineStatusCB& callback, + // + // TODO(scherkus): switch to PipelineStatus callback. + virtual void Initialize(DemuxerStream* stream, const base::Closure& callback, const StatisticsCallback& stats_callback) = 0; // Request a frame to be decoded and returned via the provided callback. diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index c8f71e8..d398448 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc @@ -166,10 +166,6 @@ void RunPipelineStatusCB(PipelineStatus status, const PipelineStatusCB& cb) { cb.Run(status); } -void RunPipelineStatusOKCB(const PipelineStatusCB& cb) { - cb.Run(PIPELINE_OK); -} - void RunFilterCallback3(::testing::Unused, const base::Closure& callback, ::testing::Unused) { callback.Run(); diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 5c36b10..13a8d2c 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -188,7 +188,7 @@ class MockVideoDecoder : public VideoDecoder { // VideoDecoder implementation. MOCK_METHOD3(Initialize, void(DemuxerStream* stream, - const PipelineStatusCB& callback, + const base::Closure& callback, const StatisticsCallback& stats_callback)); MOCK_METHOD1(Read, void(const ReadCB& callback)); MOCK_METHOD0(natural_size, const gfx::Size&()); @@ -322,7 +322,6 @@ class MockFilterCollection { void RunFilterCallback(::testing::Unused, const base::Closure& callback); void RunFilterStatusCB(::testing::Unused, const FilterStatusCB& cb); void RunPipelineStatusCB(PipelineStatus status, const PipelineStatusCB& cb); -void RunPipelineStatusOKCB(const PipelineStatusCB& cb); // Always PIPELINE_OK. void RunFilterCallback3(::testing::Unused, const base::Closure& callback, ::testing::Unused); diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index aa5ac3b..d4c1b8e 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -586,10 +586,10 @@ void PipelineImpl::DisableAudioRenderer() { } // Called from any thread. -void PipelineImpl::OnFilterInitialize(PipelineStatus status) { +void PipelineImpl::OnFilterInitialize() { // Continue the initialize task by proceeding to the next stage. - message_loop_->PostTask( - FROM_HERE, base::Bind(&PipelineImpl::InitializeTask, this, status)); + message_loop_->PostTask(FROM_HERE, + base::Bind(&PipelineImpl::InitializeTask, this)); } // Called from any thread. @@ -661,21 +661,9 @@ void PipelineImpl::StartTask(FilterCollection* filter_collection, // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It // works like a big state change table. If we no longer need to start filters // in order, we need to get rid of all the state change. -void PipelineImpl::InitializeTask(PipelineStatus last_stage_status) { +void PipelineImpl::InitializeTask() { DCHECK_EQ(MessageLoop::current(), message_loop_); - if (last_stage_status != PIPELINE_OK) { - // Currently only VideoDecoders have a recoverable error code. - if (state_ == kInitVideoDecoder && - last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { - pipeline_init_state_->composite_->RemoveFilter( - pipeline_init_state_->video_decoder_.get()); - state_ = kInitAudioRenderer; - } else { - SetError(last_stage_status); - } - } - // If we have received the stop or error signal, return immediately. if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) return; @@ -1123,8 +1111,10 @@ void PipelineImpl::FinishDestroyingFiltersTask() { bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); - if (!ret) + + if (!ret) { SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); + } return ret; } @@ -1165,7 +1155,7 @@ void PipelineImpl::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { clock_->SetTime(demuxer_->GetStartTime()); } - OnFilterInitialize(PIPELINE_OK); + OnFilterInitialize(); } bool PipelineImpl::InitializeAudioDecoder( @@ -1193,7 +1183,7 @@ bool PipelineImpl::InitializeAudioDecoder( pipeline_init_state_->audio_decoder_ = audio_decoder; audio_decoder->Initialize( stream, - base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), + base::Bind(&PipelineImpl::OnFilterInitialize, this), base::Bind(&PipelineImpl::OnUpdateStatistics, this)); return true; } @@ -1250,7 +1240,7 @@ bool PipelineImpl::InitializeAudioRenderer( audio_renderer_->Initialize( decoder, - base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), + base::Bind(&PipelineImpl::OnFilterInitialize, this), base::Bind(&PipelineImpl::OnAudioUnderflow, this)); return true; } @@ -1274,7 +1264,7 @@ bool PipelineImpl::InitializeVideoRenderer( video_renderer_->Initialize( decoder, - base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), + base::Bind(&PipelineImpl::OnFilterInitialize, this), base::Bind(&PipelineImpl::OnUpdateStatistics, this)); return true; } diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 9426688..5fb8f82 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -206,8 +206,8 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline, public FilterHost { virtual void SetCurrentReadPosition(int64 offset) OVERRIDE; virtual int64 GetCurrentReadPosition() OVERRIDE; - // Callbacks executed by filters upon completing initialization. - void OnFilterInitialize(PipelineStatus status); + // Callback executed by filters upon completing initialization. + void OnFilterInitialize(); // Callback executed by filters upon completing Play(), Pause(), or Stop(). void OnFilterStateTransition(); @@ -231,9 +231,8 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline, public FilterHost { // InitializeTask() performs initialization in multiple passes. It is executed // as a result of calling Start() or InitializationComplete() that advances // initialization to the next state. It works as a hub of state transition for - // initialization. One stage communicates its status to the next through - // |last_stage_status|. - void InitializeTask(PipelineStatus last_stage_status); + // initialization. + void InitializeTask(); // Stops and destroys all filters, placing the pipeline in the kStopped state. void StopTask(const PipelineStatusCB& stop_callback); diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 76f7a0c..fc9692e 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -21,13 +21,11 @@ using ::testing::_; using ::testing::DeleteArg; using ::testing::InSequence; using ::testing::Invoke; -using ::testing::InvokeArgument; using ::testing::Mock; using ::testing::NotNull; using ::testing::Return; using ::testing::ReturnRef; using ::testing::StrictMock; -using ::testing::WithArg; namespace media { @@ -128,7 +126,7 @@ class PipelineImplTest : public ::testing::Test { void InitializeVideoDecoder(MockDemuxerStream* stream) { EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream, _, _)) - .WillOnce(WithArg<1>(Invoke(&RunPipelineStatusOKCB))); + .WillOnce(Invoke(&RunFilterCallback3)); EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->video_decoder(), Seek(mocks_->demuxer()->GetStartTime(), _)) diff --git a/media/base/video_decoder_config.cc b/media/base/video_decoder_config.cc index 07bf9a5..ee334d3 100644 --- a/media/base/video_decoder_config.cc +++ b/media/base/video_decoder_config.cc @@ -14,7 +14,6 @@ namespace media { VideoDecoderConfig::VideoDecoderConfig() : codec_(kUnknownVideoCodec), - profile_(VIDEO_CODEC_PROFILE_UNKNOWN), format_(VideoFrame::INVALID), frame_rate_numerator_(0), frame_rate_denominator_(0), @@ -24,7 +23,6 @@ VideoDecoderConfig::VideoDecoderConfig() } VideoDecoderConfig::VideoDecoderConfig(VideoCodec codec, - VideoCodecProfile profile, VideoFrame::Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, @@ -34,7 +32,7 @@ VideoDecoderConfig::VideoDecoderConfig(VideoCodec codec, int aspect_ratio_denominator, const uint8* extra_data, size_t extra_data_size) { - Initialize(codec, profile, format, coded_size, visible_rect, + Initialize(codec, format, coded_size, visible_rect, frame_rate_numerator, frame_rate_denominator, aspect_ratio_numerator, aspect_ratio_denominator, extra_data, extra_data_size); @@ -64,9 +62,7 @@ static void UmaHistogramAspectRatio(const char* name, const T& size) { kCommonAspectRatios100, arraysize(kCommonAspectRatios100))); } -void VideoDecoderConfig::Initialize(VideoCodec codec, - VideoCodecProfile profile, - VideoFrame::Format format, +void VideoDecoderConfig::Initialize(VideoCodec codec, VideoFrame::Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, int frame_rate_numerator, @@ -78,15 +74,12 @@ void VideoDecoderConfig::Initialize(VideoCodec codec, CHECK((extra_data_size != 0) == (extra_data != NULL)); UMA_HISTOGRAM_ENUMERATION("Media.VideoCodec", codec, kVideoCodecMax + 1); - UMA_HISTOGRAM_ENUMERATION("Media.VideoCodecProfile", profile, - VIDEO_CODEC_PROFILE_MAX + 1); UMA_HISTOGRAM_COUNTS_10000("Media.VideoCodedWidth", coded_size.width()); UmaHistogramAspectRatio("Media.VideoCodedAspectRatio", coded_size); UMA_HISTOGRAM_COUNTS_10000("Media.VideoVisibleWidth", visible_rect.width()); UmaHistogramAspectRatio("Media.VideoVisibleAspectRatio", visible_rect); codec_ = codec; - profile_ = profile; format_ = format; coded_size_ = coded_size; visible_rect_ = visible_rect; @@ -132,33 +125,10 @@ bool VideoDecoderConfig::IsValidConfig() const { natural_size_.GetArea() <= limits::kMaxCanvas; } -std::string VideoDecoderConfig::AsHumanReadableString() const { - std::ostringstream s; - s << "codec: " << codec() - << " format: " << format() - << " coded size: [" << coded_size().width() - << "," << coded_size().height() << "]" - << " visible rect: [" << visible_rect().x() - << "," << visible_rect().y() - << "," << visible_rect().width() - << "," << visible_rect().height() << "]" - << " natural size: [" << natural_size().width() - << "," << natural_size().height() << "]" - << " frame rate: " << frame_rate_numerator() - << "/" << frame_rate_denominator() - << " aspect ratio: " << aspect_ratio_numerator() - << "/" << aspect_ratio_denominator(); - return s.str(); -} - VideoCodec VideoDecoderConfig::codec() const { return codec_; } -VideoCodecProfile VideoDecoderConfig::profile() const { - return profile_; -} - VideoFrame::Format VideoDecoderConfig::format() const { return format_; } diff --git a/media/base/video_decoder_config.h b/media/base/video_decoder_config.h index 28b1106..b02bee8 100644 --- a/media/base/video_decoder_config.h +++ b/media/base/video_decoder_config.h @@ -14,7 +14,7 @@ namespace media { -enum MEDIA_EXPORT VideoCodec { +enum VideoCodec { // These values are histogrammed over time; do not change their ordinal // values. When deleting a codec replace it with a dummy value; when adding a // codec, do so at the bottom (and update kVideoCodecMax). @@ -33,28 +33,6 @@ enum MEDIA_EXPORT VideoCodec { kVideoCodecMax = kCodecVP8 // Must equal the last "real" codec above. }; -// Video stream profile. This *must* match PP_VideoDecoder_Profile. -enum MEDIA_EXPORT VideoCodecProfile { - // Keep the values in this enum unique, as they imply format (h.264 vs. VP8, - // for example), and keep the values for a particular format grouped - // together for clarity. - VIDEO_CODEC_PROFILE_UNKNOWN = -1, - H264PROFILE_MIN = 0, - H264PROFILE_BASELINE = H264PROFILE_MIN, - H264PROFILE_MAIN, - H264PROFILE_EXTENDED, - H264PROFILE_HIGH, - H264PROFILE_HIGH10PROFILE, - H264PROFILE_HIGH422PROFILE, - H264PROFILE_HIGH444PREDICTIVEPROFILE, - H264PROFILE_SCALABLEBASELINE, - H264PROFILE_SCALABLEHIGH, - H264PROFILE_STEREOHIGH, - H264PROFILE_MULTIVIEWHIGH, - H264PROFILE_MAX = H264PROFILE_MULTIVIEWHIGH, - VIDEO_CODEC_PROFILE_MAX = H264PROFILE_MAX, -}; - class MEDIA_EXPORT VideoDecoderConfig { public: // Constructs an uninitialized object. Clients should call Initialize() with @@ -64,7 +42,6 @@ class MEDIA_EXPORT VideoDecoderConfig { // Constructs an initialized object. It is acceptable to pass in NULL for // |extra_data|, otherwise the memory is copied. VideoDecoderConfig(VideoCodec codec, - VideoCodecProfile profile, VideoFrame::Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, @@ -76,7 +53,6 @@ class MEDIA_EXPORT VideoDecoderConfig { // Resets the internal state of this object. void Initialize(VideoCodec codec, - VideoCodecProfile profile, VideoFrame::Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, @@ -88,12 +64,7 @@ class MEDIA_EXPORT VideoDecoderConfig { // otherwise. bool IsValidConfig() const; - // Returns a human-readable string describing |*this|. For debugging & test - // output only. - std::string AsHumanReadableString() const; - VideoCodec codec() const; - VideoCodecProfile profile() const; // Video format used to determine YUV buffer sizes. VideoFrame::Format format() const; @@ -131,7 +102,6 @@ class MEDIA_EXPORT VideoDecoderConfig { private: VideoCodec codec_; - VideoCodecProfile profile_; VideoFrame::Format format_; diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 29c4223..a0dc579 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc @@ -17,8 +17,9 @@ scoped_refptr<VideoFrame> VideoFrame::CreateFrame( base::TimeDelta duration) { DCHECK(width > 0 && height > 0); DCHECK(width * height < 100000000); - scoped_refptr<VideoFrame> frame(new VideoFrame( - format, width, height, timestamp, duration)); + scoped_refptr<VideoFrame> frame(new VideoFrame(format, width, height)); + frame->SetTimestamp(timestamp); + frame->SetDuration(duration); switch (format) { case VideoFrame::RGB555: case VideoFrame::RGB565: @@ -46,25 +47,8 @@ scoped_refptr<VideoFrame> VideoFrame::CreateFrame( } // static -scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( - uint32 texture_id, - size_t width, - size_t height, - base::TimeDelta timestamp, - base::TimeDelta duration, - const base::Closure& no_longer_needed) { - scoped_refptr<VideoFrame> frame( - new VideoFrame(NATIVE_TEXTURE, width, height, timestamp, duration)); - frame->planes_ = 0; - frame->texture_id_ = texture_id; - frame->texture_no_longer_needed_ = no_longer_needed; - return frame; -} - -// static scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() { - return new VideoFrame( - VideoFrame::EMPTY, 0, 0, base::TimeDelta(), base::TimeDelta()); + return new VideoFrame(VideoFrame::EMPTY, 0, 0); } // static @@ -154,26 +138,16 @@ void VideoFrame::AllocateYUV() { VideoFrame::VideoFrame(VideoFrame::Format format, size_t width, - size_t height, - base::TimeDelta timestamp, - base::TimeDelta duration) + size_t height) : format_(format), width_(width), height_(height), - planes_(0), - texture_id_(0) { - SetTimestamp(timestamp); - SetDuration(duration); + planes_(0) { memset(&strides_, 0, sizeof(strides_)); memset(&data_, 0, sizeof(data_)); } VideoFrame::~VideoFrame() { - if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) { - texture_no_longer_needed_.Run(); - texture_no_longer_needed_.Reset(); - } - // In multi-plane allocations, only a single block of memory is allocated // on the heap, and other |data| pointers point inside the same, single block // so just delete index 0. @@ -193,10 +167,6 @@ bool VideoFrame::IsValidPlane(size_t plane) const { case YV16: return plane == kYPlane || plane == kUPlane || plane == kVPlane; - case NATIVE_TEXTURE: - NOTREACHED() << "NATIVE_TEXTUREs don't use plane-related methods!"; - return false; - default: break; } @@ -266,12 +236,6 @@ uint8* VideoFrame::data(size_t plane) const { return data_[plane]; } -uint32 VideoFrame::texture_id() const { - DCHECK_EQ(format_, NATIVE_TEXTURE); - DCHECK_EQ(planes_, 0U); - return texture_id_; -} - bool VideoFrame::IsEndOfStream() const { return format_ == VideoFrame::EMPTY; } diff --git a/media/base/video_frame.h b/media/base/video_frame.h index 1801077..ab96544 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -5,7 +5,6 @@ #ifndef MEDIA_BASE_VIDEO_FRAME_H_ #define MEDIA_BASE_VIDEO_FRAME_H_ -#include "base/callback.h" #include "media/base/buffers.h" namespace media { @@ -26,7 +25,6 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { // Surface formats roughly based on FOURCC labels, see: // http://www.fourcc.org/rgb.php // http://www.fourcc.org/yuv.php - // Keep in sync with WebKit::WebVideoFrame! enum Format { INVALID, // Invalid format value. Used for error reporting. RGB555, // 16bpp RGB packed 5:5:5 @@ -40,7 +38,6 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { EMPTY, // An empty frame. ASCII, // A frame with ASCII content. For testing only. I420, // 12bpp YVU planar 1x1 Y, 2x2 UV samples. - NATIVE_TEXTURE, // Opaque native texture. Pixel-format agnostic. }; // Creates a new frame in system memory with given parameters. Buffers for @@ -52,16 +49,6 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { base::TimeDelta timestamp, base::TimeDelta duration); - // Wraps a native texture of the given parameters with a VideoFrame. When the - // frame is destroyed |no_longer_needed.Run()| will be called. - static scoped_refptr<VideoFrame> WrapNativeTexture( - uint32 texture_id, - size_t width, - size_t height, - base::TimeDelta timestamp, - base::TimeDelta duration, - const base::Closure& no_longer_needed); - // Creates a frame with format equals to VideoFrame::EMPTY, width, height // timestamp and duration are all 0. static scoped_refptr<VideoFrame> CreateEmptyFrame(); @@ -91,20 +78,14 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { // VideoFrame object and must not be freed by the caller. uint8* data(size_t plane) const; - // Returns the ID of the native texture wrapped by this frame. Only valid to - // call if this is a NATIVE_TEXTURE frame. - uint32 texture_id() const; - // StreamSample interface. virtual bool IsEndOfStream() const OVERRIDE; - private: + protected: // Clients must use the static CreateFrame() method to create a new frame. VideoFrame(Format format, size_t video_width, - size_t video_height, - base::TimeDelta timestamp, - base::TimeDelta duration); + size_t video_height); virtual ~VideoFrame(); @@ -122,8 +103,8 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { size_t width_; size_t height_; - // Number of planes, typically 1 for packed RGB formats, 3 for planar - // YUV formats, and 0 for native textures. + // Number of planes, typically 1 for packed RGB formats and 3 for planar + // YUV formats. size_t planes_; // Array of strides for each plane, typically greater or equal to the width @@ -134,11 +115,7 @@ class MEDIA_EXPORT VideoFrame : public StreamSample { // Array of data pointers to each plane. uint8* data_[kMaxPlanes]; - // Native texture ID, if this is a NATIVE_TEXTURE frame. - uint32 texture_id_; - base::Closure texture_no_longer_needed_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoFrame); + DISALLOW_COPY_AND_ASSIGN(VideoFrame); }; } // namespace media diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index b9776fe..396ee03 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc @@ -127,48 +127,6 @@ static CodecID VideoCodecToCodecID(VideoCodec video_codec) { return CODEC_ID_NONE; } -static VideoCodecProfile ProfileIDToVideoCodecProfile(int profile) { - switch (profile) { - case FF_PROFILE_H264_BASELINE: - return H264PROFILE_BASELINE; - case FF_PROFILE_H264_MAIN: - return H264PROFILE_MAIN; - case FF_PROFILE_H264_EXTENDED: - return H264PROFILE_EXTENDED; - case FF_PROFILE_H264_HIGH: - return H264PROFILE_HIGH; - case FF_PROFILE_H264_HIGH_10: - return H264PROFILE_HIGH10PROFILE; - case FF_PROFILE_H264_HIGH_422: - return H264PROFILE_HIGH422PROFILE; - case FF_PROFILE_H264_HIGH_444_PREDICTIVE: - return H264PROFILE_HIGH444PREDICTIVEPROFILE; - default: - return VIDEO_CODEC_PROFILE_UNKNOWN; - } -} - -static int VideoCodecProfileToProfileID(VideoCodecProfile profile) { - switch (profile) { - case H264PROFILE_BASELINE: - return FF_PROFILE_H264_BASELINE; - case H264PROFILE_MAIN: - return FF_PROFILE_H264_MAIN; - case H264PROFILE_EXTENDED: - return FF_PROFILE_H264_EXTENDED; - case H264PROFILE_HIGH: - return FF_PROFILE_H264_HIGH; - case H264PROFILE_HIGH10PROFILE: - return FF_PROFILE_H264_HIGH_10; - case H264PROFILE_HIGH422PROFILE: - return FF_PROFILE_H264_HIGH_422; - case H264PROFILE_HIGH444PREDICTIVEPROFILE: - return FF_PROFILE_H264_HIGH_444_PREDICTIVE; - default: - return FF_PROFILE_UNKNOWN; - } -} - void AVCodecContextToAudioDecoderConfig( const AVCodecContext* codec_context, AudioDecoderConfig* config) { @@ -246,7 +204,6 @@ void AVStreamToVideoDecoderConfig( aspect_ratio = stream->codec->sample_aspect_ratio; config->Initialize(CodecIDToVideoCodec(stream->codec->codec_id), - ProfileIDToVideoCodecProfile(stream->codec->profile), PixelFormatToVideoFormat(stream->codec->pix_fmt), coded_size, visible_rect, stream->r_frame_rate.num, @@ -262,7 +219,6 @@ void VideoDecoderConfigToAVCodecContext( AVCodecContext* codec_context) { codec_context->codec_type = AVMEDIA_TYPE_VIDEO; codec_context->codec_id = VideoCodecToCodecID(config.codec()); - codec_context->profile = VideoCodecProfileToProfileID(config.profile()); codec_context->coded_width = config.coded_size().width(); codec_context->coded_height = config.coded_size().height(); codec_context->pix_fmt = VideoFormatToPixelFormat(config.format()); diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 66b25b6..39d9e39 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc @@ -64,7 +64,7 @@ FFmpegVideoDecoder::~FFmpegVideoDecoder() { } void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, - const PipelineStatusCB& callback, + const base::Closure& callback, const StatisticsCallback& stats_callback) { if (MessageLoop::current() != message_loop_) { message_loop_->PostTask(FROM_HERE, base::Bind( @@ -76,7 +76,8 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, DCHECK(!demuxer_stream_); if (!demuxer_stream) { - callback.Run(PIPELINE_ERROR_DECODE); + host()->SetError(PIPELINE_ERROR_DECODE); + callback.Run(); return; } @@ -88,8 +89,24 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, // TODO(scherkus): this check should go in PipelineImpl prior to creating // decoder objects. if (!config.IsValidConfig()) { - DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); - callback.Run(PIPELINE_ERROR_DECODE); + DLOG(ERROR) << "Invalid video stream -" + << " codec: " << config.codec() + << " format: " << config.format() + << " coded size: [" << config.coded_size().width() + << "," << config.coded_size().height() << "]" + << " visible rect: [" << config.visible_rect().x() + << "," << config.visible_rect().y() + << "," << config.visible_rect().width() + << "," << config.visible_rect().height() << "]" + << " natural size: [" << config.natural_size().width() + << "," << config.natural_size().height() << "]" + << " frame rate: " << config.frame_rate_numerator() + << "/" << config.frame_rate_denominator() + << " aspect ratio: " << config.aspect_ratio_numerator() + << "/" << config.aspect_ratio_denominator(); + + host()->SetError(PIPELINE_ERROR_DECODE); + callback.Run(); return; } @@ -105,12 +122,14 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); if (!codec) { - callback.Run(PIPELINE_ERROR_DECODE); + host()->SetError(PIPELINE_ERROR_DECODE); + callback.Run(); return; } if (avcodec_open(codec_context_, codec) < 0) { - callback.Run(PIPELINE_ERROR_DECODE); + host()->SetError(PIPELINE_ERROR_DECODE); + callback.Run(); return; } @@ -121,7 +140,7 @@ void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, natural_size_ = config.natural_size(); frame_rate_numerator_ = config.frame_rate_numerator(); frame_rate_denominator_ = config.frame_rate_denominator(); - callback.Run(PIPELINE_OK); + callback.Run(); } void FFmpegVideoDecoder::Stop(const base::Closure& callback) { diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index c5a412f..34cf700 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h @@ -32,7 +32,7 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder { // VideoDecoder implementation. virtual void Initialize(DemuxerStream* demuxer_stream, - const PipelineStatusCB& callback, + const base::Closure& callback, const StatisticsCallback& stats_callback) OVERRIDE; virtual void Read(const ReadCB& callback) OVERRIDE; virtual const gfx::Size& natural_size() OVERRIDE; diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index b072993..30ed2b4 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -58,8 +58,7 @@ class FFmpegVideoDecoderTest : public testing::Test { ReadTestDataFile("vp8-I-frame-320x240", &i_frame_buffer_); ReadTestDataFile("vp8-corrupt-I-frame", &corrupt_i_frame_buffer_); - config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, - kVideoFormat, kCodedSize, kVisibleRect, + config_.Initialize(kCodecVP8, kVideoFormat, kCodedSize, kVisibleRect, kFrameRate.num, kFrameRate.den, kAspectRatio.num, kAspectRatio.den, NULL, 0); @@ -71,22 +70,17 @@ class FFmpegVideoDecoderTest : public testing::Test { InitializeWithConfig(config_); } - void InitializeWithConfigAndStatus(const VideoDecoderConfig& config, - PipelineStatus status) { + void InitializeWithConfig(const VideoDecoderConfig& config) { EXPECT_CALL(*demuxer_, video_decoder_config()) .WillOnce(ReturnRef(config)); - decoder_->Initialize(demuxer_, NewExpectedStatusCB(status), + decoder_->Initialize(demuxer_, NewExpectedClosure(), base::Bind(&MockStatisticsCallback::OnStatistics, base::Unretained(&statistics_callback_))); message_loop_.RunAllPending(); } - void InitializeWithConfig(const VideoDecoderConfig& config) { - InitializeWithConfigAndStatus(config, PIPELINE_OK); - } - void Pause() { decoder_->Pause(NewExpectedClosure()); message_loop_.RunAllPending(); @@ -248,35 +242,38 @@ TEST_F(FFmpegVideoDecoderTest, Initialize_Normal) { TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedDecoder) { // Test avcodec_find_decoder() returning NULL. - VideoDecoderConfig config(kUnknownVideoCodec, VIDEO_CODEC_PROFILE_UNKNOWN, - kVideoFormat, + VideoDecoderConfig config(kUnknownVideoCodec, kVideoFormat, kCodedSize, kVisibleRect, kFrameRate.num, kFrameRate.den, kAspectRatio.num, kAspectRatio.den, NULL, 0); - InitializeWithConfigAndStatus(config, PIPELINE_ERROR_DECODE); + + EXPECT_CALL(host_, SetError(PIPELINE_ERROR_DECODE)); + InitializeWithConfig(config); } TEST_F(FFmpegVideoDecoderTest, Initialize_UnsupportedPixelFormat) { // Ensure decoder handles unsupport pixel formats without crashing. - VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, - VideoFrame::INVALID, + VideoDecoderConfig config(kCodecVP8, VideoFrame::INVALID, kCodedSize, kVisibleRect, kFrameRate.num, kFrameRate.den, kAspectRatio.num, kAspectRatio.den, NULL, 0); - InitializeWithConfigAndStatus(config, PIPELINE_ERROR_DECODE); + + EXPECT_CALL(host_, SetError(PIPELINE_ERROR_DECODE)); + InitializeWithConfig(config); } TEST_F(FFmpegVideoDecoderTest, Initialize_OpenDecoderFails) { // Specify Theora w/o extra data so that avcodec_open() fails. - VideoDecoderConfig config(kCodecTheora, VIDEO_CODEC_PROFILE_UNKNOWN, - kVideoFormat, + VideoDecoderConfig config(kCodecTheora, kVideoFormat, kCodedSize, kVisibleRect, kFrameRate.num, kFrameRate.den, kAspectRatio.num, kAspectRatio.den, NULL, 0); - InitializeWithConfigAndStatus(config, PIPELINE_ERROR_DECODE); + + EXPECT_CALL(host_, SetError(PIPELINE_ERROR_DECODE)); + InitializeWithConfig(config); } TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) { diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc deleted file mode 100644 index 11580a3..0000000 --- a/media/filters/gpu_video_decoder.cc +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/filters/gpu_video_decoder.h" - -#include "base/bind.h" -#include "base/message_loop.h" -#include "base/stl_util.h" -#include "media/base/demuxer_stream.h" -#include "media/base/filter_host.h" -#include "media/base/video_decoder_config.h" -#include "media/ffmpeg/ffmpeg_common.h" - -namespace media { - -GpuVideoDecoder::Factories::~Factories() {} - -// Size of shared-memory segments we allocate. Since we reuse them we let them -// be on the beefy side. -static const size_t kSharedMemorySegmentBytes = 100 << 10; - -GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s) - : shm(m), size(s) { -} - -GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} - -GpuVideoDecoder::BufferPair::BufferPair( - SHMBuffer* s, const scoped_refptr<Buffer>& b) : shm_buffer(s), buffer(b) { -} - -GpuVideoDecoder::BufferPair::~BufferPair() {} - -GpuVideoDecoder::GpuVideoDecoder( - MessageLoop* message_loop, - Factories* factories) - : message_loop_(message_loop), - factories_(factories), - flush_in_progress_(false), - demuxer_read_in_progress_(false), - next_picture_buffer_id_(0), - next_bitstream_buffer_id_(0) { - DCHECK(message_loop_ && factories_.get()); -} - -GpuVideoDecoder::~GpuVideoDecoder() { - DCHECK(!vda_); // Stop should have been already called. - STLDeleteElements(&available_shm_segments_); - for (std::map<int32, BufferPair>::iterator it = - bitstream_buffers_in_decoder_.begin(); - it != bitstream_buffers_in_decoder_.end(); ++it) { - it->second.shm_buffer->shm->Close(); - } - bitstream_buffers_in_decoder_.clear(); -} - -void GpuVideoDecoder::Stop(const base::Closure& callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Stop, this, callback)); - return; - } - if (!vda_) { - callback.Run(); - return; - } - vda_->Destroy(); - vda_ = NULL; - callback.Run(); -} - -void GpuVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Seek, this, time, cb)); - return; - } - pts_stream_.Seek(time); - cb.Run(PIPELINE_OK); -} - -void GpuVideoDecoder::Pause(const base::Closure& callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Pause, this, callback)); - return; - } - callback.Run(); -} - -void GpuVideoDecoder::Flush(const base::Closure& callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Flush, this, callback)); - return; - } - // Pipeline should have quiesced (via Pause() to all filters) before calling - // us, so there should be nothing pending. - DCHECK(pending_read_cb_.is_null()); - - // Throw away any already-decoded frames. - ready_video_frames_.clear(); - - if (!vda_) { - callback.Run(); - return; - } - DCHECK(pending_flush_cb_.is_null()); - pending_flush_cb_ = callback; - pts_stream_.Flush(); - vda_->Reset(); -} - -void GpuVideoDecoder::Initialize(DemuxerStream* demuxer_stream, - const PipelineStatusCB& callback, - const StatisticsCallback& stats_callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Initialize, this, - make_scoped_refptr(demuxer_stream), callback, stats_callback)); - return; - } - - DCHECK(!demuxer_stream_); - if (!demuxer_stream) { - callback.Run(PIPELINE_ERROR_DECODE); - return; - } - - const VideoDecoderConfig& config = demuxer_stream->video_decoder_config(); - // TODO(scherkus): this check should go in PipelineImpl prior to creating - // decoder objects. - if (!config.IsValidConfig()) { - DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); - callback.Run(PIPELINE_ERROR_DECODE); - return; - } - - vda_ = factories_->CreateVideoDecodeAccelerator(config.profile(), this); - if (!vda_) { - callback.Run(DECODER_ERROR_NOT_SUPPORTED); - return; - } - - demuxer_stream_ = demuxer_stream; - statistics_callback_ = stats_callback; - - demuxer_stream_->EnableBitstreamConverter(); - - pts_stream_.Initialize(GetFrameDuration(config)); - natural_size_ = config.natural_size(); - - callback.Run(PIPELINE_OK); -} - -void GpuVideoDecoder::Read(const ReadCB& callback) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::Read, this, callback)); - return; - } - - if (!vda_) { - callback.Run(VideoFrame::CreateEmptyFrame()); - return; - } - - DCHECK(pending_read_cb_.is_null()); - pending_read_cb_ = callback; - - if (!ready_video_frames_.empty()) { - DeliverFrame(ready_video_frames_.front()); - ready_video_frames_.pop_front(); - return; - } - EnsureDemuxOrDecode(); -} - -void GpuVideoDecoder::RequestBufferDecode(const scoped_refptr<Buffer>& buffer) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::RequestBufferDecode, this, buffer)); - return; - } - demuxer_read_in_progress_ = false; - - if (!vda_) { - DeliverFrame(VideoFrame::CreateEmptyFrame()); - return; - } - - if (buffer->IsEndOfStream()) { - if (!flush_in_progress_) { - flush_in_progress_ = true; - vda_->Flush(); - } - return; - } - - size_t size = buffer->GetDataSize(); - SHMBuffer* shm_buffer = GetSHM(size); - memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); - BitstreamBuffer bitstream_buffer( - next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); - bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( - bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; - DCHECK(inserted); - pts_stream_.EnqueuePts(buffer.get()); - - vda_->Decode(bitstream_buffer); -} - -const gfx::Size& GpuVideoDecoder::natural_size() { - return natural_size_; -} - -void GpuVideoDecoder::NotifyInitializeDone() { - NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; -} - -void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, - const gfx::Size& size) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::ProvidePictureBuffers, this, count, size)); - return; - } - - std::vector<uint32> texture_ids; - if (!factories_->CreateTextures(count, size, &texture_ids)) { - NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); - return; - } - - if (!vda_) - return; - - std::vector<PictureBuffer> picture_buffers; - for (size_t i = 0; i < texture_ids.size(); ++i) { - picture_buffers.push_back(PictureBuffer( - next_picture_buffer_id_++, size, texture_ids[i])); - bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( - picture_buffers.back().id(), picture_buffers.back())).second; - DCHECK(inserted); - } - vda_->AssignPictureBuffers(picture_buffers); -} - -void GpuVideoDecoder::DismissPictureBuffer(int32 id) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::DismissPictureBuffer, this, id)); - return; - } - std::map<int32, PictureBuffer>::iterator it = - picture_buffers_in_decoder_.find(id); - if (it == picture_buffers_in_decoder_.end()) { - NOTREACHED() << "Missing picture buffer: " << id; - return; - } - if (!factories_->DeleteTexture(it->second.texture_id())) { - NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); - return; - } - picture_buffers_in_decoder_.erase(it); -} - -static void ResetAndRunCB(VideoDecoder::ReadCB* cb, - scoped_refptr<VideoFrame> frame) { - DCHECK(!cb->is_null()); - VideoDecoder::ReadCB tmp_cb(*cb); - cb->Reset(); - tmp_cb.Run(frame); -} - -void GpuVideoDecoder::PictureReady(const media::Picture& picture) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::PictureReady, this, picture)); - return; - } - std::map<int32, PictureBuffer>::iterator it = - picture_buffers_in_decoder_.find(picture.picture_buffer_id()); - if (it == picture_buffers_in_decoder_.end()) { - NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); - NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); - return; - } - const PictureBuffer& pb = it->second; - - // Update frame's timestamp. - base::TimeDelta timestamp; - base::TimeDelta duration; - std::map<int32, BufferPair>::const_iterator buf_it = - bitstream_buffers_in_decoder_.find(picture.bitstream_buffer_id()); - if (buf_it != bitstream_buffers_in_decoder_.end()) { - // Sufficiently out-of-order decoding could have already called - // NotifyEndOfBitstreamBuffer on this buffer, but that's ok since we only - // need the buffer's time info for best-effort PTS updating. - timestamp = buf_it->second.buffer->GetTimestamp(); - duration = buf_it->second.buffer->GetDuration(); - } - - scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( - pb.texture_id(), pb.size().width(), - pb.size().height(), timestamp, duration, - base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, - picture.picture_buffer_id()))); - pts_stream_.UpdatePtsAndDuration(frame.get()); - frame->SetTimestamp(pts_stream_.current_pts()); - frame->SetDuration(pts_stream_.current_duration()); - - // Deliver the frame. - DeliverFrame(frame); -} - -void GpuVideoDecoder::DeliverFrame(const scoped_refptr<VideoFrame>& frame) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::DeliverFrameOutOfLine, this, frame)); -} - -void GpuVideoDecoder::DeliverFrameOutOfLine( - const scoped_refptr<VideoFrame>& frame) { - if (pending_read_cb_.is_null()) { - ready_video_frames_.push_back(frame); - return; - } - ResetAndRunCB(&pending_read_cb_, frame); -} - -void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); - return; - } - if (!vda_) - return; - vda_->ReusePictureBuffer(picture_buffer_id); -} - -GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { - DCHECK(MessageLoop::current() == message_loop_); - if (available_shm_segments_.empty() || - available_shm_segments_.back()->size < min_size) { - size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); - base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); - DCHECK(shm); - return new SHMBuffer(shm, size_to_allocate); - } - SHMBuffer* ret = available_shm_segments_.back(); - available_shm_segments_.pop_back(); - return ret; -} - -void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { - DCHECK(MessageLoop::current() == message_loop_); - available_shm_segments_.push_back(shm_buffer); -} - -void GpuVideoDecoder::NotifyEndOfStream() { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::NotifyEndOfStream, this)); - return; - } - DeliverFrame(VideoFrame::CreateEmptyFrame()); -} - -void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, this, id)); - return; - } - - std::map<int32, BufferPair>::iterator it = - bitstream_buffers_in_decoder_.find(id); - if (it == bitstream_buffers_in_decoder_.end()) { - NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); - NOTREACHED() << "Missing bitstream buffer: " << id; - return; - } - PutSHM(it->second.shm_buffer); - const scoped_refptr<Buffer>& buffer = it->second.buffer; - if (buffer->GetDataSize()) { - PipelineStatistics statistics; - statistics.video_bytes_decoded = buffer->GetDataSize(); - statistics_callback_.Run(statistics); - } - bitstream_buffers_in_decoder_.erase(it); - - if (!pending_read_cb_.is_null()) { - DCHECK(ready_video_frames_.empty()); - EnsureDemuxOrDecode(); - } -} - -void GpuVideoDecoder::EnsureDemuxOrDecode() { - DCHECK(MessageLoop::current() == message_loop_); - if (demuxer_read_in_progress_ || !bitstream_buffers_in_decoder_.empty()) - return; - demuxer_read_in_progress_ = true; - demuxer_stream_->Read(base::Bind( - &GpuVideoDecoder::RequestBufferDecode, this)); -} - -void GpuVideoDecoder::NotifyFlushDone() { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::NotifyFlushDone, this)); - return; - } - DCHECK(flush_in_progress_); - flush_in_progress_ = false; - DeliverFrame(VideoFrame::CreateEmptyFrame()); -} - -void GpuVideoDecoder::NotifyResetDone() { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::NotifyResetDone, this)); - return; - } - // Throw away any already-decoded frames that have come in during the reset. - ready_video_frames_.clear(); - ResetAndRunCB(&pending_flush_cb_); -} - -void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask(FROM_HERE, base::Bind( - &GpuVideoDecoder::NotifyError, this, error)); - return; - } - vda_ = NULL; - DLOG(ERROR) << "VDA Error: " << error; - if (host()) - host()->SetError(PIPELINE_ERROR_DECODE); -} - -} // namespace media diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h deleted file mode 100644 index 03ceadb..0000000 --- a/media/filters/gpu_video_decoder.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_FILTERS_GPU_VIDEO_DECODER_H_ -#define MEDIA_FILTERS_GPU_VIDEO_DECODER_H_ - -#include <deque> -#include <list> -#include <map> - -#include "base/memory/scoped_ptr.h" -#include "media/base/filters.h" -#include "media/base/pipeline_status.h" -#include "media/base/pts_stream.h" -#include "media/video/video_decode_accelerator.h" -#include "ui/gfx/size.h" - -class MessageLoop; -namespace base { -class SharedMemory; -} - -namespace media { - -// GPU-accelerated video decoder implementation. Relies on -// AcceleratedVideoDecoderMsg_Decode and friends. -// All methods internally trampoline to the message_loop passed to the ctor. -class MEDIA_EXPORT GpuVideoDecoder - : public VideoDecoder, - public VideoDecodeAccelerator::Client { - public: - // Helper interface for specifying factories needed to instantiate a - // GpuVideoDecoder. - class Factories { - public: - virtual ~Factories(); - - // Caller owns returned pointer. - virtual VideoDecodeAccelerator* CreateVideoDecodeAccelerator( - VideoDecodeAccelerator::Profile, VideoDecodeAccelerator::Client*) = 0; - - // Allocate & delete native textures. - virtual bool CreateTextures(int32 count, const gfx::Size& size, - std::vector<uint32>* texture_ids) = 0; - virtual bool DeleteTexture(uint32 texture_id) = 0; - - // Allocate & return a shared memory segment. Caller is responsible for - // Close()ing the returned pointer. - virtual base::SharedMemory* CreateSharedMemory(size_t size) = 0; - }; - - // Takes ownership of |factories| but not |message_loop|. - GpuVideoDecoder(MessageLoop* message_loop, Factories* factories); - virtual ~GpuVideoDecoder(); - - // Filter implementation. - virtual void Stop(const base::Closure& callback) OVERRIDE; - virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb) OVERRIDE; - virtual void Pause(const base::Closure& callback) OVERRIDE; - virtual void Flush(const base::Closure& callback) OVERRIDE; - - // VideoDecoder implementation. - virtual void Initialize(DemuxerStream* demuxer_stream, - const PipelineStatusCB& callback, - const StatisticsCallback& stats_callback) OVERRIDE; - virtual void Read(const ReadCB& callback) OVERRIDE; - virtual const gfx::Size& natural_size() OVERRIDE; - - // VideoDecodeAccelerator::Client implementation. - virtual void NotifyInitializeDone() OVERRIDE; - virtual void ProvidePictureBuffers(uint32 count, - const gfx::Size& size) OVERRIDE; - virtual void DismissPictureBuffer(int32 id) OVERRIDE; - virtual void PictureReady(const media::Picture& picture) OVERRIDE; - virtual void NotifyEndOfStream() OVERRIDE; - virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE; - virtual void NotifyFlushDone() OVERRIDE; - virtual void NotifyResetDone() OVERRIDE; - virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE; - - private: - // If no demuxer read is in flight and no bitstream buffers are in the - // decoder, kick some off demuxing/decoding. - void EnsureDemuxOrDecode(); - - // Callback to pass to demuxer_stream_->Read() for receiving encoded bits. - void RequestBufferDecode(const scoped_refptr<Buffer>& buffer); - - // Deliver a frame to the client. Because VideoDecoder::Read() promises not - // to run its callback before returning, we need an out-of-line helper here. - void DeliverFrame(const scoped_refptr<VideoFrame>& frame); - void DeliverFrameOutOfLine(const scoped_refptr<VideoFrame>& frame); - - // Indicate the picturebuffer can be reused by the decoder. - void ReusePictureBuffer(int64 picture_buffer_id); - - // A shared memory segment and its allocated size. - struct SHMBuffer { - SHMBuffer(base::SharedMemory* m, size_t s); - ~SHMBuffer(); - base::SharedMemory* shm; - size_t size; - }; - - // Request a shared-memory segment of at least |min_size| bytes. Will - // allocate as necessary. Caller does not own returned pointer. - SHMBuffer* GetSHM(size_t min_size); - - // Return a shared-memory segment to the available pool. - void PutSHM(SHMBuffer* shm_buffer); - - PtsStream pts_stream_; - StatisticsCallback statistics_callback_; - - // TODO(scherkus): I think this should be calculated by VideoRenderers based - // on information provided by VideoDecoders (i.e., aspect ratio). - gfx::Size natural_size_; - - // Pointer to the demuxer stream that will feed us compressed buffers. - scoped_refptr<DemuxerStream> demuxer_stream_; - - // MessageLoop on which to do fire callbacks and to which trampoline calls to - // this class if they arrive on other loops. - MessageLoop* message_loop_; - - scoped_ptr<Factories> factories_; - - // Populated during Initialize() (on success) and unchanged thereafter. - scoped_refptr<VideoDecodeAccelerator> vda_; - - // Callbacks that are !is_null() only during their respective operation being - // asynchronously executed. - ReadCB pending_read_cb_; - base::Closure pending_flush_cb_; - - // Status of the decoder. - bool flush_in_progress_; - - // Is a demuxer read in flight? - bool demuxer_read_in_progress_; - - // Shared-memory buffer pool. Since allocating SHM segments requires a - // round-trip to the browser process, we keep allocation out of the - // steady-state of the decoder. - std::vector<SHMBuffer*> available_shm_segments_; - - // Book-keeping variables. - struct BufferPair { - BufferPair(SHMBuffer* s, const scoped_refptr<Buffer>& b); - ~BufferPair(); - SHMBuffer* shm_buffer; - scoped_refptr<Buffer> buffer; - }; - std::map<int32, BufferPair> bitstream_buffers_in_decoder_; - std::map<int32, PictureBuffer> picture_buffers_in_decoder_; - - // picture_buffer_id and the frame wrapping the corresponding Picture, for - // frames that have been decoded but haven't been requested by a Read() yet. - std::list<scoped_refptr<VideoFrame> > ready_video_frames_; - int64 next_picture_buffer_id_; - int64 next_bitstream_buffer_id_; - - DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_GPU_VIDEO_DECODER_H_ diff --git a/media/filters/video_renderer_base.cc b/media/filters/video_renderer_base.cc index 7b40fbc..4cd7775 100644 --- a/media/filters/video_renderer_base.cc +++ b/media/filters/video_renderer_base.cc @@ -97,15 +97,17 @@ void VideoRendererBase::SetPlaybackRate(float playback_rate) { } void VideoRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { - base::AutoLock auto_lock(lock_); - DCHECK_EQ(state_, kFlushed) << "Must flush prior to seeking."; - DCHECK(!cb.is_null()); - DCHECK(seek_cb_.is_null()); - - state_ = kSeeking; - seek_cb_ = cb; - seek_timestamp_ = time; - AttemptRead_Locked(); + { + base::AutoLock auto_lock(lock_); + DCHECK_EQ(state_, kFlushed) << "Must flush prior to seeking."; + DCHECK(!cb.is_null()); + DCHECK(seek_cb_.is_null()); + + state_ = kSeeking; + seek_cb_ = cb; + seek_timestamp_ = time; + AttemptRead_Locked(); + } } void VideoRendererBase::Initialize(VideoDecoder* decoder, @@ -274,6 +276,7 @@ void VideoRendererBase::ThreadMain() { frames_queue_ready_.pop_front(); AttemptRead_Locked(); } + // Continue waiting for the current paint to finish. continue; } @@ -476,6 +479,7 @@ void VideoRendererBase::DoStopOrError_Locked() { lock_.AssertAcquired(); current_frame_ = NULL; last_available_frame_ = NULL; + DCHECK(!pending_read_); } } // namespace media diff --git a/media/media.gyp b/media/media.gyp index fa6e870..a52d4a5 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -205,8 +205,6 @@ 'filters/file_data_source.h', 'filters/file_data_source_factory.cc', 'filters/file_data_source_factory.h', - 'filters/gpu_video_decoder.cc', - 'filters/gpu_video_decoder.h', 'filters/in_memory_url_protocol.cc', 'filters/in_memory_url_protocol.h', 'filters/null_audio_renderer.cc', diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h index d260a7c..9a31bfd 100644 --- a/media/video/video_decode_accelerator.h +++ b/media/video/video_decode_accelerator.h @@ -10,7 +10,6 @@ #include "base/basictypes.h" #include "base/callback_old.h" #include "media/base/bitstream_buffer.h" -#include "media/base/video_decoder_config.h" #include "media/video/picture.h" #include "ui/gfx/size.h" @@ -25,8 +24,25 @@ namespace media { class MEDIA_EXPORT VideoDecodeAccelerator : public base::RefCountedThreadSafe<VideoDecodeAccelerator> { public: - // TODO(fischman): fix foreign references to this and get rid of this typedef. - typedef VideoCodecProfile Profile; + // Video stream profile. This *must* match PP_VideoDecoder_Profile. + enum Profile { + // Keep the values in this enum unique, as they imply format (h.264 vs. VP8, + // for example), and keep the values for a particular format grouped + // together for clarity. + H264PROFILE_MIN = 0, + H264PROFILE_BASELINE = H264PROFILE_MIN, + H264PROFILE_MAIN, + H264PROFILE_EXTENDED, + H264PROFILE_HIGH, + H264PROFILE_HIGH10PROFILE, + H264PROFILE_HIGH422PROFILE, + H264PROFILE_HIGH444PREDICTIVEPROFILE, + H264PROFILE_SCALABLEBASELINE, + H264PROFILE_SCALABLEHIGH, + H264PROFILE_STEREOHIGH, + H264PROFILE_MULTIVIEWHIGH, + H264PROFILE_MAX = H264PROFILE_MULTIVIEWHIGH, + }; // Enumeration of potential errors generated by the API. // Note: Keep these in sync with PP_VideoDecodeError_Dev. diff --git a/ppapi/api/dev/pp_video_dev.idl b/ppapi/api/dev/pp_video_dev.idl index 9c75d66..e505714 100644 --- a/ppapi/api/dev/pp_video_dev.idl +++ b/ppapi/api/dev/pp_video_dev.idl @@ -4,7 +4,8 @@ */ /** - * NOTE: these must be kept in sync with the versions in media/! + * NOTE: these must be kept in sync with the versions in + * media/video/video_decode_accelerator.h! */ @@ -14,11 +15,9 @@ * Keep the values in this enum unique, as they imply format (h.264 vs. VP8, * for example), and keep the values for a particular format grouped together * for clarity. - * Note: Keep these in sync with media::VideoCodecProfile. */ [assert_size(4)] enum PP_VideoDecoder_Profile { - PP_VIDEODECODER_PROFILE_UNKNOWN = -1, PP_VIDEODECODER_H264PROFILE_NONE = 0, PP_VIDEODECODER_H264PROFILE_BASELINE = 1, PP_VIDEODECODER_H264PROFILE_MAIN = 2, @@ -30,8 +29,7 @@ enum PP_VideoDecoder_Profile { PP_VIDEODECODER_H264PROFILE_SCALABLEBASELINE = 8, PP_VIDEODECODER_H264PROFILE_SCALABLEHIGH = 9, PP_VIDEODECODER_H264PROFILE_STEREOHIGH = 10, - PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH = 11, - PP_VIDEODECODER_PROFILE_MAX = PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH + PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH = 11 }; /** diff --git a/ppapi/c/dev/pp_video_dev.h b/ppapi/c/dev/pp_video_dev.h index 2342d0e..c1bc999 100644 --- a/ppapi/c/dev/pp_video_dev.h +++ b/ppapi/c/dev/pp_video_dev.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From dev/pp_video_dev.idl modified Wed Nov 23 13:51:18 2011. */ +/* From dev/pp_video_dev.idl modified Fri Nov 11 20:20:20 2011. */ #ifndef PPAPI_C_DEV_PP_VIDEO_DEV_H_ #define PPAPI_C_DEV_PP_VIDEO_DEV_H_ @@ -15,7 +15,8 @@ /** * @file - * NOTE: these must be kept in sync with the versions in media/! + * NOTE: these must be kept in sync with the versions in + * media/video/video_decode_accelerator.h! */ @@ -29,10 +30,8 @@ * Keep the values in this enum unique, as they imply format (h.264 vs. VP8, * for example), and keep the values for a particular format grouped together * for clarity. - * Note: Keep these in sync with media::VideoCodecProfile. */ typedef enum { - PP_VIDEODECODER_PROFILE_UNKNOWN = -1, PP_VIDEODECODER_H264PROFILE_NONE = 0, PP_VIDEODECODER_H264PROFILE_BASELINE = 1, PP_VIDEODECODER_H264PROFILE_MAIN = 2, @@ -44,8 +43,7 @@ typedef enum { PP_VIDEODECODER_H264PROFILE_SCALABLEBASELINE = 8, PP_VIDEODECODER_H264PROFILE_SCALABLEHIGH = 9, PP_VIDEODECODER_H264PROFILE_STEREOHIGH = 10, - PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH = 11, - PP_VIDEODECODER_PROFILE_MAX = PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH + PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH = 11 } PP_VideoDecoder_Profile; PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_VideoDecoder_Profile, 4); /** diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index a4eb991..a246945 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -700,8 +700,6 @@ void WebMediaPlayerImpl::putCurrentFrame( WebVideoFrameImpl::toVideoFrame(web_video_frame)); proxy_->PutCurrentFrame(video_frame); delete web_video_frame; - } else { - proxy_->PutCurrentFrame(NULL); } } diff --git a/webkit/media/webvideoframe_impl.cc b/webkit/media/webvideoframe_impl.cc index 93970f0..5a5b182 100644 --- a/webkit/media/webvideoframe_impl.cc +++ b/webkit/media/webvideoframe_impl.cc @@ -43,8 +43,6 @@ COMPILE_ASSERT_MATCHING_ENUM(FormatYV16, YV16); COMPILE_ASSERT_MATCHING_ENUM(FormatNV12, NV12); COMPILE_ASSERT_MATCHING_ENUM(FormatEmpty, EMPTY); COMPILE_ASSERT_MATCHING_ENUM(FormatASCII, ASCII); -COMPILE_ASSERT_MATCHING_ENUM(FormatI420, I420); -COMPILE_ASSERT_MATCHING_ENUM(FormatNativeTexture, NATIVE_TEXTURE); WebVideoFrame::Format WebVideoFrameImpl::format() const { if (video_frame_.get()) @@ -77,15 +75,9 @@ int WebVideoFrameImpl::stride(unsigned plane) const { } const void* WebVideoFrameImpl::data(unsigned plane) const { - if (!video_frame_.get() || format() == FormatNativeTexture) - return NULL; - return static_cast<const void*>(video_frame_->data(plane)); -} - -unsigned WebVideoFrameImpl::textureId() const { - if (!video_frame_.get() || format() != FormatNativeTexture) - return 0; - return video_frame_->texture_id(); + if (video_frame_.get()) + return static_cast<const void*>(video_frame_->data(plane)); + return NULL; } } // namespace webkit_media diff --git a/webkit/media/webvideoframe_impl.h b/webkit/media/webvideoframe_impl.h index 72e81a5..f82c4d7 100644 --- a/webkit/media/webvideoframe_impl.h +++ b/webkit/media/webvideoframe_impl.h @@ -19,13 +19,12 @@ class WebVideoFrameImpl : public WebKit::WebVideoFrame { WebVideoFrameImpl(scoped_refptr<media::VideoFrame> video_frame); virtual ~WebVideoFrameImpl(); - virtual WebVideoFrame::Format format() const; - virtual unsigned width() const; - virtual unsigned height() const; - virtual unsigned planes() const; - virtual int stride(unsigned plane) const; - virtual const void* data(unsigned plane) const; - virtual unsigned textureId() const; + virtual WebVideoFrame::Format format() const OVERRIDE; + virtual unsigned width() const OVERRIDE; + virtual unsigned height() const OVERRIDE; + virtual unsigned planes() const OVERRIDE; + virtual int stride(unsigned plane) const OVERRIDE; + virtual const void* data(unsigned plane) const OVERRIDE; private: scoped_refptr<media::VideoFrame> video_frame_; |