Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(945)

Side by Side Diff: media/filters/decoder_stream.cc

Issue 297553002: Add callback in VideoDecoder and AudioDecoder to return decoded frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/decoder_stream.h" 5 #include "media/filters/decoder_stream.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 statistics_cb_ = statistics_cb; 73 statistics_cb_ = statistics_cb;
74 init_cb_ = init_cb; 74 init_cb_ = init_cb;
75 stream_ = stream; 75 stream_ = stream;
76 low_delay_ = low_delay; 76 low_delay_ = low_delay;
77 77
78 state_ = STATE_INITIALIZING; 78 state_ = STATE_INITIALIZING;
79 // TODO(xhwang): DecoderSelector only needs a config to select a decoder. 79 // TODO(xhwang): DecoderSelector only needs a config to select a decoder.
80 decoder_selector_->SelectDecoder( 80 decoder_selector_->SelectDecoder(
81 stream, low_delay, 81 stream, low_delay,
82 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, 82 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
83 weak_factory_.GetWeakPtr()),
84 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
83 weak_factory_.GetWeakPtr())); 85 weak_factory_.GetWeakPtr()));
84 } 86 }
85 87
86 template <DemuxerStream::Type StreamType> 88 template <DemuxerStream::Type StreamType>
87 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { 89 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
88 FUNCTION_DVLOG(2); 90 FUNCTION_DVLOG(2);
89 DCHECK(task_runner_->BelongsToCurrentThread()); 91 DCHECK(task_runner_->BelongsToCurrentThread());
90 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || 92 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
91 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || 93 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER ||
92 state_ == STATE_PENDING_DEMUXER_READ) 94 state_ == STATE_PENDING_DEMUXER_READ)
(...skipping 13 matching lines...) Expand all
106 scoped_refptr<Output>())); 108 scoped_refptr<Output>()));
107 return; 109 return;
108 } 110 }
109 111
110 if (!ready_outputs_.empty()) { 112 if (!ready_outputs_.empty()) {
111 task_runner_->PostTask(FROM_HERE, base::Bind( 113 task_runner_->PostTask(FROM_HERE, base::Bind(
112 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front())); 114 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front()));
113 ready_outputs_.pop_front(); 115 ready_outputs_.pop_front();
114 } 116 }
115 117
116 // Decoder may be in reinitializing state as result of the previous Read(). 118 if (state_ == STATE_NORMAL && CanDecodeMore())
117 if (state_ == STATE_REINITIALIZING_DECODER)
118 return;
119
120 if (!CanDecodeMore())
121 return;
122
123 if (state_ == STATE_FLUSHING_DECODER) {
124 FlushDecoder();
125 return;
126 }
127
128 if (state_ != STATE_PENDING_DEMUXER_READ)
129 ReadFromDemuxerStream(); 119 ReadFromDemuxerStream();
130 } 120 }
131 121
132 template <DemuxerStream::Type StreamType> 122 template <DemuxerStream::Type StreamType>
133 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { 123 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
134 FUNCTION_DVLOG(2); 124 FUNCTION_DVLOG(2);
135 DCHECK(task_runner_->BelongsToCurrentThread()); 125 DCHECK(task_runner_->BelongsToCurrentThread());
136 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; 126 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
137 DCHECK(reset_cb_.is_null()); 127 DCHECK(reset_cb_.is_null());
138 DCHECK(stop_cb_.is_null()); 128 DCHECK(stop_cb_.is_null());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 state_ = STATE_STOPPED; 199 state_ = STATE_STOPPED;
210 stream_ = NULL; 200 stream_ = NULL;
211 decoder_.reset(); 201 decoder_.reset();
212 decrypting_demuxer_stream_.reset(); 202 decrypting_demuxer_stream_.reset();
213 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); 203 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
214 } 204 }
215 205
216 template <DemuxerStream::Type StreamType> 206 template <DemuxerStream::Type StreamType>
217 bool DecoderStream<StreamType>::CanReadWithoutStalling() const { 207 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
218 DCHECK(task_runner_->BelongsToCurrentThread()); 208 DCHECK(task_runner_->BelongsToCurrentThread());
219 return decoder_->CanReadWithoutStalling(); 209 return decoder_->CanReadWithoutStalling();
xhwang 2014/05/29 22:15:14 !ready_outputs_.empty() || decoder_->CanReadWithou
Sergey Ulanov 2014/06/03 00:08:11 Done.
220 } 210 }
221 211
222 template <> 212 template <>
223 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { 213 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const {
224 DCHECK(task_runner_->BelongsToCurrentThread()); 214 DCHECK(task_runner_->BelongsToCurrentThread());
225 return true; 215 return true;
226 } 216 }
227 217
228 template <DemuxerStream::Type StreamType> 218 template <DemuxerStream::Type StreamType>
229 bool DecoderStream<StreamType>::CanDecodeMore() const { 219 bool DecoderStream<StreamType>::CanDecodeMore() const {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 DCHECK(CanDecodeMore()); 283 DCHECK(CanDecodeMore());
294 DCHECK(reset_cb_.is_null()); 284 DCHECK(reset_cb_.is_null());
295 DCHECK(stop_cb_.is_null()); 285 DCHECK(stop_cb_.is_null());
296 DCHECK(buffer); 286 DCHECK(buffer);
297 287
298 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); 288 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
299 289
300 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); 290 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this);
301 ++pending_decode_requests_; 291 ++pending_decode_requests_;
302 decoder_->Decode(buffer, 292 decoder_->Decode(buffer,
303 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, 293 base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
304 weak_factory_.GetWeakPtr(), 294 weak_factory_.GetWeakPtr(),
305 buffer_size)); 295 buffer_size,
296 buffer->end_of_stream()));
306 } 297 }
307 298
308 template <DemuxerStream::Type StreamType> 299 template <DemuxerStream::Type StreamType>
309 void DecoderStream<StreamType>::FlushDecoder() { 300 void DecoderStream<StreamType>::FlushDecoder() {
310 if (pending_decode_requests_ == 0) 301 Decode(DecoderBuffer::CreateEOSBuffer());
311 Decode(DecoderBuffer::CreateEOSBuffer());
312 } 302 }
313 303
314 template <DemuxerStream::Type StreamType> 304 template <DemuxerStream::Type StreamType>
315 void DecoderStream<StreamType>::OnDecodeOutputReady( 305 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
316 int buffer_size, 306 bool end_of_stream,
317 typename Decoder::Status status, 307 typename Decoder::Status status) {
318 const scoped_refptr<Output>& output) { 308 FUNCTION_DVLOG(2) << status;
319 FUNCTION_DVLOG(2) << status << " " << output;
320 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || 309 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
321 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) 310 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
322 << state_; 311 << state_;
323 DCHECK(stop_cb_.is_null()); 312 DCHECK(stop_cb_.is_null());
324 DCHECK_EQ(status == Decoder::kOk, output != NULL);
325 DCHECK_GT(pending_decode_requests_, 0); 313 DCHECK_GT(pending_decode_requests_, 0);
326 314
327 --pending_decode_requests_; 315 --pending_decode_requests_;
328 316
329 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); 317 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this);
330 318
331 if (state_ == STATE_ERROR) { 319 if (state_ == STATE_ERROR) {
332 DCHECK(read_cb_.is_null()); 320 DCHECK(read_cb_.is_null());
333 return; 321 return;
334 } 322 }
335 323
336 if (status == Decoder::kDecodeError) { 324 // Drop decoding result if Reset() was called during decoding.
337 state_ = STATE_ERROR; 325 // The resetting process will be handled when the decoder is reset.
338 ready_outputs_.clear(); 326 if (!reset_cb_.is_null())
339 if (!read_cb_.is_null()) 327 return;
340 SatisfyRead(DECODE_ERROR, NULL); 328
329 switch (status) {
330 case Decoder::kDecodeError:
331 state_ = STATE_ERROR;
332 ready_outputs_.clear();
333 if (!read_cb_.is_null())
334 SatisfyRead(DECODE_ERROR, NULL);
335 break;
336
337 case Decoder::kDecryptError:
338 state_ = STATE_ERROR;
339 ready_outputs_.clear();
340 if (!read_cb_.is_null())
341 SatisfyRead(DECRYPT_ERROR, NULL);
342 break;
xhwang 2014/05/29 22:15:14 nit: DECRYPT_ERROR is going to be obsolete. Feel f
Sergey Ulanov 2014/06/03 00:08:11 Done.
343
344 case Decoder::kAborted:
xhwang 2014/05/29 22:15:14 IIUIC, This should only happen during Reset(), whi
Sergey Ulanov 2014/06/03 00:08:11 No. This came up with a previous CL as well: https
xhwang 2014/06/05 21:53:48 hmm... Thanks for reminding me of that discussion!
Sergey Ulanov 2014/06/06 22:49:39 Done.
345 if (!read_cb_.is_null())
346 SatisfyRead(ABORTED, NULL);
347 break;
348
349 case Decoder::kOk:
350 // Any successful decode counts!
351 if (buffer_size > 0) {
352 StreamTraits::ReportStatistics(statistics_cb_, buffer_size);
353 }
354
355 if (state_ == STATE_NORMAL) {
356 if (CanDecodeMore() && !end_of_stream)
357 ReadFromDemuxerStream();
358 } else if (state_ == STATE_FLUSHING_DECODER) {
359 if (!pending_decode_requests_)
360 ReinitializeDecoder();
xhwang 2014/05/29 22:15:14 Hmm, we should only ReinitializeDecoder() after th
Sergey Ulanov 2014/06/03 00:08:11 ReinitializeDecoder() should be called only after
xhwang 2014/06/05 21:53:48 Now I understand that comment. Thanks.
361 }
362 break;
363 }
364 }
365
366 template <DemuxerStream::Type StreamType>
367 void DecoderStream<StreamType>::OnDecodeOutputReady(
368 const scoped_refptr<Output>& output) {
369 FUNCTION_DVLOG(2) << output;
370 DCHECK(output);
371 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
372 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
373 << state_;
374
375 if (state_ == STATE_ERROR) {
376 DCHECK(read_cb_.is_null());
341 return; 377 return;
342 } 378 }
343 379
344 if (status == Decoder::kDecryptError) {
345 state_ = STATE_ERROR;
346 ready_outputs_.clear();
347 if (!read_cb_.is_null())
348 SatisfyRead(DECRYPT_ERROR, NULL);
349 return;
350 }
351
352 if (status == Decoder::kAborted) {
353 if (!read_cb_.is_null())
354 SatisfyRead(ABORTED, NULL);
355 return;
356 }
357
358 // Any successful decode counts!
359 if (buffer_size > 0) {
360 StreamTraits::ReportStatistics(statistics_cb_, buffer_size);
361 }
362
363 // Drop decoding result if Reset() was called during decoding. 380 // Drop decoding result if Reset() was called during decoding.
364 // The resetting process will be handled when the decoder is reset. 381 // The resetting process will be handled when the decoder is reset.
365 if (!reset_cb_.is_null()) 382 if (!reset_cb_.is_null())
366 return; 383 return;
367 384
368 // Decoder flushed. Reinitialize the decoder. 385 if (state_ == STATE_FLUSHING_DECODER && output->end_of_stream()) {
369 if (state_ == STATE_FLUSHING_DECODER && 386 // ReinitializeDecoder() will be called from OnDecodeDone().
xhwang 2014/05/29 22:15:14 See comment above about when to ReinitializeDecode
Sergey Ulanov 2014/06/03 00:08:11 See my comment - it's better to keep it in OnDecod
370 status == Decoder::kOk && output->end_of_stream()) {
371 ReinitializeDecoder();
372 return; 387 return;
373 } 388 }
374 389
375 if (status == Decoder::kNotEnoughData) {
376 if (state_ == STATE_NORMAL)
377 ReadFromDemuxerStream();
378 else if (state_ == STATE_FLUSHING_DECODER)
379 FlushDecoder();
380 return;
381 }
382
383 DCHECK(output);
384
385 // Store decoded output. 390 // Store decoded output.
386 ready_outputs_.push_back(output); 391 ready_outputs_.push_back(output);
387 scoped_refptr<Output> extra_output;
388 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) {
389 ready_outputs_.push_back(extra_output);
390 }
391 392
392 // Satisfy outstanding read request, if any. 393 // Satisfy outstanding read request, if any.
393 if (!read_cb_.is_null()) { 394 if (!read_cb_.is_null()) {
394 scoped_refptr<Output> read_result = ready_outputs_.front(); 395 scoped_refptr<Output> read_result = ready_outputs_.front();
395 ready_outputs_.pop_front(); 396 ready_outputs_.pop_front();
396 SatisfyRead(OK, output); 397 SatisfyRead(OK, output);
397 } 398 }
398 } 399 }
399 400
400 template <DemuxerStream::Type StreamType> 401 template <DemuxerStream::Type StreamType>
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 454
454 if (!reset_cb_.is_null()) { 455 if (!reset_cb_.is_null()) {
455 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() 456 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
456 // which will continue the resetting process in it's callback. 457 // which will continue the resetting process in it's callback.
457 if (!decrypting_demuxer_stream_) 458 if (!decrypting_demuxer_stream_)
458 Reset(base::ResetAndReturn(&reset_cb_)); 459 Reset(base::ResetAndReturn(&reset_cb_));
459 return; 460 return;
460 } 461 }
461 462
462 if (status == DemuxerStream::kAborted) { 463 if (status == DemuxerStream::kAborted) {
463 SatisfyRead(DEMUXER_READ_ABORTED, NULL); 464 SatisfyRead(DEMUXER_READ_ABORTED, NULL);
xhwang 2014/06/05 21:53:48 hmm, actually, shall we check whether read_cb_.is_
464 return; 465 return;
465 } 466 }
466 467
467 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { 468 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) {
468 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); 469 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp();
469 if (active_splice_ || has_splice_ts) { 470 if (active_splice_ || has_splice_ts) {
470 splice_observer_cb_.Run(buffer->splice_timestamp()); 471 splice_observer_cb_.Run(buffer->splice_timestamp());
471 active_splice_ = has_splice_ts; 472 active_splice_ = has_splice_ts;
472 } 473 }
473 } 474 }
(...skipping 13 matching lines...) Expand all
487 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; 488 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
488 DCHECK_EQ(pending_decode_requests_, 0); 489 DCHECK_EQ(pending_decode_requests_, 0);
489 490
490 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); 491 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig());
491 state_ = STATE_REINITIALIZING_DECODER; 492 state_ = STATE_REINITIALIZING_DECODER;
492 DecoderStreamTraits<StreamType>::Initialize( 493 DecoderStreamTraits<StreamType>::Initialize(
493 decoder_.get(), 494 decoder_.get(),
494 StreamTraits::GetDecoderConfig(*stream_), 495 StreamTraits::GetDecoderConfig(*stream_),
495 low_delay_, 496 low_delay_,
496 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, 497 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
498 weak_factory_.GetWeakPtr()),
499 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
497 weak_factory_.GetWeakPtr())); 500 weak_factory_.GetWeakPtr()));
498 } 501 }
499 502
500 template <DemuxerStream::Type StreamType> 503 template <DemuxerStream::Type StreamType>
501 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { 504 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
502 FUNCTION_DVLOG(2); 505 FUNCTION_DVLOG(2);
503 DCHECK(task_runner_->BelongsToCurrentThread()); 506 DCHECK(task_runner_->BelongsToCurrentThread());
504 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; 507 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
505 DCHECK(stop_cb_.is_null()); 508 DCHECK(stop_cb_.is_null());
506 509
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 decrypting_demuxer_stream_.reset(); 578 decrypting_demuxer_stream_.reset();
576 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also 579 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also
577 // posted in Stop(). 580 // posted in Stop().
578 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); 581 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
579 } 582 }
580 583
581 template class DecoderStream<DemuxerStream::VIDEO>; 584 template class DecoderStream<DemuxerStream::VIDEO>;
582 template class DecoderStream<DemuxerStream::AUDIO>; 585 template class DecoderStream<DemuxerStream::AUDIO>;
583 586
584 } // namespace media 587 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698