diff options
99 files changed, 1724 insertions, 1184 deletions
diff --git a/chromecast/base/BUILD.gn b/chromecast/base/BUILD.gn index a249ec8..c71c147 100644 --- a/chromecast/base/BUILD.gn +++ b/chromecast/base/BUILD.gn @@ -20,6 +20,8 @@ source_set("base") { "process_utils.h", "serializers.cc", "serializers.h", + "task_runner_impl.cc", + "task_runner_impl.h", ] configs += [ "//chromecast:config" ] diff --git a/chromecast/base/task_runner_impl.cc b/chromecast/base/task_runner_impl.cc new file mode 100644 index 0000000..1fb8fc5 --- /dev/null +++ b/chromecast/base/task_runner_impl.cc @@ -0,0 +1,36 @@ +// Copyright 2015 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 "chromecast/base/task_runner_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace chromecast { + +TaskRunnerImpl::TaskRunnerImpl() + : runner_(base::ThreadTaskRunnerHandle::Get()) { + DCHECK(runner_.get()); +} + +TaskRunnerImpl::~TaskRunnerImpl() {} + +bool TaskRunnerImpl::PostTask(Task* task, uint64_t delay_milliseconds) { + DCHECK(task); + if (delay_milliseconds == 0 && runner_->BelongsToCurrentThread()) { + task->Run(); + delete task; + return true; + } + + // TODO(halliwell): FROM_HERE is misleading, we should consider a macro for + // vendor backends to send the callsite info. + return runner_->PostDelayedTask( + FROM_HERE, base::Bind(&Task::Run, base::Owned(task)), + base::TimeDelta::FromMilliseconds(delay_milliseconds)); +} + +} // namespace chromecast diff --git a/chromecast/base/task_runner_impl.h b/chromecast/base/task_runner_impl.h new file mode 100644 index 0000000..110274d --- /dev/null +++ b/chromecast/base/task_runner_impl.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_BASE_TASK_RUNNER_IMPL_H_ +#define CHROMECAST_BASE_TASK_RUNNER_IMPL_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "chromecast/public/task_runner.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace chromecast { + +// Implementation of public TaskRunner interface that just calls +// base::ThreadTaskRunnerHandle at construction time and uses it to post. +class TaskRunnerImpl : public TaskRunner { + public: + TaskRunnerImpl(); + ~TaskRunnerImpl() override; + + bool PostTask(Task* task, uint64_t delay_milliseconds) override; + + const scoped_refptr<base::SingleThreadTaskRunner>& runner() const { + return runner_; + } + + private: + const scoped_refptr<base::SingleThreadTaskRunner> runner_; + + DISALLOW_COPY_AND_ASSIGN(TaskRunnerImpl); +}; + +} // namespace chromecast + +#endif // CHROMECAST_BASE_TASK_RUNNER_IMPL_H_ diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 3d61b01..e445c1e 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc @@ -23,8 +23,8 @@ #include "chromecast/browser/media/cma_message_filter_host.h" #include "chromecast/browser/url_request_context_factory.h" #include "chromecast/common/global_descriptors.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device_factory.h" +#include "chromecast/public/cast_media_shlib.h" +#include "chromecast/public/media/media_pipeline_backend.h" #include "components/crash/app/breakpad_linux.h" #include "components/crash/browser/crash_handler_host_linux.h" #include "components/network_hints/browser/network_hints_message_filter.h" @@ -79,12 +79,11 @@ CastContentBrowserClient::CreateAudioManagerFactory() { } #if !defined(OS_ANDROID) -scoped_ptr<media::MediaPipelineDevice> -CastContentBrowserClient::CreateMediaPipelineDevice( +scoped_ptr<media::MediaPipelineBackend> +CastContentBrowserClient::CreateMediaPipelineBackend( const media::MediaPipelineDeviceParams& params) { - scoped_ptr<media::MediaPipelineDeviceFactory> factory = - GetMediaPipelineDeviceFactory(params); - return make_scoped_ptr(new media::MediaPipelineDevice(factory.Pass())); + return make_scoped_ptr( + media::CastMediaShlib::CreateMediaPipelineBackend(params)); } #endif @@ -101,9 +100,8 @@ void CastContentBrowserClient::RenderProcessWillLaunch( scoped_refptr<media::CmaMessageFilterHost> cma_message_filter( new media::CmaMessageFilterHost( host->GetID(), - base::Bind( - &CastContentBrowserClient::CreateMediaPipelineDevice, - base::Unretained(this)))); + base::Bind(&CastContentBrowserClient::CreateMediaPipelineBackend, + base::Unretained(this)))); host->AddFilter(cma_message_filter.get()); #endif // !defined(OS_ANDROID) diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index 48caf43..aca5d64 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h @@ -31,8 +31,8 @@ class HostResolver; namespace chromecast { namespace media { -class MediaPipelineDevice; -class MediaPipelineDeviceParams; +class MediaPipelineBackend; +struct MediaPipelineDeviceParams; } namespace shell { @@ -62,7 +62,7 @@ class CastContentBrowserClient: public content::ContentBrowserClient { #if !defined(OS_ANDROID) // Creates a MediaPipelineDevice (CMA backend) for media playback, called // once per media player instance. - virtual scoped_ptr<media::MediaPipelineDevice> CreateMediaPipelineDevice( + virtual scoped_ptr<media::MediaPipelineBackend> CreateMediaPipelineBackend( const media::MediaPipelineDeviceParams& params); #endif diff --git a/chromecast/browser/media/cma_message_filter_host.cc b/chromecast/browser/media/cma_message_filter_host.cc index 226d574..71ea320 100644 --- a/chromecast/browser/media/cma_message_filter_host.cc +++ b/chromecast/browser/media/cma_message_filter_host.cc @@ -299,10 +299,10 @@ void UpdateVideoSurfaceHost(int surface_id, const gfx::QuadF& quad) { CmaMessageFilterHost::CmaMessageFilterHost( int render_process_id, - const media::CreatePipelineDeviceCB& create_pipeline_device_cb) + const CreateDeviceComponentsCB& create_device_components_cb) : content::BrowserMessageFilter(CastMediaMsgStart), process_id_(render_process_id), - create_pipeline_device_cb_(create_pipeline_device_cb), + create_device_components_cb_(create_device_components_cb), task_runner_(MediaMessageLoop::GetTaskRunner()), weak_factory_(this) { weak_this_ = weak_factory_.GetWeakPtr(); @@ -387,7 +387,7 @@ void CmaMessageFilterHost::CreateMedia(int media_id, LoadType load_type) { task_runner_->PostTask( FROM_HERE, base::Bind(&MediaPipelineHost::Initialize, base::Unretained(media_pipeline_host.get()), - load_type, client, create_pipeline_device_cb_)); + load_type, client, create_device_components_cb_)); std::pair<MediaPipelineMap::iterator, bool> ret = media_pipelines_.insert( std::make_pair(media_id, media_pipeline_host.release())); diff --git a/chromecast/browser/media/cma_message_filter_host.h b/chromecast/browser/media/cma_message_filter_host.h index 9b16205..6408ba4 100644 --- a/chromecast/browser/media/cma_message_filter_host.h +++ b/chromecast/browser/media/cma_message_filter_host.h @@ -12,7 +12,6 @@ #include "base/memory/shared_memory.h" #include "base/memory/weak_ptr.h" #include "chromecast/common/media/cma_ipc_common.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" #include "chromecast/media/cma/pipeline/load_type.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" @@ -38,14 +37,20 @@ class VideoDecoderConfig; namespace chromecast { namespace media { +class MediaPipelineBackend; +struct MediaPipelineDeviceParams; class MediaPipelineHost; class CmaMessageFilterHost : public content::BrowserMessageFilter { public: + // Factory method to create a MediaPipelineBackend + typedef base::Callback<scoped_ptr<MediaPipelineBackend>( + const MediaPipelineDeviceParams&)> CreateDeviceComponentsCB; + CmaMessageFilterHost( int render_process_id, - const media::CreatePipelineDeviceCB& create_pipeline_device_cb); + const CreateDeviceComponentsCB& create_device_components_cb); // content::BrowserMessageFilter implementation. void OnChannelClosing() override; @@ -114,7 +119,7 @@ class CmaMessageFilterHost const int process_id_; // Factory function for device-specific part of media pipeline creation - media::CreatePipelineDeviceCB create_pipeline_device_cb_; + CreateDeviceComponentsCB create_device_components_cb_; // List of media pipeline and message loop media pipelines are running on. MediaPipelineMap media_pipelines_; diff --git a/chromecast/browser/media/media_pipeline_host.cc b/chromecast/browser/media/media_pipeline_host.cc index 087077d..85376d5 100644 --- a/chromecast/browser/media/media_pipeline_host.cc +++ b/chromecast/browser/media/media_pipeline_host.cc @@ -11,14 +11,17 @@ #include "base/location.h" #include "base/memory/shared_memory.h" #include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "chromecast/base/task_runner_impl.h" #include "chromecast/common/media/shared_memory_chunk.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device_params.h" +#include "chromecast/media/base/media_caps.h" #include "chromecast/media/cma/ipc/media_message_fifo.h" #include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h" #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" #include "chromecast/media/cma/pipeline/media_pipeline_impl.h" #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" +#include "chromecast/public/media/media_pipeline_backend.h" +#include "chromecast/public/media/media_pipeline_device_params.h" namespace chromecast { namespace media { @@ -53,14 +56,18 @@ MediaPipelineHost::~MediaPipelineHost() { void MediaPipelineHost::Initialize( LoadType load_type, const MediaPipelineClient& client, - const media::CreatePipelineDeviceCB& create_pipeline_device_cb) { + const CreateDeviceComponentsCB& create_device_components_cb) { DCHECK(thread_checker_.CalledOnValidThread()); media_pipeline_.reset(new MediaPipelineImpl()); - MediaPipelineDeviceParams default_parameters; - if (load_type == kLoadTypeMediaStream) - default_parameters.sync_type = MediaPipelineDeviceParams::kModeIgnorePts; + task_runner_.reset(new TaskRunnerImpl()); + MediaPipelineDeviceParams::MediaSyncType sync_type = + (load_type == kLoadTypeMediaStream) + ? MediaPipelineDeviceParams::kModeIgnorePts + : MediaPipelineDeviceParams::kModeSyncPts; + MediaPipelineDeviceParams default_parameters(sync_type, task_runner_.get()); + media_pipeline_->Initialize( - load_type, create_pipeline_device_cb.Run(default_parameters).Pass()); + load_type, create_device_components_cb.Run(default_parameters).Pass()); media_pipeline_->SetClient(client); } diff --git a/chromecast/browser/media/media_pipeline_host.h b/chromecast/browser/media/media_pipeline_host.h index 18502e4..db26bb9 100644 --- a/chromecast/browser/media/media_pipeline_host.h +++ b/chromecast/browser/media/media_pipeline_host.h @@ -15,13 +15,11 @@ #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "chromecast/common/media/cma_ipc_common.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" #include "chromecast/media/cma/pipeline/load_type.h" #include "media/base/pipeline_status.h" namespace base { class SharedMemory; -class SingleThreadTaskRunner; } namespace media { @@ -30,22 +28,29 @@ class VideoDecoderConfig; } namespace chromecast { +class TaskRunnerImpl; + namespace media { struct AvPipelineClient; class BrowserCdmCast; +class MediaPipelineBackend; struct MediaPipelineClient; +struct MediaPipelineDeviceParams; class MediaPipelineImpl; struct VideoPipelineClient; class MediaPipelineHost { public: + // Factory method to create a MediaPipelineBackend + typedef base::Callback<scoped_ptr<media::MediaPipelineBackend>( + const MediaPipelineDeviceParams&)> CreateDeviceComponentsCB; + MediaPipelineHost(); ~MediaPipelineHost(); - void Initialize( - LoadType load_type, - const MediaPipelineClient& client, - const media::CreatePipelineDeviceCB& create_pipeline_device_cb); + void Initialize(LoadType load_type, + const MediaPipelineClient& client, + const CreateDeviceComponentsCB& create_device_components_cb); void SetAvPipe(TrackId track_id, scoped_ptr<base::SharedMemory> shared_mem, @@ -72,6 +77,7 @@ class MediaPipelineHost { private: base::ThreadChecker thread_checker_; + scoped_ptr<TaskRunnerImpl> task_runner_; scoped_ptr<MediaPipelineImpl> media_pipeline_; // The shared memory for a track id must be valid until Stop is invoked on diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp index 1b0f65d..227c9bd 100644 --- a/chromecast/chromecast.gyp +++ b/chromecast/chromecast.gyp @@ -43,13 +43,30 @@ 'public/chromecast_export.h', 'public/graphics_properties_shlib.h', 'public/graphics_types.h', + 'public/media_codec_support.h', + 'public/media/audio_pipeline_device.h', + 'public/media/cast_decoder_buffer.h', + 'public/media/cast_decrypt_config.h', + 'public/media/cast_key_system.h', 'public/media/decoder_config.h', + 'public/media/decrypt_context.h', + 'public/media/media_clock_device.h', + 'public/media/media_component_device.h', + 'public/media/media_pipeline_backend.h', + 'public/media/media_pipeline_device_params.h', 'public/media/stream_id.h', + 'public/media/video_pipeline_device.h', 'public/osd_plane.h', 'public/osd_plane_shlib.h', 'public/osd_surface.h', + 'public/task_runner.h', 'public/video_plane.h', ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'public/', + ], + }, }, { 'target_name': 'cast_base', @@ -76,7 +93,9 @@ 'base/process_utils.cc', 'base/process_utils.h', 'base/serializers.cc', - 'base/serializers.h' + 'base/serializers.h', + 'base/task_runner_impl.cc', + 'base/task_runner_impl.h', ], 'conditions': [ ['OS=="android"', { @@ -624,6 +643,7 @@ 'target_name': 'cast_shell_media', 'type': '<(component)', 'dependencies': [ + 'cast_public_api', 'media/media.gyp:cast_media', '../content/content.gyp:content', '../ipc/ipc.gyp:ipc', diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn index 47f116a..1940ab3 100644 --- a/chromecast/media/base/BUILD.gn +++ b/chromecast/media/base/BUILD.gn @@ -19,6 +19,8 @@ source_set("base") { "key_systems_common.h", "media_caps.cc", "media_caps.h", + "media_codec_support.cc", + "media_codec_support.h", "media_message_loop.cc", "media_message_loop.h", "switching_media_renderer.cc", diff --git a/chromecast/media/base/cast_media_default.cc b/chromecast/media/base/cast_media_default.cc index 0c17712..703cb4e 100644 --- a/chromecast/media/base/cast_media_default.cc +++ b/chromecast/media/base/cast_media_default.cc @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chromecast/media/cma/backend/media_pipeline_backend_default.h" #include "chromecast/public/cast_media_shlib.h" #include "chromecast/public/graphics_types.h" +#include "chromecast/public/media_codec_support_shlib.h" #include "chromecast/public/video_plane.h" namespace chromecast { @@ -42,5 +44,15 @@ VideoPlane* CastMediaShlib::GetVideoPlane() { return g_video_plane; } +MediaPipelineBackend* CastMediaShlib::CreateMediaPipelineBackend( + const MediaPipelineDeviceParams& params) { + return new MediaPipelineBackendDefault(params); +} + +MediaCodecSupportShlib::CodecSupport MediaCodecSupportShlib::IsSupported( + const std::string& codec) { + return kDefault; +} + } // namespace media } // namespace chromecast diff --git a/chromecast/media/base/decrypt_context.cc b/chromecast/media/base/decrypt_context.cc deleted file mode 100644 index 38da3af..0000000 --- a/chromecast/media/base/decrypt_context.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 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 "chromecast/media/base/decrypt_context.h" - -namespace chromecast { -namespace media { - -DecryptContext::DecryptContext(CastKeySystem key_system) - : key_system_(key_system) { -} - -DecryptContext::~DecryptContext() { -} - -crypto::SymmetricKey* DecryptContext::GetKey() const { - return NULL; -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/base/decrypt_context_impl.cc b/chromecast/media/base/decrypt_context_impl.cc new file mode 100644 index 0000000..9e868d3 --- /dev/null +++ b/chromecast/media/base/decrypt_context_impl.cc @@ -0,0 +1,29 @@ +// Copyright 2014 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 "chromecast/media/base/decrypt_context_impl.h" + +namespace chromecast { +namespace media { + +DecryptContextImpl::DecryptContextImpl(CastKeySystem key_system) + : key_system_(key_system) {} + +DecryptContextImpl::~DecryptContextImpl() {} + +CastKeySystem DecryptContextImpl::GetKeySystem() { + return key_system_; +} + +bool DecryptContextImpl::Decrypt(CastDecoderBuffer* buffer, + std::vector<uint8_t>* output) { + return false; +} + +crypto::SymmetricKey* DecryptContextImpl::GetKey() const { + return NULL; +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/base/decrypt_context.h b/chromecast/media/base/decrypt_context_impl.h index 5d053c0..c2a5b96 100644 --- a/chromecast/media/base/decrypt_context.h +++ b/chromecast/media/base/decrypt_context_impl.h @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_H_ -#define CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_H_ +#ifndef CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_H_ +#define CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_H_ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "chromecast/media/base/key_systems_common.h" +#include "chromecast/public/media/decrypt_context.h" namespace crypto { class SymmetricKey; @@ -21,26 +22,26 @@ namespace media { // Each CDM should implement this and add fields needed to fully describe a // decryption context. // -class DecryptContext : public base::RefCountedThreadSafe<DecryptContext> { +class DecryptContextImpl : public DecryptContext { public: - explicit DecryptContext(CastKeySystem key_system); + explicit DecryptContextImpl(CastKeySystem key_system); + ~DecryptContextImpl() override; - CastKeySystem key_system() const { return key_system_; } + // DecryptContext implementation: + CastKeySystem GetKeySystem() override; + bool Decrypt(CastDecoderBuffer* buffer, + std::vector<uint8_t>* output) override; // Returns the clear key if available, NULL otherwise. virtual crypto::SymmetricKey* GetKey() const; - protected: - friend class base::RefCountedThreadSafe<DecryptContext>; - virtual ~DecryptContext(); - private: CastKeySystem key_system_; - DISALLOW_COPY_AND_ASSIGN(DecryptContext); + DISALLOW_COPY_AND_ASSIGN(DecryptContextImpl); }; } // namespace media } // namespace chromecast -#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_H_
\ No newline at end of file +#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_H_ diff --git a/chromecast/media/base/decrypt_context_clearkey.cc b/chromecast/media/base/decrypt_context_impl_clearkey.cc index 248cbb4..5ad3e11 100644 --- a/chromecast/media/base/decrypt_context_clearkey.cc +++ b/chromecast/media/base/decrypt_context_impl_clearkey.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromecast/media/base/decrypt_context_clearkey.h" +#include "chromecast/media/base/decrypt_context_impl_clearkey.h" #include "base/logging.h" #include "crypto/symmetric_key.h" @@ -10,16 +10,15 @@ namespace chromecast { namespace media { -DecryptContextClearKey::DecryptContextClearKey(crypto::SymmetricKey* key) - : DecryptContext(KEY_SYSTEM_CLEAR_KEY), - key_(key) { +DecryptContextImplClearKey::DecryptContextImplClearKey( + crypto::SymmetricKey* key) + : DecryptContextImpl(KEY_SYSTEM_CLEAR_KEY), key_(key) { CHECK(key); } -DecryptContextClearKey::~DecryptContextClearKey() { -} +DecryptContextImplClearKey::~DecryptContextImplClearKey() {} -crypto::SymmetricKey* DecryptContextClearKey::GetKey() const { +crypto::SymmetricKey* DecryptContextImplClearKey::GetKey() const { return key_; } diff --git a/chromecast/media/base/decrypt_context_clearkey.h b/chromecast/media/base/decrypt_context_impl_clearkey.h index a4e56d0..ffd0473 100644 --- a/chromecast/media/base/decrypt_context_clearkey.h +++ b/chromecast/media/base/decrypt_context_impl_clearkey.h @@ -2,32 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_CLEARKEY_H_ -#define CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_CLEARKEY_H_ +#ifndef CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_CLEARKEY_H_ +#define CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_CLEARKEY_H_ #include "base/macros.h" -#include "chromecast/media/base/decrypt_context.h" +#include "chromecast/media/base/decrypt_context_impl.h" namespace chromecast { namespace media { -class DecryptContextClearKey : public DecryptContext { +class DecryptContextImplClearKey : public DecryptContextImpl { public: // Note: DecryptContextClearKey does not take ownership of |key|. - explicit DecryptContextClearKey(crypto::SymmetricKey* key); + explicit DecryptContextImplClearKey(crypto::SymmetricKey* key); + ~DecryptContextImplClearKey() override; // DecryptContext implementation. crypto::SymmetricKey* GetKey() const override; private: - ~DecryptContextClearKey() override; - crypto::SymmetricKey* const key_; - DISALLOW_COPY_AND_ASSIGN(DecryptContextClearKey); + DISALLOW_COPY_AND_ASSIGN(DecryptContextImplClearKey); }; } // namespace media } // namespace chromecast -#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_CLEARKEY_H_ +#endif // CHROMECAST_MEDIA_BASE_DECRYPT_CONTEXT_IMPL_CLEARKEY_H_ diff --git a/chromecast/media/base/key_systems_common.h b/chromecast/media/base/key_systems_common.h index 1537afd..53e323c 100644 --- a/chromecast/media/base/key_systems_common.h +++ b/chromecast/media/base/key_systems_common.h @@ -10,6 +10,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "chromecast/public/media/cast_key_system.h" #include "media/base/android/media_client_android.h" namespace chromecast { @@ -19,13 +20,6 @@ namespace media { extern const char kChromecastPlayreadyKeySystem[]; #endif // defined(PLAYREADY_CDM_AVAILABLE) -enum CastKeySystem { - KEY_SYSTEM_NONE = 0, - KEY_SYSTEM_CLEAR_KEY, - KEY_SYSTEM_PLAYREADY, - KEY_SYSTEM_WIDEVINE -}; - // Translates a key system string into a CastKeySystem, calling into the // platform for known key systems if needed. CastKeySystem GetKeySystemByName(const std::string& key_system_name); diff --git a/chromecast/media/base/media_codec_support.cc b/chromecast/media/base/media_codec_support.cc index b04a077..1d82f9c 100644 --- a/chromecast/media/base/media_codec_support.cc +++ b/chromecast/media/base/media_codec_support.cc @@ -4,13 +4,41 @@ #include "chromecast/media/base/media_codec_support.h" -// TODO(gunsch/servolk): delete this file once a solution exists upstream. +#include "base/bind.h" +#include "chromecast/media/base/media_caps.h" +#include "chromecast/public/media_codec_support_shlib.h" +#include "net/base/mime_util.h" -namespace net { +namespace chromecast { +namespace media { +namespace { + +bool IsCodecSupported(const std::string& codec) { + MediaCodecSupportShlib::CodecSupport platform_support = + MediaCodecSupportShlib::IsSupported(codec); + if (platform_support == MediaCodecSupportShlib::kSupported) + return true; + else if (platform_support == MediaCodecSupportShlib::kNotSupported) + return false; + + if (codec == "aac51") { + return ::media::HdmiSinkSupportsPcmSurroundSound(); + } + if (codec == "ac-3" || codec == "mp4a.a5") { + return ::media::HdmiSinkSupportsAC3(); + } + if (codec == "ec-3" || codec == "mp4a.a6") { + return ::media::HdmiSinkSupportsEAC3(); + } -bool DefaultIsCodecSupported(const std::string&) { return true; } -} // namespace net +} // namespace + +net::IsCodecSupportedCB GetIsCodecSupportedOnChromecastCB() { + return base::Bind(&IsCodecSupported); +} +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/base/media_codec_support.h b/chromecast/media/base/media_codec_support.h index e961177..f97df1b 100644 --- a/chromecast/media/base/media_codec_support.h +++ b/chromecast/media/base/media_codec_support.h @@ -11,24 +11,18 @@ #include "net/base/mime_util.h" // TODO(gunsch/servolk): remove when this definition exists upstream. - namespace net { typedef base::Callback<bool(const std::string&)> IsCodecSupportedCB; -bool DefaultIsCodecSupported(const std::string&); } namespace chromecast { namespace media { -// This function should return a callback capable of deciding whether a given -// codec (passed in as a string representation of the codec id conforming to -// RFC 6381) is supported or not. The implementation of this function is -// expected to be provided somewhere in the vendor platform-specific libraries -// that will get linked with cast_shell_common target. +// Returns the callback to decide whether a given codec (passed in as a string +// representation of the codec id conforming to RFC 6381) is supported or not. net::IsCodecSupportedCB GetIsCodecSupportedOnChromecastCB(); } // namespace media } // namespace chromecast #endif // CHROMECAST_MEDIA_BASE_MEDIA_CODEC_SUPPORT_H_ - diff --git a/chromecast/media/base/media_codec_support_simple.cc b/chromecast/media/base/media_codec_support_simple.cc deleted file mode 100644 index 24e83be..0000000 --- a/chromecast/media/base/media_codec_support_simple.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 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 "chromecast/media/base/media_codec_support.h" - -#include "base/bind.h" - -namespace chromecast { -namespace media { - -// This is a default implementation of GetIsCodecSupportedOnChromecastCB that is -// going to be used for brandings other than 'Chrome'. Most platforms will want -// to use their own custom implementations of the IsCodecSupportedCB callback. -net::IsCodecSupportedCB GetIsCodecSupportedOnChromecastCB() { - return base::Bind(&net::DefaultIsCodecSupported); -} - -} // namespace media -} // namespace chromecast - diff --git a/chromecast/media/cdm/browser_cdm_cast.h b/chromecast/media/cdm/browser_cdm_cast.h index 0e24a51..a4c80fb 100644 --- a/chromecast/media/cdm/browser_cdm_cast.h +++ b/chromecast/media/cdm/browser_cdm_cast.h @@ -28,7 +28,7 @@ class PlayerTrackerImpl; namespace chromecast { namespace media { -class DecryptContext; +class DecryptContextImpl; // BrowserCdmCast is an extension of BrowserCdm that provides common // functionality across CDM implementations. @@ -60,7 +60,7 @@ class BrowserCdmCast : public ::media::BrowserCdm { // Returns the decryption context needed to decrypt frames encrypted with // |key_id|. // Returns null if |key_id| is not available. - virtual scoped_refptr<DecryptContext> GetDecryptContext( + virtual scoped_ptr<DecryptContextImpl> GetDecryptContext( const std::string& key_id) const = 0; protected: diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn index 51e6244..0f1dc55 100644 --- a/chromecast/media/cma/backend/BUILD.gn +++ b/chromecast/media/cma/backend/BUILD.gn @@ -4,28 +4,14 @@ source_set("backend") { sources = [ - "audio_pipeline_device.cc", - "audio_pipeline_device.h", "audio_pipeline_device_default.cc", "audio_pipeline_device_default.h", - "media_clock_device.cc", - "media_clock_device.h", "media_clock_device_default.cc", "media_clock_device_default.h", - "media_component_device.cc", - "media_component_device.h", "media_component_device_default.cc", "media_component_device_default.h", - "media_pipeline_device.cc", - "media_pipeline_device.h", - "media_pipeline_device_factory.h", - "media_pipeline_device_factory_default.cc", - "media_pipeline_device_factory_default.h", - "media_pipeline_device_factory_simple.cc", - "media_pipeline_device_params.cc", - "media_pipeline_device_params.h", - "video_pipeline_device.cc", - "video_pipeline_device.h", + "media_pipeline_backend_default.cc", + "media_pipeline_backend_default.h", "video_pipeline_device_default.cc", "video_pipeline_device_default.h", ] diff --git a/chromecast/media/cma/backend/audio_pipeline_device.cc b/chromecast/media/cma/backend/audio_pipeline_device.cc deleted file mode 100644 index 60c6c30..0000000 --- a/chromecast/media/cma/backend/audio_pipeline_device.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/audio_pipeline_device.h" - -namespace chromecast { -namespace media { - -AudioPipelineDevice::AudioPipelineDevice() { -} - -AudioPipelineDevice::~AudioPipelineDevice() { -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/audio_pipeline_device_default.cc b/chromecast/media/cma/backend/audio_pipeline_device_default.cc index 6d1bb8d..dede977 100644 --- a/chromecast/media/cma/backend/audio_pipeline_device_default.cc +++ b/chromecast/media/cma/backend/audio_pipeline_device_default.cc @@ -10,15 +10,16 @@ namespace chromecast { namespace media { AudioPipelineDeviceDefault::AudioPipelineDeviceDefault( + const MediaPipelineDeviceParams& params, MediaClockDevice* media_clock_device) - : pipeline_(new MediaComponentDeviceDefault(media_clock_device)) { - DetachFromThread(); + : pipeline_(new MediaComponentDeviceDefault(params, media_clock_device)) { + thread_checker_.DetachFromThread(); } AudioPipelineDeviceDefault::~AudioPipelineDeviceDefault() { } -void AudioPipelineDeviceDefault::SetClient(const Client& client) { +void AudioPipelineDeviceDefault::SetClient(Client* client) { pipeline_->SetClient(client); } @@ -40,27 +41,24 @@ bool AudioPipelineDeviceDefault::SetState(State new_state) { return true; } -bool AudioPipelineDeviceDefault::SetStartPts(base::TimeDelta time) { - return pipeline_->SetStartPts(time); +bool AudioPipelineDeviceDefault::SetStartPts(int64_t time_microseconds) { + return pipeline_->SetStartPts(time_microseconds); } MediaComponentDevice::FrameStatus AudioPipelineDeviceDefault::PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) { + DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) { return pipeline_->PushFrame(decrypt_context, buffer, completion_cb); } -base::TimeDelta AudioPipelineDeviceDefault::GetRenderingTime() const { - return pipeline_->GetRenderingTime(); -} - -base::TimeDelta AudioPipelineDeviceDefault::GetRenderingDelay() const { +AudioPipelineDeviceDefault::RenderingDelay +AudioPipelineDeviceDefault::GetRenderingDelay() const { return pipeline_->GetRenderingDelay(); } bool AudioPipelineDeviceDefault::SetConfig(const AudioConfig& config) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (!IsValidConfig(config)) return false; config_ = config; @@ -73,7 +71,7 @@ bool AudioPipelineDeviceDefault::SetConfig(const AudioConfig& config) { } void AudioPipelineDeviceDefault::SetStreamVolumeMultiplier(float multiplier) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); } bool AudioPipelineDeviceDefault::GetStatistics(Statistics* stats) const { diff --git a/chromecast/media/cma/backend/audio_pipeline_device_default.h b/chromecast/media/cma/backend/audio_pipeline_device_default.h index f8a1a84..814a027 100644 --- a/chromecast/media/cma/backend/audio_pipeline_device_default.h +++ b/chromecast/media/cma/backend/audio_pipeline_device_default.h @@ -8,7 +8,9 @@ #include <vector> #include "base/macros.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" +#include "chromecast/public/media/audio_pipeline_device.h" #include "chromecast/public/media/decoder_config.h" namespace chromecast { @@ -16,23 +18,23 @@ namespace media { class MediaClockDevice; class MediaComponentDeviceDefault; +struct MediaPipelineDeviceParams; class AudioPipelineDeviceDefault : public AudioPipelineDevice { public: - explicit AudioPipelineDeviceDefault(MediaClockDevice* media_clock_device); + AudioPipelineDeviceDefault(const MediaPipelineDeviceParams& params, + MediaClockDevice* media_clock_device); ~AudioPipelineDeviceDefault() override; // AudioPipelineDevice implementation. - void SetClient(const Client& client) override; + void SetClient(Client* client) override; State GetState() const override; bool SetState(State new_state) override; - bool SetStartPts(base::TimeDelta time) override; - FrameStatus PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) override; - base::TimeDelta GetRenderingTime() const override; - base::TimeDelta GetRenderingDelay() const override; + bool SetStartPts(int64_t time_microseconds) override; + FrameStatus PushFrame(DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) override; + RenderingDelay GetRenderingDelay() const override; bool SetConfig(const AudioConfig& config) override; void SetStreamVolumeMultiplier(float multiplier) override; bool GetStatistics(Statistics* stats) const override; @@ -43,6 +45,7 @@ class AudioPipelineDeviceDefault : public AudioPipelineDevice { AudioConfig config_; std::vector<uint8_t> config_extra_data_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(AudioPipelineDeviceDefault); }; diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc index 9c84b2f..d112ab2 100644 --- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc +++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc @@ -19,20 +19,19 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "chromecast/media/base/decrypt_context.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device_factory.h" -#include "chromecast/media/cma/backend/media_pipeline_device_params.h" -#include "chromecast/media/cma/backend/video_pipeline_device.h" +#include "chromecast/base/task_runner_impl.h" #include "chromecast/media/cma/base/decoder_buffer_adapter.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/base/decoder_config_adapter.h" #include "chromecast/media/cma/test/frame_segmenter_for_test.h" #include "chromecast/media/cma/test/media_component_device_feeder_for_test.h" #include "chromecast/public/cast_media_shlib.h" +#include "chromecast/public/media/audio_pipeline_device.h" +#include "chromecast/public/media/cast_decoder_buffer.h" #include "chromecast/public/media/decoder_config.h" +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/media_pipeline_backend.h" +#include "chromecast/public/media/media_pipeline_device_params.h" +#include "chromecast/public/media/video_pipeline_device.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffers.h" #include "media/base/decoder_buffer.h" @@ -110,7 +109,8 @@ class AudioVideoPipelineDeviceTest : public testing::Test { void OnEos(MediaComponentDeviceFeederForTest* device_feeder); - scoped_ptr<MediaPipelineDevice> media_pipeline_device_; + scoped_ptr<TaskRunnerImpl> task_runner_; + scoped_ptr<MediaPipelineBackend> backend_; MediaClockDevice* media_clock_device_; // Devices to feed @@ -166,8 +166,7 @@ void AudioVideoPipelineDeviceTest::LoadAudioStream(std::string filename) { DemuxResult demux_result = FFmpegDemuxForTest(file_path, true /* audio */); BufferList frames = demux_result.frames; - AudioPipelineDevice* audio_pipeline_device = - media_pipeline_device_->GetAudioPipelineDevice(); + AudioPipelineDevice* audio_pipeline_device = backend_->GetAudio(); bool success = audio_pipeline_device->SetConfig( DecoderConfigAdapter::ToCastAudioConfig(kPrimary, @@ -214,8 +213,7 @@ void AudioVideoPipelineDeviceTest::LoadVideoStream(std::string filename, kPrimary, demux_result.video_config); } - VideoPipelineDevice* video_pipeline_device = - media_pipeline_device_->GetVideoPipelineDevice(); + VideoPipelineDevice* video_pipeline_device = backend_->GetVideo(); // Set configuration. bool success = video_pipeline_device->SetConfig(video_config); @@ -253,14 +251,16 @@ void AudioVideoPipelineDeviceTest::Start() { } void AudioVideoPipelineDeviceTest::MonitorLoop() { - base::TimeDelta media_time = media_clock_device_->GetTime(); + base::TimeDelta media_time = base::TimeDelta::FromMicroseconds( + media_clock_device_->GetTimeMicroseconds()); if (!pause_pattern_.empty() && pause_pattern_[pause_pattern_idx_].delay >= base::TimeDelta() && media_time >= pause_time_ + pause_pattern_[pause_pattern_idx_].delay) { // Do Pause media_clock_device_->SetRate(0.0); - pause_time_ = media_clock_device_->GetTime(); + pause_time_ = base::TimeDelta::FromMicroseconds( + media_clock_device_->GetTimeMicroseconds()); VLOG(2) << "Pausing at " << pause_time_.InMilliseconds() << "ms for " << pause_pattern_[pause_pattern_idx_].length.InMilliseconds() << "ms"; @@ -282,7 +282,8 @@ void AudioVideoPipelineDeviceTest::MonitorLoop() { void AudioVideoPipelineDeviceTest::OnPauseCompleted() { // Make sure the media time didn't move during that time. - base::TimeDelta media_time = media_clock_device_->GetTime(); + base::TimeDelta media_time = base::TimeDelta::FromMicroseconds( + media_clock_device_->GetTimeMicroseconds()); // TODO(damienv): // Should be: @@ -322,17 +323,16 @@ void AudioVideoPipelineDeviceTest::OnEos( void AudioVideoPipelineDeviceTest::Initialize() { // Create the media device. - MediaPipelineDeviceParams params; - scoped_ptr<MediaPipelineDeviceFactory> device_factory = - GetMediaPipelineDeviceFactory(params); - media_pipeline_device_.reset(new MediaPipelineDevice(device_factory.Pass())); - media_clock_device_ = media_pipeline_device_->GetMediaClockDevice(); + task_runner_.reset(new TaskRunnerImpl()); + MediaPipelineDeviceParams params(task_runner_.get()); + backend_.reset(CastMediaShlib::CreateMediaPipelineBackend(params)); + media_clock_device_ = backend_->GetClock(); // Clock initialization and configuration. bool success = media_clock_device_->SetState(MediaClockDevice::kStateIdle); ASSERT_TRUE(success); - success = media_clock_device_->ResetTimeline(base::TimeDelta()); + success = media_clock_device_->ResetTimeline(0); ASSERT_TRUE(success); media_clock_device_->SetRate(1.0); } diff --git a/chromecast/media/cma/backend/media_clock_device.cc b/chromecast/media/cma/backend/media_clock_device.cc deleted file mode 100644 index 853e5ba..0000000 --- a/chromecast/media/cma/backend/media_clock_device.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/media_clock_device.h" - -#include "base/logging.h" - -namespace chromecast { -namespace media { - -MediaClockDevice::MediaClockDevice() { -} - -MediaClockDevice::~MediaClockDevice() { -} - -// static -bool MediaClockDevice::IsValidStateTransition(State state1, State state2) { - if (state2 == state1) - return true; - - // All states can transition to |kStateError|. - bool is_transition_valid = (state2 == kStateError); - - // All the other valid FSM transitions. - is_transition_valid = is_transition_valid || - (state1 == kStateUninitialized && (state2 == kStateIdle)) || - (state1 == kStateIdle && (state2 == kStateRunning || - state2 == kStateUninitialized)) || - (state1 == kStateRunning && (state2 == kStateIdle)) || - (state1 == kStateError && (state2 == kStateUninitialized)); - - return is_transition_valid; -} - -// static -std::string MediaClockDevice::StateToString(const State& state) { - switch (state) { - case kStateUninitialized: - return "Uninitialized"; - case kStateIdle: - return "Idle"; - case kStateRunning: - return "Running"; - case kStateError: - return "Error"; - default: - NOTREACHED() << "Unknown MediaClockDevice::State: " << state; - return ""; - } -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_clock_device.h b/chromecast/media/cma/backend/media_clock_device.h deleted file mode 100644 index b625dd5..0000000 --- a/chromecast/media/cma/backend/media_clock_device.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_CLOCK_DEVICE_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_CLOCK_DEVICE_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/macros.h" -#include "base/threading/non_thread_safe.h" -#include "base/time/time.h" - -namespace chromecast { -namespace media { - -// MediaClockDevice - -// -// State machine: -// ------------------- -// | | -// v | -// kUninitialized --> kIdle --------- kRunning -// -// {any state} --> kError -// -// Notes: -// - Hardware resources are acquired when transitioning from the -// |kUninitialized| state to the |kIdle| state. -// - The initial value of the timeline can only be set in the kIdle state. -// -class MediaClockDevice - : NON_EXPORTED_BASE(public base::NonThreadSafe) { - public: - enum State { - kStateUninitialized, - kStateIdle, - kStateRunning, - kStateError, - }; - - // Return true if transition from |state1| to |state2| is a valid state - // transition. - static bool IsValidStateTransition(State state1, State state2); - - // Returns string representation of state (for logging) - static std::string StateToString(const State& state); - - MediaClockDevice(); - virtual ~MediaClockDevice(); - - // Return the current state of the media clock. - virtual State GetState() const = 0; - - // Changes the state and performs any necessary transitions. - // Returns true when successful. - virtual bool SetState(State new_state) = 0; - - // Sets the initial value of the timeline. - // Can only be invoked in state kStateIdle. - // Returns true when successful. - virtual bool ResetTimeline(base::TimeDelta time) = 0; - - // Sets the clock rate. - // Setting it to 0 means the clock is not progressing and that the renderer - // tied to this media clock should pause rendering. - // Can only be invoked in states kStateIdle or kStateRunning. - virtual bool SetRate(float rate) = 0; - - // Retrieves the media clock time. - // Can only be invoked in states kStateIdle or kStateRunning. - virtual base::TimeDelta GetTime() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(MediaClockDevice); -}; - -} // namespace media -} // namespace chromecast - -#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_CLOCK_DEVICE_H_ diff --git a/chromecast/media/cma/backend/media_clock_device_default.cc b/chromecast/media/cma/backend/media_clock_device_default.cc index 086083d..0855cf3 100644 --- a/chromecast/media/cma/backend/media_clock_device_default.cc +++ b/chromecast/media/cma/backend/media_clock_device_default.cc @@ -8,25 +8,53 @@ namespace chromecast { namespace media { +namespace { + +// Return true if transition from |state1| to |state2| is a valid state +// transition. +inline static bool IsValidStateTransition(MediaClockDevice::State state1, + MediaClockDevice::State state2) { + if (state2 == state1) + return true; + + // All states can transition to |kStateError|. + if (state2 == MediaClockDevice::kStateError) + return true; + + // All the other valid FSM transitions. + switch (state1) { + case MediaClockDevice::kStateUninitialized: + return state2 == MediaClockDevice::kStateIdle; + case MediaClockDevice::kStateIdle: + return state2 == MediaClockDevice::kStateRunning || + state2 == MediaClockDevice::kStateUninitialized; + case MediaClockDevice::kStateRunning: + return state2 == MediaClockDevice::kStateIdle; + case MediaClockDevice::kStateError: + return state2 == MediaClockDevice::kStateUninitialized; + default: + return false; + } +} + +} // namespace MediaClockDeviceDefault::MediaClockDeviceDefault() - : state_(kStateUninitialized), - media_time_(::media::kNoTimestamp()) { - DetachFromThread(); + : state_(kStateUninitialized), media_time_(::media::kNoTimestamp()) { + thread_checker_.DetachFromThread(); } MediaClockDeviceDefault::~MediaClockDeviceDefault() { } MediaClockDevice::State MediaClockDeviceDefault::GetState() const { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); return state_; } bool MediaClockDeviceDefault::SetState(State new_state) { - DCHECK(CalledOnValidThread()); - if (!MediaClockDevice::IsValidStateTransition(state_, new_state)) - return false; + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(IsValidStateTransition(state_, new_state)); if (new_state == state_) return true; @@ -47,15 +75,15 @@ bool MediaClockDeviceDefault::SetState(State new_state) { return true; } -bool MediaClockDeviceDefault::ResetTimeline(base::TimeDelta time) { - DCHECK(CalledOnValidThread()); +bool MediaClockDeviceDefault::ResetTimeline(int64_t time_microseconds) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, kStateIdle); - media_time_ = time; + media_time_ = base::TimeDelta::FromMicroseconds(time_microseconds); return true; } bool MediaClockDeviceDefault::SetRate(float rate) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (state_ == kStateRunning) { base::TimeTicks now = base::TimeTicks::Now(); media_time_ = media_time_ + (now - stc_) * rate_; @@ -66,18 +94,18 @@ bool MediaClockDeviceDefault::SetRate(float rate) { return true; } -base::TimeDelta MediaClockDeviceDefault::GetTime() { - DCHECK(CalledOnValidThread()); +int64_t MediaClockDeviceDefault::GetTimeMicroseconds() { + DCHECK(thread_checker_.CalledOnValidThread()); if (state_ != kStateRunning) - return media_time_; + return media_time_.InMicroseconds(); if (media_time_ == ::media::kNoTimestamp()) - return ::media::kNoTimestamp(); + return media_time_.InMicroseconds(); base::TimeTicks now = base::TimeTicks::Now(); base::TimeDelta interpolated_media_time = media_time_ + (now - stc_) * rate_; - return interpolated_media_time; + return interpolated_media_time.InMicroseconds(); } } // namespace media diff --git a/chromecast/media/cma/backend/media_clock_device_default.h b/chromecast/media/cma/backend/media_clock_device_default.h index 1ac4387..e895354 100644 --- a/chromecast/media/cma/backend/media_clock_device_default.h +++ b/chromecast/media/cma/backend/media_clock_device_default.h @@ -6,7 +6,9 @@ #define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_CLOCK_DEVICE_DEFAULT_H_ #include "base/macros.h" -#include "chromecast/media/cma/backend/media_clock_device.h" +#include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "chromecast/public/media/media_clock_device.h" namespace chromecast { namespace media { @@ -19,9 +21,9 @@ class MediaClockDeviceDefault : public MediaClockDevice { // MediaClockDevice implementation. State GetState() const override; bool SetState(State new_state) override; - bool ResetTimeline(base::TimeDelta time) override; + bool ResetTimeline(int64_t time_microseconds) override; bool SetRate(float rate) override; - base::TimeDelta GetTime() override; + int64_t GetTimeMicroseconds() override; private: State state_; @@ -32,6 +34,8 @@ class MediaClockDeviceDefault : public MediaClockDevice { float rate_; + base::ThreadChecker thread_checker_; + DISALLOW_COPY_AND_ASSIGN(MediaClockDeviceDefault); }; diff --git a/chromecast/media/cma/backend/media_component_device.cc b/chromecast/media/cma/backend/media_component_device.cc deleted file mode 100644 index 7331946..0000000 --- a/chromecast/media/cma/backend/media_component_device.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/media_component_device.h" - -#include "base/logging.h" - -namespace chromecast { -namespace media { - -MediaComponentDevice::Client::Client() { -} - -MediaComponentDevice::Client::~Client() { -} - -MediaComponentDevice::MediaComponentDevice() { -} - -MediaComponentDevice::~MediaComponentDevice() { -} - -// static -bool MediaComponentDevice::IsValidStateTransition(State state1, State state2) { - if (state2 == state1) - return true; - - // All states can transition to |kStateError|. - bool is_transition_valid = (state2 == kStateError); - - // All the other valid FSM transitions. - is_transition_valid = is_transition_valid || - (state1 == kStateUninitialized && (state2 == kStateIdle)) || - (state1 == kStateIdle && (state2 == kStateRunning || - state2 == kStatePaused || - state2 == kStateUninitialized)) || - (state1 == kStatePaused && (state2 == kStateIdle || - state2 == kStateRunning)) || - (state1 == kStateRunning && (state2 == kStateIdle || - state2 == kStatePaused)) || - (state1 == kStateError && (state2 == kStateUninitialized)); - - return is_transition_valid; -} - -// static -std::string MediaComponentDevice::StateToString(const State& state) { - switch (state) { - case kStateUninitialized: - return "Uninitialized"; - case kStateIdle: - return "Idle"; - case kStateRunning: - return "Running"; - case kStatePaused: - return "Paused"; - case kStateError: - return "Error"; - default: - NOTREACHED() << "Unknown MediaComponentDevice::State: " << state; - return ""; - } -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_component_device.h b/chromecast/media/cma/backend/media_component_device.h deleted file mode 100644 index fd62d8d..0000000 --- a/chromecast/media/cma/backend/media_component_device.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2014 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_COMPONENT_DEVICE_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_COMPONENT_DEVICE_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/threading/non_thread_safe.h" -#include "base/time/time.h" - -namespace chromecast { -namespace media { -class DecoderBufferBase; -class DecryptContext; - -// MediaComponentDevice - -// -// State machine: -// -------------- kRunning <--- -// | ^ | -// v | | -// kUninitialized <--> kIdle -------------- | -// ^ | | -// | v | -// -------------- kPaused <---- -// {any state} --> kError -// kError --> kUninitialized -// -// Notes: -// - Hardware resources are acquired when transitioning from the -// |kUninitialized| state to the |kIdle| state. -// - Buffers can be pushed only in the kRunning or kPaused states. -// - The end of stream is signaled through a special buffer. -// Once the end of stream buffer is fed, no other buffer -// can be fed until the FSM goes through the kIdle state again. -// - In both kPaused and kRunning states, frames can be fed. -// However, frames are possibly rendered only in the kRunning state. -// - In the kRunning state, frames are rendered according to the clock rate. -// - All the hardware resources must be released in the |kError| state. -// -class MediaComponentDevice - : NON_EXPORTED_BASE(public base::NonThreadSafe) { - public: - enum State { - kStateUninitialized, - kStateIdle, - kStateRunning, - kStatePaused, - kStateError, - }; - - enum FrameStatus { - kFrameSuccess, - kFrameFailed, - kFramePending, - }; - typedef base::Callback<void(FrameStatus)> FrameStatusCB; - - struct Client { - Client(); - ~Client(); - - // Invoked when playback reaches the end of stream. - base::Closure eos_cb; - }; - - // The statistics are computed since the media component left the idle state. - // For video, a sample is defined as a frame. - struct Statistics { - uint64 decoded_bytes; - uint64 decoded_samples; - uint64 dropped_samples; - }; - - // Returns whether or not transitioning from |state1| to |state2| is valid. - static bool IsValidStateTransition(State state1, State state2); - - // Returns string representation of state (for logging) - static std::string StateToString(const State& state); - - MediaComponentDevice(); - virtual ~MediaComponentDevice(); - - // Register |client| as the media event handler. - virtual void SetClient(const Client& client) = 0; - - // Changes the state and performs any necessary transitions. - // Returns true when successful. - virtual bool SetState(State new_state) = 0; - - // Returns the current state of the media component. - virtual State GetState() const = 0; - - // Sets the time where rendering should start. - // Return true when successful. - // Can only be invoked in state kStateIdle. - virtual bool SetStartPts(base::TimeDelta time) = 0; - - // Pushes a frame. - // |completion_cb| is only invoked if the returned value is |kFramePending|. - // In this specific case, no additional frame can be pushed before - // |completion_cb| is invoked. - // Note: |completion_cb| cannot be invoked with |kFramePending|. - // Note: pushing the pending frame should be aborted when the state goes back - // to kStateIdle. |completion_cb| is not invoked in that case. - virtual FrameStatus PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) = 0; - - // Returns the rendering time of the latest rendered sample. - // Can be invoked only in states kStateRunning or kStatePaused. - // Returns |kNoTimestamp()| if the playback time cannot be retrieved. - virtual base::TimeDelta GetRenderingTime() const = 0; - - // Returns the pipeline latency: i.e. the amount of data - // in the pipeline that have not been rendered yet. - // Returns |kNoTimestamp()| if the latency is not available. - virtual base::TimeDelta GetRenderingDelay() const = 0; - - // Returns the playback statistics. Statistics are computed since the media - // component left the idle state. - // Returns true when successful. - // Can only be invoked in state kStateRunning. - virtual bool GetStatistics(Statistics* stats) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(MediaComponentDevice); -}; - -} // namespace media -} // namespace chromecast - -#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_COMPONENT_DEVICE_H_ diff --git a/chromecast/media/cma/backend/media_component_device_default.cc b/chromecast/media/cma/backend/media_component_device_default.cc index 3ed5f01..4c367dd 100644 --- a/chromecast/media/cma/backend/media_component_device_default.cc +++ b/chromecast/media/cma/backend/media_component_device_default.cc @@ -8,7 +8,10 @@ #include "base/callback_helpers.h" #include "base/location.h" #include "base/thread_task_runner_handle.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" +#include "chromecast/public/media/cast_decoder_buffer.h" +#include "chromecast/public/media/decrypt_context.h" +#include "chromecast/public/media/media_pipeline_device_params.h" +#include "chromecast/public/task_runner.h" #include "media/base/buffers.h" namespace chromecast { @@ -19,6 +22,48 @@ namespace { // Maximum number of frames that can be buffered. const size_t kMaxFrameCount = 20; +// Wraps base::Closure in the chromecast/public TaskRunner interface. +class ClosureTask : public TaskRunner::Task { + public: + ClosureTask(const base::Closure& cb) : cb_(cb) {} + void Run() override { cb_.Run(); } + + private: + base::Closure cb_; +}; + +// Returns whether or not transitioning from |state1| to |state2| is valid. +inline static bool IsValidStateTransition(MediaComponentDevice::State state1, + MediaComponentDevice::State state2) { + if (state2 == state1) + return true; + + // All states can transition to |kStateError|. + if (state2 == MediaComponentDevice::kStateError) + return true; + + // All the other valid FSM transitions. + switch (state1) { + case MediaComponentDevice::kStateUninitialized: + return state2 == MediaComponentDevice::kStateIdle; + case MediaComponentDevice::kStateIdle: + return state2 == MediaComponentDevice::kStateRunning || + state2 == MediaComponentDevice::kStatePaused || + state2 == MediaComponentDevice::kStateUninitialized; + case MediaComponentDevice::kStatePaused: + return state2 == MediaComponentDevice::kStateIdle || + state2 == MediaComponentDevice::kStateRunning; + case MediaComponentDevice::kStateRunning: + return state2 == MediaComponentDevice::kStateIdle || + state2 == MediaComponentDevice::kStatePaused; + case MediaComponentDevice::kStateError: + return state2 == MediaComponentDevice::kStateUninitialized; + + default: + return false; + } +} + } // namespace MediaComponentDeviceDefault::DefaultDecoderBuffer::DefaultDecoderBuffer() @@ -29,8 +74,10 @@ MediaComponentDeviceDefault::DefaultDecoderBuffer::~DefaultDecoderBuffer() { } MediaComponentDeviceDefault::MediaComponentDeviceDefault( + const MediaPipelineDeviceParams& params, MediaClockDevice* media_clock_device) - : media_clock_device_(media_clock_device), + : task_runner_(params.task_runner), + media_clock_device_(media_clock_device), state_(kStateUninitialized), rendering_time_(::media::kNoTimestamp()), decoded_frame_count_(0), @@ -38,26 +85,25 @@ MediaComponentDeviceDefault::MediaComponentDeviceDefault( scheduled_rendering_task_(false), weak_factory_(this) { weak_this_ = weak_factory_.GetWeakPtr(); - DetachFromThread(); + thread_checker_.DetachFromThread(); } MediaComponentDeviceDefault::~MediaComponentDeviceDefault() { } -void MediaComponentDeviceDefault::SetClient(const Client& client) { - DCHECK(CalledOnValidThread()); - client_ = client; +void MediaComponentDeviceDefault::SetClient(Client* client) { + DCHECK(thread_checker_.CalledOnValidThread()); + client_.reset(client); } MediaComponentDevice::State MediaComponentDeviceDefault::GetState() const { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); return state_; } bool MediaComponentDeviceDefault::SetState(State new_state) { - DCHECK(CalledOnValidThread()); - if (!MediaComponentDevice::IsValidStateTransition(state_, new_state)) - return false; + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(IsValidStateTransition(state_, new_state)); state_ = new_state; if (state_ == kStateIdle) { @@ -67,17 +113,18 @@ bool MediaComponentDeviceDefault::SetState(State new_state) { decoded_frame_count_ = 0; decoded_byte_count_ = 0; frames_.clear(); - pending_buffer_ = scoped_refptr<DecoderBufferBase>(); - frame_pushed_cb_.Reset(); + pending_buffer_ = scoped_ptr<CastDecoderBuffer>(); + frame_pushed_cb_.reset(); return true; } if (state_ == kStateRunning) { if (!scheduled_rendering_task_) { scheduled_rendering_task_ = true; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_)); + task_runner_->PostTask( + new ClosureTask( + base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_)), + 0); } return true; } @@ -85,48 +132,49 @@ bool MediaComponentDeviceDefault::SetState(State new_state) { return true; } -bool MediaComponentDeviceDefault::SetStartPts(base::TimeDelta time) { - DCHECK(CalledOnValidThread()); +bool MediaComponentDeviceDefault::SetStartPts(int64_t time_microseconds) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, kStateIdle); - rendering_time_ = time; + rendering_time_ = base::TimeDelta::FromMicroseconds(time_microseconds); return true; } MediaComponentDevice::FrameStatus MediaComponentDeviceDefault::PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) { - DCHECK(CalledOnValidThread()); + DecryptContext* decrypt_context_in, + CastDecoderBuffer* buffer_in, + FrameStatusCB* completion_cb_in) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(state_ == kStatePaused || state_ == kStateRunning); DCHECK(!is_eos_); DCHECK(!pending_buffer_.get()); - DCHECK(buffer.get()); + DCHECK(buffer_in); + + scoped_ptr<DecryptContext> decrypt_context(decrypt_context_in); + scoped_ptr<FrameStatusCB> completion_cb(completion_cb_in); + scoped_ptr<CastDecoderBuffer> buffer(buffer_in); if (buffer->end_of_stream()) { is_eos_ = true; return kFrameSuccess; } if (frames_.size() > kMaxFrameCount) { - pending_buffer_ = buffer; - frame_pushed_cb_ = completion_cb; + pending_buffer_ = buffer.Pass(); + frame_pushed_cb_ = completion_cb.Pass(); return kFramePending; } DefaultDecoderBuffer fake_buffer; fake_buffer.size = buffer->data_size(); - fake_buffer.pts = buffer->timestamp(); + fake_buffer.pts = base::TimeDelta::FromMicroseconds(buffer->timestamp()); frames_.push_back(fake_buffer); return kFrameSuccess; } -base::TimeDelta MediaComponentDeviceDefault::GetRenderingTime() const { - return rendering_time_; -} - -base::TimeDelta MediaComponentDeviceDefault::GetRenderingDelay() const { +MediaComponentDeviceDefault::RenderingDelay +MediaComponentDeviceDefault::GetRenderingDelay() const { NOTIMPLEMENTED(); - return ::media::kNoTimestamp(); + return RenderingDelay(); } void MediaComponentDeviceDefault::RenderTask() { @@ -135,13 +183,14 @@ void MediaComponentDeviceDefault::RenderTask() { if (state_ != kStateRunning) return; - base::TimeDelta media_time = media_clock_device_->GetTime(); + base::TimeDelta media_time = base::TimeDelta::FromMicroseconds( + media_clock_device_->GetTimeMicroseconds()); if (media_time == ::media::kNoTimestamp()) { scheduled_rendering_task_ = true; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_), - base::TimeDelta::FromMilliseconds(50)); + task_runner_->PostTask( + new ClosureTask( + base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_)), + 50); return; } @@ -153,24 +202,27 @@ void MediaComponentDeviceDefault::RenderTask() { if (pending_buffer_.get()) { DefaultDecoderBuffer fake_buffer; fake_buffer.size = pending_buffer_->data_size(); - fake_buffer.pts = pending_buffer_->timestamp(); + fake_buffer.pts = + base::TimeDelta::FromMicroseconds(pending_buffer_->timestamp()); frames_.push_back(fake_buffer); - pending_buffer_ = scoped_refptr<DecoderBufferBase>(); - base::ResetAndReturn(&frame_pushed_cb_).Run(kFrameSuccess); + pending_buffer_ = scoped_ptr<CastDecoderBuffer>(); + frame_pushed_cb_->Run(kFrameSuccess); + frame_pushed_cb_.reset(); } } if (frames_.empty() && is_eos_) { - if (!client_.eos_cb.is_null()) - client_.eos_cb.Run(); + if (client_) { + client_->OnEndOfStream(); + } return; } scheduled_rendering_task_ = true; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_), - base::TimeDelta::FromMilliseconds(50)); + task_runner_->PostTask( + new ClosureTask( + base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_)), + 50); } bool MediaComponentDeviceDefault::GetStatistics(Statistics* stats) const { diff --git a/chromecast/media/cma/backend/media_component_device_default.h b/chromecast/media/cma/backend/media_component_device_default.h index 5aea387..d6dc7ea 100644 --- a/chromecast/media/cma/backend/media_component_device_default.h +++ b/chromecast/media/cma/backend/media_component_device_default.h @@ -9,28 +9,32 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_component_device.h" +#include "base/threading/thread_checker.h" + +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/media_component_device.h" namespace chromecast { +class TaskRunner; + namespace media { +struct MediaPipelineDeviceParams; class MediaComponentDeviceDefault : public MediaComponentDevice { public: - explicit MediaComponentDeviceDefault(MediaClockDevice* media_clock_device); + MediaComponentDeviceDefault(const MediaPipelineDeviceParams& params, + MediaClockDevice* media_clock_device); ~MediaComponentDeviceDefault() override; // MediaComponentDevice implementation. - void SetClient(const Client& client) override; + void SetClient(Client* client) override; State GetState() const override; bool SetState(State new_state) override; - bool SetStartPts(base::TimeDelta time) override; - FrameStatus PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) override; - base::TimeDelta GetRenderingTime() const override; - base::TimeDelta GetRenderingDelay() const override; + bool SetStartPts(int64_t time_microseconds) override; + FrameStatus PushFrame(DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) override; + RenderingDelay GetRenderingDelay() const override; bool GetStatistics(Statistics* stats) const override; private: @@ -47,8 +51,9 @@ class MediaComponentDeviceDefault : public MediaComponentDevice { void RenderTask(); + TaskRunner* task_runner_; MediaClockDevice* const media_clock_device_; - Client client_; + scoped_ptr<Client> client_; State state_; @@ -69,8 +74,10 @@ class MediaComponentDeviceDefault : public MediaComponentDevice { bool scheduled_rendering_task_; // Pending frame. - scoped_refptr<DecoderBufferBase> pending_buffer_; - FrameStatusCB frame_pushed_cb_; + scoped_ptr<CastDecoderBuffer> pending_buffer_; + scoped_ptr<FrameStatusCB> frame_pushed_cb_; + + base::ThreadChecker thread_checker_; base::WeakPtr<MediaComponentDeviceDefault> weak_this_; base::WeakPtrFactory<MediaComponentDeviceDefault> weak_factory_; diff --git a/chromecast/media/cma/backend/media_pipeline_backend_default.cc b/chromecast/media/cma/backend/media_pipeline_backend_default.cc new file mode 100644 index 0000000..498c5be --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_default.cc @@ -0,0 +1,39 @@ +// Copyright 2015 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 "chromecast/media/cma/backend/media_pipeline_backend_default.h" + +#include "chromecast/media/cma/backend/audio_pipeline_device_default.h" +#include "chromecast/media/cma/backend/media_clock_device_default.h" +#include "chromecast/media/cma/backend/video_pipeline_device_default.h" + +namespace chromecast { +namespace media { + +MediaPipelineBackendDefault::MediaPipelineBackendDefault( + const MediaPipelineDeviceParams& params) + : params_(params) {} + +MediaPipelineBackendDefault::~MediaPipelineBackendDefault() {} + +MediaClockDevice* MediaPipelineBackendDefault::GetClock() { + if (!clock_) + clock_.reset(new MediaClockDeviceDefault()); + return clock_.get(); +} + +AudioPipelineDevice* MediaPipelineBackendDefault::GetAudio() { + if (!audio_) + audio_.reset(new AudioPipelineDeviceDefault(params_, GetClock())); + return audio_.get(); +} + +VideoPipelineDevice* MediaPipelineBackendDefault::GetVideo() { + if (!video_) + video_.reset(new VideoPipelineDeviceDefault(params_, GetClock())); + return video_.get(); +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_backend_default.h b/chromecast/media/cma/backend/media_pipeline_backend_default.h new file mode 100644 index 0000000..7a9a602 --- /dev/null +++ b/chromecast/media/cma/backend/media_pipeline_backend_default.h @@ -0,0 +1,38 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ + +#include "base/memory/scoped_ptr.h" +#include "chromecast/public/media/media_pipeline_backend.h" +#include "chromecast/public/media/media_pipeline_device_params.h" + +namespace chromecast { +namespace media { + +// Factory that instantiates default (stub) media pipeline device elements. +class MediaPipelineBackendDefault : public MediaPipelineBackend { + public: + MediaPipelineBackendDefault(const MediaPipelineDeviceParams& params); + ~MediaPipelineBackendDefault() override; + + // MediaPipelineBackend implementation + MediaClockDevice* GetClock() override; + AudioPipelineDevice* GetAudio() override; + VideoPipelineDevice* GetVideo() override; + + private: + MediaPipelineDeviceParams params_; + scoped_ptr<MediaClockDevice> clock_; + scoped_ptr<AudioPipelineDevice> audio_; + scoped_ptr<VideoPipelineDevice> video_; + + DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendDefault); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_device.cc b/chromecast/media/cma/backend/media_pipeline_device.cc deleted file mode 100644 index ec2370b..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/media_pipeline_device.h" - -#include "chromecast/media/cma/backend/audio_pipeline_device_default.h" -#include "chromecast/media/cma/backend/media_clock_device_default.h" -#include "chromecast/media/cma/backend/media_pipeline_device_factory.h" -#include "chromecast/media/cma/backend/video_pipeline_device_default.h" - -namespace chromecast { -namespace media { - -MediaPipelineDevice::MediaPipelineDevice( - scoped_ptr<MediaPipelineDeviceFactory> factory) - : media_clock_device_(factory->CreateMediaClockDevice()), - audio_pipeline_device_(factory->CreateAudioPipelineDevice()), - video_pipeline_device_(factory->CreateVideoPipelineDevice()) { -} - -MediaPipelineDevice::MediaPipelineDevice( - scoped_ptr<MediaClockDevice> media_clock_device, - scoped_ptr<AudioPipelineDevice> audio_pipeline_device, - scoped_ptr<VideoPipelineDevice> video_pipeline_device) - : media_clock_device_(media_clock_device.Pass()), - audio_pipeline_device_(audio_pipeline_device.Pass()), - video_pipeline_device_(video_pipeline_device.Pass()) { -} - -MediaPipelineDevice::~MediaPipelineDevice() { -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_device.h b/chromecast/media/cma/backend/media_pipeline_device.h deleted file mode 100644 index e010176..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_H_ - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" - -namespace chromecast { -namespace media { -class AudioPipelineDevice; -class MediaClockDevice; -class MediaPipelineDeviceFactory; -class MediaPipelineDeviceParams; -class VideoPipelineDevice; - -// MediaPipelineDevice is the owner of the underlying audio/video/clock -// devices. It ensures that the clock outlives the audio and video devices, so -// it is safe for them to reference the clock with a raw pointer. -class MediaPipelineDevice { - public: - // Constructs object using clock, audio, video created by given factory. - explicit MediaPipelineDevice(scoped_ptr<MediaPipelineDeviceFactory> factory); - - // Constructs explicitly from separate clock, audio, video elements - MediaPipelineDevice(scoped_ptr<MediaClockDevice> media_clock_device, - scoped_ptr<AudioPipelineDevice> audio_pipeline_device, - scoped_ptr<VideoPipelineDevice> video_pipeline_device); - ~MediaPipelineDevice(); - - AudioPipelineDevice* GetAudioPipelineDevice() const { - return audio_pipeline_device_.get(); - } - VideoPipelineDevice* GetVideoPipelineDevice() const { - return video_pipeline_device_.get(); - } - MediaClockDevice* GetMediaClockDevice() const { - return media_clock_device_.get(); - } - - private: - scoped_ptr<MediaClockDevice> media_clock_device_; - scoped_ptr<AudioPipelineDevice> audio_pipeline_device_; - scoped_ptr<VideoPipelineDevice> video_pipeline_device_; - - DISALLOW_COPY_AND_ASSIGN(MediaPipelineDevice); -}; - -// Factory method to create a MediaPipelineDevice. -typedef base::Callback<scoped_ptr<MediaPipelineDevice>( - const MediaPipelineDeviceParams&)> CreatePipelineDeviceCB; - -} // namespace media -} // namespace chromecast - -#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_device_factory.h b/chromecast/media/cma/backend/media_pipeline_device_factory.h deleted file mode 100644 index 28da119..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device_factory.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_H_ - -#include "base/memory/scoped_ptr.h" - -namespace chromecast { -namespace media { - -class AudioPipelineDevice; -class MediaClockDevice; -class MediaPipelineDeviceParams; -class VideoPipelineDevice; - -// Factory for creating platform-specific clock, audio and video devices. -// A new factory will be instantiated for each media player instance. -class MediaPipelineDeviceFactory { - public: - MediaPipelineDeviceFactory() {} - virtual ~MediaPipelineDeviceFactory() {} - - virtual scoped_ptr<MediaClockDevice> CreateMediaClockDevice() = 0; - virtual scoped_ptr<AudioPipelineDevice> CreateAudioPipelineDevice() = 0; - virtual scoped_ptr<VideoPipelineDevice> CreateVideoPipelineDevice() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(MediaPipelineDeviceFactory); -}; - -// Creates the platform-specific pipeline device factory. -// TODO(halliwell): move into libcast_media -scoped_ptr<MediaPipelineDeviceFactory> GetMediaPipelineDeviceFactory( - const MediaPipelineDeviceParams& params); - -} // namespace media -} // namespace chromecast - -#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_device_factory_default.cc b/chromecast/media/cma/backend/media_pipeline_device_factory_default.cc deleted file mode 100644 index 78663fe..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device_factory_default.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 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 "chromecast/media/cma/backend/media_pipeline_device_factory_default.h" - -#include "chromecast/media/cma/backend/audio_pipeline_device_default.h" -#include "chromecast/media/cma/backend/media_clock_device_default.h" -#include "chromecast/media/cma/backend/video_pipeline_device_default.h" - -namespace chromecast { -namespace media { - -MediaPipelineDeviceFactoryDefault::MediaPipelineDeviceFactoryDefault() - : clock_(nullptr) { -} - -scoped_ptr<MediaClockDevice> -MediaPipelineDeviceFactoryDefault::CreateMediaClockDevice() { - DCHECK(!clock_); - clock_ = new MediaClockDeviceDefault(); - return make_scoped_ptr(clock_); -} - -scoped_ptr<AudioPipelineDevice> -MediaPipelineDeviceFactoryDefault::CreateAudioPipelineDevice() { - DCHECK(clock_); - return make_scoped_ptr(new AudioPipelineDeviceDefault(clock_)); -} - -scoped_ptr<VideoPipelineDevice> -MediaPipelineDeviceFactoryDefault::CreateVideoPipelineDevice() { - DCHECK(clock_); - return make_scoped_ptr(new VideoPipelineDeviceDefault(clock_)); -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_device_factory_default.h b/chromecast/media/cma/backend/media_pipeline_device_factory_default.h deleted file mode 100644 index 1927847..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device_factory_default.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 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 CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ - -#include "chromecast/media/cma/backend/media_pipeline_device_factory.h" - -namespace chromecast { -namespace media { - -// Factory that instantiates default (stub) media pipeline device elements. -class MediaPipelineDeviceFactoryDefault : public MediaPipelineDeviceFactory { - public: - MediaPipelineDeviceFactoryDefault(); - ~MediaPipelineDeviceFactoryDefault() override {} - - // MediaPipelineDeviceFactory implementation - scoped_ptr<MediaClockDevice> CreateMediaClockDevice() override; - scoped_ptr<AudioPipelineDevice> CreateAudioPipelineDevice() override; - scoped_ptr<VideoPipelineDevice> CreateVideoPipelineDevice() override; - - private: - // Owned by MediaPipelineDevice, but we hold raw pointer in order to wire up - // to audio and video devices. MediaPipelineDevice guarantees the clock will - // outlive the audio and video devices. - MediaClockDevice* clock_; - - DISALLOW_COPY_AND_ASSIGN(MediaPipelineDeviceFactoryDefault); -}; - -} // namespace media -} // namespace chromecast - -#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_DEFAULT_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_device_factory_simple.cc b/chromecast/media/cma/backend/media_pipeline_device_factory_simple.cc deleted file mode 100644 index 92efca1..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device_factory_simple.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 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 "chromecast/media/cma/backend/media_pipeline_device_factory_default.h" - -namespace chromecast { -namespace media { - -// Creates default (no-op) media pipeline device elements. -scoped_ptr<MediaPipelineDeviceFactory> GetMediaPipelineDeviceFactory( - const MediaPipelineDeviceParams& params) { - return make_scoped_ptr(new MediaPipelineDeviceFactoryDefault()); -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/media_pipeline_device_params.cc b/chromecast/media/cma/backend/media_pipeline_device_params.cc deleted file mode 100644 index 1f4e2eb..0000000 --- a/chromecast/media/cma/backend/media_pipeline_device_params.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/media_pipeline_device_params.h" - -namespace chromecast { -namespace media { - -MediaPipelineDeviceParams::MediaPipelineDeviceParams() - : sync_type(kModeSyncPts) { -} - -MediaPipelineDeviceParams::~MediaPipelineDeviceParams() { -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/video_pipeline_device.cc b/chromecast/media/cma/backend/video_pipeline_device.cc deleted file mode 100644 index d00c2cd..0000000 --- a/chromecast/media/cma/backend/video_pipeline_device.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/backend/video_pipeline_device.h" - -namespace chromecast { -namespace media { - -VideoPipelineDevice::VideoClient::VideoClient() { -} - -VideoPipelineDevice::VideoClient::~VideoClient() { -} - -VideoPipelineDevice::VideoPipelineDevice() { -} - -VideoPipelineDevice::~VideoPipelineDevice() { -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/backend/video_pipeline_device_default.cc b/chromecast/media/cma/backend/video_pipeline_device_default.cc index 90970cb..dd30517 100644 --- a/chromecast/media/cma/backend/video_pipeline_device_default.cc +++ b/chromecast/media/cma/backend/video_pipeline_device_default.cc @@ -10,15 +10,16 @@ namespace chromecast { namespace media { VideoPipelineDeviceDefault::VideoPipelineDeviceDefault( + const MediaPipelineDeviceParams& params, MediaClockDevice* media_clock_device) - : pipeline_(new MediaComponentDeviceDefault(media_clock_device)) { - DetachFromThread(); + : pipeline_(new MediaComponentDeviceDefault(params, media_clock_device)) { + thread_checker_.DetachFromThread(); } VideoPipelineDeviceDefault::~VideoPipelineDeviceDefault() { } -void VideoPipelineDeviceDefault::SetClient(const Client& client) { +void VideoPipelineDeviceDefault::SetClient(Client* client) { pipeline_->SetClient(client); } @@ -40,30 +41,28 @@ bool VideoPipelineDeviceDefault::SetState(State new_state) { return true; } -bool VideoPipelineDeviceDefault::SetStartPts(base::TimeDelta time) { - return pipeline_->SetStartPts(time); +bool VideoPipelineDeviceDefault::SetStartPts(int64_t time_microseconds) { + return pipeline_->SetStartPts(time_microseconds); } MediaComponentDevice::FrameStatus VideoPipelineDeviceDefault::PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) { + DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) { return pipeline_->PushFrame(decrypt_context, buffer, completion_cb); } -base::TimeDelta VideoPipelineDeviceDefault::GetRenderingTime() const { - return pipeline_->GetRenderingTime(); -} - -base::TimeDelta VideoPipelineDeviceDefault::GetRenderingDelay() const { +VideoPipelineDeviceDefault::RenderingDelay +VideoPipelineDeviceDefault::GetRenderingDelay() const { return pipeline_->GetRenderingDelay(); } -void VideoPipelineDeviceDefault::SetVideoClient(const VideoClient& client) { +void VideoPipelineDeviceDefault::SetVideoClient(VideoClient* client) { + delete client; } bool VideoPipelineDeviceDefault::SetConfig(const VideoConfig& config) { - DCHECK(CalledOnValidThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (!IsValidConfig(config)) return false; config_ = config; diff --git a/chromecast/media/cma/backend/video_pipeline_device_default.h b/chromecast/media/cma/backend/video_pipeline_device_default.h index 49a4a03..8dd61d8 100644 --- a/chromecast/media/cma/backend/video_pipeline_device_default.h +++ b/chromecast/media/cma/backend/video_pipeline_device_default.h @@ -8,32 +8,34 @@ #include <vector> #include "base/macros.h" -#include "chromecast/media/cma/backend/video_pipeline_device.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" #include "chromecast/public/media/decoder_config.h" +#include "chromecast/public/media/video_pipeline_device.h" namespace chromecast { namespace media { class MediaClockDevice; class MediaComponentDeviceDefault; +struct MediaPipelineDeviceParams; class VideoPipelineDeviceDefault : public VideoPipelineDevice { public: - explicit VideoPipelineDeviceDefault(MediaClockDevice* media_clock_device); + VideoPipelineDeviceDefault(const MediaPipelineDeviceParams& params, + MediaClockDevice* media_clock_device); ~VideoPipelineDeviceDefault() override; // VideoPipelineDevice implementation. - void SetClient(const Client& client) override; + void SetClient(Client* client) override; State GetState() const override; bool SetState(State new_state) override; - bool SetStartPts(base::TimeDelta time) override; - FrameStatus PushFrame( - const scoped_refptr<DecryptContext>& decrypt_context, - const scoped_refptr<DecoderBufferBase>& buffer, - const FrameStatusCB& completion_cb) override; - base::TimeDelta GetRenderingTime() const override; - base::TimeDelta GetRenderingDelay() const override; - void SetVideoClient(const VideoClient& client) override; + bool SetStartPts(int64_t time_microseconds) override; + FrameStatus PushFrame(DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) override; + RenderingDelay GetRenderingDelay() const override; + void SetVideoClient(VideoClient* client) override; bool SetConfig(const VideoConfig& config) override; bool GetStatistics(Statistics* stats) const override; @@ -43,6 +45,7 @@ class VideoPipelineDeviceDefault : public VideoPipelineDevice { VideoConfig config_; std::vector<uint8_t> config_extra_data_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(VideoPipelineDeviceDefault); }; @@ -50,4 +53,3 @@ class VideoPipelineDeviceDefault : public VideoPipelineDevice { } // namespace chromecast #endif // CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PIPELINE_DEVICE_DEFAULT_H_ - diff --git a/chromecast/media/cma/base/BUILD.gn b/chromecast/media/cma/base/BUILD.gn index 49dbbde..fc53156 100644 --- a/chromecast/media/cma/base/BUILD.gn +++ b/chromecast/media/cma/base/BUILD.gn @@ -14,12 +14,15 @@ source_set("base") { "buffering_frame_provider.h", "buffering_state.cc", "buffering_state.h", + "cast_decoder_buffer_impl.cc", + "cast_decoder_buffer_impl.h", + "cast_decrypt_config_impl.cc", + "cast_decrypt_config_impl.h", "cma_logging.h", "coded_frame_provider.cc", "coded_frame_provider.h", "decoder_buffer_adapter.cc", "decoder_buffer_adapter.h", - "decoder_buffer_base.cc", "decoder_buffer_base.h", "decoder_config_adapter.cc", "decoder_config_adapter.h", diff --git a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc index 8e02736..95c6dc3 100644 --- a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc +++ b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc @@ -12,10 +12,10 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "chromecast/media/cma/base/buffering_frame_provider.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/test/frame_generator_for_test.h" #include "chromecast/media/cma/test/mock_frame_consumer.h" #include "chromecast/media/cma/test/mock_frame_provider.h" +#include "chromecast/public/media/cast_decoder_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" #include "media/base/video_decoder_config.h" diff --git a/chromecast/media/cma/base/cast_decoder_buffer_impl.cc b/chromecast/media/cma/base/cast_decoder_buffer_impl.cc new file mode 100644 index 0000000..e29b620 --- /dev/null +++ b/chromecast/media/cma/base/cast_decoder_buffer_impl.cc @@ -0,0 +1,45 @@ +// Copyright 2015 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 "chromecast/media/cma/base/cast_decoder_buffer_impl.h" + +namespace chromecast { +namespace media { + +CastDecoderBufferImpl::CastDecoderBufferImpl( + const scoped_refptr<DecoderBufferBase>& buffer) + : buffer_(buffer) {} + +CastDecoderBufferImpl::~CastDecoderBufferImpl() {} + +StreamId CastDecoderBufferImpl::stream_id() const { + return buffer_->stream_id(); +} + +int64_t CastDecoderBufferImpl::timestamp() const { + return buffer_->timestamp().InMicroseconds(); +} + +const uint8* CastDecoderBufferImpl::data() const { + return buffer_->data(); +} + +size_t CastDecoderBufferImpl::data_size() const { + return buffer_->data_size(); +} + +const CastDecryptConfig* CastDecoderBufferImpl::decrypt_config() const { + return buffer_->decrypt_config(); +} + +bool CastDecoderBufferImpl::end_of_stream() const { + return buffer_->end_of_stream(); +} + +const scoped_refptr<DecoderBufferBase>& CastDecoderBufferImpl::buffer() const { + return buffer_; +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/base/cast_decoder_buffer_impl.h b/chromecast/media/cma/base/cast_decoder_buffer_impl.h new file mode 100644 index 0000000..444ccf4 --- /dev/null +++ b/chromecast/media/cma/base/cast_decoder_buffer_impl.h @@ -0,0 +1,53 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_IMPL_H_ + +#include "chromecast/public/media/cast_decoder_buffer.h" +#include "chromecast/media/cma/base/decoder_buffer_base.h" + +namespace chromecast { +namespace media { + +// Implementation of public DecoderBuffer interface. +// Holds a (refcounted) DecoderBufferBase. This way, ownership throughout +// the pipeline is refcounted, but without exposing RefCountedBase in +// the public API. +class CastDecoderBufferImpl : public CastDecoderBuffer { + public: + CastDecoderBufferImpl(const scoped_refptr<DecoderBufferBase>& buffer); + ~CastDecoderBufferImpl() override; + + // Returns the stream id of this decoder buffer belonging to. it's optional + // and default value is kPrimary. + StreamId stream_id() const override; + + // Returns the PTS of the frame in microseconds. + int64_t timestamp() const override; + + // Gets the frame data. + const uint8* data() const override; + + // Returns the size of the frame in bytes. + size_t data_size() const override; + + // Returns the decrypt configuration. + // Returns NULL if the buffer has no decrypt info. + const CastDecryptConfig* decrypt_config() const override; + + // Indicate if this is a special frame that indicates the end of the stream. + // If true, functions to access the frame content cannot be called. + bool end_of_stream() const override; + + const scoped_refptr<DecoderBufferBase>& buffer() const; + + private: + scoped_refptr<DecoderBufferBase> buffer_; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_BASE_H_ diff --git a/chromecast/media/cma/base/cast_decrypt_config_impl.cc b/chromecast/media/cma/base/cast_decrypt_config_impl.cc new file mode 100644 index 0000000..51ef53e --- /dev/null +++ b/chromecast/media/cma/base/cast_decrypt_config_impl.cc @@ -0,0 +1,42 @@ +// Copyright 2015 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 "chromecast/media/cma/base/cast_decrypt_config_impl.h" + +#include "media/base/decrypt_config.h" + +namespace chromecast { +namespace media { + +CastDecryptConfigImpl::CastDecryptConfigImpl( + const ::media::DecryptConfig& config) + : key_id_(config.key_id()), iv_(config.iv()) { + for (const auto& sample : config.subsamples()) { + subsamples_.push_back( + SubsampleEntry(sample.clear_bytes, sample.cypher_bytes)); + } +} + +CastDecryptConfigImpl::CastDecryptConfigImpl( + const std::string& key_id, + const std::string& iv, + const std::vector<SubsampleEntry>& subsamples) + : key_id_(key_id), iv_(iv), subsamples_(subsamples) {} + +CastDecryptConfigImpl::~CastDecryptConfigImpl() {} + +const std::string& CastDecryptConfigImpl::key_id() const { + return key_id_; +} + +const std::string& CastDecryptConfigImpl::iv() const { + return iv_; +} + +const std::vector<SubsampleEntry>& CastDecryptConfigImpl::subsamples() const { + return subsamples_; +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/base/cast_decrypt_config_impl.h b/chromecast/media/cma/base/cast_decrypt_config_impl.h new file mode 100644 index 0000000..b78494b --- /dev/null +++ b/chromecast/media/cma/base/cast_decrypt_config_impl.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_BASE_CAST_DECRYPT_CONFIG_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_BASE_CAST_DECRYPT_CONFIG_IMPL_H_ + +#include "chromecast/public/media/cast_decrypt_config.h" + +namespace media { +class DecryptConfig; +} + +namespace chromecast { +namespace media { + +// Contains all information that a decryptor needs to decrypt a media sample. +class CastDecryptConfigImpl : public CastDecryptConfig { + public: + CastDecryptConfigImpl(const ::media::DecryptConfig& config); + CastDecryptConfigImpl(const std::string& key_id, + const std::string& iv, + const std::vector<SubsampleEntry>& subsamples); + ~CastDecryptConfigImpl() override; + + const std::string& key_id() const override; + const std::string& iv() const override; + const std::vector<SubsampleEntry>& subsamples() const override; + + private: + std::string key_id_; + std::string iv_; + std::vector<SubsampleEntry> subsamples_; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BASE_CAST_DECRYPT_CONFIG_IMPL_H_ diff --git a/chromecast/media/cma/base/decoder_buffer_adapter.cc b/chromecast/media/cma/base/decoder_buffer_adapter.cc index ed8a779..10ffddc 100644 --- a/chromecast/media/cma/base/decoder_buffer_adapter.cc +++ b/chromecast/media/cma/base/decoder_buffer_adapter.cc @@ -4,6 +4,8 @@ #include "chromecast/media/cma/base/decoder_buffer_adapter.h" +#include "chromecast/media/cma/base/cast_decrypt_config_impl.h" +#include "chromecast/public/media/cast_decrypt_config.h" #include "media/base/decoder_buffer.h" namespace chromecast { @@ -31,7 +33,7 @@ base::TimeDelta DecoderBufferAdapter::timestamp() const { return buffer_->timestamp(); } -void DecoderBufferAdapter::set_timestamp(const base::TimeDelta& timestamp) { +void DecoderBufferAdapter::set_timestamp(base::TimeDelta timestamp) { buffer_->set_timestamp(timestamp); } @@ -47,8 +49,13 @@ size_t DecoderBufferAdapter::data_size() const { return buffer_->data_size(); } -const ::media::DecryptConfig* DecoderBufferAdapter::decrypt_config() const { - return buffer_->decrypt_config(); +const CastDecryptConfig* DecoderBufferAdapter::decrypt_config() const { + if (buffer_->decrypt_config() && !decrypt_config_) { + const ::media::DecryptConfig* config = buffer_->decrypt_config(); + decrypt_config_.reset(new CastDecryptConfigImpl(*config)); + } + + return decrypt_config_.get(); } bool DecoderBufferAdapter::end_of_stream() const { diff --git a/chromecast/media/cma/base/decoder_buffer_adapter.h b/chromecast/media/cma/base/decoder_buffer_adapter.h index 7c48ec8..5118694 100644 --- a/chromecast/media/cma/base/decoder_buffer_adapter.h +++ b/chromecast/media/cma/base/decoder_buffer_adapter.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" namespace media { @@ -30,11 +31,11 @@ class DecoderBufferAdapter : public DecoderBufferBase { // DecoderBufferBase implementation. StreamId stream_id() const override; base::TimeDelta timestamp() const override; - void set_timestamp(const base::TimeDelta& timestamp) override; + void set_timestamp(base::TimeDelta timestamp) override; const uint8* data() const override; uint8* writable_data() const override; size_t data_size() const override; - const ::media::DecryptConfig* decrypt_config() const override; + const CastDecryptConfig* decrypt_config() const override; bool end_of_stream() const override; private: @@ -42,6 +43,7 @@ class DecoderBufferAdapter : public DecoderBufferBase { StreamId stream_id_; scoped_refptr<::media::DecoderBuffer> const buffer_; + mutable scoped_ptr<CastDecryptConfig> decrypt_config_; DISALLOW_COPY_AND_ASSIGN(DecoderBufferAdapter); }; diff --git a/chromecast/media/cma/base/decoder_buffer_base.cc b/chromecast/media/cma/base/decoder_buffer_base.cc deleted file mode 100644 index 40c0a7d..0000000 --- a/chromecast/media/cma/base/decoder_buffer_base.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 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 "chromecast/media/cma/base/decoder_buffer_base.h" - -namespace chromecast { -namespace media { - -DecoderBufferBase::DecoderBufferBase() { -} - -DecoderBufferBase::~DecoderBufferBase() { -} - -} // namespace media -} // namespace chromecast diff --git a/chromecast/media/cma/base/decoder_buffer_base.h b/chromecast/media/cma/base/decoder_buffer_base.h index 1fca1b2..08cf94b 100644 --- a/chromecast/media/cma/base/decoder_buffer_base.h +++ b/chromecast/media/cma/base/decoder_buffer_base.h @@ -11,12 +11,9 @@ #include "base/time/time.h" #include "chromecast/public/media/stream_id.h" -namespace media { -class DecryptConfig; -} - namespace chromecast { namespace media { +class CastDecryptConfig; // DecoderBufferBase exposes only the properties of an audio/video buffer. // The way a DecoderBufferBase is created and organized in memory @@ -24,7 +21,7 @@ namespace media { class DecoderBufferBase : public base::RefCountedThreadSafe<DecoderBufferBase> { public: - DecoderBufferBase(); + DecoderBufferBase() {} // Returns the stream id of this decoder buffer belonging to. it's optional // and default value is kPrimary. @@ -34,7 +31,7 @@ class DecoderBufferBase virtual base::TimeDelta timestamp() const = 0; // Sets the PTS of the frame. - virtual void set_timestamp(const base::TimeDelta& timestamp) = 0; + virtual void set_timestamp(base::TimeDelta timestamp) = 0; // Gets the frame data. virtual const uint8* data() const = 0; @@ -45,7 +42,7 @@ class DecoderBufferBase // Returns the decrypt configuration. // Returns NULL if the buffer has no decrypt info. - virtual const ::media::DecryptConfig* decrypt_config() const = 0; + virtual const CastDecryptConfig* decrypt_config() const = 0; // Indicate if this is a special frame that indicates the end of the stream. // If true, functions to access the frame content cannot be called. @@ -53,7 +50,7 @@ class DecoderBufferBase protected: friend class base::RefCountedThreadSafe<DecoderBufferBase>; - virtual ~DecoderBufferBase(); + virtual ~DecoderBufferBase() {} private: DISALLOW_COPY_AND_ASSIGN(DecoderBufferBase); diff --git a/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc index f7d668a..990f0cb 100644 --- a/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc +++ b/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc @@ -16,6 +16,7 @@ #include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/filters/demuxer_stream_adapter.h" #include "chromecast/media/cma/test/demuxer_stream_for_test.h" +#include "chromecast/public/media/cast_decoder_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" @@ -112,7 +113,7 @@ void DemuxerStreamAdapterTest::OnNewFrame( ASSERT_TRUE(buffer.get() != NULL); ASSERT_EQ(buffer->timestamp(), - frame_received_count_ * base::TimeDelta::FromMilliseconds(40)); + base::TimeDelta::FromMilliseconds(40 * frame_received_count_)); frame_received_count_++; if (frame_received_count_ >= total_frames_) { diff --git a/chromecast/media/cma/filters/multi_demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/filters/multi_demuxer_stream_adapter_unittest.cc index 6aaf213..ed5c519 100644 --- a/chromecast/media/cma/filters/multi_demuxer_stream_adapter_unittest.cc +++ b/chromecast/media/cma/filters/multi_demuxer_stream_adapter_unittest.cc @@ -14,6 +14,7 @@ #include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/filters/demuxer_stream_adapter.h" #include "chromecast/media/cma/test/demuxer_stream_for_test.h" +#include "chromecast/public/media/cast_decoder_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" diff --git a/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc b/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc index 9aff31d..b3e4970 100644 --- a/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc +++ b/chromecast/media/cma/ipc_streamer/av_streamer_unittest.cc @@ -12,7 +12,6 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/ipc/media_memory_chunk.h" #include "chromecast/media/cma/ipc/media_message_fifo.h" #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" @@ -20,6 +19,7 @@ #include "chromecast/media/cma/test/frame_generator_for_test.h" #include "chromecast/media/cma/test/mock_frame_consumer.h" #include "chromecast/media/cma/test/mock_frame_provider.h" +#include "chromecast/public/media/cast_decoder_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" #include "media/base/video_decoder_config.h" diff --git a/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc b/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc index ab3a258..1bc97a5 100644 --- a/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc +++ b/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc @@ -5,10 +5,12 @@ #include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h" #include "base/logging.h" +#include "chromecast/media/cma/base/cast_decrypt_config_impl.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/ipc/media_message.h" #include "chromecast/media/cma/ipc/media_message_type.h" #include "chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h" +#include "chromecast/public/media/cast_decrypt_config.h" #include "media/base/decrypt_config.h" namespace chromecast { @@ -26,11 +28,11 @@ class DecoderBufferFromMsg : public DecoderBufferBase { // DecoderBufferBase implementation. StreamId stream_id() const override; base::TimeDelta timestamp() const override; - void set_timestamp(const base::TimeDelta& timestamp) override; + void set_timestamp(base::TimeDelta timestamp) override; const uint8* data() const override; uint8* writable_data() const override; size_t data_size() const override; - const ::media::DecryptConfig* decrypt_config() const override; + const CastDecryptConfig* decrypt_config() const override; bool end_of_stream() const override; private: @@ -46,7 +48,7 @@ class DecoderBufferFromMsg : public DecoderBufferBase { base::TimeDelta pts_; // CENC parameters. - scoped_ptr< ::media::DecryptConfig> decrypt_config_; + scoped_ptr<CastDecryptConfig> decrypt_config_; // Size of the frame. size_t data_size_; @@ -81,7 +83,7 @@ void DecoderBufferFromMsg::Initialize() { int64 pts_internal = 0; CHECK(msg_->ReadPod(&pts_internal)); - pts_ = base::TimeDelta::FromInternalValue(pts_internal); + pts_ = base::TimeDelta::FromMicroseconds(pts_internal); bool has_decrypt_config = false; CHECK(msg_->ReadPod(&has_decrypt_config)); @@ -115,7 +117,7 @@ base::TimeDelta DecoderBufferFromMsg::timestamp() const { return pts_; } -void DecoderBufferFromMsg::set_timestamp(const base::TimeDelta& timestamp) { +void DecoderBufferFromMsg::set_timestamp(base::TimeDelta timestamp) { pts_ = timestamp; } @@ -133,7 +135,7 @@ size_t DecoderBufferFromMsg::data_size() const { return data_size_; } -const ::media::DecryptConfig* DecoderBufferFromMsg::decrypt_config() const { +const CastDecryptConfig* DecoderBufferFromMsg::decrypt_config() const { return decrypt_config_.get(); } @@ -152,7 +154,7 @@ void DecoderBufferBaseMarshaller::Write( return; CHECK(msg->WritePod(buffer->stream_id())); - CHECK(msg->WritePod(buffer->timestamp().ToInternalValue())); + CHECK(msg->WritePod(buffer->timestamp().InMicroseconds())); bool has_decrypt_config = (buffer->decrypt_config() != NULL && @@ -164,12 +166,11 @@ void DecoderBufferBaseMarshaller::Write( // Map this case to a single fully-encrypted "subsample" for more consistent // backend handling. if (buffer->decrypt_config()->subsamples().empty()) { - std::vector< ::media::SubsampleEntry> encrypted_subsample_list(1); + std::vector<SubsampleEntry> encrypted_subsample_list(1); encrypted_subsample_list[0].clear_bytes = 0; encrypted_subsample_list[0].cypher_bytes = buffer->data_size(); - ::media::DecryptConfig full_sample_config( - buffer->decrypt_config()->key_id(), - buffer->decrypt_config()->iv(), + CastDecryptConfigImpl full_sample_config( + buffer->decrypt_config()->key_id(), buffer->decrypt_config()->iv(), encrypted_subsample_list); DecryptConfigMarshaller::Write(full_sample_config, msg); } else { diff --git a/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc b/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc index 72eacd6..bc373f6 100644 --- a/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc +++ b/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.cc @@ -5,8 +5,9 @@ #include "chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h" #include "base/logging.h" +#include "chromecast/media/cma/base/cast_decrypt_config_impl.h" #include "chromecast/media/cma/ipc/media_message.h" -#include "media/base/decrypt_config.h" +#include "chromecast/public/media/cast_decrypt_config.h" namespace chromecast { namespace media { @@ -18,8 +19,8 @@ const size_t kMaxSubsampleCount = 1024; } // static -void DecryptConfigMarshaller::Write( - const ::media::DecryptConfig& config, MediaMessage* msg) { +void DecryptConfigMarshaller::Write(const CastDecryptConfig& config, + MediaMessage* msg) { CHECK_GT(config.key_id().size(), 0u); CHECK_GT(config.iv().size(), 0u); CHECK_GT(config.subsamples().size(), 0u); @@ -36,8 +37,7 @@ void DecryptConfigMarshaller::Write( } // static -scoped_ptr< ::media::DecryptConfig> DecryptConfigMarshaller::Read( - MediaMessage* msg) { +scoped_ptr<CastDecryptConfig> DecryptConfigMarshaller::Read(MediaMessage* msg) { size_t key_id_size = 0; CHECK(msg->ReadPod(&key_id_size)); CHECK_GT(key_id_size, 0u); @@ -56,7 +56,7 @@ scoped_ptr< ::media::DecryptConfig> DecryptConfigMarshaller::Read( CHECK(msg->ReadPod(&subsample_count)); CHECK_GT(subsample_count, 0u); CHECK_LT(subsample_count, kMaxSubsampleCount); - std::vector< ::media::SubsampleEntry> subsamples(subsample_count); + std::vector<SubsampleEntry> subsamples(subsample_count); for (size_t k = 0; k < subsample_count; k++) { subsamples[k].clear_bytes = 0; subsamples[k].cypher_bytes = 0; @@ -64,11 +64,9 @@ scoped_ptr< ::media::DecryptConfig> DecryptConfigMarshaller::Read( CHECK(msg->ReadPod(&subsamples[k].cypher_bytes)); } - return scoped_ptr< ::media::DecryptConfig>( - new ::media::DecryptConfig( - std::string(key_id.get(), key_id_size), - std::string(iv.get(), iv_size), - subsamples)); + return scoped_ptr<CastDecryptConfig>( + new CastDecryptConfigImpl(std::string(key_id.get(), key_id_size), + std::string(iv.get(), iv_size), subsamples)); } } // namespace media diff --git a/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h b/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h index b600ba4..7d32d1b 100644 --- a/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h +++ b/chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h @@ -13,16 +13,16 @@ class DecryptConfig; namespace chromecast { namespace media { +class CastDecryptConfig; class MediaMessage; class DecryptConfigMarshaller { public: // Writes the serialized structure of |config| into |msg|. - static void Write( - const ::media::DecryptConfig& config, MediaMessage* msg); + static void Write(const CastDecryptConfig& config, MediaMessage* msg); // Returns a DecryptConfig from its serialized structure. - static scoped_ptr< ::media::DecryptConfig> Read(MediaMessage* msg); + static scoped_ptr<CastDecryptConfig> Read(MediaMessage* msg); }; } // namespace media diff --git a/chromecast/media/cma/pipeline/BUILD.gn b/chromecast/media/cma/pipeline/BUILD.gn index f82a8d9..caa8e49 100644 --- a/chromecast/media/cma/pipeline/BUILD.gn +++ b/chromecast/media/cma/pipeline/BUILD.gn @@ -14,7 +14,11 @@ source_set("pipeline") { "av_pipeline_impl.h", "decrypt_util.cc", "decrypt_util.h", + "frame_status_cb_impl.cc", + "frame_status_cb_impl.h", "load_type.h", + "media_component_device_client_impl.cc", + "media_component_device_client_impl.h", "media_pipeline.h", "media_pipeline_client.cc", "media_pipeline_client.h", @@ -24,6 +28,8 @@ source_set("pipeline") { "video_pipeline.h", "video_pipeline_client.cc", "video_pipeline_client.h", + "video_pipeline_device_client_impl.cc", + "video_pipeline_device_client_impl.h", "video_pipeline_impl.cc", "video_pipeline_impl.h", ] diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc index 006ea82..c7bdfda 100644 --- a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc @@ -5,12 +5,12 @@ #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" #include "base/bind.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" #include "chromecast/media/cma/base/buffering_defs.h" #include "chromecast/media/cma/base/cma_logging.h" #include "chromecast/media/cma/base/coded_frame_provider.h" #include "chromecast/media/cma/base/decoder_config_adapter.h" #include "chromecast/media/cma/pipeline/av_pipeline_impl.h" +#include "chromecast/public/media/audio_pipeline_device.h" #include "chromecast/public/media/decoder_config.h" #include "media/base/audio_decoder_config.h" diff --git a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc index 81b5e38..309aca0 100644 --- a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc +++ b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc @@ -12,10 +12,8 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/time/time.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device_factory_default.h" +#include "chromecast/base/task_runner_impl.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_default.h" #include "chromecast/media/cma/base/buffering_controller.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" @@ -25,6 +23,8 @@ #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" #include "chromecast/media/cma/test/frame_generator_for_test.h" #include "chromecast/media/cma/test/mock_frame_provider.h" +#include "chromecast/public/media/audio_pipeline_device.h" +#include "chromecast/public/media/media_clock_device.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffers.h" #include "media/base/decoder_buffer.h" @@ -51,20 +51,23 @@ class AudioVideoPipelineImplTest : public testing::Test { void OnEos(); base::Closure task_after_eos_cb_; + scoped_ptr<base::MessageLoop> message_loop_; private: + scoped_ptr<TaskRunnerImpl> task_runner_; scoped_ptr<MediaPipelineImpl> media_pipeline_; DISALLOW_COPY_AND_ASSIGN(AudioVideoPipelineImplTest); }; AudioVideoPipelineImplTest::AudioVideoPipelineImplTest() - : media_pipeline_(new MediaPipelineImpl()) { - scoped_ptr<MediaPipelineDeviceFactory> factory = - make_scoped_ptr(new MediaPipelineDeviceFactoryDefault()); - scoped_ptr<MediaPipelineDevice> media_pipeline_device = - make_scoped_ptr(new MediaPipelineDevice(factory.Pass())); - media_pipeline_->Initialize(kLoadTypeURL, media_pipeline_device.Pass()); + : message_loop_(new base::MessageLoop()), + task_runner_(new TaskRunnerImpl()), + media_pipeline_(new MediaPipelineImpl()) { + MediaPipelineDeviceParams params(task_runner_.get()); + scoped_ptr<MediaPipelineBackend> backend = + make_scoped_ptr(new MediaPipelineBackendDefault(params)); + media_pipeline_->Initialize(kLoadTypeURL, backend.Pass()); media_pipeline_->SetPlaybackRate(1.0); } @@ -181,14 +184,11 @@ TEST_F(AudioVideoPipelineImplTest, AudioFullCycleInitToStop) { &AudioVideoPipelineImplTest::Flush, base::Unretained(this), base::Closure(), ::media::PIPELINE_OK); - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); - message_loop->PostTask( - FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Initialize, - base::Unretained(this), - base::Closure(), - ::media::PIPELINE_OK, is_audio)); - message_loop->Run(); + message_loop_->PostTask(FROM_HERE, + base::Bind(&AudioVideoPipelineImplTest::Initialize, + base::Unretained(this), base::Closure(), + ::media::PIPELINE_OK, is_audio)); + message_loop_->Run(); }; TEST_F(AudioVideoPipelineImplTest, VideoFullCycleInitToStop) { @@ -197,14 +197,11 @@ TEST_F(AudioVideoPipelineImplTest, VideoFullCycleInitToStop) { &AudioVideoPipelineImplTest::Flush, base::Unretained(this), base::Closure(), ::media::PIPELINE_OK); - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); - message_loop->PostTask( - FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Initialize, - base::Unretained(this), - base::Closure(), - ::media::PIPELINE_OK, is_audio)); - message_loop->Run(); + message_loop_->PostTask(FROM_HERE, + base::Bind(&AudioVideoPipelineImplTest::Initialize, + base::Unretained(this), base::Closure(), + ::media::PIPELINE_OK, is_audio)); + message_loop_->Run(); }; } // namespace media diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.cc b/chromecast/media/cma/pipeline/av_pipeline_impl.cc index ab0a2a7..7046b01 100644 --- a/chromecast/media/cma/pipeline/av_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/av_pipeline_impl.cc @@ -9,16 +9,20 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/thread_task_runner_handle.h" -#include "chromecast/media/base/decrypt_context.h" +#include "chromecast/media/base/decrypt_context_impl.h" #include "chromecast/media/cdm/browser_cdm_cast.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_component_device.h" #include "chromecast/media/cma/base/buffering_frame_provider.h" #include "chromecast/media/cma/base/buffering_state.h" +#include "chromecast/media/cma/base/cast_decoder_buffer_impl.h" #include "chromecast/media/cma/base/cma_logging.h" #include "chromecast/media/cma/base/coded_frame_provider.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" #include "chromecast/media/cma/pipeline/decrypt_util.h" +#include "chromecast/media/cma/pipeline/frame_status_cb_impl.h" +#include "chromecast/media/cma/pipeline/media_component_device_client_impl.h" +#include "chromecast/public/media/cast_decrypt_config.h" +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/media_component_device.h" #include "media/base/audio_decoder_config.h" #include "media/base/bind_to_current_loop.h" #include "media/base/buffers.h" @@ -33,9 +37,8 @@ const int kNoCallbackId = -1; } // namespace -AvPipelineImpl::AvPipelineImpl( - MediaComponentDevice* media_component_device, - const UpdateConfigCB& update_config_cb) +AvPipelineImpl::AvPipelineImpl(MediaComponentDevice* media_component_device, + const UpdateConfigCB& update_config_cb) : update_config_cb_(update_config_cb), media_component_device_(media_component_device), state_(kUninitialized), @@ -56,7 +59,7 @@ AvPipelineImpl::AvPipelineImpl( AvPipelineImpl::~AvPipelineImpl() { DCHECK(thread_checker_.CalledOnValidThread()); - media_component_device_->SetClient(MediaComponentDevice::Client()); + media_component_device_->SetClient(nullptr); if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) media_keys_->UnregisterPlayer(media_keys_callback_id_); @@ -93,9 +96,8 @@ bool AvPipelineImpl::Initialize() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, kUninitialized); - MediaComponentDevice::Client client; - client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_); - media_component_device_->SetClient(client); + media_component_device_->SetClient(new MediaComponentDeviceClientImpl( + base::Bind(&AvPipelineImpl::OnEos, weak_this_))); if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle)) return false; @@ -110,7 +112,7 @@ bool AvPipelineImpl::StartPlayingFrom( // Media time where rendering should start // and switch to a state where the audio device accepts incoming buffers. - if (!media_component_device_->SetStartPts(time) || + if (!media_component_device_->SetStartPts(time.InMicroseconds()) || !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { return false; } @@ -252,7 +254,7 @@ void AvPipelineImpl::ProcessPendingBuffer() { enable_feeding_ = false; } - scoped_refptr<DecryptContext> decrypt_context; + scoped_ptr<DecryptContextImpl> decrypt_context; if (!pending_buffer_->end_of_stream() && pending_buffer_->decrypt_config()) { // Verify that CDM has the key ID. @@ -277,7 +279,7 @@ void AvPipelineImpl::ProcessPendingBuffer() { crypto::SymmetricKey* key = decrypt_context->GetKey(); if (key != NULL) { pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key); - decrypt_context = scoped_refptr<DecryptContext>(); + decrypt_context.reset(); } } @@ -288,9 +290,9 @@ void AvPipelineImpl::ProcessPendingBuffer() { } MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( - decrypt_context, - pending_buffer_, - base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_)); + decrypt_context.release(), new CastDecoderBufferImpl(pending_buffer_), + new FrameStatusCBImpl( + base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); pending_buffer_ = scoped_refptr<DecoderBufferBase>(); pending_push_ = (status == MediaComponentDevice::kFramePending); @@ -335,9 +337,8 @@ void AvPipelineImpl::OnFrameBuffered( if (!buffering_state_.get()) return; - if (!buffer->end_of_stream() && - (buffered_time_ == ::media::kNoTimestamp() || - buffered_time_ < buffer->timestamp())) { + if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() || + buffered_time_ < buffer->timestamp())) { buffered_time_ = buffer->timestamp(); } @@ -360,7 +361,7 @@ void AvPipelineImpl::UpdatePlayableFrames() { if (non_playable_frame->end_of_stream()) { buffering_state_->NotifyEos(); } else { - const ::media::DecryptConfig* decrypt_config = + const CastDecryptConfig* decrypt_config = non_playable_frame->decrypt_config(); if (decrypt_config && !(media_keys_ && diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.h b/chromecast/media/cma/pipeline/av_pipeline_impl.h index 70395fc9..2aa9d51 100644 --- a/chromecast/media/cma/pipeline/av_pipeline_impl.h +++ b/chromecast/media/cma/pipeline/av_pipeline_impl.h @@ -12,8 +12,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" -#include "chromecast/media/cma/backend/media_component_device.h" #include "chromecast/media/cma/pipeline/av_pipeline_client.h" +#include "chromecast/public/media/media_component_device.h" #include "chromecast/public/media/stream_id.h" namespace media { diff --git a/chromecast/media/cma/pipeline/decrypt_util.cc b/chromecast/media/cma/pipeline/decrypt_util.cc index abd4661..7f57cec 100644 --- a/chromecast/media/cma/pipeline/decrypt_util.cc +++ b/chromecast/media/cma/pipeline/decrypt_util.cc @@ -9,8 +9,8 @@ #include "base/logging.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" +#include "chromecast/public/media/cast_decrypt_config.h" #include "crypto/symmetric_key.h" -#include "media/base/decrypt_config.h" namespace chromecast { namespace media { @@ -24,11 +24,11 @@ class DecoderBufferClear : public DecoderBufferBase { // DecoderBufferBase implementation. StreamId stream_id() const override; base::TimeDelta timestamp() const override; - void set_timestamp(const base::TimeDelta& timestamp) override; + void set_timestamp(base::TimeDelta timestamp) override; const uint8* data() const override; uint8* writable_data() const override; size_t data_size() const override; - const ::media::DecryptConfig* decrypt_config() const override; + const CastDecryptConfig* decrypt_config() const override; bool end_of_stream() const override; private: @@ -55,7 +55,7 @@ base::TimeDelta DecoderBufferClear::timestamp() const { return buffer_->timestamp(); } -void DecoderBufferClear::set_timestamp(const base::TimeDelta& timestamp) { +void DecoderBufferClear::set_timestamp(base::TimeDelta timestamp) { buffer_->set_timestamp(timestamp); } @@ -71,7 +71,7 @@ size_t DecoderBufferClear::data_size() const { return buffer_->data_size(); } -const ::media::DecryptConfig* DecoderBufferClear::decrypt_config() const { +const CastDecryptConfig* DecoderBufferClear::decrypt_config() const { // Buffer is clear so no decryption info. return NULL; } @@ -88,7 +88,7 @@ scoped_refptr<DecoderBufferBase> DecryptDecoderBuffer( if (buffer->end_of_stream()) return buffer; - const ::media::DecryptConfig* decrypt_config = buffer->decrypt_config(); + const CastDecryptConfig* decrypt_config = buffer->decrypt_config(); if (!decrypt_config || decrypt_config->iv().size() == 0) return buffer; @@ -117,8 +117,7 @@ scoped_refptr<DecoderBufferBase> DecryptDecoderBuffer( uint8 ecount_buf[AES_BLOCK_SIZE]; // Perform the decryption. - const std::vector< ::media::SubsampleEntry>& subsamples = - decrypt_config->subsamples(); + const std::vector<SubsampleEntry>& subsamples = decrypt_config->subsamples(); uint8* data = buffer->writable_data(); uint32 offset = 0; for (size_t k = 0; k < subsamples.size(); k++) { diff --git a/chromecast/media/cma/pipeline/frame_status_cb_impl.cc b/chromecast/media/cma/pipeline/frame_status_cb_impl.cc new file mode 100644 index 0000000..06769f7 --- /dev/null +++ b/chromecast/media/cma/pipeline/frame_status_cb_impl.cc @@ -0,0 +1,30 @@ +// Copyright 2015 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 "chromecast/media/cma/pipeline/frame_status_cb_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace chromecast { +namespace media { + +FrameStatusCBImpl::FrameStatusCBImpl(const CallbackType& cb) + : cb_(cb), task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + +FrameStatusCBImpl::~FrameStatusCBImpl() {} + +void FrameStatusCBImpl::Run(MediaComponentDevice::FrameStatus status) { + if (task_runner_->BelongsToCurrentThread()) { + if (!cb_.is_null()) + cb_.Run(status); + } else { + task_runner_->PostTask(FROM_HERE, base::Bind(cb_, status)); + } +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/pipeline/frame_status_cb_impl.h b/chromecast/media/cma/pipeline/frame_status_cb_impl.h new file mode 100644 index 0000000..9cd3de7 --- /dev/null +++ b/chromecast/media/cma/pipeline/frame_status_cb_impl.h @@ -0,0 +1,38 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_PIPELINE_FRAME_STATUS_CB_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_PIPELINE_FRAME_STATUS_CB_IMPL_H_ + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "chromecast/public/media/media_component_device.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace chromecast { +namespace media { + +// Helper for implementing MediaComponentDevice::FrameStatusCB with +// a base::Callback. +class FrameStatusCBImpl : public MediaComponentDevice::FrameStatusCB { + public: + typedef base::Callback<void(MediaComponentDevice::FrameStatus)> CallbackType; + + FrameStatusCBImpl(const CallbackType& cb); + ~FrameStatusCBImpl() override; + + void Run(MediaComponentDevice::FrameStatus status) override; + + private: + CallbackType cb_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_PIPELINE_FRAME_STATUS_CB_IMPL_H_ diff --git a/chromecast/media/cma/pipeline/media_component_device_client_impl.cc b/chromecast/media/cma/pipeline/media_component_device_client_impl.cc new file mode 100644 index 0000000..e81ec0a --- /dev/null +++ b/chromecast/media/cma/pipeline/media_component_device_client_impl.cc @@ -0,0 +1,31 @@ +// Copyright 2015 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 "chromecast/media/cma/pipeline/media_component_device_client_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace chromecast { +namespace media { + +MediaComponentDeviceClientImpl::MediaComponentDeviceClientImpl( + const base::Closure& eos_cb) + : eos_cb_(eos_cb), task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + +MediaComponentDeviceClientImpl::~MediaComponentDeviceClientImpl() {} + +void MediaComponentDeviceClientImpl::OnEndOfStream() { + if (task_runner_->BelongsToCurrentThread()) { + if (!eos_cb_.is_null()) + eos_cb_.Run(); + } else { + task_runner_->PostTask(FROM_HERE, eos_cb_); + } +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/pipeline/media_component_device_client_impl.h b/chromecast/media/cma/pipeline/media_component_device_client_impl.h new file mode 100644 index 0000000..8f47d30 --- /dev/null +++ b/chromecast/media/cma/pipeline/media_component_device_client_impl.h @@ -0,0 +1,37 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_COMPONENT_DEVICE_CLIENT_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_COMPONENT_DEVICE_CLIENT_IMPL_H_ + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "chromecast/public/media/media_component_device.h" +#include "chromecast/public/media/video_pipeline_device.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace chromecast { +namespace media { + +// Helper for implementing MediaComponentDevice::Client with +// a base::Callback. +class MediaComponentDeviceClientImpl : public MediaComponentDevice::Client { + public: + MediaComponentDeviceClientImpl(const base::Closure& eos_cb); + ~MediaComponentDeviceClientImpl() override; + + void OnEndOfStream() override; + + private: + base::Closure eos_cb_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_PIPELINE_MEDIA_COMPONENT_DEVICE_CLIENT_IMPL_H_ diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromecast/media/cma/pipeline/media_pipeline_impl.cc index fe5a2ebd..c9d0e28 100644 --- a/chromecast/media/cma/pipeline/media_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/media_pipeline_impl.cc @@ -13,14 +13,14 @@ #include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "chromecast/media/cdm/browser_cdm_cast.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" #include "chromecast/media/cma/base/buffering_controller.h" #include "chromecast/media/cma/base/buffering_state.h" #include "chromecast/media/cma/base/cma_logging.h" #include "chromecast/media/cma/base/coded_frame_provider.h" #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/media_pipeline_backend.h" #include "media/base/buffers.h" namespace chromecast { @@ -70,11 +70,11 @@ MediaPipelineImpl::~MediaPipelineImpl() { void MediaPipelineImpl::Initialize( LoadType load_type, - scoped_ptr<MediaPipelineDevice> media_pipeline_device) { + scoped_ptr<MediaPipelineBackend> media_pipeline_backend) { CMALOG(kLogControl) << __FUNCTION__; DCHECK(thread_checker_.CalledOnValidThread()); - media_pipeline_device_.reset(media_pipeline_device.release()); - clock_device_ = media_pipeline_device_->GetMediaClockDevice(); + media_pipeline_backend_.reset(media_pipeline_backend.release()); + clock_device_ = media_pipeline_backend_->GetClock(); if (load_type == kLoadTypeURL || load_type == kLoadTypeMediaSource) { base::TimeDelta low_threshold(kLowBufferThresholdURL); @@ -90,11 +90,11 @@ void MediaPipelineImpl::Initialize( base::Bind(&MediaPipelineImpl::OnBufferingNotification, weak_this_))); } - audio_pipeline_.reset(new AudioPipelineImpl( - media_pipeline_device_->GetAudioPipelineDevice())); + audio_pipeline_.reset( + new AudioPipelineImpl(media_pipeline_backend_->GetAudio())); - video_pipeline_.reset(new VideoPipelineImpl( - media_pipeline_device_->GetVideoPipelineDevice())); + video_pipeline_.reset( + new VideoPipelineImpl(media_pipeline_backend_->GetVideo())); } void MediaPipelineImpl::SetClient(const MediaPipelineClient& client) { @@ -166,7 +166,7 @@ void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { // Reset the start of the timeline. DCHECK_EQ(clock_device_->GetState(), MediaClockDevice::kStateIdle); - clock_device_->ResetTimeline(time); + clock_device_->ResetTimeline(time.InMicroseconds()); // Start the clock. If the playback rate is 0, then the clock is started // but does not increase. @@ -210,6 +210,8 @@ void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(has_audio_ || has_video_); DCHECK(!pending_flush_callbacks_); + DCHECK(clock_device_->GetState() == MediaClockDevice::kStateUninitialized || + clock_device_->GetState() == MediaClockDevice::kStateRunning); // No need to update media time anymore. enable_time_update_ = false; @@ -272,7 +274,7 @@ void MediaPipelineImpl::SetPlaybackRate(double rate) { DCHECK(thread_checker_.CalledOnValidThread()); target_playback_rate_ = rate; if (!buffering_controller_ || !buffering_controller_->IsBuffering()) - media_pipeline_device_->GetMediaClockDevice()->SetRate(rate); + media_pipeline_backend_->GetClock()->SetRate(rate); } AudioPipelineImpl* MediaPipelineImpl::GetAudioPipelineImpl() const { @@ -301,17 +303,16 @@ void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) { client_.buffering_state_cb.Run(buffering_state); } - if (media_pipeline_device_->GetMediaClockDevice()->GetState() == + if (media_pipeline_backend_->GetClock()->GetState() == MediaClockDevice::kStateUninitialized) { return; } if (is_buffering) { // Do not consume data in a rebuffering phase. - media_pipeline_device_->GetMediaClockDevice()->SetRate(0.0); + media_pipeline_backend_->GetClock()->SetRate(0.0); } else { - media_pipeline_device_->GetMediaClockDevice()->SetRate( - target_playback_rate_); + media_pipeline_backend_->GetClock()->SetRate(target_playback_rate_); } } @@ -327,7 +328,8 @@ void MediaPipelineImpl::UpdateMediaTime() { statistics_rolling_counter_ = (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod; - base::TimeDelta media_time(clock_device_->GetTime()); + base::TimeDelta media_time = + base::TimeDelta::FromMicroseconds(clock_device_->GetTimeMicroseconds()); if (media_time == ::media::kNoTimestamp()) { pending_time_update_task_ = true; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.h b/chromecast/media/cma/pipeline/media_pipeline_impl.h index 71a5384..e2dba4f 100644 --- a/chromecast/media/cma/pipeline/media_pipeline_impl.h +++ b/chromecast/media/cma/pipeline/media_pipeline_impl.h @@ -22,7 +22,7 @@ class AudioPipelineImpl; class BrowserCdmCast; class BufferingController; class MediaClockDevice; -class MediaPipelineDevice; +class MediaPipelineBackend; class VideoPipelineImpl; class MediaPipelineImpl : public MediaPipeline { @@ -33,7 +33,7 @@ class MediaPipelineImpl : public MediaPipeline { // Initialize the media pipeline: the pipeline is configured based on // |load_type|. void Initialize(LoadType load_type, - scoped_ptr<MediaPipelineDevice> media_pipeline_device); + scoped_ptr<MediaPipelineBackend> media_pipeline_backend); // MediaPipeline implementation. void SetClient(const MediaPipelineClient& client) override; @@ -76,7 +76,7 @@ class MediaPipelineImpl : public MediaPipeline { scoped_ptr<BufferingController> buffering_controller_; // Interface with the underlying hardware media pipeline. - scoped_ptr<MediaPipelineDevice> media_pipeline_device_; + scoped_ptr<MediaPipelineBackend> media_pipeline_backend_; MediaClockDevice* clock_device_; bool has_audio_; diff --git a/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.cc new file mode 100644 index 0000000..a604be3 --- /dev/null +++ b/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.cc @@ -0,0 +1,33 @@ +// Copyright 2015 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 "chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "chromecast/public/graphics_types.h" + +namespace chromecast { +namespace media { + +VideoPipelineDeviceClientImpl::VideoPipelineDeviceClientImpl( + const SizeChangeCB& size_change_cb) + : size_change_cb_(size_change_cb), + task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + +VideoPipelineDeviceClientImpl::~VideoPipelineDeviceClientImpl() {} + +void VideoPipelineDeviceClientImpl::OnNaturalSizeChanged(const Size& size) { + if (task_runner_->BelongsToCurrentThread()) { + if (!size_change_cb_.is_null()) + size_change_cb_.Run(size); + } else { + task_runner_->PostTask(FROM_HERE, base::Bind(size_change_cb_, size)); + } +} + +} // namespace media +} // namespace chromecast diff --git a/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h b/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h new file mode 100644 index 0000000..e39fdc9 --- /dev/null +++ b/chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_DEVICE_CLIENT_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_DEVICE_CLIENT_IMPL_H_ + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "chromecast/public/media/media_component_device.h" +#include "chromecast/public/media/video_pipeline_device.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace chromecast { +namespace media { + +// Helper for implementing VideoPipelineDevice::VideoClient with +// a base::Callback. +class VideoPipelineDeviceClientImpl : public VideoPipelineDevice::VideoClient { + public: + typedef base::Callback<void(const Size&)> SizeChangeCB; + + VideoPipelineDeviceClientImpl(const SizeChangeCB& size_change_cb); + ~VideoPipelineDeviceClientImpl() override; + + void OnNaturalSizeChanged(const Size& size) override; + + private: + SizeChangeCB size_change_cb_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_PIPELINE_VIDEO_PIPELINE_DEVICE_CLIENT_IMPL_H_ diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc index 5f79d55..89d82cf 100644 --- a/chromecast/media/cma/pipeline/video_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc @@ -5,13 +5,15 @@ #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" #include "base/bind.h" -#include "chromecast/media/cma/backend/video_pipeline_device.h" #include "chromecast/media/cma/base/buffering_defs.h" #include "chromecast/media/cma/base/cma_logging.h" #include "chromecast/media/cma/base/coded_frame_provider.h" #include "chromecast/media/cma/base/decoder_config_adapter.h" #include "chromecast/media/cma/pipeline/av_pipeline_impl.h" +#include "chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h" +#include "chromecast/public/graphics_types.h" #include "chromecast/public/media/decoder_config.h" +#include "chromecast/public/media/video_pipeline_device.h" #include "media/base/video_decoder_config.h" namespace chromecast { @@ -109,10 +111,8 @@ void VideoPipelineImpl::Initialize( CMALOG(kLogControl) << __FUNCTION__ << " " << config.AsHumanReadableString(); } - VideoPipelineDevice::VideoClient client; - client.natural_size_changed_cb = - base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_); - video_device_->SetVideoClient(client); + video_device_->SetVideoClient(new VideoPipelineDeviceClientImpl( + base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_))); if (frame_provider) SetCodedFrameProvider(frame_provider.Pass()); @@ -159,12 +159,14 @@ void VideoPipelineImpl::OnUpdateConfig( } } -void VideoPipelineImpl::OnNaturalSizeChanged(const gfx::Size& size) { +void VideoPipelineImpl::OnNaturalSizeChanged(const Size& size) { if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying) return; - if (!video_client_.natural_size_changed_cb.is_null()) - video_client_.natural_size_changed_cb.Run(size); + if (!video_client_.natural_size_changed_cb.is_null()) { + video_client_.natural_size_changed_cb.Run( + gfx::Size(size.width, size.height)); + } } void VideoPipelineImpl::UpdateStatistics() { diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.h b/chromecast/media/cma/pipeline/video_pipeline_impl.h index 6f8e583..e488c26 100644 --- a/chromecast/media/cma/pipeline/video_pipeline_impl.h +++ b/chromecast/media/cma/pipeline/video_pipeline_impl.h @@ -14,10 +14,7 @@ #include "chromecast/media/cma/pipeline/video_pipeline.h" #include "chromecast/media/cma/pipeline/video_pipeline_client.h" #include "chromecast/public/media/stream_id.h" - -namespace gfx { -class Size; -} +#include "chromecast/public/media/video_pipeline_device.h" namespace media { class AudioDecoderConfig; @@ -25,6 +22,7 @@ class VideoDecoderConfig; } namespace chromecast { +struct Size; namespace media { class AvPipelineImpl; class BrowserCdmCast; @@ -61,11 +59,14 @@ class VideoPipelineImpl : public VideoPipeline { void SetClient(const VideoPipelineClient& client) override; private: + class DeviceClientImpl; + friend class DeviceClientImpl; + void OnFlushDone(const ::media::PipelineStatusCB& status_cb); void OnUpdateConfig(StreamId id, const ::media::AudioDecoderConfig& audio_config, const ::media::VideoDecoderConfig& video_config); - void OnNaturalSizeChanged(const gfx::Size& size); + void OnNaturalSizeChanged(const Size& size); VideoPipelineDevice* video_device_; diff --git a/chromecast/media/cma/test/cma_end_to_end_test.cc b/chromecast/media/cma/test/cma_end_to_end_test.cc index 9a8e4cd..70483e6 100644 --- a/chromecast/media/cma/test/cma_end_to_end_test.cc +++ b/chromecast/media/cma/test/cma_end_to_end_test.cc @@ -8,8 +8,8 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/time/time.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device_factory_default.h" +#include "chromecast/base/task_runner_impl.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_default.h" #include "chromecast/media/cma/base/buffering_defs.h" #include "chromecast/media/cma/filters/cma_renderer.h" #include "chromecast/media/cma/pipeline/media_pipeline_impl.h" @@ -39,8 +39,10 @@ class CmaEndToEndTest : public testing::Test { message_loop_.task_runner())); scoped_ptr<MediaPipelineImpl> media_pipeline(new MediaPipelineImpl()); - scoped_ptr<MediaPipelineDeviceFactory> factory = - make_scoped_ptr(new MediaPipelineDeviceFactoryDefault()); + task_runner_.reset(new TaskRunnerImpl()); + MediaPipelineDeviceParams params(task_runner_.get()); + scoped_ptr<MediaPipelineBackend> backend = + make_scoped_ptr(new MediaPipelineBackendDefault(params)); gles2_.reset(new gpu::gles2::GLES2InterfaceStub()); mock_gpu_factories_ = new ::media::MockGpuVideoAcceleratorFactories(); @@ -48,9 +50,7 @@ class CmaEndToEndTest : public testing::Test { EXPECT_CALL(*mock_gpu_factories_.get(), GetGLES2Interface()) .WillRepeatedly(testing::Return(gles2_.get())); - media_pipeline->Initialize( - kLoadTypeMediaSource, - make_scoped_ptr(new MediaPipelineDevice(factory.Pass()))); + media_pipeline->Initialize(kLoadTypeMediaSource, backend.Pass()); renderer_.reset(new CmaRenderer(media_pipeline.Pass(), null_sink_.get(), mock_gpu_factories_)); @@ -61,6 +61,7 @@ class CmaEndToEndTest : public testing::Test { protected: base::MessageLoop message_loop_; + scoped_ptr<TaskRunnerImpl> task_runner_; scoped_ptr<::media::FakeDemuxerStreamProvider> demuxer_stream_provider_; scoped_ptr<CmaRenderer> renderer_; scoped_refptr<::media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; diff --git a/chromecast/media/cma/test/media_component_device_feeder_for_test.cc b/chromecast/media/cma/test/media_component_device_feeder_for_test.cc index 84cc3da..9ca1800 100644 --- a/chromecast/media/cma/test/media_component_device_feeder_for_test.cc +++ b/chromecast/media/cma/test/media_component_device_feeder_for_test.cc @@ -16,14 +16,16 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/time/time.h" -#include "chromecast/media/base/decrypt_context.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/video_pipeline_device.h" +#include "chromecast/media/cma/base/cast_decoder_buffer_impl.h" #include "chromecast/media/cma/base/decoder_buffer_adapter.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" +#include "chromecast/media/cma/pipeline/frame_status_cb_impl.h" +#include "chromecast/media/cma/pipeline/media_component_device_client_impl.h" #include "chromecast/media/cma/test/frame_segmenter_for_test.h" +#include "chromecast/public/media/audio_pipeline_device.h" +#include "chromecast/public/media/cast_decoder_buffer.h" +#include "chromecast/public/media/decrypt_context.h" +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/video_pipeline_device.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffers.h" #include "media/base/decoder_buffer.h" @@ -50,16 +52,14 @@ void MediaComponentDeviceFeederForTest::Initialize( const base::Closure& eos_cb) { eos_cb_ = eos_cb; - MediaComponentDevice::Client client; - client.eos_cb = - base::Bind(&MediaComponentDeviceFeederForTest::OnEos, - base::Unretained(this)); - media_component_device_->SetClient(client); + media_component_device_->SetClient( + new MediaComponentDeviceClientImpl(base::Bind( + &MediaComponentDeviceFeederForTest::OnEos, base::Unretained(this)))); bool success = media_component_device_->SetState(MediaComponentDevice::kStateIdle); ASSERT_TRUE(success); - success = media_component_device_->SetStartPts(base::TimeDelta()); + success = media_component_device_->SetStartPts(0); ASSERT_TRUE(success); success = media_component_device_->SetState(MediaComponentDevice::kStatePaused); @@ -78,12 +78,12 @@ void MediaComponentDeviceFeederForTest::Feed() { DCHECK(!frames_.empty()); scoped_refptr<DecoderBufferBase> buffer = frames_.front(); - MediaComponentDevice::FrameStatus status = - media_component_device_->PushFrame( - scoped_refptr<DecryptContext>(), - buffer, + MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( + nullptr, // decrypt_context + new CastDecoderBufferImpl(buffer), + new FrameStatusCBImpl( base::Bind(&MediaComponentDeviceFeederForTest::OnFramePushed, - base::Unretained(this))); + base::Unretained(this)))); EXPECT_NE(status, MediaComponentDevice::kFrameFailed); frames_.pop_front(); diff --git a/chromecast/media/cma/test/media_component_device_feeder_for_test.h b/chromecast/media/cma/test/media_component_device_feeder_for_test.h index 1397b52..cd28eb4 100644 --- a/chromecast/media/cma/test/media_component_device_feeder_for_test.h +++ b/chromecast/media/cma/test/media_component_device_feeder_for_test.h @@ -9,17 +9,18 @@ #include <vector> #include "base/basictypes.h" +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" -#include "chromecast/media/cma/backend/audio_pipeline_device.h" -#include "chromecast/media/cma/backend/media_clock_device.h" -#include "chromecast/media/cma/backend/media_pipeline_device.h" -#include "chromecast/media/cma/backend/video_pipeline_device.h" -#include "chromecast/media/cma/base/decoder_buffer_base.h" +#include "chromecast/public/media/audio_pipeline_device.h" +#include "chromecast/public/media/cast_decoder_buffer.h" +#include "chromecast/public/media/media_clock_device.h" +#include "chromecast/public/media/video_pipeline_device.h" namespace chromecast { namespace media { +class DecoderBufferBase; typedef std::list<scoped_refptr<DecoderBufferBase> > BufferList; diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp index 7483070..6237af1 100644 --- a/chromecast/media/media.gyp +++ b/chromecast/media/media.gyp @@ -9,6 +9,11 @@ 'libcast_media_gyp%': '', 'use_default_libcast_media%': 1, }, + 'target_defaults': { + 'include_dirs': [ + '../public/', # Public APIs + ], + }, 'targets': [ # TODO(gunsch): delete this target once Chromecast M44/earlier is obsolete. # See: b/21639416 @@ -27,10 +32,10 @@ '<(libcast_media_gyp):libcast_media_1.0', ], 'sources': [ - 'base/decrypt_context.cc', - 'base/decrypt_context.h', - 'base/decrypt_context_clearkey.cc', - 'base/decrypt_context_clearkey.h', + 'base/decrypt_context_impl.cc', + 'base/decrypt_context_impl.h', + 'base/decrypt_context_impl_clearkey.cc', + 'base/decrypt_context_impl_clearkey.h', 'base/key_systems_common.cc', 'base/key_systems_common.h', 'base/media_caps.cc', @@ -99,13 +104,15 @@ 'cma/base/buffering_frame_provider.h', 'cma/base/buffering_state.cc', 'cma/base/buffering_state.h', + 'cma/base/cast_decoder_buffer_impl.cc', + 'cma/base/cast_decoder_buffer_impl.h', + 'cma/base/cast_decrypt_config_impl.cc', + 'cma/base/cast_decrypt_config_impl.h', 'cma/base/cma_logging.h', 'cma/base/coded_frame_provider.cc', 'cma/base/coded_frame_provider.h', 'cma/base/decoder_buffer_adapter.cc', 'cma/base/decoder_buffer_adapter.h', - 'cma/base/decoder_buffer_base.cc', - 'cma/base/decoder_buffer_base.h', 'cma/base/decoder_config_adapter.cc', 'cma/base/decoder_config_adapter.h', 'cma/base/media_task_runner.cc', @@ -115,52 +122,26 @@ ], }, { - 'target_name': 'cma_backend', + 'target_name': 'default_cma_backend', 'type': '<(component)', 'dependencies': [ - 'cma_base', - 'media_base', + '../chromecast.gyp:cast_base', '../../base/base.gyp:base', - '../../media/media.gyp:media', ], 'include_dirs': [ '../..', ], 'sources': [ - 'cma/backend/audio_pipeline_device.cc', - 'cma/backend/audio_pipeline_device.h', 'cma/backend/audio_pipeline_device_default.cc', 'cma/backend/audio_pipeline_device_default.h', - 'cma/backend/media_clock_device.cc', - 'cma/backend/media_clock_device.h', 'cma/backend/media_clock_device_default.cc', 'cma/backend/media_clock_device_default.h', - 'cma/backend/media_component_device.cc', - 'cma/backend/media_component_device.h', 'cma/backend/media_component_device_default.cc', 'cma/backend/media_component_device_default.h', - 'cma/backend/media_pipeline_device.cc', - 'cma/backend/media_pipeline_device.h', - 'cma/backend/media_pipeline_device_factory.h', - 'cma/backend/media_pipeline_device_factory_default.cc', - 'cma/backend/media_pipeline_device_factory_default.h', - 'cma/backend/media_pipeline_device_params.cc', - 'cma/backend/media_pipeline_device_params.h', - 'cma/backend/video_pipeline_device.cc', + 'cma/backend/media_pipeline_backend_default.cc', + 'cma/backend/media_pipeline_backend_default.h', 'cma/backend/video_pipeline_device_default.cc', 'cma/backend/video_pipeline_device_default.h', - 'cma/backend/video_pipeline_device.h', - ], - 'conditions': [ - ['chromecast_branding!="public"', { - 'dependencies': [ - '../internal/chromecast_internal.gyp:cma_backend_internal', - ], - }, { - 'sources': [ - 'cma/backend/media_pipeline_device_factory_simple.cc' - ], - }], ], }, { @@ -205,7 +186,6 @@ 'target_name': 'cma_pipeline', 'type': '<(component)', 'dependencies': [ - 'cma_backend', 'cma_base', 'media_base', 'media_cdm', @@ -225,7 +205,11 @@ 'cma/pipeline/av_pipeline_impl.h', 'cma/pipeline/decrypt_util.cc', 'cma/pipeline/decrypt_util.h', + 'cma/pipeline/frame_status_cb_impl.cc', + 'cma/pipeline/frame_status_cb_impl.h', 'cma/pipeline/load_type.h', + 'cma/pipeline/media_component_device_client_impl.cc', + 'cma/pipeline/media_component_device_client_impl.h', 'cma/pipeline/media_pipeline.h', 'cma/pipeline/media_pipeline_client.cc', 'cma/pipeline/media_pipeline_client.h', @@ -235,6 +219,8 @@ 'cma/pipeline/video_pipeline.h', 'cma/pipeline/video_pipeline_client.cc', 'cma/pipeline/video_pipeline_client.h', + 'cma/pipeline/video_pipeline_device_client_impl.cc', + 'cma/pipeline/video_pipeline_device_client_impl.h', 'cma/pipeline/video_pipeline_impl.cc', 'cma/pipeline/video_pipeline_impl.h', ], @@ -260,12 +246,12 @@ 'target_name': 'cast_media', 'type': 'none', 'dependencies': [ - 'cma_backend', 'cma_base', 'cma_filters', 'cma_ipc', 'cma_ipc_streamer', 'cma_pipeline', + 'default_cma_backend', 'media_cdm', ], }, @@ -321,7 +307,8 @@ 'target_name': 'libcast_media_1.0', 'type': 'shared_library', 'dependencies': [ - '../../chromecast/chromecast.gyp:cast_public_api' + '../../chromecast/chromecast.gyp:cast_public_api', + 'default_cma_backend' ], 'include_dirs': [ '../..', diff --git a/chromecast/public/BUILD.gn b/chromecast/public/BUILD.gn index 5ad19d3..779c5fd 100644 --- a/chromecast/public/BUILD.gn +++ b/chromecast/public/BUILD.gn @@ -11,9 +11,11 @@ source_set("public") { "chromecast_export.h", "graphics_properties_shlib.h", "graphics_types.h", + "media_codec_support_shlib.h", "osd_plane.h", "osd_plane_shlib.h", "osd_surface.h", + "task_runner.h", "video_plane.h", ] } diff --git a/chromecast/public/cast_media_shlib.h b/chromecast/public/cast_media_shlib.h index 8b776da..d523db88 100644 --- a/chromecast/public/cast_media_shlib.h +++ b/chromecast/public/cast_media_shlib.h @@ -13,6 +13,8 @@ namespace chromecast { namespace media { +class MediaPipelineBackend; +struct MediaPipelineDeviceParams; class VideoPlane; // Provides access to platform-specific media systems and hardware resources. @@ -39,6 +41,12 @@ class CHROMECAST_EXPORT CastMediaShlib { // While an implementation is in an initialized state, this function may be // called at any time. The VideoPlane object must be destroyed in Finalize. static VideoPlane* GetVideoPlane(); + + // Creates a factory object for a media pipeline backend. Called in the + // browser process, any number of times (once per media pipeline). Each call + // must instantiate a new factory object + static MediaPipelineBackend* CreateMediaPipelineBackend( + const MediaPipelineDeviceParams& params); }; } // namespace media diff --git a/chromecast/public/media/BUILD.gn b/chromecast/public/media/BUILD.gn new file mode 100644 index 0000000..5b00f0b --- /dev/null +++ b/chromecast/public/media/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright 2015 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. + +source_set("public") { + sources = [ + "audio_pipeline_device.h", + "cast_decoder_buffer.h", + "cast_decrypt_config.h", + "cast_key_system.h", + "decoder_config.h", + "media_clock_device.h", + "media_component_device.h", + "media_pipeline_backend.h", + "media_pipeline_device_params.h", + "stream_id.h", + "video_pipeline_device.h", + ] +} diff --git a/chromecast/media/cma/backend/audio_pipeline_device.h b/chromecast/public/media/audio_pipeline_device.h index 84c1af1..02fadeb 100644 --- a/chromecast/media/cma/backend/audio_pipeline_device.h +++ b/chromecast/public/media/audio_pipeline_device.h @@ -2,34 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_PIPELINE_DEVICE_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_PIPELINE_DEVICE_H_ +#ifndef CHROMECAST_PUBLIC_MEDIA_AUDIO_PIPELINE_DEVICE_H_ +#define CHROMECAST_PUBLIC_MEDIA_AUDIO_PIPELINE_DEVICE_H_ -#include "base/macros.h" -#include "chromecast/media/cma/backend/media_component_device.h" +#include "media_component_device.h" namespace chromecast { namespace media { class AudioPipelineDeviceClient; struct AudioConfig; +// Interface for platform-specific audio pipeline backend. +// See comments on MediaComponentDevice. class AudioPipelineDevice : public MediaComponentDevice { public: - AudioPipelineDevice(); - ~AudioPipelineDevice() override; + ~AudioPipelineDevice() override {} - // Provide the audio configuration. - // Must be called before switching from |kStateUninitialized| to |kStateIdle|. + // Provides the audio configuration. + // Will be called before switching from |kStateUninitialized| to |kStateIdle|. // Afterwards, this can be invoked any time the configuration changes. // Returns true if the configuration is a supported configuration. virtual bool SetConfig(const AudioConfig& config) = 0; // Sets the volume multiplier. - // The multiplier must be in the range [0.0, 1.0]. + // The multiplier is in the range [0.0, 1.0]. virtual void SetStreamVolumeMultiplier(float multiplier) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(AudioPipelineDevice); }; } // namespace media diff --git a/chromecast/public/media/cast_decoder_buffer.h b/chromecast/public/media/cast_decoder_buffer.h new file mode 100644 index 0000000..bf3d76c --- /dev/null +++ b/chromecast/public/media/cast_decoder_buffer.h @@ -0,0 +1,53 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_CAST_DECODER_BUFFER_H_ +#define CHROMECAST_PUBLIC_MEDIA_CAST_DECODER_BUFFER_H_ + +#include <stdint.h> + +#include <cstddef> + +#include "stream_id.h" + +namespace chromecast { +namespace media { + +class CastDecryptConfig; + +// CastDecoderBuffer provides an interface for passing a single frame of audio +// or video data to the pipeline backend. End-of-stream is indicated by passing +// a frame where end_of_stream() returns true. +// Buffer ownership passes to backend when they are pushed (see +// MediaComponentDevice::PushFrame). +// TODO(halliwell): consider renaming functions here to camel case. +class CastDecoderBuffer { + public: + virtual ~CastDecoderBuffer() {} + + // Returns the stream id of this decoder buffer. + virtual StreamId stream_id() const = 0; + + // Returns the PTS of the frame in microseconds. + virtual int64_t timestamp() const = 0; + + // Gets the frame data. + virtual const uint8_t* data() const = 0; + + // Returns the size of the frame in bytes. + virtual size_t data_size() const = 0; + + // Returns the decrypt configuration. + // Returns NULL if and only if the buffer is unencrypted. + virtual const CastDecryptConfig* decrypt_config() const = 0; + + // Indicates if this is a special frame that indicates the end of the stream. + // If true, functions to access the frame content cannot be called. + virtual bool end_of_stream() const = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_MEDIA_CAST_DECODER_BUFFER_H_ diff --git a/chromecast/public/media/cast_decrypt_config.h b/chromecast/public/media/cast_decrypt_config.h new file mode 100644 index 0000000..582bce9 --- /dev/null +++ b/chromecast/public/media/cast_decrypt_config.h @@ -0,0 +1,50 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_CAST_DECRYPT_CONFIG_H_ +#define CHROMECAST_PUBLIC_MEDIA_CAST_DECRYPT_CONFIG_H_ + +#include <stdint.h> +#include <string> +#include <vector> + +namespace chromecast { +namespace media { + +// The Common Encryption spec provides for subsample encryption, where portions +// of a sample are set in cleartext. A SubsampleEntry specifies the number of +// clear and encrypted bytes in each subsample. For decryption, all of the +// encrypted bytes in a sample should be considered a single logical stream, +// regardless of how they are divided into subsamples, and the clear bytes +// should not be considered as part of decryption. This is logically equivalent +// to concatenating all 'cypher_bytes' portions of subsamples, decrypting that +// result, and then copying each byte from the decrypted block over the +// position of the corresponding encrypted byte. +struct SubsampleEntry { + SubsampleEntry() : clear_bytes(0), cypher_bytes(0) {} + SubsampleEntry(uint32_t clear_bytes, uint32_t cypher_bytes) + : clear_bytes(clear_bytes), cypher_bytes(cypher_bytes) {} + uint32_t clear_bytes; + uint32_t cypher_bytes; +}; + +// Contains all metadata needed to decrypt a media sample. +class CastDecryptConfig { + public: + virtual ~CastDecryptConfig() {} + + // Returns the ID for this sample's decryption key. + virtual const std::string& key_id() const = 0; + + // Returns the initialization vector as defined by the encryption format. + virtual const std::string& iv() const = 0; + + // Returns the clear and encrypted portions of the sample as described above. + virtual const std::vector<SubsampleEntry>& subsamples() const = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_MEDIA_CAST_DECRYPT_CONFIG_H_ diff --git a/chromecast/public/media/cast_key_system.h b/chromecast/public/media/cast_key_system.h new file mode 100644 index 0000000..29403cd --- /dev/null +++ b/chromecast/public/media/cast_key_system.h @@ -0,0 +1,22 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_CAST_KEY_SYSTEM_H_ +#define CHROMECAST_PUBLIC_MEDIA_CAST_KEY_SYSTEM_H_ + +namespace chromecast { +namespace media { + +// Specifies the encryption key system used by a given buffer. +enum CastKeySystem { + KEY_SYSTEM_NONE = 0, + KEY_SYSTEM_CLEAR_KEY, + KEY_SYSTEM_PLAYREADY, + KEY_SYSTEM_WIDEVINE +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_MEDIA_CAST_KEY_SYSTEM_H_ diff --git a/chromecast/public/media/decoder_config.h b/chromecast/public/media/decoder_config.h index 45fd1d4..7652c3c 100644 --- a/chromecast/public/media/decoder_config.h +++ b/chromecast/public/media/decoder_config.h @@ -8,7 +8,7 @@ #include <stdint.h> #include <vector> -#include "chromecast/public/media/stream_id.h" +#include "stream_id.h" namespace chromecast { namespace media { diff --git a/chromecast/public/media/decrypt_context.h b/chromecast/public/media/decrypt_context.h new file mode 100644 index 0000000..05e5a1a --- /dev/null +++ b/chromecast/public/media/decrypt_context.h @@ -0,0 +1,34 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_DECRYPT_CONTEXT_H_ +#define CHROMECAST_PUBLIC_MEDIA_DECRYPT_CONTEXT_H_ + +#include <stdint.h> +#include <vector> + +#include "cast_key_system.h" + +namespace chromecast { +namespace media { +class CastDecoderBuffer; + +// Provides the information needed to decrypt frames. +class DecryptContext { + public: + virtual ~DecryptContext() {} + + // Get the key system to use for decryption. + virtual CastKeySystem GetKeySystem() = 0; + + // Decrypts the given buffer. Returns true/false for success/failure, + // and places the decrypted data in output if successful. + virtual bool Decrypt(CastDecoderBuffer* buffer, + std::vector<uint8_t>* output) = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_MEDIA_DECRYPT_CONTEXT_H_ diff --git a/chromecast/public/media/media_clock_device.h b/chromecast/public/media/media_clock_device.h new file mode 100644 index 0000000..7bb945e --- /dev/null +++ b/chromecast/public/media/media_clock_device.h @@ -0,0 +1,63 @@ +// Copyright 2014 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 CHROMECAST_PUBLIC_MEDIA_MEDIA_CLOCK_DEVICE_H_ +#define CHROMECAST_PUBLIC_MEDIA_MEDIA_CLOCK_DEVICE_H_ + +#include <string> + +namespace chromecast { +namespace media { + +// Interface for platform-specific pipeline clock. +// Pipeline clocks follow this state machine: +// ------------------- +// | | +// v | +// kUninitialized --> kIdle --------- kRunning +// +// {any state} --> kError +// +// Notes: +// - Hardware resources should be acquired when transitioning from the +// |kUninitialized| state to the |kIdle| state. +// - The initial value of the timeline will only be set in the kIdle state. +class MediaClockDevice { + public: + enum State { + kStateUninitialized, + kStateIdle, + kStateRunning, + kStateError, + }; + + virtual ~MediaClockDevice() {} + + // Returns the current state of the media clock. + virtual State GetState() const = 0; + + // Changes the state and performs any necessary transitions. + // Returns true when successful. + virtual bool SetState(State new_state) = 0; + + // Sets the initial value of the timeline in microseconds. + // Will only be invoked in state kStateIdle. + // Returns true when successful. + virtual bool ResetTimeline(int64_t time_microseconds) = 0; + + // Sets the clock rate. + // |rate| == 0 means the clock is not progressing and that the renderer + // tied to this media clock should pause rendering. + // Will only be invoked in states kStateIdle or kStateRunning. + virtual bool SetRate(float rate) = 0; + + // Retrieves the media clock time in microseconds. + // Will only be invoked in states kStateIdle or kStateRunning. + virtual int64_t GetTimeMicroseconds() = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_CLOCK_DEVICE_H_ diff --git a/chromecast/public/media/media_component_device.h b/chromecast/public/media/media_component_device.h new file mode 100644 index 0000000..b6f6255 --- /dev/null +++ b/chromecast/public/media/media_component_device.h @@ -0,0 +1,142 @@ +// Copyright 2014 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 CHROMECAST_PUBLIC_MEDIA_MEDIA_COMPONENT_DEVICE_H_ +#define CHROMECAST_PUBLIC_MEDIA_MEDIA_COMPONENT_DEVICE_H_ + +#include <stdint.h> +#include <string> + +#include "cast_key_system.h" + +namespace chromecast { +namespace media { +class CastDecoderBuffer; +class DecryptContext; + +// Common base interface for both platform-specific audio and video pipeline +// backends. Both follow this state machine: +// +------------- kRunning <--+ +// | ^ | +// v | | +// kUninitialized <--> kIdle -------------+ | +// ^ | | +// | v | +// +------------- kPaused <---+ +// {any state} --> kError +// kError --> kUninitialized +// +// Notes: +// - Hardware resources should be acquired when transitioning from the +// |kUninitialized| state to the |kIdle| state. +// - Buffers will be pushed only in the kRunning or kPaused states. +// - The end of stream is signaled through a special buffer. +// Once the end of stream buffer is fed, no other buffer +// will be fed until the FSM goes through the kIdle state again. +// - In both kPaused and kRunning states, frames can be fed. +// However, frames are possibly rendered only in the kRunning state. +// - In the kRunning state, frames are rendered according to the clock rate. +// - All the hardware resources must be released in the |kError| state. +class MediaComponentDevice { + public: + enum State { + kStateUninitialized, + kStateIdle, + kStateRunning, + kStatePaused, + kStateError, + }; + + enum FrameStatus { + kFrameSuccess, + kFrameFailed, + kFramePending, + }; + + // Interface for receiving status when PushFrame has completed. + class FrameStatusCB { + public: + virtual ~FrameStatusCB() {} + virtual void Run(FrameStatus status) = 0; + }; + + // Client callbacks interface + class Client { + public: + virtual ~Client() {} + virtual void OnEndOfStream() = 0; + }; + + // The statistics are computed since the media component left the idle state. + // For video, a sample is defined as a frame. + struct Statistics { + uint64_t decoded_bytes; + uint64_t decoded_samples; + uint64_t dropped_samples; + }; + + // Info on pipeline latency: amount of data in pipeline not rendered yet, + // and timestamp of system clock (must be CLOCK_MONOTONIC) at which delay + // measurement was taken. Both times in microseconds. + struct RenderingDelay { + RenderingDelay() + : delay_microseconds(INT64_MIN), timestamp_microseconds(INT64_MIN) {} + RenderingDelay(int64_t delay_microseconds_in, + int64_t timestamp_microseconds_in) + : delay_microseconds(delay_microseconds_in), + timestamp_microseconds(timestamp_microseconds_in) {} + int64_t delay_microseconds; + int64_t timestamp_microseconds; + }; + + virtual ~MediaComponentDevice() {} + + // Registers |client| as the media event handler. Implementation + // takes ownership of |client| and call OnEndOfStream when an end-of-stream + // buffer is processed. + virtual void SetClient(Client* client) = 0; + + // Changes the state and performs any necessary transitions. + // Returns true when successful. + virtual bool SetState(State new_state) = 0; + + // Returns the current state of the media component. + virtual State GetState() const = 0; + + // Sets the time where rendering should start. + // Return true when successful. + // Will only be invoked in state kStateIdle. + virtual bool SetStartPts(int64_t microseconds) = 0; + + // Pushes a frame. If the implementation cannot push the buffer + // now, it must store the buffer, return |kFramePending| and execute the push + // at a later time when it becomes possible to do so. The implementation must + // then invoke |completion_cb|. Pushing a pending frame should be aborted if + // the state returns to kStateIdle, and |completion_cb| need not be invoked. + // If |kFramePending| is returned, the pipeline will stop pushing any further + // buffers until the |completion_cb| is invoked. + // Ownership: |decrypt_context|, |buffer|, |completion_cb| are all owned by + // the implementation and must be deleted once no longer needed (even in the + // case where |completion_cb| is not called). + // |completion_cb| should be only be invoked to indicate completion of a + // pending buffer push - not for the immediate |kFrameSuccess| return case. + virtual FrameStatus PushFrame(DecryptContext* decrypt_context, + CastDecoderBuffer* buffer, + FrameStatusCB* completion_cb) = 0; + + // Returns the pipeline latency: i.e. the amount of data + // in the pipeline that have not been rendered yet, in microseconds. + // Returns delay = INT64_MIN if the latency is not available. + virtual RenderingDelay GetRenderingDelay() const = 0; + + // Returns the playback statistics since the last transition from idle state. + // Returns true when successful. + // Is only invoked in state kStateRunning. + virtual bool GetStatistics(Statistics* stats) const = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_COMPONENT_DEVICE_H_ diff --git a/chromecast/public/media/media_pipeline_backend.h b/chromecast/public/media/media_pipeline_backend.h new file mode 100644 index 0000000..cf64acc --- /dev/null +++ b/chromecast/public/media/media_pipeline_backend.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_MEDIA_PIPELINE_BACKEND_H_ +#define CHROMECAST_PUBLIC_MEDIA_MEDIA_PIPELINE_BACKEND_H_ + +namespace chromecast { +namespace media { + +class AudioPipelineDevice; +class MediaClockDevice; +struct MediaPipelineDeviceParams; +class VideoPipelineDevice; + +// Interface for creating and managing ownership of platform-specific clock, +// audio and video devices. cast_shell owns the MediaPipelineBackend for +// as long as it is needed; the implementation is responsible for +// tearing down the individual components correctly when it is destroyed. +// A new MediaPipelineBackend will be instantiated for each media player +// instance. +class MediaPipelineBackend { + public: + virtual ~MediaPipelineBackend() {} + + // Returns the platform-specific pipeline clock. + virtual MediaClockDevice* GetClock() = 0; + + // Returns the platform-specific audio backend. + virtual AudioPipelineDevice* GetAudio() = 0; + + // Returns the platform-specific video backend. + virtual VideoPipelineDevice* GetVideo() = 0; +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_FACTORY_H_ diff --git a/chromecast/media/cma/backend/media_pipeline_device_params.h b/chromecast/public/media/media_pipeline_device_params.h index d13e4e3..fa7779b 100644 --- a/chromecast/media/cma/backend/media_pipeline_device_params.h +++ b/chromecast/public/media/media_pipeline_device_params.h @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_PARAMS_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_MEDIA_PIPELINE_DEVICE_PARAMS_H_ +#ifndef CHROMECAST_PUBLIC_MEDIA_MEDIA_PIPELINE_DEVICE_PARAMS_H_ +#define CHROMECAST_PUBLIC_MEDIA_MEDIA_PIPELINE_DEVICE_PARAMS_H_ -#include "base/macros.h" +#include "task_runner.h" namespace chromecast { namespace media { -class MediaPipelineDeviceParams { - public: +// Supplies creation parameters to platform-specific pipeline backend. +struct MediaPipelineDeviceParams { enum MediaSyncType { // Default operation, synchronize playback using PTS with higher latency. kModeSyncPts = 0, @@ -27,10 +27,20 @@ class MediaPipelineDeviceParams { kModeIgnorePtsAndVSync = 2, }; - MediaPipelineDeviceParams(); - ~MediaPipelineDeviceParams(); + MediaPipelineDeviceParams(TaskRunner* task_runner_in) + : sync_type(kModeSyncPts), task_runner(task_runner_in) {} - MediaSyncType sync_type; + MediaPipelineDeviceParams(MediaSyncType sync_type_in, + TaskRunner* task_runner_in) + : sync_type(sync_type_in), task_runner(task_runner_in) {} + + const MediaSyncType sync_type; + + // task_runner allows backend implementations to post tasks to the media + // thread. Since all calls from cast_shell into the backend are made on + // the media thread, this may simplify thread management and safety for + // some backends. + TaskRunner* const task_runner; }; } // namespace media diff --git a/chromecast/media/cma/backend/video_pipeline_device.h b/chromecast/public/media/video_pipeline_device.h index ee7dff4..1019ec3 100644 --- a/chromecast/media/cma/backend/video_pipeline_device.h +++ b/chromecast/public/media/video_pipeline_device.h @@ -2,23 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PIPELINE_DEVICE_H_ -#define CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_PIPELINE_DEVICE_H_ +#ifndef CHROMECAST_PUBLIC_MEDIA_VIDEO_PIPELINE_DEVICE_H_ +#define CHROMECAST_PUBLIC_MEDIA_VIDEO_PIPELINE_DEVICE_H_ -#include "base/callback.h" -#include "base/macros.h" -#include "chromecast/media/cma/backend/media_component_device.h" - -namespace gfx { -class Size; -} +#include "media_component_device.h" namespace chromecast { +struct Size; + namespace media { -class DecoderBufferBase; struct VideoConfig; -// VideoPipelineDevice - +// Interface for platform-specific video pipeline backend. +// See comments on MediaComponentDevice. // // Notes: // - Like a regular MediaComponentDevice, frames are possibly rendered only @@ -26,32 +22,26 @@ struct VideoConfig; // However, the first frame must be rendered regardless of the clock state: // - no synchronization needed to display the first frame, // - the clock rate has no impact on the presentation of the first frame. -// class VideoPipelineDevice : public MediaComponentDevice { public: - struct VideoClient { - VideoClient(); - ~VideoClient(); - - // Invoked each time the natural size is updated. - base::Callback<void(const gfx::Size& natural_size)> - natural_size_changed_cb; + // Callback interface for natural size of video changing. + class VideoClient { + public: + virtual ~VideoClient() {} + virtual void OnNaturalSizeChanged(const Size& size) = 0; }; - VideoPipelineDevice(); - ~VideoPipelineDevice() override; + ~VideoPipelineDevice() override {} // Registers |client| as the video specific event handler. - virtual void SetVideoClient(const VideoClient& client) = 0; + // Implementation takes ownership of |client|. + virtual void SetVideoClient(VideoClient* client) = 0; - // Provide the video configuration. - // Must be called before switching from |kStateUninitialized| to |kStateIdle|. + // Provides the video configuration. + // Called before switching from |kStateUninitialized| to |kStateIdle|. // Afterwards, this can be invoked any time the configuration changes. // Returns true if the configuration is a supported configuration. virtual bool SetConfig(const VideoConfig& config) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(VideoPipelineDevice); }; } // namespace media diff --git a/chromecast/public/media_codec_support_shlib.h b/chromecast/public/media_codec_support_shlib.h new file mode 100644 index 0000000..168ecd8 --- /dev/null +++ b/chromecast/public/media_codec_support_shlib.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_MEDIA_CODEC_SUPPORT_SHLIB_H_ +#define CHROMECAST_PUBLIC_MEDIA_CODEC_SUPPORT_SHLIB_H_ + +#include <string> + +#include "chromecast_export.h" + +namespace chromecast { +namespace media { + +// Provides information on which codecs are supported by a platform. +// Note: these queries are made only in the renderer process. +class CHROMECAST_EXPORT MediaCodecSupportShlib { + public: + // Possible values for 'is codec supported' query + enum CodecSupport { + // Codec is definitely supported on this platform. + kSupported, + // Codec is definitely not supported on this platform. + kNotSupported, + // No platform-specific constraints on codec's support. + // Support is determined by cast_shell default behaviour (which + // may include taking current HDMI-out capabilities into account). + kDefault + }; + + // Returns whether or not the given codec (passed in as a string + // representation of the codec id conforming to RFC 6381) is supported. + static CodecSupport IsSupported(const std::string& codec); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_MEDIA_CODEC_SUPPORT_SHLIB_H_ diff --git a/chromecast/public/task_runner.h b/chromecast/public/task_runner.h new file mode 100644 index 0000000..fd2eb32 --- /dev/null +++ b/chromecast/public/task_runner.h @@ -0,0 +1,39 @@ +// Copyright 2015 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 CHROMECAST_PUBLIC_TASK_RUNNER_H_ +#define CHROMECAST_PUBLIC_TASK_RUNNER_H_ + +#include <stdint.h> + +namespace chromecast { + +// Provides a way for vendor libraries to run code on a specific thread. +// For example, cast_shell supplies an implementation of this interface through +// media APIs (see MediaPipelineDeviceParams) to allow media backends to +// schedule tasks to be run on the media thread. +class TaskRunner { + public: + // Subclass and implement 'Run' to supply code to be run by PostTask or + // PostDelayedTask. They both take ownership of the Task object passed in + // and will delete after running the Task. + class Task { + public: + virtual ~Task() {} + virtual void Run() = 0; + }; + + // Posts a task to the thread's task queue. Delay of 0 could mean task + // runs immediately (within the call to PostTask, if it's called on the + // target thread) but there also could be some delay (the task could be added + // to target thread's task queue). + virtual bool PostTask(Task* task, uint64_t delay_milliseconds) = 0; + + protected: + virtual ~TaskRunner() {} +}; + +} // namespace chromecast + +#endif // CHROMECAST_PUBLIC_TASK_RUNNER_H_ |