Report errors from ChromiumEnv::GetChildren in Posix.
[chromium-blink-merge.git] / media / filters / video_frame_stream.cc
blob29c5781bc832d1833501e3efe1ced44c52e042bf
1 // Copyright (c) 2013 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 "media/filters/video_frame_stream.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "media/base/bind_to_loop.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/demuxer_stream.h"
15 #include "media/base/video_decoder_config.h"
16 #include "media/filters/decrypting_demuxer_stream.h"
17 #include "media/filters/video_decoder_selector.h"
19 namespace media {
21 VideoFrameStream::VideoFrameStream(
22 const scoped_refptr<base::MessageLoopProxy>& message_loop,
23 ScopedVector<VideoDecoder> decoders,
24 const SetDecryptorReadyCB& set_decryptor_ready_cb)
25 : message_loop_(message_loop),
26 weak_factory_(this),
27 state_(STATE_UNINITIALIZED),
28 stream_(NULL),
29 decoder_selector_(new VideoDecoderSelector(message_loop,
30 decoders.Pass(),
31 set_decryptor_ready_cb)) {
34 VideoFrameStream::~VideoFrameStream() {
35 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_;
38 void VideoFrameStream::Initialize(DemuxerStream* stream,
39 const StatisticsCB& statistics_cb,
40 const InitCB& init_cb) {
41 DVLOG(2) << __FUNCTION__;
42 DCHECK(message_loop_->BelongsToCurrentThread());
43 DCHECK_EQ(state_, STATE_UNINITIALIZED) << state_;
44 DCHECK(init_cb_.is_null());
45 DCHECK(!init_cb.is_null());
47 statistics_cb_ = statistics_cb;
48 init_cb_ = init_cb;
49 stream_ = stream;
51 state_ = STATE_INITIALIZING;
52 // TODO(xhwang): VideoDecoderSelector only needs a config to select a decoder.
53 decoder_selector_->SelectVideoDecoder(
54 stream,
55 base::Bind(&VideoFrameStream::OnDecoderSelected,
56 weak_factory_.GetWeakPtr()));
59 void VideoFrameStream::Read(const ReadCB& read_cb) {
60 DVLOG(2) << __FUNCTION__;
61 DCHECK(message_loop_->BelongsToCurrentThread());
62 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
63 state_ == STATE_ERROR) << state_;
64 // No two reads in the flight at any time.
65 DCHECK(read_cb_.is_null());
66 // No read during resetting or stopping process.
67 DCHECK(reset_cb_.is_null());
68 DCHECK(stop_cb_.is_null());
70 if (state_ == STATE_ERROR) {
71 message_loop_->PostTask(FROM_HERE, base::Bind(
72 read_cb, DECODE_ERROR, scoped_refptr<VideoFrame>()));
73 return;
76 read_cb_ = read_cb;
78 if (state_ == STATE_FLUSHING_DECODER) {
79 FlushDecoder();
80 return;
83 ReadFromDemuxerStream();
86 void VideoFrameStream::Reset(const base::Closure& closure) {
87 DVLOG(2) << __FUNCTION__;
88 DCHECK(message_loop_->BelongsToCurrentThread());
89 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
90 DCHECK(reset_cb_.is_null());
91 DCHECK(stop_cb_.is_null());
93 reset_cb_ = closure;
95 // During decoder reinitialization, VideoDecoder does not need to be and
96 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder
97 // reinitialization.
98 if (state_ == STATE_REINITIALIZING_DECODER)
99 return;
101 // During pending demuxer read and when not using DecryptingDemuxerStream,
102 // VideoDecoder will be reset after demuxer read is returned
103 // (in OnBufferReady()).
104 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_)
105 return;
107 // VideoDecoder API guarantees that if VideoDecoder::Reset() is called during
108 // a pending decode, the decode callback must be fired before the reset
109 // callback is fired. Therefore, we can call VideoDecoder::Reset() regardless
110 // of if we have a pending decode and always satisfy the reset callback when
111 // the decoder reset is finished.
112 if (decrypting_demuxer_stream_) {
113 decrypting_demuxer_stream_->Reset(base::Bind(
114 &VideoFrameStream::ResetDecoder, weak_factory_.GetWeakPtr()));
115 return;
118 ResetDecoder();
121 void VideoFrameStream::Stop(const base::Closure& closure) {
122 DVLOG(2) << __FUNCTION__;
123 DCHECK(message_loop_->BelongsToCurrentThread());
124 DCHECK_NE(state_, STATE_STOPPED) << state_;
125 DCHECK(stop_cb_.is_null());
127 stop_cb_ = closure;
129 if (state_ == STATE_INITIALIZING) {
130 decoder_selector_->Abort();
131 return;
134 DCHECK(init_cb_.is_null());
136 // All pending callbacks will be dropped.
137 weak_factory_.InvalidateWeakPtrs();
139 // Post callbacks to prevent reentrance into this object.
140 if (!read_cb_.is_null())
141 message_loop_->PostTask(FROM_HERE, base::Bind(
142 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<VideoFrame>()));
143 if (!reset_cb_.is_null())
144 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
146 if (decrypting_demuxer_stream_) {
147 decrypting_demuxer_stream_->Reset(base::Bind(
148 &VideoFrameStream::StopDecoder, weak_factory_.GetWeakPtr()));
149 return;
152 // We may not have a |decoder_| if Stop() was called during initialization.
153 if (decoder_) {
154 StopDecoder();
155 return;
158 state_ = STATE_STOPPED;
159 stream_ = NULL;
160 decoder_.reset();
161 decrypting_demuxer_stream_.reset();
162 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
165 bool VideoFrameStream::CanReadWithoutStalling() const {
166 DCHECK(message_loop_->BelongsToCurrentThread());
167 return decoder_->CanReadWithoutStalling();
170 void VideoFrameStream::OnDecoderSelected(
171 scoped_ptr<VideoDecoder> selected_decoder,
172 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
173 DVLOG(2) << __FUNCTION__;
174 DCHECK(message_loop_->BelongsToCurrentThread());
175 DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
176 DCHECK(!init_cb_.is_null());
177 DCHECK(read_cb_.is_null());
178 DCHECK(reset_cb_.is_null());
180 decoder_selector_.reset();
182 if (!selected_decoder) {
183 state_ = STATE_UNINITIALIZED;
184 base::ResetAndReturn(&init_cb_).Run(false, false);
185 } else {
186 state_ = STATE_NORMAL;
187 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
188 if (decrypting_demuxer_stream_)
189 stream_ = decrypting_demuxer_stream_.get();
190 decoder_ = selected_decoder.Pass();
191 if (decoder_->NeedsBitstreamConversion())
192 stream_->EnableBitstreamConverter();
193 // TODO(xhwang): We assume |decoder_->HasAlpha()| does not change after
194 // reinitialization. Check this condition.
195 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha());
198 // Stop() called during initialization.
199 if (!stop_cb_.is_null()) {
200 Stop(base::ResetAndReturn(&stop_cb_));
201 return;
205 void VideoFrameStream::SatisfyRead(Status status,
206 const scoped_refptr<VideoFrame>& frame) {
207 DCHECK(!read_cb_.is_null());
208 base::ResetAndReturn(&read_cb_).Run(status, frame);
211 void VideoFrameStream::AbortRead() {
212 // Abort read during pending reset. It is safe to fire the |read_cb_| directly
213 // instead of posting it because VideoRenderBase won't call into this class
214 // again when it's in kFlushing state.
215 // TODO(xhwang): Improve the resetting process to avoid this dependency on the
216 // caller.
217 DCHECK(!reset_cb_.is_null());
218 SatisfyRead(ABORTED, NULL);
221 void VideoFrameStream::Decode(const scoped_refptr<DecoderBuffer>& buffer) {
222 DVLOG(2) << __FUNCTION__;
223 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
224 DCHECK(!read_cb_.is_null());
225 DCHECK(reset_cb_.is_null());
226 DCHECK(stop_cb_.is_null());
227 DCHECK(buffer);
229 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
230 decoder_->Decode(buffer, base::Bind(&VideoFrameStream::OnFrameReady,
231 weak_factory_.GetWeakPtr(), buffer_size));
234 void VideoFrameStream::FlushDecoder() {
235 Decode(DecoderBuffer::CreateEOSBuffer());
238 void VideoFrameStream::OnFrameReady(int buffer_size,
239 const VideoDecoder::Status status,
240 const scoped_refptr<VideoFrame>& frame) {
241 DVLOG(2) << __FUNCTION__;
242 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
243 DCHECK(!read_cb_.is_null());
244 DCHECK(stop_cb_.is_null());
246 if (status == VideoDecoder::kDecodeError) {
247 DCHECK(!frame.get());
248 state_ = STATE_ERROR;
249 SatisfyRead(DECODE_ERROR, NULL);
250 return;
253 if (status == VideoDecoder::kDecryptError) {
254 DCHECK(!frame.get());
255 state_ = STATE_ERROR;
256 SatisfyRead(DECRYPT_ERROR, NULL);
257 return;
260 // Any successful decode counts!
261 if (buffer_size > 0) {
262 PipelineStatistics statistics;
263 statistics.video_bytes_decoded = buffer_size;
264 statistics_cb_.Run(statistics);
267 // Drop decoding result if Reset() was called during decoding.
268 // The resetting process will be handled when the decoder is reset.
269 if (!reset_cb_.is_null()) {
270 AbortRead();
271 return;
274 // Decoder flushed. Reinitialize the video decoder.
275 if (state_ == STATE_FLUSHING_DECODER &&
276 status == VideoDecoder::kOk && frame->IsEndOfStream()) {
277 ReinitializeDecoder();
278 return;
281 if (status == VideoDecoder::kNotEnoughData) {
282 if (state_ == STATE_NORMAL)
283 ReadFromDemuxerStream();
284 else if (state_ == STATE_FLUSHING_DECODER)
285 FlushDecoder();
286 return;
289 SatisfyRead(OK, frame);
292 void VideoFrameStream::ReadFromDemuxerStream() {
293 DVLOG(2) << __FUNCTION__;
294 DCHECK_EQ(state_, STATE_NORMAL) << state_;
295 DCHECK(!read_cb_.is_null());
296 DCHECK(reset_cb_.is_null());
297 DCHECK(stop_cb_.is_null());
299 state_ = STATE_PENDING_DEMUXER_READ;
300 stream_->Read(
301 base::Bind(&VideoFrameStream::OnBufferReady, weak_factory_.GetWeakPtr()));
304 void VideoFrameStream::OnBufferReady(
305 DemuxerStream::Status status,
306 const scoped_refptr<DecoderBuffer>& buffer) {
307 DVLOG(2) << __FUNCTION__;
308 DCHECK(message_loop_->BelongsToCurrentThread());
309 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_;
310 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
311 DCHECK(!read_cb_.is_null());
312 DCHECK(stop_cb_.is_null());
314 state_ = STATE_NORMAL;
316 if (status == DemuxerStream::kConfigChanged) {
317 state_ = STATE_FLUSHING_DECODER;
318 if (!reset_cb_.is_null()) {
319 AbortRead();
320 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
321 // which will continue the resetting process in it's callback.
322 if (!decrypting_demuxer_stream_)
323 Reset(base::ResetAndReturn(&reset_cb_));
324 // Reinitialization will continue after Reset() is done.
325 } else {
326 FlushDecoder();
328 return;
331 if (!reset_cb_.is_null()) {
332 AbortRead();
333 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
334 // which will continue the resetting process in it's callback.
335 if (!decrypting_demuxer_stream_)
336 Reset(base::ResetAndReturn(&reset_cb_));
337 return;
340 if (status == DemuxerStream::kAborted) {
341 SatisfyRead(DEMUXER_READ_ABORTED, NULL);
342 return;
345 DCHECK(status == DemuxerStream::kOk) << status;
346 Decode(buffer);
349 void VideoFrameStream::ReinitializeDecoder() {
350 DVLOG(2) << __FUNCTION__;
351 DCHECK(message_loop_->BelongsToCurrentThread());
352 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
354 DCHECK(stream_->video_decoder_config().IsValidConfig());
355 state_ = STATE_REINITIALIZING_DECODER;
356 decoder_->Initialize(stream_->video_decoder_config(),
357 base::Bind(&VideoFrameStream::OnDecoderReinitialized,
358 weak_factory_.GetWeakPtr()));
361 void VideoFrameStream::OnDecoderReinitialized(PipelineStatus status) {
362 DVLOG(2) << __FUNCTION__;
363 DCHECK(message_loop_->BelongsToCurrentThread());
364 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
365 DCHECK(stop_cb_.is_null());
367 // ReinitializeDecoder() can be called in two cases:
368 // 1, Flushing decoder finished (see OnFrameReady()).
369 // 2, Reset() was called during flushing decoder (see OnDecoderReset()).
370 // Also, Reset() can be called during pending ReinitializeDecoder().
371 // This function needs to handle them all!
373 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR;
375 if (!reset_cb_.is_null()) {
376 if (!read_cb_.is_null())
377 AbortRead();
378 base::ResetAndReturn(&reset_cb_).Run();
381 if (read_cb_.is_null())
382 return;
384 if (state_ == STATE_ERROR) {
385 SatisfyRead(DECODE_ERROR, NULL);
386 return;
389 ReadFromDemuxerStream();
392 void VideoFrameStream::ResetDecoder() {
393 DVLOG(2) << __FUNCTION__;
394 DCHECK(message_loop_->BelongsToCurrentThread());
395 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
396 state_ == STATE_ERROR) << state_;
397 DCHECK(!reset_cb_.is_null());
399 decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset,
400 weak_factory_.GetWeakPtr()));
403 void VideoFrameStream::OnDecoderReset() {
404 DVLOG(2) << __FUNCTION__;
405 DCHECK(message_loop_->BelongsToCurrentThread());
406 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
407 state_ == STATE_ERROR) << state_;
408 // If Reset() was called during pending read, read callback should be fired
409 // before the reset callback is fired.
410 DCHECK(read_cb_.is_null());
411 DCHECK(!reset_cb_.is_null());
412 DCHECK(stop_cb_.is_null());
414 if (state_ != STATE_FLUSHING_DECODER) {
415 base::ResetAndReturn(&reset_cb_).Run();
416 return;
419 // The resetting process will be continued in OnDecoderReinitialized().
420 ReinitializeDecoder();
423 void VideoFrameStream::StopDecoder() {
424 DVLOG(2) << __FUNCTION__;
425 DCHECK(message_loop_->BelongsToCurrentThread());
426 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
427 DCHECK(!stop_cb_.is_null());
429 decoder_->Stop(base::Bind(&VideoFrameStream::OnDecoderStopped,
430 weak_factory_.GetWeakPtr()));
433 void VideoFrameStream::OnDecoderStopped() {
434 DVLOG(2) << __FUNCTION__;
435 DCHECK(message_loop_->BelongsToCurrentThread());
436 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
437 // If Stop() was called during pending read/reset, read/reset callback should
438 // be fired before the stop callback is fired.
439 DCHECK(read_cb_.is_null());
440 DCHECK(reset_cb_.is_null());
441 DCHECK(!stop_cb_.is_null());
443 state_ = STATE_STOPPED;
444 stream_ = NULL;
445 decoder_.reset();
446 decrypting_demuxer_stream_.reset();
447 base::ResetAndReturn(&stop_cb_).Run();
450 } // namespace media