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::CanReadWithoutStalling() const { | 152 bool VideoFrameStream::CanReadWithoutStalling() const { |
145 DCHECK(message_loop_->BelongsToCurrentThread()); | 153 DCHECK(message_loop_->BelongsToCurrentThread()); |
146 return decoder_->CanReadWithoutStalling(); | 154 return decoder_->CanReadWithoutStalling(); |
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 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 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.get()); | 223 DCHECK(!frame.get()); |
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.get() != NULL, status == DemuxerStream::kOk) << status; | 270 DCHECK_EQ(buffer.get() != 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()) |
296 return; | 346 return; |
297 } | |
298 | |
299 DCHECK(!read_cb_.is_null()); | |
300 | 347 |
301 if (!stop_cb_.is_null()) { | 348 if (!stop_cb_.is_null()) { |
302 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kOk, NULL); | 349 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kOk, NULL); |
303 return; | 350 return; |
304 } | 351 } |
305 | 352 |
306 if (state_ == STATE_ERROR) { | 353 if (state_ == STATE_ERROR) { |
307 base::ResetAndReturn(&read_cb_).Run(VideoDecoder::kDecodeError, NULL); | 354 SatisfyRead(VideoDecoder::kDecodeError, NULL); |
308 return; | 355 return; |
309 } | 356 } |
310 | 357 |
311 decoder_->Read(base::Bind(&VideoFrameStream::OnFrameReady, weak_this_)); | 358 ReadFromDemuxerStream(); |
312 } | 359 } |
313 | 360 |
314 void VideoFrameStream::ResetDecoder() { | 361 void VideoFrameStream::ResetDecoder() { |
315 DCHECK(message_loop_->BelongsToCurrentThread()); | 362 DCHECK(message_loop_->BelongsToCurrentThread()); |
316 DCHECK(state_ == STATE_NORMAL || | 363 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
317 state_ == STATE_FLUSHING_DECODER || | |
318 state_ == STATE_ERROR) << state_; | 364 state_ == STATE_ERROR) << state_; |
319 DCHECK(!reset_cb_.is_null()); | 365 DCHECK(!reset_cb_.is_null()); |
320 | 366 |
321 decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset, weak_this_)); | 367 decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset, weak_this_)); |
322 } | 368 } |
323 | 369 |
324 void VideoFrameStream::OnDecoderReset() { | 370 void VideoFrameStream::OnDecoderReset() { |
325 DCHECK(message_loop_->BelongsToCurrentThread()); | 371 DCHECK(message_loop_->BelongsToCurrentThread()); |
326 DCHECK(state_ == STATE_NORMAL || | 372 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
327 state_ == STATE_FLUSHING_DECODER || | |
328 state_ == STATE_ERROR) << state_; | 373 state_ == STATE_ERROR) << state_; |
329 // If Reset() was called during pending read, read callback should be fired | 374 // If Reset() was called during pending read, read callback should be fired |
330 // before the reset callback is fired. | 375 // before the reset callback is fired. |
331 DCHECK(read_cb_.is_null()); | 376 DCHECK(read_cb_.is_null()); |
332 DCHECK(!reset_cb_.is_null()); | 377 DCHECK(!reset_cb_.is_null()); |
333 | 378 |
334 if (state_ != STATE_FLUSHING_DECODER || !stop_cb_.is_null()) { | 379 if (state_ != STATE_FLUSHING_DECODER || !stop_cb_.is_null()) { |
335 base::ResetAndReturn(&reset_cb_).Run(); | 380 base::ResetAndReturn(&reset_cb_).Run(); |
336 return; | 381 return; |
337 } | 382 } |
(...skipping 20 matching lines...) Expand all Loading... |
358 DCHECK(!stop_cb_.is_null()); | 403 DCHECK(!stop_cb_.is_null()); |
359 | 404 |
360 state_ = STATE_STOPPED; | 405 state_ = STATE_STOPPED; |
361 stream_ = NULL; | 406 stream_ = NULL; |
362 decoder_.reset(); | 407 decoder_.reset(); |
363 decrypting_demuxer_stream_.reset(); | 408 decrypting_demuxer_stream_.reset(); |
364 base::ResetAndReturn(&stop_cb_).Run(); | 409 base::ResetAndReturn(&stop_cb_).Run(); |
365 } | 410 } |
366 | 411 |
367 } // namespace media | 412 } // namespace media |
OLD | NEW |