| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/video_frame_stream.h" | 5 #include "media/filters/video_frame_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/location.h" | 9 #include "base/location.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 DCHECK(init_cb_.is_null()); | 42 DCHECK(init_cb_.is_null()); |
| 43 DCHECK(!init_cb.is_null()); | 43 DCHECK(!init_cb.is_null()); |
| 44 | 44 |
| 45 weak_this_ = weak_factory_.GetWeakPtr(); | 45 weak_this_ = weak_factory_.GetWeakPtr(); |
| 46 | 46 |
| 47 statistics_cb_ = statistics_cb; | 47 statistics_cb_ = statistics_cb; |
| 48 init_cb_ = init_cb; | 48 init_cb_ = init_cb; |
| 49 stream_ = stream; | 49 stream_ = stream; |
| 50 | 50 |
| 51 state_ = STATE_INITIALIZING; | 51 state_ = STATE_INITIALIZING; |
| 52 decoder_selector_->SelectVideoDecoder(this, statistics_cb, base::Bind( | 52 // TODO(xhwang): VideoDecoderSelector only needs a config to select a decoder. |
| 53 decoder_selector_->SelectVideoDecoder(stream, statistics_cb, base::Bind( |
| 53 &VideoFrameStream::OnDecoderSelected, weak_this_)); | 54 &VideoFrameStream::OnDecoderSelected, weak_this_)); |
| 54 } | 55 } |
| 55 | 56 |
| 56 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { | 57 void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) { |
| 57 DCHECK(message_loop_->BelongsToCurrentThread()); | 58 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 58 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 59 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 59 state_ == STATE_ERROR) << state_; | 60 state_ == STATE_ERROR) << state_; |
| 60 // No two reads in the flight at any time. | 61 // No two reads in the flight at any time. |
| 61 DCHECK(read_cb_.is_null()); | 62 DCHECK(read_cb_.is_null()); |
| 62 // No read during resetting or stopping process. | 63 // No read during resetting or stopping process. |
| 63 DCHECK(reset_cb_.is_null()); | 64 DCHECK(reset_cb_.is_null()); |
| 64 DCHECK(stop_cb_.is_null()); | 65 DCHECK(stop_cb_.is_null()); |
| 65 | 66 |
| 67 read_cb_ = read_cb; |
| 68 |
| 66 if (state_ == STATE_ERROR) { | 69 if (state_ == STATE_ERROR) { |
| 67 message_loop_->PostTask(FROM_HERE, base::Bind( | 70 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 68 read_cb, VideoDecoder::kDecodeError, scoped_refptr<VideoFrame>())); | 71 read_cb, VideoDecoder::kDecodeError, scoped_refptr<VideoFrame>())); |
| 69 return; | 72 return; |
| 70 } | 73 } |
| 71 | 74 |
| 72 read_cb_ = read_cb; | 75 if (state_ == STATE_FLUSHING_DECODER) { |
| 73 decoder_->Read(base::Bind(&VideoFrameStream::OnFrameReady, weak_this_)); | 76 FlushDecoder(); |
| 77 return; |
| 78 } |
| 79 |
| 80 ReadFromDemuxerStream(); |
| 74 } | 81 } |
| 75 | 82 |
| 76 // VideoDecoder API guarantees that if VideoDecoder::Reset() is called during | |
| 77 // a pending read, the read callback must be fired before the reset callback is | |
| 78 // fired. Therefore, we can call VideoDecoder::Reset() regardless of if we have | |
| 79 // a pending read and always satisfy the reset callback when the decoder reset | |
| 80 // is finished. The only exception is when Reset() is called during decoder | |
| 81 // reinitialization. In this case we cannot and don't need to reset the decoder. | |
| 82 // We should just wait for the reinitialization to finish to satisfy the reset | |
| 83 // callback. | |
| 84 void VideoFrameStream::Reset(const base::Closure& closure) { | 83 void VideoFrameStream::Reset(const base::Closure& closure) { |
| 85 DCHECK(message_loop_->BelongsToCurrentThread()); | 84 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 86 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 85 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
| 87 DCHECK(reset_cb_.is_null()); | 86 DCHECK(reset_cb_.is_null()); |
| 88 DCHECK(stop_cb_.is_null()); | 87 DCHECK(stop_cb_.is_null()); |
| 89 | 88 |
| 90 reset_cb_ = closure; | 89 reset_cb_ = closure; |
| 91 | 90 |
| 92 // VideoDecoder does not need to be and cannot be Reset() during | 91 // During decoder reinitialization, VideoDecoder does not need to be and |
| 93 // reinitialization. |decrypting_demuxer_stream_| was reset before decoder | 92 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder |
| 94 // reinitialization. | 93 // reinitialization. |
| 95 if (state_ == STATE_REINITIALIZING_DECODER) | 94 // During pending demuxer read, VideoDecoder will be reset after demuxer read |
| 95 // is returned (in OnBufferReady()). |
| 96 if (state_ == STATE_REINITIALIZING_DECODER || |
| 97 state_ == STATE_PENDING_DEMUXER_READ) { |
| 96 return; | 98 return; |
| 99 } |
| 97 | 100 |
| 98 // We may or may not have pending read, but we'll start to reset everything | 101 // VideoDecoder API guarantees that if VideoDecoder::Reset() is called during |
| 99 // regardless. | 102 // a pending decode, the decode callback must be fired before the reset |
| 103 // callback is fired. Therefore, we can call VideoDecoder::Reset() regardless |
| 104 // of if we have a pending decode and always satisfy the reset callback when |
| 105 // the decoder reset is finished. |
| 100 if (decrypting_demuxer_stream_) { | 106 if (decrypting_demuxer_stream_) { |
| 101 decrypting_demuxer_stream_->Reset(base::Bind( | 107 decrypting_demuxer_stream_->Reset(base::Bind( |
| 102 &VideoFrameStream::ResetDecoder, weak_this_)); | 108 &VideoFrameStream::ResetDecoder, weak_this_)); |
| 103 return; | 109 return; |
| 104 } | 110 } |
| 105 | 111 |
| 106 ResetDecoder(); | 112 ResetDecoder(); |
| 107 } | 113 } |
| 108 | 114 |
| 109 void VideoFrameStream::Stop(const base::Closure& closure) { | 115 void VideoFrameStream::Stop(const base::Closure& closure) { |
| 110 DCHECK(message_loop_->BelongsToCurrentThread()); | 116 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 111 DCHECK_NE(state_, STATE_STOPPED) << state_; | 117 DCHECK_NE(state_, STATE_STOPPED) << state_; |
| 112 DCHECK(stop_cb_.is_null()); | 118 DCHECK(stop_cb_.is_null()); |
| 113 | 119 |
| 114 stop_cb_ = closure; | 120 stop_cb_ = closure; |
| 115 | 121 |
| 116 // The stopping will continue after all of the following pending callbacks | 122 // The stopping process will continue after the pending operation is finished. |
| 117 // (if they are not null) are satisfied. | |
| 118 // TODO(xhwang): Now we cannot stop the initialization process through | 123 // TODO(xhwang): Now we cannot stop the initialization process through |
| 119 // VideoDecoderSelector. Fix this. See: http://crbug.com/222054 | 124 // VideoDecoderSelector. Fix this. See: http://crbug.com/222054 |
| 120 if (state_ == STATE_INITIALIZING) | 125 if (state_ == STATE_INITIALIZING || state_ == STATE_PENDING_DEMUXER_READ) |
| 121 return; | 126 return; |
| 122 | 127 |
| 123 // We may or may not have pending read and/or pending reset, but we'll start | 128 // VideoDecoder API guarantees that if VideoDecoder::Stop() is called during |
| 124 // to stop everything regardless. | 129 // a pending reset or a pending decode, the callbacks are always fired in the |
| 125 | 130 // decode -> reset -> stop order. Therefore, we can call VideoDecoder::Stop() |
| 131 // regardless of if we have a pending decode or reset and always satisfy the |
| 132 // stop callback when the decoder decode/reset is finished. |
| 126 if (decrypting_demuxer_stream_) { | 133 if (decrypting_demuxer_stream_) { |
| 127 decrypting_demuxer_stream_->Reset(base::Bind( | 134 decrypting_demuxer_stream_->Reset(base::Bind( |
| 128 &VideoFrameStream::StopDecoder, weak_this_)); | 135 &VideoFrameStream::StopDecoder, weak_this_)); |
| 129 return; | 136 return; |
| 130 } | 137 } |
| 131 | 138 |
| 139 // We may not have a |decoder_| if Stop() was called during initialization. |
| 132 if (decoder_) { | 140 if (decoder_) { |
| 133 StopDecoder(); | 141 StopDecoder(); |
| 134 return; | 142 return; |
| 135 } | 143 } |
| 136 | 144 |
| 137 state_ = STATE_STOPPED; | 145 state_ = STATE_STOPPED; |
| 138 stream_ = NULL; | 146 stream_ = NULL; |
| 139 decoder_.reset(); | 147 decoder_.reset(); |
| 140 decrypting_demuxer_stream_.reset(); | 148 decrypting_demuxer_stream_.reset(); |
| 141 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 149 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| 142 } | 150 } |
| 143 | 151 |
| 144 bool VideoFrameStream::HasOutputFrameAvailable() const { | 152 bool VideoFrameStream::HasOutputFrameAvailable() const { |
| 145 DCHECK(message_loop_->BelongsToCurrentThread()); | 153 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 146 return decoder_->HasOutputFrameAvailable(); | 154 return decoder_->HasOutputFrameAvailable(); |
| 147 } | 155 } |
| 148 | 156 |
| 149 void VideoFrameStream::Read(const DemuxerStream::ReadCB& demuxer_read_cb) { | |
| 150 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 151 | |
| 152 if (state_ == STATE_FLUSHING_DECODER) { | |
| 153 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 154 demuxer_read_cb, DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer())); | |
| 155 return; | |
| 156 } | |
| 157 | |
| 158 stream_->Read(base::Bind( | |
| 159 &VideoFrameStream::OnBufferReady, weak_this_, demuxer_read_cb)); | |
| 160 } | |
| 161 | |
| 162 const AudioDecoderConfig& VideoFrameStream::audio_decoder_config() { | |
| 163 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 164 LOG(FATAL) << "Method audio_decoder_config() called on VideoFrameStream"; | |
| 165 return stream_->audio_decoder_config(); | |
| 166 } | |
| 167 | |
| 168 const VideoDecoderConfig& VideoFrameStream::video_decoder_config() { | |
| 169 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 170 return stream_->video_decoder_config(); | |
| 171 } | |
| 172 | |
| 173 DemuxerStream::Type VideoFrameStream::type() { | |
| 174 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 175 return VIDEO; | |
| 176 } | |
| 177 | |
| 178 void VideoFrameStream::EnableBitstreamConverter() { | |
| 179 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 180 NOTREACHED(); | |
| 181 } | |
| 182 | |
| 183 void VideoFrameStream::OnDecoderSelected( | 157 void VideoFrameStream::OnDecoderSelected( |
| 184 scoped_ptr<VideoDecoder> selected_decoder, | 158 scoped_ptr<VideoDecoder> selected_decoder, |
| 185 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 159 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| 186 DCHECK(message_loop_->BelongsToCurrentThread()); | 160 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 187 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 161 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
| 188 DCHECK(!init_cb_.is_null()); | 162 DCHECK(!init_cb_.is_null()); |
| 163 DCHECK(read_cb_.is_null()); |
| 164 DCHECK(reset_cb_.is_null()); |
| 165 |
| 189 decoder_selector_.reset(); | 166 decoder_selector_.reset(); |
| 190 | 167 |
| 191 if (!selected_decoder) { | 168 if (!selected_decoder) { |
| 192 state_ = STATE_UNINITIALIZED; | 169 state_ = STATE_UNINITIALIZED; |
| 193 base::ResetAndReturn(&init_cb_).Run(false, false); | 170 base::ResetAndReturn(&init_cb_).Run(false, false); |
| 194 } else { | 171 } else { |
| 195 state_ = STATE_NORMAL; | 172 state_ = STATE_NORMAL; |
| 173 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass(); |
| 174 if (decrypting_demuxer_stream_) |
| 175 stream_ = decrypting_demuxer_stream_.get(); |
| 196 decoder_ = selected_decoder.Pass(); | 176 decoder_ = selected_decoder.Pass(); |
| 197 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass(); | 177 if (decoder_->NeedsBitstreamConversion()) |
| 198 if (decoder_->NeedsBitstreamConversion()) { | |
| 199 stream_->EnableBitstreamConverter(); | 178 stream_->EnableBitstreamConverter(); |
| 200 } | |
| 201 // TODO(xhwang): We assume |decoder_->HasAlpha()| does not change after | 179 // TODO(xhwang): We assume |decoder_->HasAlpha()| does not change after |
| 202 // reinitialization. Check this condition. | 180 // reinitialization. Check this condition. |
| 203 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); | 181 base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha()); |
| 204 } | 182 } |
| 205 | 183 |
| 206 // Stop() called during initialization. | 184 // Stop() called during initialization. |
| 207 if (!stop_cb_.is_null()) { | 185 if (!stop_cb_.is_null()) { |
| 208 Stop(base::ResetAndReturn(&stop_cb_)); | 186 Stop(base::ResetAndReturn(&stop_cb_)); |
| 209 return; | 187 return; |
| 210 } | 188 } |
| 211 } | 189 } |
| 212 | 190 |
| 191 void VideoFrameStream::SatisfyRead(VideoDecoder::Status status, |
| 192 const scoped_refptr<VideoFrame>& frame) { |
| 193 DCHECK(!read_cb_.is_null()); |
| 194 base::ResetAndReturn(&read_cb_).Run(status, frame); |
| 195 } |
| 196 |
| 197 void VideoFrameStream::AbortRead() { |
| 198 SatisfyRead(VideoDecoder::kOk, NULL); |
| 199 } |
| 200 |
| 201 void VideoFrameStream::Decode(const scoped_refptr<DecoderBuffer>& buffer) { |
| 202 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
| 203 DCHECK(!read_cb_.is_null()); |
| 204 DCHECK(reset_cb_.is_null()); |
| 205 DCHECK(stop_cb_.is_null()); |
| 206 DCHECK(buffer); |
| 207 |
| 208 decoder_->Decode(buffer, base::Bind(&VideoFrameStream::OnFrameReady, |
| 209 weak_this_)); |
| 210 } |
| 211 |
| 212 void VideoFrameStream::FlushDecoder() { |
| 213 Decode(DecoderBuffer::CreateEOSBuffer()); |
| 214 } |
| 215 |
| 213 void VideoFrameStream::OnFrameReady(const VideoDecoder::Status status, | 216 void VideoFrameStream::OnFrameReady(const VideoDecoder::Status status, |
| 214 const scoped_refptr<VideoFrame>& frame) { | 217 const scoped_refptr<VideoFrame>& frame) { |
| 215 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 218 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
| 216 DCHECK(!read_cb_.is_null()); | 219 DCHECK(!read_cb_.is_null()); |
| 217 | 220 |
| 218 if (status != VideoDecoder::kOk) { | 221 if (status == VideoDecoder::kDecodeError || |
| 222 status == VideoDecoder::kDecryptError) { |
| 219 DCHECK(!frame); | 223 DCHECK(!frame); |
| 220 state_ = STATE_ERROR; | 224 state_ = STATE_ERROR; |
| 221 base::ResetAndReturn(&read_cb_).Run(status, NULL); | 225 SatisfyRead(status, NULL); |
| 222 return; | 226 return; |
| 223 } | 227 } |
| 224 | 228 |
| 229 // Drop decoding result if Reset()/Stop() was called during decoding. |
| 225 // The stopping/resetting process will be handled when the decoder is | 230 // The stopping/resetting process will be handled when the decoder is |
| 226 // stopped/reset. | 231 // stopped/reset. |
| 227 if (!stop_cb_.is_null() || !reset_cb_.is_null()) { | 232 if (!stop_cb_.is_null() || !reset_cb_.is_null()) { |
| 228 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kOk, NULL); | 233 AbortRead(); |
| 229 return; | 234 return; |
| 230 } | 235 } |
| 231 | 236 |
| 232 // Decoder flush finished. Reinitialize the video decoder. | 237 // Decoder flushed. Reinitialize the video decoder. |
| 233 if (state_ == STATE_FLUSHING_DECODER && | 238 if (state_ == STATE_FLUSHING_DECODER && |
| 234 status == VideoDecoder::kOk && frame->IsEndOfStream()) { | 239 status == VideoDecoder::kOk && frame->IsEndOfStream()) { |
| 235 ReinitializeDecoder(); | 240 ReinitializeDecoder(); |
| 236 return; | 241 return; |
| 237 } | 242 } |
| 238 | 243 |
| 239 base::ResetAndReturn(&read_cb_).Run(status, frame); | 244 if (status == VideoDecoder::kNotEnoughData) { |
| 245 if (state_ == STATE_NORMAL) |
| 246 ReadFromDemuxerStream(); |
| 247 else if (state_ == STATE_FLUSHING_DECODER) |
| 248 FlushDecoder(); |
| 249 return; |
| 250 } |
| 251 |
| 252 SatisfyRead(status, frame); |
| 253 } |
| 254 |
| 255 void VideoFrameStream::ReadFromDemuxerStream() { |
| 256 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
| 257 DCHECK(!read_cb_.is_null()); |
| 258 DCHECK(reset_cb_.is_null()); |
| 259 DCHECK(stop_cb_.is_null()); |
| 260 |
| 261 state_ = STATE_PENDING_DEMUXER_READ; |
| 262 stream_->Read(base::Bind(&VideoFrameStream::OnBufferReady, weak_this_)); |
| 240 } | 263 } |
| 241 | 264 |
| 242 void VideoFrameStream::OnBufferReady( | 265 void VideoFrameStream::OnBufferReady( |
| 243 const DemuxerStream::ReadCB& demuxer_read_cb, | |
| 244 DemuxerStream::Status status, | 266 DemuxerStream::Status status, |
| 245 const scoped_refptr<DecoderBuffer>& buffer) { | 267 const scoped_refptr<DecoderBuffer>& buffer) { |
| 246 DCHECK(message_loop_->BelongsToCurrentThread()); | 268 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 247 // VideoFrameStream reads from demuxer stream only when in NORMAL state. | 269 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; |
| 248 DCHECK_EQ(state_, STATE_NORMAL) << state_; | |
| 249 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 270 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
| 271 DCHECK(!read_cb_.is_null()); |
| 250 | 272 |
| 251 if (status == DemuxerStream::kConfigChanged) { | 273 state_ = STATE_NORMAL; |
| 252 DVLOG(2) << "OnBufferReady() - kConfigChanged"; | 274 |
| 253 state_ = STATE_FLUSHING_DECODER; | 275 // Reset()/Stop() was postponed during STATE_PENDING_DEMUXER_READ state. |
| 254 demuxer_read_cb.Run(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 276 // We need to handle them in this function. |
| 277 |
| 278 if (!stop_cb_.is_null()) { |
| 279 AbortRead(); |
| 280 if (!reset_cb_.is_null()) |
| 281 Reset(base::ResetAndReturn(&reset_cb_)); |
| 282 Stop(base::ResetAndReturn(&stop_cb_)); |
| 255 return; | 283 return; |
| 256 } | 284 } |
| 257 | 285 |
| 258 DCHECK(status == DemuxerStream::kOk || status == DemuxerStream::kAborted); | 286 if (status == DemuxerStream::kConfigChanged) { |
| 259 demuxer_read_cb.Run(status, buffer); | 287 state_ = STATE_FLUSHING_DECODER; |
| 288 if (!reset_cb_.is_null()) { |
| 289 AbortRead(); |
| 290 Reset(base::ResetAndReturn(&reset_cb_)); |
| 291 // Reinitialization will continue after Reset() is done. |
| 292 } else { |
| 293 FlushDecoder(); |
| 294 } |
| 295 return; |
| 296 } |
| 297 |
| 298 if (!reset_cb_.is_null()) { |
| 299 AbortRead(); |
| 300 Reset(base::ResetAndReturn(&reset_cb_)); |
| 301 return; |
| 302 } |
| 303 |
| 304 if (status == DemuxerStream::kAborted) { |
| 305 AbortRead(); |
| 306 return; |
| 307 } |
| 308 |
| 309 DCHECK(status == DemuxerStream::kOk) << status; |
| 310 Decode(buffer); |
| 260 } | 311 } |
| 261 | 312 |
| 262 void VideoFrameStream::ReinitializeDecoder() { | 313 void VideoFrameStream::ReinitializeDecoder() { |
| 263 DCHECK(message_loop_->BelongsToCurrentThread()); | 314 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 264 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 315 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
| 265 | 316 |
| 266 DemuxerStream* stream = this; | 317 DCHECK(stream_->video_decoder_config().IsValidConfig()); |
| 267 if (decrypting_demuxer_stream_) { | |
| 268 // TODO(xhwang): Remove this hack! Since VideoFrameStream handles | |
| 269 // kConfigChange internally and hides it from downstream filters. The | |
| 270 // DecryptingDemuxerStream never receives kConfigChanged to reset it's | |
| 271 // internal VideoDecoderConfig. Call InitializeDecoderConfig() here | |
| 272 // explicitly to solve this. This will be removed when we separate the | |
| 273 // DemuxerStream from the VideoDecoder. | |
| 274 decrypting_demuxer_stream_->InitializeDecoderConfig(); | |
| 275 stream = decrypting_demuxer_stream_.get(); | |
| 276 } | |
| 277 | |
| 278 DCHECK(stream->video_decoder_config().IsValidConfig()); | |
| 279 state_ = STATE_REINITIALIZING_DECODER; | 318 state_ = STATE_REINITIALIZING_DECODER; |
| 280 decoder_->Initialize( | 319 decoder_->Initialize( |
| 281 stream, | 320 stream_->video_decoder_config(), |
| 282 base::Bind(&VideoFrameStream::OnDecoderReinitialized, weak_this_), | 321 base::Bind(&VideoFrameStream::OnDecoderReinitialized, weak_this_), |
| 283 statistics_cb_); | 322 statistics_cb_); |
| 284 } | 323 } |
| 285 | 324 |
| 286 void VideoFrameStream::OnDecoderReinitialized(PipelineStatus status) { | 325 void VideoFrameStream::OnDecoderReinitialized(PipelineStatus status) { |
| 287 DCHECK(message_loop_->BelongsToCurrentThread()); | 326 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 288 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 327 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
| 289 | 328 |
| 329 // ReinitializeDecoder() can be called in two cases: |
| 330 // 1, Flushing decoder finished (see OnFrameReady()). |
| 331 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
| 332 // Also, Reset()/Stop() can be called during pending ReinitializeDecoder(). |
| 333 // This function needs to handle them all! |
| 334 |
| 290 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 335 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
| 291 | 336 |
| 292 if (!reset_cb_.is_null()) { | 337 if (!read_cb_.is_null() && (!stop_cb_.is_null() || !reset_cb_.is_null())) |
| 293 if (!read_cb_.is_null()) | 338 AbortRead(); |
| 294 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kOk, NULL); | 339 |
| 340 if (!reset_cb_.is_null()) |
| 295 base::ResetAndReturn(&reset_cb_).Run(); | 341 base::ResetAndReturn(&reset_cb_).Run(); |
| 342 |
| 343 // If !stop_cb_.is_null(), it will be handled in OnDecoderStopped(). |
| 344 |
| 345 if (read_cb_.is_null()) |
| 346 return; |
| 347 |
| 348 if (state_ == STATE_ERROR) { |
| 349 SatisfyRead(VideoDecoder::kDecodeError, NULL); |
| 296 return; | 350 return; |
| 297 } | 351 } |
| 298 | 352 |
| 299 DCHECK(!read_cb_.is_null()); | 353 ReadFromDemuxerStream(); |
| 300 | |
| 301 if (state_ == STATE_ERROR) { | |
| 302 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kDecodeError, NULL); | |
| 303 return; | |
| 304 } | |
| 305 | |
| 306 decoder_->Read(base::Bind(&VideoFrameStream::OnFrameReady, weak_this_)); | |
| 307 } | 354 } |
| 308 | 355 |
| 309 void VideoFrameStream::ResetDecoder() { | 356 void VideoFrameStream::ResetDecoder() { |
| 310 DCHECK(message_loop_->BelongsToCurrentThread()); | 357 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 311 DCHECK(state_ == STATE_NORMAL || | 358 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 312 state_ == STATE_FLUSHING_DECODER || | |
| 313 state_ == STATE_ERROR) << state_; | 359 state_ == STATE_ERROR) << state_; |
| 314 DCHECK(!reset_cb_.is_null()); | 360 DCHECK(!reset_cb_.is_null()); |
| 315 | 361 |
| 316 decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset, weak_this_)); | 362 decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset, weak_this_)); |
| 317 } | 363 } |
| 318 | 364 |
| 319 void VideoFrameStream::OnDecoderReset() { | 365 void VideoFrameStream::OnDecoderReset() { |
| 320 DCHECK(message_loop_->BelongsToCurrentThread()); | 366 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 321 DCHECK(state_ == STATE_NORMAL || | 367 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
| 322 state_ == STATE_FLUSHING_DECODER || | |
| 323 state_ == STATE_ERROR) << state_; | 368 state_ == STATE_ERROR) << state_; |
| 324 // If Reset() was called during pending read, read callback should be fired | 369 // If Reset() was called during pending read, read callback should be fired |
| 325 // before the reset callback is fired. | 370 // before the reset callback is fired. |
| 326 DCHECK(read_cb_.is_null()); | 371 DCHECK(read_cb_.is_null()); |
| 327 DCHECK(!reset_cb_.is_null()); | 372 DCHECK(!reset_cb_.is_null()); |
| 328 | 373 |
| 329 if (state_ != STATE_FLUSHING_DECODER || !stop_cb_.is_null()) { | 374 if (state_ != STATE_FLUSHING_DECODER || !stop_cb_.is_null()) { |
| 330 base::ResetAndReturn(&reset_cb_).Run(); | 375 base::ResetAndReturn(&reset_cb_).Run(); |
| 331 return; | 376 return; |
| 332 } | 377 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 353 DCHECK(!stop_cb_.is_null()); | 398 DCHECK(!stop_cb_.is_null()); |
| 354 | 399 |
| 355 state_ = STATE_STOPPED; | 400 state_ = STATE_STOPPED; |
| 356 stream_ = NULL; | 401 stream_ = NULL; |
| 357 decoder_.reset(); | 402 decoder_.reset(); |
| 358 decrypting_demuxer_stream_.reset(); | 403 decrypting_demuxer_stream_.reset(); |
| 359 base::ResetAndReturn(&stop_cb_).Run(); | 404 base::ResetAndReturn(&stop_cb_).Run(); |
| 360 } | 405 } |
| 361 | 406 |
| 362 } // namespace media | 407 } // namespace media |
| OLD | NEW |