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

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: address comments 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
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_ = read_cb;
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 // If the decoder has queued output ready to go we don't need a demuxer read.
104 if (scoped_refptr<Output> output = decoder_->GetDecodeOutput()) {
xhwang 2014/03/05 00:40:46 This is neat, but I am not sure whether it's more
rileya (GONE FROM CHROMIUM) 2014/03/05 08:08:28 Done.
105 SatisfyRead(OK, output);
xhwang 2014/03/05 00:40:46 Can we add a unit test to cover this logic?
rileya (GONE FROM CHROMIUM) 2014/03/05 08:08:28 Sounds good, will do.
rileya (GONE FROM CHROMIUM) 2014/03/06 22:11:56 Done. There's currently no tests for DecoderStream
106 return;
107 }
108
98 ReadFromDemuxerStream(); 109 ReadFromDemuxerStream();
99 } 110 }
100 111
101 template <DemuxerStream::Type StreamType> 112 template <DemuxerStream::Type StreamType>
102 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { 113 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
103 DVLOG(2) << __FUNCTION__; 114 DVLOG(2) << __FUNCTION__;
104 DCHECK(task_runner_->BelongsToCurrentThread()); 115 DCHECK(task_runner_->BelongsToCurrentThread());
105 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; 116 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
106 DCHECK(reset_cb_.is_null()); 117 DCHECK(reset_cb_.is_null());
107 DCHECK(stop_cb_.is_null()); 118 DCHECK(stop_cb_.is_null());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 decrypting_demuxer_stream_.reset(); 189 decrypting_demuxer_stream_.reset();
179 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); 190 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
180 } 191 }
181 192
182 template <DemuxerStream::Type StreamType> 193 template <DemuxerStream::Type StreamType>
183 bool DecoderStream<StreamType>::CanReadWithoutStalling() const { 194 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
184 DCHECK(task_runner_->BelongsToCurrentThread()); 195 DCHECK(task_runner_->BelongsToCurrentThread());
185 return decoder_->CanReadWithoutStalling(); 196 return decoder_->CanReadWithoutStalling();
186 } 197 }
187 198
199 template <>
200 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const {
201 DCHECK(task_runner_->BelongsToCurrentThread());
202 return true;
203 }
204
188 template <DemuxerStream::Type StreamType> 205 template <DemuxerStream::Type StreamType>
189 void DecoderStream<StreamType>::OnDecoderSelected( 206 void DecoderStream<StreamType>::OnDecoderSelected(
190 scoped_ptr<Decoder> selected_decoder, 207 scoped_ptr<Decoder> selected_decoder,
191 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { 208 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
192 DVLOG(2) << __FUNCTION__; 209 DVLOG(2) << __FUNCTION__;
193 DCHECK(task_runner_->BelongsToCurrentThread()); 210 DCHECK(task_runner_->BelongsToCurrentThread());
194 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; 211 DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
195 DCHECK(!init_cb_.is_null()); 212 DCHECK(!init_cb_.is_null());
196 DCHECK(read_cb_.is_null()); 213 DCHECK(read_cb_.is_null());
197 DCHECK(reset_cb_.is_null()); 214 DCHECK(reset_cb_.is_null());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 } 329 }
313 330
314 if (status == Decoder::kNotEnoughData) { 331 if (status == Decoder::kNotEnoughData) {
315 if (state_ == STATE_NORMAL) 332 if (state_ == STATE_NORMAL)
316 ReadFromDemuxerStream(); 333 ReadFromDemuxerStream();
317 else if (state_ == STATE_FLUSHING_DECODER) 334 else if (state_ == STATE_FLUSHING_DECODER)
318 FlushDecoder(); 335 FlushDecoder();
319 return; 336 return;
320 } 337 }
321 338
339 DCHECK(output);
322 SatisfyRead(OK, output); 340 SatisfyRead(OK, output);
323 } 341 }
324 342
325 template <DemuxerStream::Type StreamType> 343 template <DemuxerStream::Type StreamType>
326 void DecoderStream<StreamType>::ReadFromDemuxerStream() { 344 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
327 DVLOG(2) << __FUNCTION__; 345 DVLOG(2) << __FUNCTION__;
328 DCHECK_EQ(state_, STATE_NORMAL) << state_; 346 DCHECK_EQ(state_, STATE_NORMAL) << state_;
329 DCHECK(!read_cb_.is_null()); 347 DCHECK(!read_cb_.is_null());
330 DCHECK(reset_cb_.is_null()); 348 DCHECK(reset_cb_.is_null());
331 DCHECK(stop_cb_.is_null()); 349 DCHECK(stop_cb_.is_null());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 DCHECK(status == DemuxerStream::kOk) << status; 398 DCHECK(status == DemuxerStream::kOk) << status;
381 Decode(buffer); 399 Decode(buffer);
382 } 400 }
383 401
384 template <DemuxerStream::Type StreamType> 402 template <DemuxerStream::Type StreamType>
385 void DecoderStream<StreamType>::ReinitializeDecoder() { 403 void DecoderStream<StreamType>::ReinitializeDecoder() {
386 DVLOG(2) << __FUNCTION__; 404 DVLOG(2) << __FUNCTION__;
387 DCHECK(task_runner_->BelongsToCurrentThread()); 405 DCHECK(task_runner_->BelongsToCurrentThread());
388 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; 406 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
389 407
390 // TODO(rileya): Specialize this for audio, or, better yet, change 408 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig());
391 // DemuxerStream config getters to be templated.
392 DCHECK(stream_->video_decoder_config().IsValidConfig());
393 state_ = STATE_REINITIALIZING_DECODER; 409 state_ = STATE_REINITIALIZING_DECODER;
394 decoder_->Initialize( 410 decoder_->Initialize(
395 stream_->video_decoder_config(), 411 StreamTraits::GetDecoderConfig(*stream_),
396 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, 412 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
397 weak_factory_.GetWeakPtr())); 413 weak_factory_.GetWeakPtr()));
398 } 414 }
399 415
400 template <DemuxerStream::Type StreamType> 416 template <DemuxerStream::Type StreamType>
401 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { 417 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
402 DVLOG(2) << __FUNCTION__; 418 DVLOG(2) << __FUNCTION__;
403 DCHECK(task_runner_->BelongsToCurrentThread()); 419 DCHECK(task_runner_->BelongsToCurrentThread());
404 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; 420 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
405 DCHECK(stop_cb_.is_null()); 421 DCHECK(stop_cb_.is_null());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 DCHECK(!stop_cb_.is_null()); 501 DCHECK(!stop_cb_.is_null());
486 502
487 state_ = STATE_STOPPED; 503 state_ = STATE_STOPPED;
488 stream_ = NULL; 504 stream_ = NULL;
489 decoder_.reset(); 505 decoder_.reset();
490 decrypting_demuxer_stream_.reset(); 506 decrypting_demuxer_stream_.reset();
491 base::ResetAndReturn(&stop_cb_).Run(); 507 base::ResetAndReturn(&stop_cb_).Run();
492 } 508 }
493 509
494 template class DecoderStream<DemuxerStream::VIDEO>; 510 template class DecoderStream<DemuxerStream::VIDEO>;
511 template class DecoderStream<DemuxerStream::AUDIO>;
495 512
496 } // namespace media 513 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698