[MediaRouter] Update MR-2-Extension's PostMessage to return boolean.
[chromium-blink-merge.git] / chromecast / media / cma / ipc_streamer / av_streamer_proxy.cc
blob93d662590ca8ce5bc6833d9a48ddf09bb295c1c1
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/media/cma/ipc_streamer/av_streamer_proxy.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chromecast/media/cma/base/coded_frame_provider.h"
12 #include "chromecast/media/cma/base/decoder_buffer_base.h"
13 #include "chromecast/media/cma/ipc/media_memory_chunk.h"
14 #include "chromecast/media/cma/ipc/media_message.h"
15 #include "chromecast/media/cma/ipc/media_message_fifo.h"
16 #include "chromecast/media/cma/ipc/media_message_type.h"
17 #include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h"
18 #include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h"
19 #include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h"
21 namespace chromecast {
22 namespace media {
24 AvStreamerProxy::AvStreamerProxy()
25 : is_running_(false),
26 pending_read_(false),
27 pending_av_data_(false),
28 weak_factory_(this) {
29 weak_this_ = weak_factory_.GetWeakPtr();
30 thread_checker_.DetachFromThread();
33 AvStreamerProxy::~AvStreamerProxy() {
34 DCHECK(thread_checker_.CalledOnValidThread());
37 void AvStreamerProxy::SetCodedFrameProvider(
38 scoped_ptr<CodedFrameProvider> frame_provider) {
39 DCHECK(thread_checker_.CalledOnValidThread());
40 DCHECK(!frame_provider_);
41 frame_provider_.reset(frame_provider.release());
44 void AvStreamerProxy::SetMediaMessageFifo(
45 scoped_ptr<MediaMessageFifo> fifo) {
46 DCHECK(thread_checker_.CalledOnValidThread());
47 DCHECK(!fifo_);
48 fifo_.reset(fifo.release());
51 void AvStreamerProxy::Start() {
52 DCHECK(!is_running_);
54 is_running_ = true;
55 RequestBufferIfNeeded();
58 void AvStreamerProxy::StopAndFlush(const base::Closure& done_cb) {
59 pending_av_data_ = false;
60 pending_audio_config_ = ::media::AudioDecoderConfig();
61 pending_video_config_ = ::media::VideoDecoderConfig();
62 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
64 pending_read_ = false;
66 // StopAndFlush may happen twice in a row when Stop happens while a previous
67 // pending Seek (which requires Flush). We only need to perform Flush once
68 // when entering stopped state. Chromium pipeline will call Start eventually
69 // to set is_running_, after Seek (next state of Seek is Play), which
70 // guarantees Flush be called when there is no pending tasks.
71 if (is_running_) {
72 frame_provider_->Flush(done_cb);
74 is_running_ = false;
77 void AvStreamerProxy::OnFifoReadEvent() {
78 DCHECK(thread_checker_.CalledOnValidThread());
80 // Some enough space might have been released
81 // to accommodate the pending data.
82 if (pending_av_data_)
83 ProcessPendingData();
86 void AvStreamerProxy::RequestBufferIfNeeded() {
87 DCHECK(thread_checker_.CalledOnValidThread());
89 if (!is_running_ || pending_read_ || pending_av_data_)
90 return;
92 // |frame_provider_| is assumed to run on the same message loop.
93 // Add a BindToCurrentLoop if that's not the case in the future.
94 pending_read_ = true;
95 frame_provider_->Read(base::Bind(&AvStreamerProxy::OnNewBuffer, weak_this_));
98 void AvStreamerProxy::OnNewBuffer(
99 const scoped_refptr<DecoderBufferBase>& buffer,
100 const ::media::AudioDecoderConfig& audio_config,
101 const ::media::VideoDecoderConfig& video_config) {
102 DCHECK(thread_checker_.CalledOnValidThread());
104 pending_read_ = false;
106 if (buffer->end_of_stream())
107 is_running_ = false;
109 DCHECK(!pending_av_data_);
110 pending_av_data_ = true;
112 pending_buffer_ = buffer;
113 pending_audio_config_ = audio_config;
114 pending_video_config_ = video_config;
116 ProcessPendingData();
119 void AvStreamerProxy::ProcessPendingData() {
120 if (pending_audio_config_.IsValidConfig()) {
121 if (!SendAudioDecoderConfig(pending_audio_config_))
122 return;
123 pending_audio_config_ = ::media::AudioDecoderConfig();
126 if (pending_video_config_.IsValidConfig()) {
127 if (!SendVideoDecoderConfig(pending_video_config_))
128 return;
129 pending_video_config_ = ::media::VideoDecoderConfig();
132 if (pending_buffer_.get()) {
133 if (!SendBuffer(pending_buffer_))
134 return;
135 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
138 pending_av_data_ = false;
139 base::ThreadTaskRunnerHandle::Get()->PostTask(
140 FROM_HERE,
141 base::Bind(&AvStreamerProxy::RequestBufferIfNeeded, weak_this_));
144 bool AvStreamerProxy::SendAudioDecoderConfig(
145 const ::media::AudioDecoderConfig& config) {
146 // Create a dummy message to calculate first the message size.
147 scoped_ptr<MediaMessage> dummy_msg(
148 MediaMessage::CreateDummyMessage(AudioConfigMediaMsg));
149 AudioDecoderConfigMarshaller::Write(config, dummy_msg.get());
151 // Create the real message and write the actual content.
152 scoped_ptr<MediaMessage> msg(
153 MediaMessage::CreateMessage(
154 AudioConfigMediaMsg,
155 base::Bind(&MediaMessageFifo::ReserveMemory,
156 base::Unretained(fifo_.get())),
157 dummy_msg->content_size()));
158 if (!msg)
159 return false;
161 AudioDecoderConfigMarshaller::Write(config, msg.get());
162 return true;
165 bool AvStreamerProxy::SendVideoDecoderConfig(
166 const ::media::VideoDecoderConfig& config) {
167 // Create a dummy message to calculate first the message size.
168 scoped_ptr<MediaMessage> dummy_msg(
169 MediaMessage::CreateDummyMessage(VideoConfigMediaMsg));
170 VideoDecoderConfigMarshaller::Write(config, dummy_msg.get());
172 // Create the real message and write the actual content.
173 scoped_ptr<MediaMessage> msg(
174 MediaMessage::CreateMessage(
175 VideoConfigMediaMsg,
176 base::Bind(&MediaMessageFifo::ReserveMemory,
177 base::Unretained(fifo_.get())),
178 dummy_msg->content_size()));
179 if (!msg)
180 return false;
182 VideoDecoderConfigMarshaller::Write(config, msg.get());
183 return true;
186 bool AvStreamerProxy::SendBuffer(
187 const scoped_refptr<DecoderBufferBase>& buffer) {
188 // Create a dummy message to calculate first the message size.
189 scoped_ptr<MediaMessage> dummy_msg(
190 MediaMessage::CreateDummyMessage(FrameMediaMsg));
191 DecoderBufferBaseMarshaller::Write(buffer, dummy_msg.get());
193 // Create the real message and write the actual content.
194 scoped_ptr<MediaMessage> msg(
195 MediaMessage::CreateMessage(
196 FrameMediaMsg,
197 base::Bind(&MediaMessageFifo::ReserveMemory,
198 base::Unretained(fifo_.get())),
199 dummy_msg->content_size()));
200 if (!msg)
201 return false;
203 DecoderBufferBaseMarshaller::Write(buffer, msg.get());
204 return true;
207 } // namespace media
208 } // namespace chromecast