OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/single_thread_task_runner.h" | |
10 #include "base/threading/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" | |
20 | |
21 namespace chromecast { | |
22 namespace media { | |
23 | |
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(); | |
31 } | |
32 | |
33 AvStreamerProxy::~AvStreamerProxy() { | |
34 DCHECK(thread_checker_.CalledOnValidThread()); | |
35 } | |
36 | |
37 void AvStreamerProxy::SetCodedFrameProvider( | |
38 std::unique_ptr<CodedFrameProvider> frame_provider) { | |
39 DCHECK(thread_checker_.CalledOnValidThread()); | |
40 DCHECK(!frame_provider_); | |
41 frame_provider_.reset(frame_provider.release()); | |
42 } | |
43 | |
44 void AvStreamerProxy::SetMediaMessageFifo( | |
45 std::unique_ptr<MediaMessageFifo> fifo) { | |
46 DCHECK(thread_checker_.CalledOnValidThread()); | |
47 DCHECK(!fifo_); | |
48 fifo_.reset(fifo.release()); | |
49 } | |
50 | |
51 void AvStreamerProxy::Start() { | |
52 DCHECK(!is_running_); | |
53 | |
54 is_running_ = true; | |
55 RequestBufferIfNeeded(); | |
56 } | |
57 | |
58 void AvStreamerProxy::StopAndFlush(const base::Closure& done_cb) { | |
59 DCHECK(thread_checker_.CalledOnValidThread()); | |
60 DCHECK(!done_cb.is_null()); | |
61 | |
62 pending_av_data_ = false; | |
63 pending_audio_config_ = ::media::AudioDecoderConfig(); | |
64 pending_video_config_ = ::media::VideoDecoderConfig(); | |
65 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | |
66 | |
67 pending_read_ = false; | |
68 is_running_ = false; | |
69 | |
70 // If there's another pending Flush, for example, the pipeline is stopped | |
71 // while another seek is pending, then we don't need to call Flush again. Save | |
72 // the callback and fire it later when Flush is done. | |
73 pending_stop_flush_cb_list_.push_back(done_cb); | |
74 if (pending_stop_flush_cb_list_.size() == 1) { | |
75 frame_provider_->Flush( | |
76 base::Bind(&AvStreamerProxy::OnStopAndFlushDone, weak_this_)); | |
77 } | |
78 } | |
79 | |
80 void AvStreamerProxy::OnStopAndFlushDone() { | |
81 DCHECK(thread_checker_.CalledOnValidThread()); | |
82 | |
83 // Flush is done. Fire all the "flush done" callbacks in order. This is | |
84 // necessary to guarantee proper state transition in pipeline. | |
85 for (const auto& cb : pending_stop_flush_cb_list_) { | |
86 cb.Run(); | |
87 } | |
88 pending_stop_flush_cb_list_.clear(); | |
89 } | |
90 | |
91 void AvStreamerProxy::OnFifoReadEvent() { | |
92 DCHECK(thread_checker_.CalledOnValidThread()); | |
93 | |
94 // Some enough space might have been released | |
95 // to accommodate the pending data. | |
96 if (pending_av_data_) | |
97 ProcessPendingData(); | |
98 } | |
99 | |
100 void AvStreamerProxy::RequestBufferIfNeeded() { | |
101 DCHECK(thread_checker_.CalledOnValidThread()); | |
102 | |
103 if (!is_running_ || pending_read_ || pending_av_data_) | |
104 return; | |
105 | |
106 // |frame_provider_| is assumed to run on the same message loop. | |
107 // Add a BindToCurrentLoop if that's not the case in the future. | |
108 pending_read_ = true; | |
109 frame_provider_->Read(base::Bind(&AvStreamerProxy::OnNewBuffer, weak_this_)); | |
110 } | |
111 | |
112 void AvStreamerProxy::OnNewBuffer( | |
113 const scoped_refptr<DecoderBufferBase>& buffer, | |
114 const ::media::AudioDecoderConfig& audio_config, | |
115 const ::media::VideoDecoderConfig& video_config) { | |
116 DCHECK(thread_checker_.CalledOnValidThread()); | |
117 | |
118 pending_read_ = false; | |
119 | |
120 if (buffer->end_of_stream()) | |
121 is_running_ = false; | |
122 | |
123 DCHECK(!pending_av_data_); | |
124 pending_av_data_ = true; | |
125 | |
126 pending_buffer_ = buffer; | |
127 pending_audio_config_ = audio_config; | |
128 pending_video_config_ = video_config; | |
129 | |
130 ProcessPendingData(); | |
131 } | |
132 | |
133 void AvStreamerProxy::ProcessPendingData() { | |
134 if (pending_audio_config_.IsValidConfig()) { | |
135 if (!SendAudioDecoderConfig(pending_audio_config_)) | |
136 return; | |
137 pending_audio_config_ = ::media::AudioDecoderConfig(); | |
138 } | |
139 | |
140 if (pending_video_config_.IsValidConfig()) { | |
141 if (!SendVideoDecoderConfig(pending_video_config_)) | |
142 return; | |
143 pending_video_config_ = ::media::VideoDecoderConfig(); | |
144 } | |
145 | |
146 if (pending_buffer_.get()) { | |
147 if (!SendBuffer(pending_buffer_)) | |
148 return; | |
149 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | |
150 } | |
151 | |
152 pending_av_data_ = false; | |
153 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
154 FROM_HERE, | |
155 base::Bind(&AvStreamerProxy::RequestBufferIfNeeded, weak_this_)); | |
156 } | |
157 | |
158 bool AvStreamerProxy::SendAudioDecoderConfig( | |
159 const ::media::AudioDecoderConfig& config) { | |
160 // Create a dummy message to calculate first the message size. | |
161 std::unique_ptr<MediaMessage> dummy_msg( | |
162 MediaMessage::CreateDummyMessage(AudioConfigMediaMsg)); | |
163 AudioDecoderConfigMarshaller::Write(config, dummy_msg.get()); | |
164 | |
165 // Create the real message and write the actual content. | |
166 std::unique_ptr<MediaMessage> msg(MediaMessage::CreateMessage( | |
167 AudioConfigMediaMsg, base::Bind(&MediaMessageFifo::ReserveMemory, | |
168 base::Unretained(fifo_.get())), | |
169 dummy_msg->content_size())); | |
170 if (!msg) | |
171 return false; | |
172 | |
173 AudioDecoderConfigMarshaller::Write(config, msg.get()); | |
174 return true; | |
175 } | |
176 | |
177 bool AvStreamerProxy::SendVideoDecoderConfig( | |
178 const ::media::VideoDecoderConfig& config) { | |
179 // Create a dummy message to calculate first the message size. | |
180 std::unique_ptr<MediaMessage> dummy_msg( | |
181 MediaMessage::CreateDummyMessage(VideoConfigMediaMsg)); | |
182 VideoDecoderConfigMarshaller::Write(config, dummy_msg.get()); | |
183 | |
184 // Create the real message and write the actual content. | |
185 std::unique_ptr<MediaMessage> msg(MediaMessage::CreateMessage( | |
186 VideoConfigMediaMsg, base::Bind(&MediaMessageFifo::ReserveMemory, | |
187 base::Unretained(fifo_.get())), | |
188 dummy_msg->content_size())); | |
189 if (!msg) | |
190 return false; | |
191 | |
192 VideoDecoderConfigMarshaller::Write(config, msg.get()); | |
193 return true; | |
194 } | |
195 | |
196 bool AvStreamerProxy::SendBuffer( | |
197 const scoped_refptr<DecoderBufferBase>& buffer) { | |
198 // Create a dummy message to calculate first the message size. | |
199 std::unique_ptr<MediaMessage> dummy_msg( | |
200 MediaMessage::CreateDummyMessage(FrameMediaMsg)); | |
201 DecoderBufferBaseMarshaller::Write(buffer, dummy_msg.get()); | |
202 | |
203 // Create the real message and write the actual content. | |
204 std::unique_ptr<MediaMessage> msg(MediaMessage::CreateMessage( | |
205 FrameMediaMsg, base::Bind(&MediaMessageFifo::ReserveMemory, | |
206 base::Unretained(fifo_.get())), | |
207 dummy_msg->content_size())); | |
208 if (!msg) | |
209 return false; | |
210 | |
211 DecoderBufferBaseMarshaller::Write(buffer, msg.get()); | |
212 return true; | |
213 } | |
214 | |
215 } // namespace media | |
216 } // namespace chromecast | |
OLD | NEW |