| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 stream_(NULL), | 48 stream_(NULL), |
| 49 decoder_selector_( | 49 decoder_selector_( |
| 50 new DecoderSelector<StreamType>(task_runner, | 50 new DecoderSelector<StreamType>(task_runner, |
| 51 decoders.Pass(), | 51 decoders.Pass(), |
| 52 set_decryptor_ready_cb)), | 52 set_decryptor_ready_cb)), |
| 53 active_splice_(false), | 53 active_splice_(false), |
| 54 pending_decode_requests_(0), |
| 54 weak_factory_(this) {} | 55 weak_factory_(this) {} |
| 55 | 56 |
| 56 template <DemuxerStream::Type StreamType> | 57 template <DemuxerStream::Type StreamType> |
| 57 DecoderStream<StreamType>::~DecoderStream() { | 58 DecoderStream<StreamType>::~DecoderStream() { |
| 58 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 59 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
| 59 } | 60 } |
| 60 | 61 |
| 61 template <DemuxerStream::Type StreamType> | 62 template <DemuxerStream::Type StreamType> |
| 62 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 63 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
| 63 const StatisticsCB& statistics_cb, | 64 const StatisticsCB& statistics_cb, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 78 stream, | 79 stream, |
| 79 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 80 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
| 80 weak_factory_.GetWeakPtr())); | 81 weak_factory_.GetWeakPtr())); |
| 81 } | 82 } |
| 82 | 83 |
| 83 template <DemuxerStream::Type StreamType> | 84 template <DemuxerStream::Type StreamType> |
| 84 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 85 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
| 85 FUNCTION_DVLOG(2); | 86 FUNCTION_DVLOG(2); |
| 86 DCHECK(task_runner_->BelongsToCurrentThread()); | 87 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 87 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 88 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 88 state_ == STATE_ERROR) << state_; | 89 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || |
| 90 state_ == STATE_PENDING_DEMUXER_READ) |
| 91 << state_; |
| 89 // No two reads in the flight at any time. | 92 // No two reads in the flight at any time. |
| 90 DCHECK(read_cb_.is_null()); | 93 DCHECK(read_cb_.is_null()); |
| 91 // No read during resetting or stopping process. | 94 // No read during resetting or stopping process. |
| 92 DCHECK(reset_cb_.is_null()); | 95 DCHECK(reset_cb_.is_null()); |
| 93 DCHECK(stop_cb_.is_null()); | 96 DCHECK(stop_cb_.is_null()); |
| 94 | 97 |
| 98 read_cb_ = read_cb; |
| 99 |
| 95 if (state_ == STATE_ERROR) { | 100 if (state_ == STATE_ERROR) { |
| 96 task_runner_->PostTask(FROM_HERE, base::Bind( | 101 task_runner_->PostTask(FROM_HERE, |
| 97 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 102 base::Bind(base::ResetAndReturn(&read_cb_), |
| 103 DECODE_ERROR, |
| 104 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 (!CanDecodeMore()) |
| 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>::CanDecodeMore() 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 int num_decodes = |
| 234 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; |
| 235 return num_decodes < decoder_->GetMaxDecodeRequests(); |
| 236 } |
| 237 |
| 238 template <> |
| 239 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeMore() const { |
| 240 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 241 return !pending_decode_requests_ && ready_outputs_.empty(); |
| 242 } |
| 243 |
| 244 template <DemuxerStream::Type StreamType> |
| 214 void DecoderStream<StreamType>::OnDecoderSelected( | 245 void DecoderStream<StreamType>::OnDecoderSelected( |
| 215 scoped_ptr<Decoder> selected_decoder, | 246 scoped_ptr<Decoder> selected_decoder, |
| 216 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 247 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| 217 FUNCTION_DVLOG(2); | 248 FUNCTION_DVLOG(2); |
| 218 DCHECK(task_runner_->BelongsToCurrentThread()); | 249 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 219 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 250 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
| 220 DCHECK(!init_cb_.is_null()); | 251 DCHECK(!init_cb_.is_null()); |
| 221 DCHECK(read_cb_.is_null()); | 252 DCHECK(read_cb_.is_null()); |
| 222 DCHECK(reset_cb_.is_null()); | 253 DCHECK(reset_cb_.is_null()); |
| 223 | 254 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 246 | 277 |
| 247 template <DemuxerStream::Type StreamType> | 278 template <DemuxerStream::Type StreamType> |
| 248 void DecoderStream<StreamType>::SatisfyRead( | 279 void DecoderStream<StreamType>::SatisfyRead( |
| 249 Status status, | 280 Status status, |
| 250 const scoped_refptr<Output>& output) { | 281 const scoped_refptr<Output>& output) { |
| 251 DCHECK(!read_cb_.is_null()); | 282 DCHECK(!read_cb_.is_null()); |
| 252 base::ResetAndReturn(&read_cb_).Run(status, output); | 283 base::ResetAndReturn(&read_cb_).Run(status, output); |
| 253 } | 284 } |
| 254 | 285 |
| 255 template <DemuxerStream::Type StreamType> | 286 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( | 287 void DecoderStream<StreamType>::Decode( |
| 268 const scoped_refptr<DecoderBuffer>& buffer) { | 288 const scoped_refptr<DecoderBuffer>& buffer) { |
| 269 FUNCTION_DVLOG(2); | 289 FUNCTION_DVLOG(2); |
| 270 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 290 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
| 271 DCHECK(!read_cb_.is_null()); | 291 DCHECK(CanDecodeMore()); |
| 272 DCHECK(reset_cb_.is_null()); | 292 DCHECK(reset_cb_.is_null()); |
| 273 DCHECK(stop_cb_.is_null()); | 293 DCHECK(stop_cb_.is_null()); |
| 274 DCHECK(buffer); | 294 DCHECK(buffer); |
| 275 | 295 |
| 276 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 296 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
| 277 | 297 |
| 278 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 298 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
| 299 ++pending_decode_requests_; |
| 279 decoder_->Decode(buffer, | 300 decoder_->Decode(buffer, |
| 280 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 301 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
| 281 weak_factory_.GetWeakPtr(), | 302 weak_factory_.GetWeakPtr(), |
| 282 buffer_size)); | 303 buffer_size)); |
| 283 } | 304 } |
| 284 | 305 |
| 285 template <DemuxerStream::Type StreamType> | 306 template <DemuxerStream::Type StreamType> |
| 286 void DecoderStream<StreamType>::FlushDecoder() { | 307 void DecoderStream<StreamType>::FlushDecoder() { |
| 287 Decode(DecoderBuffer::CreateEOSBuffer()); | 308 if (pending_decode_requests_ == 0) |
| 309 Decode(DecoderBuffer::CreateEOSBuffer()); |
| 288 } | 310 } |
| 289 | 311 |
| 290 template <DemuxerStream::Type StreamType> | 312 template <DemuxerStream::Type StreamType> |
| 291 void DecoderStream<StreamType>::OnDecodeOutputReady( | 313 void DecoderStream<StreamType>::OnDecodeOutputReady( |
| 292 int buffer_size, | 314 int buffer_size, |
| 293 typename Decoder::Status status, | 315 typename Decoder::Status status, |
| 294 const scoped_refptr<Output>& output) { | 316 const scoped_refptr<Output>& output) { |
| 295 FUNCTION_DVLOG(2); | 317 FUNCTION_DVLOG(2) << status << " " << output; |
| 296 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 318 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 297 DCHECK(!read_cb_.is_null()); | 319 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 320 << state_; |
| 298 DCHECK(stop_cb_.is_null()); | 321 DCHECK(stop_cb_.is_null()); |
| 299 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 322 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
| 323 DCHECK_GT(pending_decode_requests_, 0); |
| 324 |
| 325 --pending_decode_requests_; |
| 300 | 326 |
| 301 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 327 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
| 302 | 328 |
| 329 if (state_ == STATE_ERROR) { |
| 330 DCHECK(read_cb_.is_null()); |
| 331 return; |
| 332 } |
| 333 |
| 303 if (status == Decoder::kDecodeError) { | 334 if (status == Decoder::kDecodeError) { |
| 304 state_ = STATE_ERROR; | 335 state_ = STATE_ERROR; |
| 305 SatisfyRead(DECODE_ERROR, NULL); | 336 ready_outputs_.clear(); |
| 337 if (!read_cb_.is_null()) |
| 338 SatisfyRead(DECODE_ERROR, NULL); |
| 306 return; | 339 return; |
| 307 } | 340 } |
| 308 | 341 |
| 309 if (status == Decoder::kDecryptError) { | 342 if (status == Decoder::kDecryptError) { |
| 310 state_ = STATE_ERROR; | 343 state_ = STATE_ERROR; |
| 311 SatisfyRead(DECRYPT_ERROR, NULL); | 344 ready_outputs_.clear(); |
| 345 if (!read_cb_.is_null()) |
| 346 SatisfyRead(DECRYPT_ERROR, NULL); |
| 312 return; | 347 return; |
| 313 } | 348 } |
| 314 | 349 |
| 315 if (status == Decoder::kAborted) { | 350 if (status == Decoder::kAborted) { |
| 316 SatisfyRead(ABORTED, NULL); | 351 if (!read_cb_.is_null()) |
| 352 SatisfyRead(ABORTED, NULL); |
| 317 return; | 353 return; |
| 318 } | 354 } |
| 319 | 355 |
| 320 // Any successful decode counts! | 356 // Any successful decode counts! |
| 321 if (buffer_size > 0) { | 357 if (buffer_size > 0) { |
| 322 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 358 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
| 323 } | 359 } |
| 324 | 360 |
| 325 // Drop decoding result if Reset() was called during decoding. | 361 // Drop decoding result if Reset() was called during decoding. |
| 326 // The resetting process will be handled when the decoder is reset. | 362 // The resetting process will be handled when the decoder is reset. |
| 327 if (!reset_cb_.is_null()) { | 363 if (!reset_cb_.is_null()) |
| 328 AbortRead(); | |
| 329 return; | 364 return; |
| 330 } | |
| 331 | 365 |
| 332 // Decoder flushed. Reinitialize the decoder. | 366 // Decoder flushed. Reinitialize the decoder. |
| 333 if (state_ == STATE_FLUSHING_DECODER && | 367 if (state_ == STATE_FLUSHING_DECODER && |
| 334 status == Decoder::kOk && output->end_of_stream()) { | 368 status == Decoder::kOk && output->end_of_stream()) { |
| 335 ReinitializeDecoder(); | 369 ReinitializeDecoder(); |
| 336 return; | 370 return; |
| 337 } | 371 } |
| 338 | 372 |
| 339 if (status == Decoder::kNotEnoughData) { | 373 if (status == Decoder::kNotEnoughData) { |
| 340 if (state_ == STATE_NORMAL) | 374 if (state_ == STATE_NORMAL) |
| 341 ReadFromDemuxerStream(); | 375 ReadFromDemuxerStream(); |
| 342 else if (state_ == STATE_FLUSHING_DECODER) | 376 else if (state_ == STATE_FLUSHING_DECODER) |
| 343 FlushDecoder(); | 377 FlushDecoder(); |
| 344 return; | 378 return; |
| 345 } | 379 } |
| 346 | 380 |
| 347 DCHECK(output); | 381 DCHECK(output); |
| 348 SatisfyRead(OK, output); | 382 |
| 383 // Store decoded output. |
| 384 ready_outputs_.push_back(output); |
| 385 scoped_refptr<Output> extra_output; |
| 386 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { |
| 387 ready_outputs_.push_back(extra_output); |
| 388 } |
| 389 |
| 390 // Satisfy outstanding read request, if any. |
| 391 if (!read_cb_.is_null()) { |
| 392 scoped_refptr<Output> read_result = ready_outputs_.front(); |
| 393 ready_outputs_.pop_front(); |
| 394 SatisfyRead(OK, output); |
| 395 } |
| 349 } | 396 } |
| 350 | 397 |
| 351 template <DemuxerStream::Type StreamType> | 398 template <DemuxerStream::Type StreamType> |
| 352 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 399 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
| 353 FUNCTION_DVLOG(2); | 400 FUNCTION_DVLOG(2); |
| 354 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 401 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
| 355 DCHECK(!read_cb_.is_null()); | 402 DCHECK(CanDecodeMore()); |
| 356 DCHECK(reset_cb_.is_null()); | 403 DCHECK(reset_cb_.is_null()); |
| 357 DCHECK(stop_cb_.is_null()); | 404 DCHECK(stop_cb_.is_null()); |
| 358 | 405 |
| 359 state_ = STATE_PENDING_DEMUXER_READ; | 406 state_ = STATE_PENDING_DEMUXER_READ; |
| 360 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 407 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
| 361 weak_factory_.GetWeakPtr())); | 408 weak_factory_.GetWeakPtr())); |
| 362 } | 409 } |
| 363 | 410 |
| 364 template <DemuxerStream::Type StreamType> | 411 template <DemuxerStream::Type StreamType> |
| 365 void DecoderStream<StreamType>::OnBufferReady( | 412 void DecoderStream<StreamType>::OnBufferReady( |
| 366 DemuxerStream::Status status, | 413 DemuxerStream::Status status, |
| 367 const scoped_refptr<DecoderBuffer>& buffer) { | 414 const scoped_refptr<DecoderBuffer>& buffer) { |
| 368 FUNCTION_DVLOG(2) << ": " << status; | 415 FUNCTION_DVLOG(2) << ": " << status; |
| 369 DCHECK(task_runner_->BelongsToCurrentThread()); | 416 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 370 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 417 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 418 state_ == STATE_STOPPED) |
| 419 << state_; |
| 371 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 420 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| 372 DCHECK(!read_cb_.is_null()); | |
| 373 DCHECK(stop_cb_.is_null()); | 421 DCHECK(stop_cb_.is_null()); |
| 374 | 422 |
| 423 // Decoding has been stopped (e.g due to an error). |
| 424 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 425 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); |
| 426 DCHECK(read_cb_.is_null()); |
| 427 return; |
| 428 } |
| 429 |
| 375 state_ = STATE_NORMAL; | 430 state_ = STATE_NORMAL; |
| 376 | 431 |
| 377 if (status == DemuxerStream::kConfigChanged) { | 432 if (status == DemuxerStream::kConfigChanged) { |
| 378 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 433 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
| 379 DCHECK(stream_->SupportsConfigChanges()); | 434 DCHECK(stream_->SupportsConfigChanges()); |
| 380 | 435 |
| 381 if (!config_change_observer_cb_.is_null()) | 436 if (!config_change_observer_cb_.is_null()) |
| 382 config_change_observer_cb_.Run(); | 437 config_change_observer_cb_.Run(); |
| 383 | 438 |
| 384 state_ = STATE_FLUSHING_DECODER; | 439 state_ = STATE_FLUSHING_DECODER; |
| 385 if (!reset_cb_.is_null()) { | 440 if (!reset_cb_.is_null()) { |
| 386 AbortRead(); | |
| 387 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 441 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
| 388 // which will continue the resetting process in it's callback. | 442 // which will continue the resetting process in it's callback. |
| 389 if (!decrypting_demuxer_stream_) | 443 if (!decrypting_demuxer_stream_) |
| 390 Reset(base::ResetAndReturn(&reset_cb_)); | 444 Reset(base::ResetAndReturn(&reset_cb_)); |
| 391 // Reinitialization will continue after Reset() is done. | 445 // Reinitialization will continue after Reset() is done. |
| 392 } else { | 446 } else { |
| 393 FlushDecoder(); | 447 FlushDecoder(); |
| 394 } | 448 } |
| 395 return; | 449 return; |
| 396 } | 450 } |
| 397 | 451 |
| 398 if (!reset_cb_.is_null()) { | 452 if (!reset_cb_.is_null()) { |
| 399 AbortRead(); | |
| 400 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 453 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
| 401 // which will continue the resetting process in it's callback. | 454 // which will continue the resetting process in it's callback. |
| 402 if (!decrypting_demuxer_stream_) | 455 if (!decrypting_demuxer_stream_) |
| 403 Reset(base::ResetAndReturn(&reset_cb_)); | 456 Reset(base::ResetAndReturn(&reset_cb_)); |
| 404 return; | 457 return; |
| 405 } | 458 } |
| 406 | 459 |
| 407 if (status == DemuxerStream::kAborted) { | 460 if (status == DemuxerStream::kAborted) { |
| 408 SatisfyRead(DEMUXER_READ_ABORTED, NULL); | 461 SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
| 409 return; | 462 return; |
| 410 } | 463 } |
| 411 | 464 |
| 412 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { | 465 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { |
| 413 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); | 466 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); |
| 414 if (active_splice_ || has_splice_ts) { | 467 if (active_splice_ || has_splice_ts) { |
| 415 splice_observer_cb_.Run(buffer->splice_timestamp()); | 468 splice_observer_cb_.Run(buffer->splice_timestamp()); |
| 416 active_splice_ = has_splice_ts; | 469 active_splice_ = has_splice_ts; |
| 417 } | 470 } |
| 418 } | 471 } |
| 419 | 472 |
| 420 DCHECK(status == DemuxerStream::kOk) << status; | 473 DCHECK(status == DemuxerStream::kOk) << status; |
| 421 Decode(buffer); | 474 Decode(buffer); |
| 475 |
| 476 // Read more data if the decoder supports multiple parallel decoding requests. |
| 477 if (CanDecodeMore() && !buffer->end_of_stream()) |
| 478 ReadFromDemuxerStream(); |
| 422 } | 479 } |
| 423 | 480 |
| 424 template <DemuxerStream::Type StreamType> | 481 template <DemuxerStream::Type StreamType> |
| 425 void DecoderStream<StreamType>::ReinitializeDecoder() { | 482 void DecoderStream<StreamType>::ReinitializeDecoder() { |
| 426 FUNCTION_DVLOG(2); | 483 FUNCTION_DVLOG(2); |
| 427 DCHECK(task_runner_->BelongsToCurrentThread()); | 484 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 428 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 485 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
| 486 DCHECK_EQ(pending_decode_requests_, 0); |
| 429 | 487 |
| 430 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 488 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
| 431 state_ = STATE_REINITIALIZING_DECODER; | 489 state_ = STATE_REINITIALIZING_DECODER; |
| 432 decoder_->Initialize( | 490 decoder_->Initialize( |
| 433 StreamTraits::GetDecoderConfig(*stream_), | 491 StreamTraits::GetDecoderConfig(*stream_), |
| 434 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 492 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
| 435 weak_factory_.GetWeakPtr())); | 493 weak_factory_.GetWeakPtr())); |
| 436 } | 494 } |
| 437 | 495 |
| 438 template <DemuxerStream::Type StreamType> | 496 template <DemuxerStream::Type StreamType> |
| 439 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { | 497 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { |
| 440 FUNCTION_DVLOG(2); | 498 FUNCTION_DVLOG(2); |
| 441 DCHECK(task_runner_->BelongsToCurrentThread()); | 499 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 442 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 500 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
| 443 DCHECK(stop_cb_.is_null()); | 501 DCHECK(stop_cb_.is_null()); |
| 444 | 502 |
| 445 // ReinitializeDecoder() can be called in two cases: | 503 // ReinitializeDecoder() can be called in two cases: |
| 446 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 504 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
| 447 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). | 505 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
| 448 // Also, Reset() can be called during pending ReinitializeDecoder(). | 506 // Also, Reset() can be called during pending ReinitializeDecoder(). |
| 449 // This function needs to handle them all! | 507 // This function needs to handle them all! |
| 450 | 508 |
| 451 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 509 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
| 452 | 510 |
| 453 if (!reset_cb_.is_null()) { | 511 if (!reset_cb_.is_null()) { |
| 454 if (!read_cb_.is_null()) | |
| 455 AbortRead(); | |
| 456 base::ResetAndReturn(&reset_cb_).Run(); | 512 base::ResetAndReturn(&reset_cb_).Run(); |
| 513 return; |
| 457 } | 514 } |
| 458 | 515 |
| 459 if (read_cb_.is_null()) | 516 if (read_cb_.is_null()) |
| 460 return; | 517 return; |
| 461 | 518 |
| 462 if (state_ == STATE_ERROR) { | 519 if (state_ == STATE_ERROR) { |
| 463 SatisfyRead(DECODE_ERROR, NULL); | 520 SatisfyRead(DECODE_ERROR, NULL); |
| 464 return; | 521 return; |
| 465 } | 522 } |
| 466 | 523 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 decrypting_demuxer_stream_.reset(); | 571 decrypting_demuxer_stream_.reset(); |
| 515 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 572 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
| 516 // posted in Stop(). | 573 // posted in Stop(). |
| 517 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 574 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| 518 } | 575 } |
| 519 | 576 |
| 520 template class DecoderStream<DemuxerStream::VIDEO>; | 577 template class DecoderStream<DemuxerStream::VIDEO>; |
| 521 template class DecoderStream<DemuxerStream::AUDIO>; | 578 template class DecoderStream<DemuxerStream::AUDIO>; |
| 522 | 579 |
| 523 } // namespace media | 580 } // namespace media |
| OLD | NEW |