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

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

Issue 141243003: Add AudioBufferStream. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@decoderstream_rebased
Patch Set: fix ffmpeg_regression_tests failures Created 6 years, 9 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
« no previous file with comments | « media/filters/decoder_stream.h ('k') | media/filters/decoder_stream_traits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "media/base/audio_decoder.h"
13 #include "media/base/bind_to_current_loop.h" 14 #include "media/base/bind_to_current_loop.h"
14 #include "media/base/decoder_buffer.h" 15 #include "media/base/decoder_buffer.h"
15 #include "media/base/demuxer_stream.h" 16 #include "media/base/demuxer_stream.h"
16 #include "media/base/video_decoder.h" 17 #include "media/base/video_decoder.h"
17 #include "media/filters/decrypting_demuxer_stream.h" 18 #include "media/filters/decrypting_demuxer_stream.h"
18 19
19 namespace media { 20 namespace media {
20 21
21 // TODO(rileya): Devise a better way of specifying trace/UMA/etc strings for 22 // TODO(rileya): Devise a better way of specifying trace/UMA/etc strings for
22 // templated classes such as this. 23 // templated classes such as this.
23 template <DemuxerStream::Type StreamType> 24 template <DemuxerStream::Type StreamType>
24 static const char* GetTraceString(); 25 static const char* GetTraceString();
25 26
26 template <> 27 template <>
27 const char* GetTraceString<DemuxerStream::VIDEO>() { 28 const char* GetTraceString<DemuxerStream::VIDEO>() {
28 return "DecoderStream<VIDEO>::Decode"; 29 return "DecoderStream<VIDEO>::Decode";
29 } 30 }
30 31
32 template <>
33 const char* GetTraceString<DemuxerStream::AUDIO>() {
34 return "DecoderStream<AUDIO>::Decode";
35 }
36
31 template <DemuxerStream::Type StreamType> 37 template <DemuxerStream::Type StreamType>
32 DecoderStream<StreamType>::DecoderStream( 38 DecoderStream<StreamType>::DecoderStream(
33 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 39 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
34 ScopedVector<Decoder> decoders, 40 ScopedVector<Decoder> decoders,
35 const SetDecryptorReadyCB& set_decryptor_ready_cb) 41 const SetDecryptorReadyCB& set_decryptor_ready_cb)
36 : task_runner_(task_runner), 42 : task_runner_(task_runner),
37 weak_factory_(this), 43 weak_factory_(this),
38 state_(STATE_UNINITIALIZED), 44 state_(STATE_UNINITIALIZED),
39 stream_(NULL), 45 stream_(NULL),
40 decoder_selector_( 46 decoder_selector_(
(...skipping 17 matching lines...) Expand all
58 DCHECK(!init_cb.is_null()); 64 DCHECK(!init_cb.is_null());
59 65
60 statistics_cb_ = statistics_cb; 66 statistics_cb_ = statistics_cb;
61 init_cb_ = init_cb; 67 init_cb_ = init_cb;
62 stream_ = stream; 68 stream_ = stream;
63 69
64 state_ = STATE_INITIALIZING; 70 state_ = STATE_INITIALIZING;
65 // TODO(xhwang): DecoderSelector only needs a config to select a decoder. 71 // TODO(xhwang): DecoderSelector only needs a config to select a decoder.
66 decoder_selector_->SelectDecoder( 72 decoder_selector_->SelectDecoder(
67 stream, 73 stream,
68 StatisticsCB(),
69 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, 74 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
70 weak_factory_.GetWeakPtr())); 75 weak_factory_.GetWeakPtr()));
71 } 76 }
72 77
73 template <DemuxerStream::Type StreamType> 78 template <DemuxerStream::Type StreamType>
74 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { 79 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
75 DVLOG(2) << __FUNCTION__; 80 DVLOG(2) << __FUNCTION__;
76 DCHECK(task_runner_->BelongsToCurrentThread()); 81 DCHECK(task_runner_->BelongsToCurrentThread());
77 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || 82 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
78 state_ == STATE_ERROR) << state_; 83 state_ == STATE_ERROR) << state_;
79 // No two reads in the flight at any time. 84 // No two reads in the flight at any time.
80 DCHECK(read_cb_.is_null()); 85 DCHECK(read_cb_.is_null());
81 // No read during resetting or stopping process. 86 // No read during resetting or stopping process.
82 DCHECK(reset_cb_.is_null()); 87 DCHECK(reset_cb_.is_null());
83 DCHECK(stop_cb_.is_null()); 88 DCHECK(stop_cb_.is_null());
84 89
85 if (state_ == STATE_ERROR) { 90 if (state_ == STATE_ERROR) {
86 task_runner_->PostTask(FROM_HERE, base::Bind( 91 task_runner_->PostTask(FROM_HERE, base::Bind(
87 read_cb, DECODE_ERROR, scoped_refptr<Output>())); 92 read_cb, DECODE_ERROR, scoped_refptr<Output>()));
88 return; 93 return;
89 } 94 }
90 95
91 read_cb_ = read_cb; 96 read_cb_ = BindToCurrentLoop(read_cb);
rileya (GONE FROM CHROMIUM) 2014/03/10 18:22:25 Is this reasonable? This fixes a failure in ffmpeg
xhwang 2014/03/10 18:36:31 In general we want to avoid unnecessary posts. For
92 97
93 if (state_ == STATE_FLUSHING_DECODER) { 98 if (state_ == STATE_FLUSHING_DECODER) {
94 FlushDecoder(); 99 FlushDecoder();
95 return; 100 return;
96 } 101 }
97 102
103 scoped_refptr<Output> output = decoder_->GetDecodeOutput();
104
105 // If the decoder has queued output ready to go we don't need a demuxer read.
106 if (output) {
107 SatisfyRead(OK, output);
108 return;
109 }
110
98 ReadFromDemuxerStream(); 111 ReadFromDemuxerStream();
99 } 112 }
100 113
101 template <DemuxerStream::Type StreamType> 114 template <DemuxerStream::Type StreamType>
102 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { 115 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
103 DVLOG(2) << __FUNCTION__; 116 DVLOG(2) << __FUNCTION__;
104 DCHECK(task_runner_->BelongsToCurrentThread()); 117 DCHECK(task_runner_->BelongsToCurrentThread());
105 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; 118 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
106 DCHECK(reset_cb_.is_null()); 119 DCHECK(reset_cb_.is_null());
107 DCHECK(stop_cb_.is_null()); 120 DCHECK(stop_cb_.is_null());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 decrypting_demuxer_stream_.reset(); 191 decrypting_demuxer_stream_.reset();
179 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); 192 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
180 } 193 }
181 194
182 template <DemuxerStream::Type StreamType> 195 template <DemuxerStream::Type StreamType>
183 bool DecoderStream<StreamType>::CanReadWithoutStalling() const { 196 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
184 DCHECK(task_runner_->BelongsToCurrentThread()); 197 DCHECK(task_runner_->BelongsToCurrentThread());
185 return decoder_->CanReadWithoutStalling(); 198 return decoder_->CanReadWithoutStalling();
186 } 199 }
187 200
201 template <>
202 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const {
203 DCHECK(task_runner_->BelongsToCurrentThread());
204 return true;
205 }
206
188 template <DemuxerStream::Type StreamType> 207 template <DemuxerStream::Type StreamType>
189 void DecoderStream<StreamType>::OnDecoderSelected( 208 void DecoderStream<StreamType>::OnDecoderSelected(
190 scoped_ptr<Decoder> selected_decoder, 209 scoped_ptr<Decoder> selected_decoder,
191 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { 210 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
192 DVLOG(2) << __FUNCTION__; 211 DVLOG(2) << __FUNCTION__;
193 DCHECK(task_runner_->BelongsToCurrentThread()); 212 DCHECK(task_runner_->BelongsToCurrentThread());
194 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; 213 DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
195 DCHECK(!init_cb_.is_null()); 214 DCHECK(!init_cb_.is_null());
196 DCHECK(read_cb_.is_null()); 215 DCHECK(read_cb_.is_null());
197 DCHECK(reset_cb_.is_null()); 216 DCHECK(reset_cb_.is_null());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 } 331 }
313 332
314 if (status == Decoder::kNotEnoughData) { 333 if (status == Decoder::kNotEnoughData) {
315 if (state_ == STATE_NORMAL) 334 if (state_ == STATE_NORMAL)
316 ReadFromDemuxerStream(); 335 ReadFromDemuxerStream();
317 else if (state_ == STATE_FLUSHING_DECODER) 336 else if (state_ == STATE_FLUSHING_DECODER)
318 FlushDecoder(); 337 FlushDecoder();
319 return; 338 return;
320 } 339 }
321 340
341 DCHECK(output);
322 SatisfyRead(OK, output); 342 SatisfyRead(OK, output);
323 } 343 }
324 344
325 template <DemuxerStream::Type StreamType> 345 template <DemuxerStream::Type StreamType>
326 void DecoderStream<StreamType>::ReadFromDemuxerStream() { 346 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
327 DVLOG(2) << __FUNCTION__; 347 DVLOG(2) << __FUNCTION__;
328 DCHECK_EQ(state_, STATE_NORMAL) << state_; 348 DCHECK_EQ(state_, STATE_NORMAL) << state_;
329 DCHECK(!read_cb_.is_null()); 349 DCHECK(!read_cb_.is_null());
330 DCHECK(reset_cb_.is_null()); 350 DCHECK(reset_cb_.is_null());
331 DCHECK(stop_cb_.is_null()); 351 DCHECK(stop_cb_.is_null());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 DCHECK(status == DemuxerStream::kOk) << status; 400 DCHECK(status == DemuxerStream::kOk) << status;
381 Decode(buffer); 401 Decode(buffer);
382 } 402 }
383 403
384 template <DemuxerStream::Type StreamType> 404 template <DemuxerStream::Type StreamType>
385 void DecoderStream<StreamType>::ReinitializeDecoder() { 405 void DecoderStream<StreamType>::ReinitializeDecoder() {
386 DVLOG(2) << __FUNCTION__; 406 DVLOG(2) << __FUNCTION__;
387 DCHECK(task_runner_->BelongsToCurrentThread()); 407 DCHECK(task_runner_->BelongsToCurrentThread());
388 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; 408 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
389 409
390 // TODO(rileya): Specialize this for audio, or, better yet, change 410 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig());
391 // DemuxerStream config getters to be templated.
392 DCHECK(stream_->video_decoder_config().IsValidConfig());
393 state_ = STATE_REINITIALIZING_DECODER; 411 state_ = STATE_REINITIALIZING_DECODER;
394 decoder_->Initialize( 412 decoder_->Initialize(
395 stream_->video_decoder_config(), 413 StreamTraits::GetDecoderConfig(*stream_),
396 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, 414 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
397 weak_factory_.GetWeakPtr())); 415 weak_factory_.GetWeakPtr()));
398 } 416 }
399 417
400 template <DemuxerStream::Type StreamType> 418 template <DemuxerStream::Type StreamType>
401 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { 419 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
402 DVLOG(2) << __FUNCTION__; 420 DVLOG(2) << __FUNCTION__;
403 DCHECK(task_runner_->BelongsToCurrentThread()); 421 DCHECK(task_runner_->BelongsToCurrentThread());
404 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; 422 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
405 DCHECK(stop_cb_.is_null()); 423 DCHECK(stop_cb_.is_null());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 DCHECK(!stop_cb_.is_null()); 503 DCHECK(!stop_cb_.is_null());
486 504
487 state_ = STATE_STOPPED; 505 state_ = STATE_STOPPED;
488 stream_ = NULL; 506 stream_ = NULL;
489 decoder_.reset(); 507 decoder_.reset();
490 decrypting_demuxer_stream_.reset(); 508 decrypting_demuxer_stream_.reset();
491 base::ResetAndReturn(&stop_cb_).Run(); 509 base::ResetAndReturn(&stop_cb_).Run();
492 } 510 }
493 511
494 template class DecoderStream<DemuxerStream::VIDEO>; 512 template class DecoderStream<DemuxerStream::VIDEO>;
513 template class DecoderStream<DemuxerStream::AUDIO>;
495 514
496 } // namespace media 515 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decoder_stream.h ('k') | media/filters/decoder_stream_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698