Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 27 matching lines...) Expand all Loading... | |
| 38 return "DecoderStream<AUDIO>::Decode"; | 38 return "DecoderStream<AUDIO>::Decode"; |
| 39 } | 39 } |
| 40 | 40 |
| 41 template <DemuxerStream::Type StreamType> | 41 template <DemuxerStream::Type StreamType> |
| 42 DecoderStream<StreamType>::DecoderStream( | 42 DecoderStream<StreamType>::DecoderStream( |
| 43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 44 ScopedVector<Decoder> decoders, | 44 ScopedVector<Decoder> decoders, |
| 45 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 45 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
| 46 : task_runner_(task_runner), | 46 : task_runner_(task_runner), |
| 47 state_(STATE_UNINITIALIZED), | 47 state_(STATE_UNINITIALIZED), |
| 48 error_(OK), | |
| 48 stream_(NULL), | 49 stream_(NULL), |
| 49 decoder_selector_( | 50 decoder_selector_( |
| 50 new DecoderSelector<StreamType>(task_runner, | 51 new DecoderSelector<StreamType>(task_runner, |
| 51 decoders.Pass(), | 52 decoders.Pass(), |
| 52 set_decryptor_ready_cb)), | 53 set_decryptor_ready_cb)), |
| 53 active_splice_(false), | 54 active_splice_(false), |
| 55 pending_decode_requests_(0), | |
| 54 weak_factory_(this) {} | 56 weak_factory_(this) {} |
| 55 | 57 |
| 56 template <DemuxerStream::Type StreamType> | 58 template <DemuxerStream::Type StreamType> |
| 57 DecoderStream<StreamType>::~DecoderStream() { | 59 DecoderStream<StreamType>::~DecoderStream() { |
| 58 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 60 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
| 59 } | 61 } |
| 60 | 62 |
| 61 template <DemuxerStream::Type StreamType> | 63 template <DemuxerStream::Type StreamType> |
| 62 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 64 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
| 63 const StatisticsCB& statistics_cb, | 65 const StatisticsCB& statistics_cb, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 78 stream, | 80 stream, |
| 79 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 81 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
| 80 weak_factory_.GetWeakPtr())); | 82 weak_factory_.GetWeakPtr())); |
| 81 } | 83 } |
| 82 | 84 |
| 83 template <DemuxerStream::Type StreamType> | 85 template <DemuxerStream::Type StreamType> |
| 84 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 86 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
| 85 FUNCTION_DVLOG(2); | 87 FUNCTION_DVLOG(2); |
| 86 DCHECK(task_runner_->BelongsToCurrentThread()); | 88 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 87 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 89 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 88 state_ == STATE_ERROR) << state_; | 90 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || |
| 91 state_ == STATE_PENDING_DEMUXER_READ) | |
| 92 << state_; | |
| 89 // No two reads in the flight at any time. | 93 // No two reads in the flight at any time. |
| 90 DCHECK(read_cb_.is_null()); | 94 DCHECK(read_cb_.is_null()); |
| 91 // No read during resetting or stopping process. | 95 // No read during resetting or stopping process. |
| 92 DCHECK(reset_cb_.is_null()); | 96 DCHECK(reset_cb_.is_null()); |
| 93 DCHECK(stop_cb_.is_null()); | 97 DCHECK(stop_cb_.is_null()); |
| 94 | 98 |
| 99 read_cb_ = read_cb; | |
| 100 | |
| 95 if (state_ == STATE_ERROR) { | 101 if (state_ == STATE_ERROR) { |
| 102 DCHECK_NE(error_, OK); | |
| 96 task_runner_->PostTask(FROM_HERE, base::Bind( | 103 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 97 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 104 base::ResetAndReturn(&read_cb_), error_, scoped_refptr<Output>())); |
| 98 return; | 105 return; |
| 99 } | 106 } |
| 100 | 107 |
| 101 read_cb_ = read_cb; | 108 if (!ready_outputs_.empty()) { |
| 109 task_runner_->PostTask(FROM_HERE, base::Bind( | |
| 110 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front())); | |
| 111 ready_outputs_.pop_front(); | |
| 112 } | |
| 113 | |
| 114 // Decoder may be in reinitializing state as result of the previous Read(). | |
| 115 if (state_ == STATE_REINITIALIZING_DECODER) | |
| 116 return; | |
| 117 | |
| 118 if (!CanDecodeAnotherBuffer()) | |
| 119 return; | |
| 102 | 120 |
| 103 if (state_ == STATE_FLUSHING_DECODER) { | 121 if (state_ == STATE_FLUSHING_DECODER) { |
| 104 FlushDecoder(); | 122 FlushDecoder(); |
| 105 return; | 123 return; |
| 106 } | 124 } |
| 107 | 125 |
| 108 scoped_refptr<Output> output = decoder_->GetDecodeOutput(); | 126 if (state_ != STATE_PENDING_DEMUXER_READ) |
| 109 | 127 ReadFromDemuxerStream(); |
| 110 // If the decoder has queued output ready to go we don't need a demuxer read. | |
| 111 if (output) { | |
| 112 task_runner_->PostTask( | |
| 113 FROM_HERE, base::Bind(base::ResetAndReturn(&read_cb_), OK, output)); | |
| 114 return; | |
| 115 } | |
| 116 | |
| 117 ReadFromDemuxerStream(); | |
| 118 } | 128 } |
| 119 | 129 |
| 120 template <DemuxerStream::Type StreamType> | 130 template <DemuxerStream::Type StreamType> |
| 121 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { | 131 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { |
| 122 FUNCTION_DVLOG(2); | 132 FUNCTION_DVLOG(2); |
| 123 DCHECK(task_runner_->BelongsToCurrentThread()); | 133 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 124 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 134 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
| 125 DCHECK(reset_cb_.is_null()); | 135 DCHECK(reset_cb_.is_null()); |
| 126 DCHECK(stop_cb_.is_null()); | 136 DCHECK(stop_cb_.is_null()); |
| 127 | 137 |
| 128 reset_cb_ = closure; | 138 reset_cb_ = closure; |
| 129 | 139 |
| 140 if (!read_cb_.is_null()) { | |
| 141 task_runner_->PostTask(FROM_HERE, base::Bind( | |
| 142 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); | |
| 143 } | |
| 144 | |
| 145 ready_outputs_.clear(); | |
| 146 | |
| 130 // During decoder reinitialization, the Decoder does not need to be and | 147 // During decoder reinitialization, the Decoder does not need to be and |
| 131 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder | 148 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder |
| 132 // reinitialization. | 149 // reinitialization. |
| 133 if (state_ == STATE_REINITIALIZING_DECODER) | 150 if (state_ == STATE_REINITIALIZING_DECODER) |
| 134 return; | 151 return; |
| 135 | 152 |
| 136 // During pending demuxer read and when not using DecryptingDemuxerStream, | 153 // During pending demuxer read and when not using DecryptingDemuxerStream, |
| 137 // the Decoder will be reset after demuxer read is returned | 154 // the Decoder will be reset after demuxer read is returned |
| 138 // (in OnBufferReady()). | 155 // (in OnBufferReady()). |
| 139 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) | 156 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) |
| 140 return; | 157 return; |
| 141 | 158 |
| 142 // The Decoder API guarantees that if Decoder::Reset() is called during | |
| 143 // a pending decode, the decode callback must be fired before the reset | |
| 144 // callback is fired. Therefore, we can call Decoder::Reset() regardless | |
| 145 // of if we have a pending decode and always satisfy the reset callback when | |
| 146 // the decoder reset is finished. | |
| 147 if (decrypting_demuxer_stream_) { | 159 if (decrypting_demuxer_stream_) { |
| 148 decrypting_demuxer_stream_->Reset(base::Bind( | 160 decrypting_demuxer_stream_->Reset(base::Bind( |
| 149 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); | 161 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); |
| 150 return; | 162 return; |
| 151 } | 163 } |
| 152 | 164 |
| 153 ResetDecoder(); | 165 ResetDecoder(); |
| 154 } | 166 } |
| 155 | 167 |
| 156 template <DemuxerStream::Type StreamType> | 168 template <DemuxerStream::Type StreamType> |
| 157 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { | 169 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { |
| 158 FUNCTION_DVLOG(2); | 170 FUNCTION_DVLOG(2); |
| 159 DCHECK(task_runner_->BelongsToCurrentThread()); | 171 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 160 DCHECK_NE(state_, STATE_STOPPED) << state_; | 172 DCHECK_NE(state_, STATE_STOPPED) << state_; |
| 161 DCHECK(stop_cb_.is_null()); | 173 DCHECK(stop_cb_.is_null()); |
| 162 | 174 |
| 163 stop_cb_ = closure; | 175 stop_cb_ = closure; |
| 164 | 176 |
| 165 if (state_ == STATE_INITIALIZING) { | 177 if (state_ == STATE_INITIALIZING) { |
| 166 decoder_selector_->Abort(); | 178 decoder_selector_->Abort(); |
| 167 return; | 179 return; |
| 168 } | 180 } |
| 169 | 181 |
| 170 DCHECK(init_cb_.is_null()); | 182 DCHECK(init_cb_.is_null()); |
| 171 | 183 |
| 172 // All pending callbacks will be dropped. | 184 // All pending callbacks will be dropped. |
| 173 weak_factory_.InvalidateWeakPtrs(); | 185 weak_factory_.InvalidateWeakPtrs(); |
| 174 | 186 |
| 175 // Post callbacks to prevent reentrance into this object. | 187 // Post callbacks to prevent reentrance into this object. |
| 176 if (!read_cb_.is_null()) | 188 if (!read_cb_.is_null()) { |
| 177 task_runner_->PostTask(FROM_HERE, base::Bind( | 189 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 178 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); | 190 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); |
| 191 } | |
| 179 if (!reset_cb_.is_null()) | 192 if (!reset_cb_.is_null()) |
| 180 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); | 193 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); |
| 181 | 194 |
| 182 if (decrypting_demuxer_stream_) { | 195 if (decrypting_demuxer_stream_) { |
| 183 decrypting_demuxer_stream_->Stop(base::Bind( | 196 decrypting_demuxer_stream_->Stop(base::Bind( |
| 184 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); | 197 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); |
| 185 return; | 198 return; |
| 186 } | 199 } |
| 187 | 200 |
| 188 // We may not have a |decoder_| if Stop() was called during initialization. | 201 // We may not have a |decoder_| if Stop() was called during initialization. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 204 return decoder_->CanReadWithoutStalling(); | 217 return decoder_->CanReadWithoutStalling(); |
| 205 } | 218 } |
| 206 | 219 |
| 207 template <> | 220 template <> |
| 208 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { | 221 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { |
| 209 DCHECK(task_runner_->BelongsToCurrentThread()); | 222 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 210 return true; | 223 return true; |
| 211 } | 224 } |
| 212 | 225 |
| 213 template <DemuxerStream::Type StreamType> | 226 template <DemuxerStream::Type StreamType> |
| 227 bool DecoderStream<StreamType>::CanDecodeAnotherBuffer() const { | |
| 228 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 229 | |
| 230 // Limit total number of outputs stored in |ready_outputs_| and being decoded. | |
| 231 // It only makes sense to saturate decoder completely when output queue is | |
| 232 // empty. | |
| 233 // TODO(sergeyu): Is that the best way to throttle decoding requests? | |
|
xhwang
2014/04/25 00:36:03
I don't see a better way to do that. The current a
Sergey Ulanov
2014/04/26 00:59:29
removed TODO
| |
| 234 int num_decodes = | |
| 235 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; | |
| 236 return num_decodes < decoder_->GetMaxDecodeRequests(); | |
| 237 } | |
| 238 | |
| 239 template <> | |
| 240 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeAnotherBuffer() const { | |
| 241 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 242 return !pending_decode_requests_ && ready_outputs_.empty(); | |
| 243 } | |
| 244 | |
| 245 template <DemuxerStream::Type StreamType> | |
| 214 void DecoderStream<StreamType>::OnDecoderSelected( | 246 void DecoderStream<StreamType>::OnDecoderSelected( |
| 215 scoped_ptr<Decoder> selected_decoder, | 247 scoped_ptr<Decoder> selected_decoder, |
| 216 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 248 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| 217 FUNCTION_DVLOG(2); | 249 FUNCTION_DVLOG(2); |
| 218 DCHECK(task_runner_->BelongsToCurrentThread()); | 250 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 219 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 251 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
| 220 DCHECK(!init_cb_.is_null()); | 252 DCHECK(!init_cb_.is_null()); |
| 221 DCHECK(read_cb_.is_null()); | 253 DCHECK(read_cb_.is_null()); |
| 222 DCHECK(reset_cb_.is_null()); | 254 DCHECK(reset_cb_.is_null()); |
| 223 | 255 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 246 | 278 |
| 247 template <DemuxerStream::Type StreamType> | 279 template <DemuxerStream::Type StreamType> |
| 248 void DecoderStream<StreamType>::SatisfyRead( | 280 void DecoderStream<StreamType>::SatisfyRead( |
| 249 Status status, | 281 Status status, |
| 250 const scoped_refptr<Output>& output) { | 282 const scoped_refptr<Output>& output) { |
| 251 DCHECK(!read_cb_.is_null()); | 283 DCHECK(!read_cb_.is_null()); |
| 252 base::ResetAndReturn(&read_cb_).Run(status, output); | 284 base::ResetAndReturn(&read_cb_).Run(status, output); |
| 253 } | 285 } |
| 254 | 286 |
| 255 template <DemuxerStream::Type StreamType> | 287 template <DemuxerStream::Type StreamType> |
| 256 void DecoderStream<StreamType>::AbortRead() { | |
| 257 // Abort read during pending reset. It is safe to fire the |read_cb_| directly | |
| 258 // instead of posting it because the renderer won't call into this class | |
| 259 // again when it's in kFlushing state. | |
| 260 // TODO(xhwang): Improve the resetting process to avoid this dependency on the | |
| 261 // caller. | |
| 262 DCHECK(!reset_cb_.is_null()); | |
| 263 SatisfyRead(ABORTED, NULL); | |
| 264 } | |
| 265 | |
| 266 template <DemuxerStream::Type StreamType> | |
| 267 void DecoderStream<StreamType>::Decode( | 288 void DecoderStream<StreamType>::Decode( |
| 268 const scoped_refptr<DecoderBuffer>& buffer) { | 289 const scoped_refptr<DecoderBuffer>& buffer) { |
| 269 FUNCTION_DVLOG(2); | 290 FUNCTION_DVLOG(2); |
| 270 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 291 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
| 271 DCHECK(!read_cb_.is_null()); | 292 DCHECK(CanDecodeAnotherBuffer()); |
| 272 DCHECK(reset_cb_.is_null()); | 293 DCHECK(reset_cb_.is_null()); |
| 273 DCHECK(stop_cb_.is_null()); | 294 DCHECK(stop_cb_.is_null()); |
| 274 DCHECK(buffer); | 295 DCHECK(buffer); |
| 275 | 296 |
| 276 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 297 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
| 277 | 298 |
| 278 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 299 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
| 300 ++pending_decode_requests_; | |
| 279 decoder_->Decode(buffer, | 301 decoder_->Decode(buffer, |
| 280 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 302 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 281 weak_factory_.GetWeakPtr(), | 303 weak_factory_.GetWeakPtr(), |
| 282 buffer_size)); | 304 buffer_size)); |
| 283 } | 305 } |
| 284 | 306 |
| 285 template <DemuxerStream::Type StreamType> | 307 template <DemuxerStream::Type StreamType> |
| 286 void DecoderStream<StreamType>::FlushDecoder() { | 308 void DecoderStream<StreamType>::FlushDecoder() { |
| 287 Decode(DecoderBuffer::CreateEOSBuffer()); | 309 if (pending_decode_requests_ == 0) |
|
xhwang
2014/04/25 00:36:03
This also depends on the fact that GVD doesn't hav
Sergey Ulanov
2014/04/26 00:59:29
Added condition in VideoDecoder comment requiring
xhwang
2014/04/29 20:01:26
By "decoding delay", I mean the case where VideoDe
Sergey Ulanov
2014/04/30 18:56:51
Ah, I see your point. Yes, decoders must never wai
| |
| 310 Decode(DecoderBuffer::CreateEOSBuffer()); | |
| 288 } | 311 } |
| 289 | 312 |
| 290 template <DemuxerStream::Type StreamType> | 313 template <DemuxerStream::Type StreamType> |
| 291 void DecoderStream<StreamType>::OnDecodeOutputReady( | 314 void DecoderStream<StreamType>::OnDecodeOutputReady( |
| 292 int buffer_size, | 315 int buffer_size, |
| 293 typename Decoder::Status status, | 316 typename Decoder::Status status, |
| 294 const scoped_refptr<Output>& output) { | 317 const scoped_refptr<Output>& output) { |
| 295 FUNCTION_DVLOG(2); | 318 FUNCTION_DVLOG(2) << status << " " << output; |
| 296 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 319 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 297 DCHECK(!read_cb_.is_null()); | 320 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 321 << state_; | |
| 298 DCHECK(stop_cb_.is_null()); | 322 DCHECK(stop_cb_.is_null()); |
| 299 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 323 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
| 324 DCHECK_GT(pending_decode_requests_, 0); | |
| 325 | |
| 326 --pending_decode_requests_; | |
| 300 | 327 |
| 301 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 328 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
| 302 | 329 |
| 330 if (state_ == STATE_ERROR) | |
|
xhwang
2014/04/25 00:36:03
DCHECK(!read_cb_.is_null())?
Sergey Ulanov
2014/04/26 00:59:29
I think you meant "DCHECK(read_cb_.is_null())"
Do
| |
| 331 return; | |
| 332 | |
| 303 if (status == Decoder::kDecodeError) { | 333 if (status == Decoder::kDecodeError) { |
| 304 state_ = STATE_ERROR; | 334 state_ = STATE_ERROR; |
| 305 SatisfyRead(DECODE_ERROR, NULL); | 335 error_ = DECODE_ERROR; |
|
xhwang
2014/04/25 00:36:03
Shall we clear the ready_outputs_ in case of error
Sergey Ulanov
2014/04/26 00:59:29
Done.
| |
| 336 if (!read_cb_.is_null()) | |
| 337 SatisfyRead(DECODE_ERROR, NULL); | |
| 306 return; | 338 return; |
| 307 } | 339 } |
| 308 | 340 |
| 309 if (status == Decoder::kDecryptError) { | 341 if (status == Decoder::kDecryptError) { |
| 310 state_ = STATE_ERROR; | 342 state_ = STATE_ERROR; |
| 311 SatisfyRead(DECRYPT_ERROR, NULL); | 343 error_ = DECRYPT_ERROR; |
|
xhwang
2014/04/25 00:36:03
ditto
Sergey Ulanov
2014/04/26 00:59:29
Done.
| |
| 344 if (!read_cb_.is_null()) | |
| 345 SatisfyRead(DECRYPT_ERROR, NULL); | |
| 312 return; | 346 return; |
| 313 } | 347 } |
| 314 | 348 |
| 315 if (status == Decoder::kAborted) { | 349 if (status == Decoder::kAborted) { |
| 316 SatisfyRead(ABORTED, NULL); | 350 if (!read_cb_.is_null()) |
|
xhwang
2014/04/25 00:36:03
kAborted must be a result of Reset(). In Reset() c
Sergey Ulanov
2014/04/26 00:59:29
There are some tests that return kAborted from dec
xhwang
2014/04/29 20:01:26
You are right. kAborted can also be a result of De
| |
| 351 SatisfyRead(ABORTED, NULL); | |
| 317 return; | 352 return; |
| 318 } | 353 } |
| 319 | 354 |
| 320 // Any successful decode counts! | 355 // Any successful decode counts! |
| 321 if (buffer_size > 0) { | 356 if (buffer_size > 0) { |
| 322 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 357 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
| 323 } | 358 } |
| 324 | 359 |
| 325 // Drop decoding result if Reset() was called during decoding. | 360 // Drop decoding result if Reset() was called during decoding. |
| 326 // The resetting process will be handled when the decoder is reset. | 361 // The resetting process will be handled when the decoder is reset. |
| 327 if (!reset_cb_.is_null()) { | 362 if (!reset_cb_.is_null()) |
| 328 AbortRead(); | |
| 329 return; | 363 return; |
| 330 } | |
| 331 | 364 |
| 332 // Decoder flushed. Reinitialize the decoder. | 365 // Decoder flushed. Reinitialize the decoder. |
| 333 if (state_ == STATE_FLUSHING_DECODER && | 366 if (state_ == STATE_FLUSHING_DECODER && |
| 334 status == Decoder::kOk && output->end_of_stream()) { | 367 status == Decoder::kOk && output->end_of_stream()) { |
| 335 ReinitializeDecoder(); | 368 ReinitializeDecoder(); |
| 336 return; | 369 return; |
| 337 } | 370 } |
| 338 | 371 |
| 339 if (status == Decoder::kNotEnoughData) { | 372 if (status == Decoder::kNotEnoughData) { |
| 340 if (state_ == STATE_NORMAL) | 373 if (state_ == STATE_NORMAL) |
| 341 ReadFromDemuxerStream(); | 374 ReadFromDemuxerStream(); |
| 342 else if (state_ == STATE_FLUSHING_DECODER) | 375 else if (state_ == STATE_FLUSHING_DECODER) |
| 343 FlushDecoder(); | 376 FlushDecoder(); |
| 344 return; | 377 return; |
| 345 } | 378 } |
| 346 | 379 |
| 347 DCHECK(output); | 380 DCHECK(output); |
| 348 SatisfyRead(OK, output); | 381 |
| 382 // Store decoded output. | |
| 383 ready_outputs_.push_back(output); | |
| 384 scoped_refptr<Output> extra_output; | |
| 385 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { | |
| 386 ready_outputs_.push_back(extra_output); | |
| 387 } | |
| 388 | |
| 389 // Satisfy outstanding read request, if any. | |
| 390 if (!read_cb_.is_null()) { | |
| 391 scoped_refptr<Output> read_result = ready_outputs_.front(); | |
| 392 ready_outputs_.pop_front(); | |
| 393 SatisfyRead(OK, output); | |
| 394 } | |
| 349 } | 395 } |
| 350 | 396 |
| 351 template <DemuxerStream::Type StreamType> | 397 template <DemuxerStream::Type StreamType> |
| 352 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 398 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
| 353 FUNCTION_DVLOG(2); | 399 FUNCTION_DVLOG(2); |
| 354 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 400 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
| 355 DCHECK(!read_cb_.is_null()); | 401 DCHECK(CanDecodeAnotherBuffer()); |
| 356 DCHECK(reset_cb_.is_null()); | 402 DCHECK(reset_cb_.is_null()); |
| 357 DCHECK(stop_cb_.is_null()); | 403 DCHECK(stop_cb_.is_null()); |
| 358 | 404 |
| 359 state_ = STATE_PENDING_DEMUXER_READ; | 405 state_ = STATE_PENDING_DEMUXER_READ; |
| 360 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 406 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
| 361 weak_factory_.GetWeakPtr())); | 407 weak_factory_.GetWeakPtr())); |
| 362 } | 408 } |
| 363 | 409 |
| 364 template <DemuxerStream::Type StreamType> | 410 template <DemuxerStream::Type StreamType> |
| 365 void DecoderStream<StreamType>::OnBufferReady( | 411 void DecoderStream<StreamType>::OnBufferReady( |
| 366 DemuxerStream::Status status, | 412 DemuxerStream::Status status, |
| 367 const scoped_refptr<DecoderBuffer>& buffer) { | 413 const scoped_refptr<DecoderBuffer>& buffer) { |
| 368 FUNCTION_DVLOG(2) << ": " << status; | 414 FUNCTION_DVLOG(2) << ": " << status; |
| 369 DCHECK(task_runner_->BelongsToCurrentThread()); | 415 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 370 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 416 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 417 state_ == STATE_STOPPED) | |
| 418 << state_; | |
| 371 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 419 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| 372 DCHECK(!read_cb_.is_null()); | |
| 373 DCHECK(stop_cb_.is_null()); | 420 DCHECK(stop_cb_.is_null()); |
| 374 | 421 |
| 422 // Decoding has been stopped (e.g due to an error). | |
| 423 if (state_ != STATE_PENDING_DEMUXER_READ) | |
|
xhwang
2014/04/25 00:36:03
Can we
DCHECK_EQ(state_, STATE_ERROR);
DCHECK(rea
Sergey Ulanov
2014/04/26 00:59:29
Done. state_ can be either STATE_ERROR or STATE_ST
| |
| 424 return; | |
| 425 | |
| 375 state_ = STATE_NORMAL; | 426 state_ = STATE_NORMAL; |
| 376 | 427 |
| 377 if (status == DemuxerStream::kConfigChanged) { | 428 if (status == DemuxerStream::kConfigChanged) { |
| 378 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 429 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
| 379 DCHECK(stream_->SupportsConfigChanges()); | 430 DCHECK(stream_->SupportsConfigChanges()); |
| 380 | 431 |
| 381 if (!config_change_observer_cb_.is_null()) | 432 if (!config_change_observer_cb_.is_null()) |
| 382 config_change_observer_cb_.Run(); | 433 config_change_observer_cb_.Run(); |
| 383 | 434 |
| 384 state_ = STATE_FLUSHING_DECODER; | 435 state_ = STATE_FLUSHING_DECODER; |
| 385 if (!reset_cb_.is_null()) { | 436 if (!reset_cb_.is_null()) { |
| 386 AbortRead(); | |
| 387 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 437 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
| 388 // which will continue the resetting process in it's callback. | 438 // which will continue the resetting process in it's callback. |
| 389 if (!decrypting_demuxer_stream_) | 439 if (!decrypting_demuxer_stream_) |
| 390 Reset(base::ResetAndReturn(&reset_cb_)); | 440 Reset(base::ResetAndReturn(&reset_cb_)); |
| 391 // Reinitialization will continue after Reset() is done. | 441 // Reinitialization will continue after Reset() is done. |
| 392 } else { | 442 } else { |
| 393 FlushDecoder(); | 443 FlushDecoder(); |
| 394 } | 444 } |
| 395 return; | 445 return; |
| 396 } | 446 } |
| 397 | 447 |
| 398 if (!reset_cb_.is_null()) { | 448 if (!reset_cb_.is_null()) { |
| 399 AbortRead(); | |
| 400 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 449 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
| 401 // which will continue the resetting process in it's callback. | 450 // which will continue the resetting process in it's callback. |
| 402 if (!decrypting_demuxer_stream_) | 451 if (!decrypting_demuxer_stream_) |
| 403 Reset(base::ResetAndReturn(&reset_cb_)); | 452 Reset(base::ResetAndReturn(&reset_cb_)); |
| 404 return; | 453 return; |
| 405 } | 454 } |
| 406 | 455 |
| 407 if (status == DemuxerStream::kAborted) { | 456 if (status == DemuxerStream::kAborted) { |
| 408 SatisfyRead(DEMUXER_READ_ABORTED, NULL); | 457 SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
| 409 return; | 458 return; |
| 410 } | 459 } |
| 411 | 460 |
| 412 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { | 461 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { |
| 413 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); | 462 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); |
| 414 if (active_splice_ || has_splice_ts) { | 463 if (active_splice_ || has_splice_ts) { |
| 415 splice_observer_cb_.Run(buffer->splice_timestamp()); | 464 splice_observer_cb_.Run(buffer->splice_timestamp()); |
| 416 active_splice_ = has_splice_ts; | 465 active_splice_ = has_splice_ts; |
| 417 } | 466 } |
| 418 } | 467 } |
| 419 | 468 |
| 420 DCHECK(status == DemuxerStream::kOk) << status; | 469 DCHECK(status == DemuxerStream::kOk) << status; |
| 421 Decode(buffer); | 470 Decode(buffer); |
| 471 | |
| 472 // Read more data if the decoder supports multiple parallel decoding requests. | |
| 473 if (CanDecodeAnotherBuffer() && !buffer->end_of_stream()) | |
| 474 ReadFromDemuxerStream(); | |
| 422 } | 475 } |
| 423 | 476 |
| 424 template <DemuxerStream::Type StreamType> | 477 template <DemuxerStream::Type StreamType> |
| 425 void DecoderStream<StreamType>::ReinitializeDecoder() { | 478 void DecoderStream<StreamType>::ReinitializeDecoder() { |
| 426 FUNCTION_DVLOG(2); | 479 FUNCTION_DVLOG(2); |
| 427 DCHECK(task_runner_->BelongsToCurrentThread()); | 480 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 428 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 481 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
| 482 DCHECK_EQ(pending_decode_requests_, 0); | |
| 429 | 483 |
| 430 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 484 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
| 431 state_ = STATE_REINITIALIZING_DECODER; | 485 state_ = STATE_REINITIALIZING_DECODER; |
| 432 decoder_->Initialize( | 486 decoder_->Initialize( |
| 433 StreamTraits::GetDecoderConfig(*stream_), | 487 StreamTraits::GetDecoderConfig(*stream_), |
| 434 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 488 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
| 435 weak_factory_.GetWeakPtr())); | 489 weak_factory_.GetWeakPtr())); |
| 436 } | 490 } |
| 437 | 491 |
| 438 template <DemuxerStream::Type StreamType> | 492 template <DemuxerStream::Type StreamType> |
| 439 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { | 493 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { |
| 440 FUNCTION_DVLOG(2); | 494 FUNCTION_DVLOG(2); |
| 441 DCHECK(task_runner_->BelongsToCurrentThread()); | 495 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 442 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 496 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
| 443 DCHECK(stop_cb_.is_null()); | 497 DCHECK(stop_cb_.is_null()); |
| 444 | 498 |
| 445 // ReinitializeDecoder() can be called in two cases: | 499 // ReinitializeDecoder() can be called in two cases: |
| 446 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 500 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
| 447 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). | 501 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
| 448 // Also, Reset() can be called during pending ReinitializeDecoder(). | 502 // Also, Reset() can be called during pending ReinitializeDecoder(). |
| 449 // This function needs to handle them all! | 503 // This function needs to handle them all! |
| 450 | 504 |
| 451 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 505 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
| 452 | 506 |
| 453 if (!reset_cb_.is_null()) { | 507 if (!reset_cb_.is_null()) { |
| 454 if (!read_cb_.is_null()) | |
| 455 AbortRead(); | |
| 456 base::ResetAndReturn(&reset_cb_).Run(); | 508 base::ResetAndReturn(&reset_cb_).Run(); |
| 509 return; | |
| 457 } | 510 } |
| 458 | 511 |
| 459 if (read_cb_.is_null()) | 512 if (read_cb_.is_null()) |
| 460 return; | 513 return; |
| 461 | 514 |
| 462 if (state_ == STATE_ERROR) { | 515 if (state_ == STATE_ERROR) { |
| 463 SatisfyRead(DECODE_ERROR, NULL); | 516 SatisfyRead(DECODE_ERROR, NULL); |
| 464 return; | 517 return; |
| 465 } | 518 } |
| 466 | 519 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 decrypting_demuxer_stream_.reset(); | 567 decrypting_demuxer_stream_.reset(); |
| 515 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 568 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
| 516 // posted in Stop(). | 569 // posted in Stop(). |
| 517 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 570 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| 518 } | 571 } |
| 519 | 572 |
| 520 template class DecoderStream<DemuxerStream::VIDEO>; | 573 template class DecoderStream<DemuxerStream::VIDEO>; |
| 521 template class DecoderStream<DemuxerStream::AUDIO>; | 574 template class DecoderStream<DemuxerStream::AUDIO>; |
| 522 | 575 |
| 523 } // namespace media | 576 } // namespace media |
| OLD | NEW |