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"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "chromecast/media/cma/base/coded_frame_provider.h"
11 #include "chromecast/media/cma/base/decoder_buffer_base.h"
12 #include "chromecast/media/cma/ipc/media_memory_chunk.h"
13 #include "chromecast/media/cma/ipc/media_message.h"
14 #include "chromecast/media/cma/ipc/media_message_fifo.h"
15 #include "chromecast/media/cma/ipc/media_message_type.h"
16 #include "chromecast/media/cma/ipc_streamer/audio_decoder_config_marshaller.h"
17 #include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h"
18 #include "chromecast/media/cma/ipc_streamer/video_decoder_config_marshaller.h"
20 namespace chromecast
{
23 AvStreamerProxy::AvStreamerProxy()
26 pending_av_data_(false),
28 weak_this_
= weak_factory_
.GetWeakPtr();
29 thread_checker_
.DetachFromThread();
32 AvStreamerProxy::~AvStreamerProxy() {
33 DCHECK(thread_checker_
.CalledOnValidThread());
36 void AvStreamerProxy::SetCodedFrameProvider(
37 scoped_ptr
<CodedFrameProvider
> frame_provider
) {
38 DCHECK(thread_checker_
.CalledOnValidThread());
39 DCHECK(!frame_provider_
);
40 frame_provider_
.reset(frame_provider
.release());
43 void AvStreamerProxy::SetMediaMessageFifo(
44 scoped_ptr
<MediaMessageFifo
> fifo
) {
45 DCHECK(thread_checker_
.CalledOnValidThread());
47 fifo_
.reset(fifo
.release());
50 void AvStreamerProxy::Start() {
54 RequestBufferIfNeeded();
57 void AvStreamerProxy::StopAndFlush(const base::Closure
& done_cb
) {
60 pending_av_data_
= false;
61 pending_audio_config_
= ::media::AudioDecoderConfig();
62 pending_video_config_
= ::media::VideoDecoderConfig();
63 pending_buffer_
= scoped_refptr
<DecoderBufferBase
>();
65 pending_read_
= false;
66 frame_provider_
->Flush(done_cb
);
69 void AvStreamerProxy::OnFifoReadEvent() {
70 DCHECK(thread_checker_
.CalledOnValidThread());
72 // Some enough space might have been released
73 // to accommodate the pending data.
78 void AvStreamerProxy::RequestBufferIfNeeded() {
79 DCHECK(thread_checker_
.CalledOnValidThread());
81 if (!is_running_
|| pending_read_
|| pending_av_data_
)
84 // |frame_provider_| is assumed to run on the same message loop.
85 // Add a BindToCurrentLoop if that's not the case in the future.
87 frame_provider_
->Read(base::Bind(&AvStreamerProxy::OnNewBuffer
, weak_this_
));
90 void AvStreamerProxy::OnNewBuffer(
91 const scoped_refptr
<DecoderBufferBase
>& buffer
,
92 const ::media::AudioDecoderConfig
& audio_config
,
93 const ::media::VideoDecoderConfig
& video_config
) {
94 DCHECK(thread_checker_
.CalledOnValidThread());
96 pending_read_
= false;
98 if (buffer
->end_of_stream())
101 DCHECK(!pending_av_data_
);
102 pending_av_data_
= true;
104 pending_buffer_
= buffer
;
105 pending_audio_config_
= audio_config
;
106 pending_video_config_
= video_config
;
108 ProcessPendingData();
111 void AvStreamerProxy::ProcessPendingData() {
112 if (pending_audio_config_
.IsValidConfig()) {
113 if (!SendAudioDecoderConfig(pending_audio_config_
))
115 pending_audio_config_
= ::media::AudioDecoderConfig();
118 if (pending_video_config_
.IsValidConfig()) {
119 if (!SendVideoDecoderConfig(pending_video_config_
))
121 pending_video_config_
= ::media::VideoDecoderConfig();
124 if (pending_buffer_
.get()) {
125 if (!SendBuffer(pending_buffer_
))
127 pending_buffer_
= scoped_refptr
<DecoderBufferBase
>();
130 pending_av_data_
= false;
131 base::MessageLoopProxy::current()->PostTask(
133 base::Bind(&AvStreamerProxy::RequestBufferIfNeeded
, weak_this_
));
136 bool AvStreamerProxy::SendAudioDecoderConfig(
137 const ::media::AudioDecoderConfig
& config
) {
138 // Create a dummy message to calculate first the message size.
139 scoped_ptr
<MediaMessage
> dummy_msg(
140 MediaMessage::CreateDummyMessage(AudioConfigMediaMsg
));
141 AudioDecoderConfigMarshaller::Write(config
, dummy_msg
.get());
143 // Create the real message and write the actual content.
144 scoped_ptr
<MediaMessage
> msg(
145 MediaMessage::CreateMessage(
147 base::Bind(&MediaMessageFifo::ReserveMemory
,
148 base::Unretained(fifo_
.get())),
149 dummy_msg
->content_size()));
153 AudioDecoderConfigMarshaller::Write(config
, msg
.get());
157 bool AvStreamerProxy::SendVideoDecoderConfig(
158 const ::media::VideoDecoderConfig
& config
) {
159 // Create a dummy message to calculate first the message size.
160 scoped_ptr
<MediaMessage
> dummy_msg(
161 MediaMessage::CreateDummyMessage(VideoConfigMediaMsg
));
162 VideoDecoderConfigMarshaller::Write(config
, dummy_msg
.get());
164 // Create the real message and write the actual content.
165 scoped_ptr
<MediaMessage
> msg(
166 MediaMessage::CreateMessage(
168 base::Bind(&MediaMessageFifo::ReserveMemory
,
169 base::Unretained(fifo_
.get())),
170 dummy_msg
->content_size()));
174 VideoDecoderConfigMarshaller::Write(config
, msg
.get());
178 bool AvStreamerProxy::SendBuffer(
179 const scoped_refptr
<DecoderBufferBase
>& buffer
) {
180 // Create a dummy message to calculate first the message size.
181 scoped_ptr
<MediaMessage
> dummy_msg(
182 MediaMessage::CreateDummyMessage(FrameMediaMsg
));
183 DecoderBufferBaseMarshaller::Write(buffer
, dummy_msg
.get());
185 // Create the real message and write the actual content.
186 scoped_ptr
<MediaMessage
> msg(
187 MediaMessage::CreateMessage(
189 base::Bind(&MediaMessageFifo::ReserveMemory
,
190 base::Unretained(fifo_
.get())),
191 dummy_msg
->content_size()));
195 DecoderBufferBaseMarshaller::Write(buffer
, msg
.get());
200 } // namespace chromecast