1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/browser/media/media_pipeline_host.h"
10 #include "base/callback.h"
11 #include "base/location.h"
12 #include "base/memory/shared_memory.h"
13 #include "base/single_thread_task_runner.h"
14 #include "chromecast/common/media/shared_memory_chunk.h"
15 #include "chromecast/media/cma/backend/media_pipeline_device.h"
16 #include "chromecast/media/cma/backend/media_pipeline_device_params.h"
17 #include "chromecast/media/cma/ipc/media_message_fifo.h"
18 #include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h"
19 #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
20 #include "chromecast/media/cma/pipeline/media_pipeline_impl.h"
21 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
23 namespace chromecast
{
26 struct MediaPipelineHost::MediaTrackHost
{
30 base::Closure pipe_write_cb
;
33 MediaPipelineHost::MediaTrackHost::MediaTrackHost() {
36 MediaPipelineHost::MediaTrackHost::~MediaTrackHost() {
39 MediaPipelineHost::MediaPipelineHost() {
40 thread_checker_
.DetachFromThread();
43 MediaPipelineHost::~MediaPipelineHost() {
44 DCHECK(thread_checker_
.CalledOnValidThread());
46 for (MediaTrackMap::iterator it
= media_track_map_
.begin();
47 it
!= media_track_map_
.end(); ++it
) {
48 scoped_ptr
<MediaTrackHost
> media_track(it
->second
);
50 media_track_map_
.clear();
53 void MediaPipelineHost::Initialize(
55 const MediaPipelineClient
& client
) {
56 DCHECK(thread_checker_
.CalledOnValidThread());
57 media_pipeline_
.reset(new MediaPipelineImpl());
58 MediaPipelineDeviceParams default_parameters
;
59 if (load_type
== kLoadTypeMediaStream
)
60 default_parameters
.sync_type
= MediaPipelineDeviceParams::kModeIgnorePts
;
61 media_pipeline_
->Initialize(
63 CreateMediaPipelineDevice(default_parameters
).Pass());
64 media_pipeline_
->SetClient(client
);
67 void MediaPipelineHost::SetAvPipe(
69 scoped_ptr
<base::SharedMemory
> shared_mem
,
70 const base::Closure
& pipe_read_activity_cb
,
71 const base::Closure
& av_pipe_set_cb
) {
72 DCHECK(thread_checker_
.CalledOnValidThread());
73 CHECK(track_id
== kAudioTrackId
|| track_id
== kVideoTrackId
);
75 size_t shared_mem_size
= shared_mem
->requested_size();
76 scoped_ptr
<MediaMemoryChunk
> shared_memory_chunk(
77 new SharedMemoryChunk(shared_mem
.Pass(), shared_mem_size
));
78 scoped_ptr
<MediaMessageFifo
> media_message_fifo(
79 new MediaMessageFifo(shared_memory_chunk
.Pass(), shared_mem_size
));
80 media_message_fifo
->ObserveReadActivity(pipe_read_activity_cb
);
81 scoped_ptr
<CodedFrameProviderHost
> frame_provider_host(
82 new CodedFrameProviderHost(media_message_fifo
.Pass()));
84 MediaTrackMap::iterator it
= media_track_map_
.find(track_id
);
85 MediaTrackHost
* media_track_host
;
86 if (it
== media_track_map_
.end()) {
87 media_track_host
= new MediaTrackHost();
88 media_track_map_
.insert(
89 std::pair
<TrackId
, MediaTrackHost
*>(track_id
, media_track_host
));
91 media_track_host
= it
->second
;
93 media_track_host
->pipe_write_cb
= frame_provider_host
->GetFifoWriteEventCb();
95 scoped_ptr
<CodedFrameProvider
> frame_provider(frame_provider_host
.release());
96 if (track_id
== kAudioTrackId
) {
97 media_pipeline_
->GetAudioPipelineImpl()->SetCodedFrameProvider(
98 frame_provider
.Pass());
100 media_pipeline_
->GetVideoPipelineImpl()->SetCodedFrameProvider(
101 frame_provider
.Pass());
103 av_pipe_set_cb
.Run();
106 void MediaPipelineHost::AudioInitialize(
108 const AvPipelineClient
& client
,
109 const ::media::AudioDecoderConfig
& config
,
110 const ::media::PipelineStatusCB
& status_cb
) {
111 DCHECK(thread_checker_
.CalledOnValidThread());
112 CHECK(track_id
== kAudioTrackId
);
113 media_pipeline_
->GetAudioPipeline()->SetClient(client
);
114 media_pipeline_
->InitializeAudio(
115 config
, scoped_ptr
<CodedFrameProvider
>(), status_cb
);
118 void MediaPipelineHost::VideoInitialize(
120 const VideoPipelineClient
& client
,
121 const ::media::VideoDecoderConfig
& config
,
122 const ::media::PipelineStatusCB
& status_cb
) {
123 DCHECK(thread_checker_
.CalledOnValidThread());
124 CHECK(track_id
== kVideoTrackId
);
125 media_pipeline_
->GetVideoPipeline()->SetClient(client
);
126 media_pipeline_
->InitializeVideo(
127 config
, scoped_ptr
<CodedFrameProvider
>(), status_cb
);
130 void MediaPipelineHost::StartPlayingFrom(base::TimeDelta time
) {
131 DCHECK(thread_checker_
.CalledOnValidThread());
132 media_pipeline_
->StartPlayingFrom(time
);
135 void MediaPipelineHost::Flush(const ::media::PipelineStatusCB
& status_cb
) {
136 DCHECK(thread_checker_
.CalledOnValidThread());
137 media_pipeline_
->Flush(status_cb
);
140 void MediaPipelineHost::Stop() {
141 DCHECK(thread_checker_
.CalledOnValidThread());
142 media_pipeline_
->Stop();
145 void MediaPipelineHost::SetPlaybackRate(float playback_rate
) {
146 DCHECK(thread_checker_
.CalledOnValidThread());
147 media_pipeline_
->SetPlaybackRate(playback_rate
);
150 void MediaPipelineHost::SetVolume(TrackId track_id
, float volume
) {
151 DCHECK(thread_checker_
.CalledOnValidThread());
152 CHECK(track_id
== kAudioTrackId
);
153 media_pipeline_
->GetAudioPipeline()->SetVolume(volume
);
156 void MediaPipelineHost::SetCdm(
157 int render_process_id
, int render_frame_id
, int cdm_id
) {
158 DCHECK(thread_checker_
.CalledOnValidThread());
160 // TODO(gunsch): crbug.com/444930. Find a way to get
161 // content::BrowserCdmManager since it is not under content/public/.
165 void MediaPipelineHost::NotifyPipeWrite(TrackId track_id
) {
166 DCHECK(thread_checker_
.CalledOnValidThread());
167 MediaTrackMap::iterator it
= media_track_map_
.find(track_id
);
168 if (it
== media_track_map_
.end())
171 MediaTrackHost
* media_track_host
= it
->second
;
172 if (!media_track_host
->pipe_write_cb
.is_null())
173 media_track_host
->pipe_write_cb
.Run();
177 } // namespace chromecast