OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/base/android/media_codec_decoder.h" | 5 #include "media/base/android/media_codec_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 // Request new data in the kRunning state if the queue size is less than this. | 21 // Request new data in the kRunning state if the queue size is less than this. |
22 const int kPlaybackLowLimit = 4; | 22 const int kPlaybackLowLimit = 4; |
23 | 23 |
24 // Posting delay of the next frame processing, in milliseconds | 24 // Posting delay of the next frame processing, in milliseconds |
25 const int kNextFrameDelay = 1; | 25 const int kNextFrameDelay = 1; |
26 | 26 |
27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds. | 27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds. |
28 const int kInputBufferTimeout = 20; | 28 const int kInputBufferTimeout = 20; |
29 | 29 |
30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds. | 30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds. |
31 const int kOutputBufferTimeout = 20; | 31 const int kOutputBufferTimeout = 10; |
Tima Vaisburd
2015/08/03 19:44:34
Upon more detailed examination of unit tests I fou
qinmin
2015/08/03 21:25:15
these values are too small, some devices will alwa
Tima Vaisburd
2015/08/03 22:49:05
Restored to 20 ms
| |
32 } | 32 } |
33 | 33 |
34 MediaCodecDecoder::MediaCodecDecoder( | 34 MediaCodecDecoder::MediaCodecDecoder( |
35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
36 const base::Closure& external_request_data_cb, | 36 const base::Closure& external_request_data_cb, |
37 const base::Closure& starvation_cb, | 37 const base::Closure& starvation_cb, |
38 const base::Closure& preroll_done_cb, | |
38 const base::Closure& stop_done_cb, | 39 const base::Closure& stop_done_cb, |
39 const base::Closure& error_cb, | 40 const base::Closure& error_cb, |
40 const char* decoder_thread_name) | 41 const char* decoder_thread_name) |
41 : media_task_runner_(media_task_runner), | 42 : media_task_runner_(media_task_runner), |
42 decoder_thread_(decoder_thread_name), | 43 decoder_thread_(decoder_thread_name), |
43 needs_reconfigure_(false), | 44 needs_reconfigure_(false), |
44 external_request_data_cb_(external_request_data_cb), | 45 external_request_data_cb_(external_request_data_cb), |
45 starvation_cb_(starvation_cb), | 46 starvation_cb_(starvation_cb), |
47 preroll_done_cb_(preroll_done_cb), | |
46 stop_done_cb_(stop_done_cb), | 48 stop_done_cb_(stop_done_cb), |
47 error_cb_(error_cb), | 49 error_cb_(error_cb), |
48 state_(kStopped), | 50 state_(kStopped), |
51 needs_preroll_(true), | |
49 eos_enqueued_(false), | 52 eos_enqueued_(false), |
50 completed_(false), | 53 completed_(false), |
51 last_frame_posted_(false), | 54 last_frame_posted_(false), |
52 is_data_request_in_progress_(false), | 55 is_data_request_in_progress_(false), |
53 is_incoming_data_invalid_(false), | 56 is_incoming_data_invalid_(false), |
54 #ifndef NDEBUG | 57 #ifndef NDEBUG |
55 verify_next_frame_is_key_(false), | 58 verify_next_frame_is_key_(false), |
56 #endif | 59 #endif |
57 weak_factory_(this) { | 60 weak_factory_(this) { |
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 61 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
59 | 62 |
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; | 63 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; |
61 | 64 |
62 internal_error_cb_ = | 65 internal_error_cb_ = |
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); | 66 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); |
67 internal_preroll_done_cb_ = | |
68 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr()); | |
64 request_data_cb_ = | 69 request_data_cb_ = |
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); | 70 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); |
66 } | 71 } |
67 | 72 |
68 MediaCodecDecoder::~MediaCodecDecoder() { | 73 MediaCodecDecoder::~MediaCodecDecoder() { |
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 74 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
70 | 75 |
71 DVLOG(1) << "Decoder::~Decoder()"; | 76 DVLOG(1) << "Decoder::~Decoder()"; |
72 | 77 |
73 // NB: ReleaseDecoderResources() is virtual | 78 // NB: ReleaseDecoderResources() is virtual |
74 ReleaseDecoderResources(); | 79 ReleaseDecoderResources(); |
75 } | 80 } |
76 | 81 |
77 const char* MediaCodecDecoder::class_name() const { | 82 const char* MediaCodecDecoder::class_name() const { |
78 return "Decoder"; | 83 return "Decoder"; |
79 } | 84 } |
80 | 85 |
81 void MediaCodecDecoder::ReleaseDecoderResources() { | 86 void MediaCodecDecoder::ReleaseDecoderResources() { |
82 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 87 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
83 | 88 |
84 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 89 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
85 | 90 |
86 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | 91 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). |
87 SetState(kInEmergencyStop); | 92 SetState(kInEmergencyStop); |
88 | 93 |
89 decoder_thread_.Stop(); // synchronous | 94 decoder_thread_.Stop(); // synchronous |
90 | 95 |
91 SetState(kStopped); | 96 SetState(kStopped); |
92 media_codec_bridge_.reset(); | 97 ReleaseMediaCodec(); |
98 | |
99 needs_preroll_ = true; | |
93 } | 100 } |
94 | 101 |
95 void MediaCodecDecoder::Flush() { | 102 void MediaCodecDecoder::Flush() { |
96 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 103 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
97 | 104 |
98 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 105 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
99 | 106 |
100 DCHECK_EQ(GetState(), kStopped); | 107 DCHECK_EQ(GetState(), kStopped); |
101 | 108 |
102 // Flush() is a part of the Seek request. Whenever we request a seek we need | 109 // Flush() is a part of the Seek request. Whenever we request a seek we need |
(...skipping 29 matching lines...) Expand all Loading... | |
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 139 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
133 | 140 |
134 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 141 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
135 | 142 |
136 media_codec_bridge_.reset(); | 143 media_codec_bridge_.reset(); |
137 } | 144 } |
138 | 145 |
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { | 146 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { |
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 147 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
141 | 148 |
149 // Whether decoder needs to be stopped. | |
142 base::AutoLock lock(state_lock_); | 150 base::AutoLock lock(state_lock_); |
143 return state_ == kPrefetching || state_ == kRunning; | 151 switch (state_) { |
152 case kPrefetching: | |
153 case kPrefetched: | |
154 case kPrerolling: | |
155 case kPrerolled: | |
156 case kRunning: | |
157 return true; | |
158 case kStopped: | |
159 case kStopping: | |
160 case kInEmergencyStop: | |
161 case kError: | |
162 return false; | |
163 } | |
164 NOTREACHED(); | |
165 return false; | |
166 } | |
167 | |
168 bool MediaCodecDecoder::IsPrerollDone() const { | |
169 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
170 | |
171 return !HasStream() || IsCompleted() || GetState() == kPrerolled; | |
144 } | 172 } |
145 | 173 |
146 bool MediaCodecDecoder::IsStopped() const { | 174 bool MediaCodecDecoder::IsStopped() const { |
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 175 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
148 | 176 |
149 return GetState() == kStopped; | 177 return GetState() == kStopped; |
150 } | 178 } |
151 | 179 |
152 bool MediaCodecDecoder::IsCompleted() const { | 180 bool MediaCodecDecoder::IsCompleted() const { |
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 181 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 | 213 |
186 if (GetState() == kError) { | 214 if (GetState() == kError) { |
187 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; | 215 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; |
188 return kConfigFailure; | 216 return kConfigFailure; |
189 } | 217 } |
190 | 218 |
191 if (needs_reconfigure_) { | 219 if (needs_reconfigure_) { |
192 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 220 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
193 << ": needs reconfigure, deleting MediaCodec"; | 221 << ": needs reconfigure, deleting MediaCodec"; |
194 needs_reconfigure_ = false; | 222 needs_reconfigure_ = false; |
195 media_codec_bridge_.reset(); | 223 ReleaseMediaCodec(); |
196 | |
197 // No need to release these buffers since the MediaCodec is deleted, just | |
198 // remove their indexes from |delayed_buffers_|. | |
199 | |
200 ClearDelayedBuffers(false); | |
201 } | 224 } |
202 | 225 |
203 MediaCodecDecoder::ConfigStatus result; | 226 MediaCodecDecoder::ConfigStatus result; |
204 if (media_codec_bridge_) { | 227 if (media_codec_bridge_) { |
205 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 228 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
206 << ": reconfiguration is not required, ignoring"; | 229 << ": reconfiguration is not required, ignoring"; |
207 result = kConfigOk; | 230 result = kConfigOk; |
208 } else { | 231 } else { |
209 result = ConfigureInternal(); | 232 result = ConfigureInternal(); |
210 | 233 |
211 #ifndef NDEBUG | 234 #ifndef NDEBUG |
212 // We check and reset |verify_next_frame_is_key_| on Decoder thread. | 235 // We check and reset |verify_next_frame_is_key_| on Decoder thread. |
213 // This DCHECK ensures we won't need to lock this variable. | 236 // This DCHECK ensures we won't need to lock this variable. |
214 DCHECK(!decoder_thread_.IsRunning()); | 237 DCHECK(!decoder_thread_.IsRunning()); |
215 | 238 |
216 // For video the first frame after reconfiguration must be key frame. | 239 // For video the first frame after reconfiguration must be key frame. |
217 if (result == kConfigOk) | 240 if (result == kConfigOk) |
218 verify_next_frame_is_key_ = true; | 241 verify_next_frame_is_key_ = true; |
219 #endif | 242 #endif |
220 } | 243 } |
221 | 244 |
222 return result; | 245 return result; |
223 } | 246 } |
224 | 247 |
225 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { | 248 void MediaCodecDecoder::SetNeedsPreroll(bool value) { |
249 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
250 | |
251 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ":" << value; | |
252 | |
253 needs_preroll_ = value; | |
254 } | |
255 | |
256 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) { | |
226 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 257 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
227 | 258 |
228 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 259 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
229 << " current_time:" << current_time; | 260 << " start_timestamp:" << start_timestamp; |
230 | 261 |
231 DecoderState state = GetState(); | 262 DecoderState state = GetState(); |
232 if (state == kRunning) { | 263 if (state == kPrerolling || state == kRunning) { |
233 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; | 264 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; |
234 return true; // already started | 265 return true; // already started |
235 } | 266 } |
236 | 267 |
237 if (state != kPrefetched) { | 268 if (state != kPrefetched) { |
238 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " | 269 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " |
239 << AsString(state) << ", ignoring"; | 270 << AsString(state) << ", ignoring"; |
240 return false; | 271 return false; |
241 } | 272 } |
242 | 273 |
243 if (!media_codec_bridge_) { | 274 if (!media_codec_bridge_) { |
244 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 275 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
245 << ": not configured, ignoring"; | 276 << ": not configured, ignoring"; |
246 return false; | 277 return false; |
247 } | 278 } |
248 | 279 |
249 DCHECK(!decoder_thread_.IsRunning()); | 280 DCHECK(!decoder_thread_.IsRunning()); |
250 | 281 |
251 // We only synchronize video stream. | 282 // We only synchronize video stream. |
252 // When audio is present, the |current_time| is audio time. | 283 if (needs_preroll_) { |
253 SynchronizePTSWithTime(current_time); | 284 DissociatePTSFromTime(); // associaton will happen after preroll is done. |
285 preroll_timestamp_ = start_timestamp; | |
286 } else { | |
287 AssociateCurrentTimeWithPTS(start_timestamp); | |
288 preroll_timestamp_ = base::TimeDelta(); | |
289 } | |
254 | 290 |
255 last_frame_posted_ = false; | 291 last_frame_posted_ = false; |
256 | 292 |
257 // Start the decoder thread | 293 // Start the decoder thread |
258 if (!decoder_thread_.Start()) { | 294 if (!decoder_thread_.Start()) { |
259 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 295 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
260 << ": cannot start decoder thread"; | 296 << ": cannot start decoder thread"; |
261 return false; | 297 return false; |
262 } | 298 } |
263 | 299 |
264 SetState(kRunning); | 300 SetState(needs_preroll_ ? kPrerolling : kRunning); |
301 needs_preroll_ = false; | |
265 | 302 |
266 decoder_thread_.task_runner()->PostTask( | 303 decoder_thread_.task_runner()->PostTask( |
267 FROM_HERE, | 304 FROM_HERE, |
268 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); | 305 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); |
269 | 306 |
270 return true; | 307 return true; |
271 } | 308 } |
272 | 309 |
310 void MediaCodecDecoder::ResumeAfterPreroll() { | |
311 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
312 | |
313 DVLOG(1) << class_name() << "::" << __FUNCTION__; | |
314 | |
315 DCHECK(GetState() == kPrerolled); | |
316 DCHECK(decoder_thread_.IsRunning()); | |
317 | |
318 SetState(kRunning); | |
319 | |
320 AssociateCurrentTimeWithPTS(preroll_timestamp_); | |
321 preroll_timestamp_ = base::TimeDelta(); | |
322 | |
323 decoder_thread_.task_runner()->PostTask( | |
324 FROM_HERE, | |
325 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); | |
326 } | |
327 | |
273 void MediaCodecDecoder::SyncStop() { | 328 void MediaCodecDecoder::SyncStop() { |
274 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 329 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
275 | 330 |
276 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 331 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
277 | 332 |
278 if (GetState() == kError) { | 333 if (GetState() == kError) { |
279 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 334 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
280 << ": wrong state kError, ignoring"; | 335 << ": wrong state kError, ignoring"; |
281 return; | 336 return; |
282 } | 337 } |
283 | 338 |
284 // After this method returns, decoder thread will not be running. | 339 // After this method returns, decoder thread will not be running. |
285 | 340 |
286 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). | 341 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). |
287 SetState(kInEmergencyStop); | 342 SetState(kInEmergencyStop); |
288 | 343 |
289 decoder_thread_.Stop(); // synchronous | 344 decoder_thread_.Stop(); // synchronous |
290 | 345 |
291 SetState(kStopped); | 346 SetState(kStopped); |
292 | 347 |
293 ClearDelayedBuffers(true); // release prior to clearing |delayed_buffers_|. | 348 ReleaseDelayedBuffers(); |
294 } | 349 } |
295 | 350 |
296 void MediaCodecDecoder::RequestToStop() { | 351 void MediaCodecDecoder::RequestToStop() { |
297 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 352 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
298 | 353 |
299 DVLOG(1) << class_name() << "::" << __FUNCTION__; | 354 DVLOG(1) << class_name() << "::" << __FUNCTION__; |
300 | 355 |
301 DecoderState state = GetState(); | 356 DecoderState state = GetState(); |
302 switch (state) { | 357 switch (state) { |
303 case kError: | 358 case kError: |
304 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 359 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
305 << ": wrong state kError, ignoring"; | 360 << ": wrong state kError, ignoring"; |
306 break; | 361 break; |
307 case kRunning: | 362 case kRunning: |
308 SetState(kStopping); | 363 SetState(kStopping); |
309 break; | 364 break; |
365 case kPrerolling: | |
366 case kPrerolled: | |
367 DCHECK(decoder_thread_.IsRunning()); | |
368 // Synchronous stop. | |
369 decoder_thread_.Stop(); | |
370 SetState(kStopped); | |
371 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | |
372 break; | |
310 case kStopping: | 373 case kStopping: |
311 break; // ignore | 374 break; // ignore |
312 case kStopped: | 375 case kStopped: |
313 case kPrefetching: | 376 case kPrefetching: |
314 case kPrefetched: | 377 case kPrefetched: |
315 // There is nothing to wait for, we can sent nofigication right away. | 378 // There is nothing to wait for, we can sent nofigication right away. |
316 DCHECK(!decoder_thread_.IsRunning()); | 379 DCHECK(!decoder_thread_.IsRunning()); |
317 SetState(kStopped); | 380 SetState(kStopped); |
318 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 381 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
319 break; | 382 break; |
(...skipping 10 matching lines...) Expand all Loading... | |
330 << " completed:" << completed; | 393 << " completed:" << completed; |
331 | 394 |
332 decoder_thread_.Stop(); // synchronous | 395 decoder_thread_.Stop(); // synchronous |
333 | 396 |
334 SetState(kStopped); | 397 SetState(kStopped); |
335 completed_ = completed; | 398 completed_ = completed; |
336 | 399 |
337 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); | 400 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); |
338 } | 401 } |
339 | 402 |
403 void MediaCodecDecoder::OnPrerollDone() { | |
404 DCHECK(media_task_runner_->BelongsToCurrentThread()); | |
405 | |
406 DVLOG(1) << class_name() << "::" << __FUNCTION__; | |
407 | |
408 if (GetState() == kPrerolling) { | |
409 SetState(kPrerolled); | |
410 media_task_runner_->PostTask(FROM_HERE, preroll_done_cb_); | |
411 } | |
412 } | |
413 | |
340 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { | 414 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { |
341 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 415 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
342 | 416 |
343 // If |data| contains an aborted data, the last AU will have kAborted status. | 417 // If |data| contains an aborted data, the last AU will have kAborted status. |
344 bool aborted_data = | 418 bool aborted_data = |
345 !data.access_units.empty() && | 419 !data.access_units.empty() && |
346 data.access_units.back().status == DemuxerStream::kAborted; | 420 data.access_units.back().status == DemuxerStream::kAborted; |
347 | 421 |
348 #ifndef NDEBUG | 422 #ifndef NDEBUG |
349 const char* explain_if_skipped = | 423 const char* explain_if_skipped = |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 request_data_cb_.Run(); | 505 request_data_cb_.Run(); |
432 } | 506 } |
433 | 507 |
434 void MediaCodecDecoder::ProcessNextFrame() { | 508 void MediaCodecDecoder::ProcessNextFrame() { |
435 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 509 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
436 | 510 |
437 DVLOG(2) << class_name() << "::" << __FUNCTION__; | 511 DVLOG(2) << class_name() << "::" << __FUNCTION__; |
438 | 512 |
439 DecoderState state = GetState(); | 513 DecoderState state = GetState(); |
440 | 514 |
441 if (state != kRunning && state != kStopping) { | 515 if (state != kPrerolling && state != kRunning && state != kStopping) { |
442 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; | 516 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; |
443 return; | 517 return; |
444 } | 518 } |
445 | 519 |
446 if (state == kStopping) { | 520 if (state == kStopping) { |
447 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { | 521 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { |
448 DVLOG(1) << class_name() << "::" << __FUNCTION__ | 522 DVLOG(1) << class_name() << "::" << __FUNCTION__ |
449 << ": kStopping, posting OnLastFrameRendered"; | 523 << ": kStopping, posting OnLastFrameRendered"; |
450 media_task_runner_->PostTask( | 524 media_task_runner_->PostTask( |
451 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, | 525 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, |
452 weak_factory_.GetWeakPtr(), false)); | 526 weak_factory_.GetWeakPtr(), false)); |
453 last_frame_posted_ = true; | 527 last_frame_posted_ = true; |
454 } | 528 } |
455 | 529 |
456 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. | 530 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. |
457 // We only need to let finish the delayed rendering tasks. | 531 // We only need to let finish the delayed rendering tasks. |
458 return; | 532 return; |
459 } | 533 } |
460 | 534 |
461 DCHECK(state == kRunning); | 535 DCHECK(state == kPrerolling || state == kRunning); |
462 | 536 |
463 if (!EnqueueInputBuffer()) | 537 if (!EnqueueInputBuffer()) |
464 return; | 538 return; |
465 | 539 |
466 if (!DepleteOutputBufferQueue()) | 540 if (!DepleteOutputBufferQueue()) |
467 return; | 541 return; |
468 | 542 |
469 // We need a small delay if we want to stop this thread by | 543 // We need a small delay if we want to stop this thread by |
470 // decoder_thread_.Stop() reliably. | 544 // decoder_thread_.Stop() reliably. |
471 // The decoder thread message loop processes all pending | 545 // The decoder thread message loop processes all pending |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 | 667 |
594 DVLOG(2) << class_name() << "::" << __FUNCTION__; | 668 DVLOG(2) << class_name() << "::" << __FUNCTION__; |
595 | 669 |
596 int buffer_index = 0; | 670 int buffer_index = 0; |
597 size_t offset = 0; | 671 size_t offset = 0; |
598 size_t size = 0; | 672 size_t size = 0; |
599 base::TimeDelta pts; | 673 base::TimeDelta pts; |
600 MediaCodecStatus status; | 674 MediaCodecStatus status; |
601 bool eos_encountered = false; | 675 bool eos_encountered = false; |
602 | 676 |
677 RenderMode render_mode; | |
678 | |
603 base::TimeDelta timeout = | 679 base::TimeDelta timeout = |
604 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); | 680 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); |
605 | 681 |
606 // Extract all output buffers that are available. | 682 // Extract all output buffers that are available. |
607 // Usually there will be only one, but sometimes it is preceeded by | 683 // Usually there will be only one, but sometimes it is preceeded by |
608 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. | 684 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. |
609 do { | 685 do { |
610 status = media_codec_bridge_->DequeueOutputBuffer( | 686 status = media_codec_bridge_->DequeueOutputBuffer( |
611 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, | 687 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, |
612 nullptr); | 688 nullptr); |
613 | 689 |
614 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls | 690 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls |
615 // to quickly break the loop after we got all currently available buffers. | 691 // to quickly break the loop after we got all currently available buffers. |
616 timeout = base::TimeDelta::FromMilliseconds(0); | 692 timeout = base::TimeDelta::FromMilliseconds(0); |
617 | 693 |
618 switch (status) { | 694 switch (status) { |
619 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 695 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
620 // Output buffers are replaced in MediaCodecBridge, nothing to do. | 696 // Output buffers are replaced in MediaCodecBridge, nothing to do. |
621 break; | 697 break; |
622 | 698 |
623 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 699 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ | 700 DVLOG(2) << class_name() << "::" << __FUNCTION__ |
625 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; | 701 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; |
626 OnOutputFormatChanged(); | 702 OnOutputFormatChanged(); |
627 break; | 703 break; |
628 | 704 |
629 case MEDIA_CODEC_OK: | 705 case MEDIA_CODEC_OK: |
630 // We got the decoded frame | 706 // We got the decoded frame. |
631 Render(buffer_index, size, true, pts, eos_encountered); | 707 |
708 if (pts < preroll_timestamp_) | |
709 render_mode = kRenderSkip; | |
710 else if (GetState() == kPrerolling) | |
711 render_mode = kRenderAfterPreroll; | |
712 else | |
713 render_mode = kRenderNow; | |
714 | |
715 Render(buffer_index, size, render_mode, pts, eos_encountered); | |
716 | |
717 if (render_mode == kRenderAfterPreroll) { | |
718 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts | |
719 << " preroll done, stopping frame processing"; | |
720 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_); | |
721 return false; | |
722 } | |
632 break; | 723 break; |
633 | 724 |
634 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 725 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
635 // Nothing to do. | 726 // Nothing to do. |
636 break; | 727 break; |
637 | 728 |
638 case MEDIA_CODEC_ERROR: | 729 case MEDIA_CODEC_ERROR: |
639 DVLOG(0) << class_name() << "::" << __FUNCTION__ | 730 DVLOG(0) << class_name() << "::" << __FUNCTION__ |
640 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; | 731 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; |
641 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); | 732 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 | 765 |
675 base::AutoLock lock(state_lock_); | 766 base::AutoLock lock(state_lock_); |
676 state_ = state; | 767 state_ = state; |
677 } | 768 } |
678 | 769 |
679 #undef RETURN_STRING | 770 #undef RETURN_STRING |
680 #define RETURN_STRING(x) \ | 771 #define RETURN_STRING(x) \ |
681 case x: \ | 772 case x: \ |
682 return #x; | 773 return #x; |
683 | 774 |
775 const char* MediaCodecDecoder::AsString(RenderMode render_mode) { | |
776 switch (render_mode) { | |
777 RETURN_STRING(kRenderSkip); | |
778 RETURN_STRING(kRenderAfterPreroll); | |
779 RETURN_STRING(kRenderNow); | |
780 } | |
781 return nullptr; // crash early | |
782 } | |
783 | |
684 const char* MediaCodecDecoder::AsString(DecoderState state) { | 784 const char* MediaCodecDecoder::AsString(DecoderState state) { |
685 switch (state) { | 785 switch (state) { |
686 RETURN_STRING(kStopped); | 786 RETURN_STRING(kStopped); |
687 RETURN_STRING(kPrefetching); | 787 RETURN_STRING(kPrefetching); |
688 RETURN_STRING(kPrefetched); | 788 RETURN_STRING(kPrefetched); |
789 RETURN_STRING(kPrerolling); | |
790 RETURN_STRING(kPrerolled); | |
689 RETURN_STRING(kRunning); | 791 RETURN_STRING(kRunning); |
690 RETURN_STRING(kStopping); | 792 RETURN_STRING(kStopping); |
691 RETURN_STRING(kInEmergencyStop); | 793 RETURN_STRING(kInEmergencyStop); |
692 RETURN_STRING(kError); | 794 RETURN_STRING(kError); |
693 default: | |
694 return "Unknown DecoderState"; | |
695 } | 795 } |
796 return nullptr; // crash early | |
696 } | 797 } |
697 | 798 |
698 #undef RETURN_STRING | 799 #undef RETURN_STRING |
699 | 800 |
700 } // namespace media | 801 } // namespace media |
OLD | NEW |