Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: media/base/android/media_codec_decoder.cc

Issue 1287423004: MediaCodecPlayer implementation (stage 5 - reconfiguration) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-cleanuptest
Patch Set: Made a helper method for advancing AU queue, report starvation if cannot advance whether we drain d… Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 17 matching lines...) Expand all
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 = 20;
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& decoder_drained_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),
45 drain_decoder_(false),
46 always_reconfigure_for_tests_(false),
44 external_request_data_cb_(external_request_data_cb), 47 external_request_data_cb_(external_request_data_cb),
45 starvation_cb_(starvation_cb), 48 starvation_cb_(starvation_cb),
49 decoder_drained_cb_(decoder_drained_cb),
46 stop_done_cb_(stop_done_cb), 50 stop_done_cb_(stop_done_cb),
47 error_cb_(error_cb), 51 error_cb_(error_cb),
48 state_(kStopped), 52 state_(kStopped),
49 needs_preroll_(true), 53 preroll_mode_(kPrerollTillPTS),
50 eos_enqueued_(false), 54 eos_enqueued_(false),
51 completed_(false), 55 completed_(false),
52 last_frame_posted_(false), 56 last_frame_posted_(false),
53 is_data_request_in_progress_(false), 57 is_data_request_in_progress_(false),
54 is_incoming_data_invalid_(false), 58 is_incoming_data_invalid_(false),
55 #ifndef NDEBUG 59 #ifndef NDEBUG
56 verify_next_frame_is_key_(false), 60 verify_next_frame_is_key_(false),
57 #endif 61 #endif
58 weak_factory_(this) { 62 weak_factory_(this) {
59 DCHECK(media_task_runner_->BelongsToCurrentThread()); 63 DCHECK(media_task_runner_->BelongsToCurrentThread());
(...skipping 21 matching lines...) Expand all
81 85
82 DCHECK_EQ(GetState(), kStopped); 86 DCHECK_EQ(GetState(), kStopped);
83 87
84 // Flush() is a part of the Seek request. Whenever we request a seek we need 88 // Flush() is a part of the Seek request. Whenever we request a seek we need
85 // to invalidate the current data request. 89 // to invalidate the current data request.
86 if (is_data_request_in_progress_) 90 if (is_data_request_in_progress_)
87 is_incoming_data_invalid_ = true; 91 is_incoming_data_invalid_ = true;
88 92
89 eos_enqueued_ = false; 93 eos_enqueued_ = false;
90 completed_ = false; 94 completed_ = false;
95 drain_decoder_ = false;
91 au_queue_.Flush(); 96 au_queue_.Flush();
92 97
93 #ifndef NDEBUG 98 #ifndef NDEBUG
94 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 99 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
95 // This DCHECK ensures we won't need to lock this variable. 100 // This DCHECK ensures we won't need to lock this variable.
96 DCHECK(!decoder_thread_.IsRunning()); 101 DCHECK(!decoder_thread_.IsRunning());
97 102
98 // For video the first frame after flush must be key frame. 103 // For video the first frame after flush must be key frame.
99 verify_next_frame_is_key_ = true; 104 verify_next_frame_is_key_ = true;
100 #endif 105 #endif
101 106
102 needs_preroll_ = true; 107 preroll_mode_ = kPrerollTillPTS;
103 108
104 if (media_codec_bridge_) { 109 if (media_codec_bridge_) {
105 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush() 110 // MediaCodecBridge::Reset() performs MediaCodecBridge.flush()
106 MediaCodecStatus flush_status = media_codec_bridge_->Reset(); 111 MediaCodecStatus flush_status = media_codec_bridge_->Reset();
107 if (flush_status != MEDIA_CODEC_OK) { 112 if (flush_status != MEDIA_CODEC_OK) {
108 DVLOG(0) << class_name() << "::" << __FUNCTION__ 113 DVLOG(0) << class_name() << "::" << __FUNCTION__
109 << "MediaCodecBridge::Reset() failed"; 114 << "MediaCodecBridge::Reset() failed";
110 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 115 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
111 } 116 }
112 } 117 }
113 } 118 }
114 119
115 void MediaCodecDecoder::ReleaseMediaCodec() { 120 void MediaCodecDecoder::ReleaseMediaCodec() {
116 DCHECK(media_task_runner_->BelongsToCurrentThread()); 121 DCHECK(media_task_runner_->BelongsToCurrentThread());
117 122
118 DVLOG(1) << class_name() << "::" << __FUNCTION__; 123 DVLOG(1) << class_name() << "::" << __FUNCTION__;
119 124
120 media_codec_bridge_.reset(); 125 media_codec_bridge_.reset();
121 needs_preroll_ = true; 126 preroll_mode_ = kPrerollTillPTS;
122 } 127 }
123 128
124 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { 129 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
125 DCHECK(media_task_runner_->BelongsToCurrentThread()); 130 DCHECK(media_task_runner_->BelongsToCurrentThread());
126 131
127 // Whether decoder needs to be stopped. 132 // Whether decoder needs to be stopped.
128 base::AutoLock lock(state_lock_); 133 base::AutoLock lock(state_lock_);
129 switch (state_) { 134 switch (state_) {
130 case kPrefetching: 135 case kPrefetching:
131 case kPrefetched: 136 case kPrefetched:
(...skipping 19 matching lines...) Expand all
151 156
152 bool MediaCodecDecoder::IsCompleted() const { 157 bool MediaCodecDecoder::IsCompleted() const {
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); 158 DCHECK(media_task_runner_->BelongsToCurrentThread());
154 159
155 return completed_; 160 return completed_;
156 } 161 }
157 162
158 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const { 163 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const {
159 DCHECK(media_task_runner_->BelongsToCurrentThread()); 164 DCHECK(media_task_runner_->BelongsToCurrentThread());
160 165
161 return HasStream() && needs_preroll_ && !completed_; 166 return HasStream() && preroll_mode_ != kNoPreroll && !completed_;
167 }
168
169 void MediaCodecDecoder::SetDecodingUntilOutputIsPresent() {
170 DCHECK(media_task_runner_->BelongsToCurrentThread());
171 DVLOG(1) << class_name() << "::" << __FUNCTION__;
172
173 preroll_mode_ = kPrerollTillOutputIsPresent;
162 } 174 }
163 175
164 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { 176 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() {
165 base::android::ScopedJavaLocalRef<jobject> media_crypto; 177 base::android::ScopedJavaLocalRef<jobject> media_crypto;
166 178
167 // TODO(timav): implement DRM. 179 // TODO(timav): implement DRM.
168 // drm_bridge_ is not implemented 180 // drm_bridge_ is not implemented
169 // if (drm_bridge_) 181 // if (drm_bridge_)
170 // media_crypto = drm_bridge_->GetMediaCrypto(); 182 // media_crypto = drm_bridge_->GetMediaCrypto();
171 return media_crypto; 183 return media_crypto;
(...skipping 22 matching lines...) Expand all
194 return kConfigFailure; 206 return kConfigFailure;
195 } 207 }
196 208
197 if (needs_reconfigure_) { 209 if (needs_reconfigure_) {
198 DVLOG(1) << class_name() << "::" << __FUNCTION__ 210 DVLOG(1) << class_name() << "::" << __FUNCTION__
199 << ": needs reconfigure, deleting MediaCodec"; 211 << ": needs reconfigure, deleting MediaCodec";
200 needs_reconfigure_ = false; 212 needs_reconfigure_ = false;
201 ReleaseMediaCodec(); 213 ReleaseMediaCodec();
202 } 214 }
203 215
204 MediaCodecDecoder::ConfigStatus result;
205 if (media_codec_bridge_) { 216 if (media_codec_bridge_) {
206 DVLOG(1) << class_name() << "::" << __FUNCTION__ 217 DVLOG(1) << class_name() << "::" << __FUNCTION__
207 << ": reconfiguration is not required, ignoring"; 218 << ": reconfiguration is not required, ignoring";
208 result = kConfigOk; 219 return kConfigOk;
209 } else { 220 }
210 result = ConfigureInternal(); 221
222 // Read all |kConfigChanged| units preceding the data one.
223 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
224 while (au_info.configs) {
225 SetDemuxerConfigs(*au_info.configs);
226 au_queue_.Advance();
227 au_info = au_queue_.GetInfo();
228 }
229
230 MediaCodecDecoder::ConfigStatus result = ConfigureInternal();
211 231
212 #ifndef NDEBUG 232 #ifndef NDEBUG
213 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 233 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
214 // This DCHECK ensures we won't need to lock this variable. 234 // This DCHECK ensures we won't need to lock this variable.
215 DCHECK(!decoder_thread_.IsRunning()); 235 DCHECK(!decoder_thread_.IsRunning());
216 236
217 // For video the first frame after reconfiguration must be key frame. 237 // For video the first frame after reconfiguration must be key frame.
218 if (result == kConfigOk) 238 if (result == kConfigOk)
219 verify_next_frame_is_key_ = true; 239 verify_next_frame_is_key_ = true;
220 #endif 240 #endif
221 }
222 241
223 return result; 242 return result;
224 } 243 }
225 244
226 bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp, 245 bool MediaCodecDecoder::Preroll(base::TimeDelta preroll_timestamp,
227 const base::Closure& preroll_done_cb) { 246 const base::Closure& preroll_done_cb) {
228 DCHECK(media_task_runner_->BelongsToCurrentThread()); 247 DCHECK(media_task_runner_->BelongsToCurrentThread());
229 248
230 DVLOG(1) << class_name() << "::" << __FUNCTION__ 249 DVLOG(1) << class_name() << "::" << __FUNCTION__
231 << " preroll_timestamp:" << preroll_timestamp; 250 << " preroll_timestamp:" << preroll_timestamp;
232 251
233 DecoderState state = GetState(); 252 DecoderState state = GetState();
234 if (state != kPrefetched) { 253 if (state != kPrefetched) {
235 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 254 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
236 << AsString(state) << ", ignoring"; 255 << AsString(state) << ", ignoring";
237 return false; 256 return false;
238 } 257 }
239 258
240 if (!media_codec_bridge_) { 259 if (!media_codec_bridge_) {
241 DVLOG(0) << class_name() << "::" << __FUNCTION__ 260 DVLOG(0) << class_name() << "::" << __FUNCTION__
242 << ": not configured, ignoring"; 261 << ": not configured, ignoring";
243 return false; 262 return false;
244 } 263 }
245 264
246 DCHECK(!decoder_thread_.IsRunning()); 265 DCHECK(!decoder_thread_.IsRunning());
247 DCHECK(needs_preroll_); 266 DCHECK(preroll_mode_ != kNoPreroll);
248 267
249 preroll_done_cb_ = preroll_done_cb; 268 preroll_done_cb_ = preroll_done_cb;
250 269
251 // We only synchronize video stream. 270 // We only synchronize video stream.
252 DissociatePTSFromTime(); // associaton will happen after preroll is done. 271 DissociatePTSFromTime(); // associaton will happen after preroll is done.
253 preroll_timestamp_ = preroll_timestamp; 272
273 preroll_timestamp_ = (preroll_mode_ == kPrerollTillPTS) ? preroll_timestamp
274 : base::TimeDelta();
254 275
255 last_frame_posted_ = false; 276 last_frame_posted_ = false;
256 277
257 // Start the decoder thread 278 // Start the decoder thread
258 if (!decoder_thread_.Start()) { 279 if (!decoder_thread_.Start()) {
259 DVLOG(0) << class_name() << "::" << __FUNCTION__ 280 DVLOG(0) << class_name() << "::" << __FUNCTION__
260 << ": cannot start decoder thread"; 281 << ": cannot start decoder thread";
261 return false; 282 return false;
262 } 283 }
263 284
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 // Synchronous stop. 370 // Synchronous stop.
350 decoder_thread_.Stop(); 371 decoder_thread_.Stop();
351 SetState(kStopped); 372 SetState(kStopped);
352 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 373 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
353 break; 374 break;
354 case kStopping: 375 case kStopping:
355 break; // ignore 376 break; // ignore
356 case kStopped: 377 case kStopped:
357 case kPrefetching: 378 case kPrefetching:
358 case kPrefetched: 379 case kPrefetched:
359 // There is nothing to wait for, we can sent nofigication right away. 380 // There is nothing to wait for, we can sent notification right away.
360 DCHECK(!decoder_thread_.IsRunning()); 381 DCHECK(!decoder_thread_.IsRunning());
361 SetState(kStopped); 382 SetState(kStopped);
362 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 383 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
363 break; 384 break;
364 default: 385 default:
365 NOTREACHED(); 386 NOTREACHED();
366 break; 387 break;
367 } 388 }
368 } 389 }
369 390
370 void MediaCodecDecoder::OnLastFrameRendered(bool completed) { 391 void MediaCodecDecoder::OnLastFrameRendered(bool eos_encountered) {
371 DCHECK(media_task_runner_->BelongsToCurrentThread()); 392 DCHECK(media_task_runner_->BelongsToCurrentThread());
372 393
373 DVLOG(0) << class_name() << "::" << __FUNCTION__ 394 DVLOG(1) << class_name() << "::" << __FUNCTION__
374 << " completed:" << completed; 395 << " eos_encountered:" << eos_encountered;
375 396
376 decoder_thread_.Stop(); // synchronous 397 decoder_thread_.Stop(); // synchronous
377 398
378 SetState(kStopped); 399 SetState(kStopped);
379 completed_ = completed; 400 completed_ = (eos_encountered && !drain_decoder_);
380 401
381 if (completed_ && !preroll_done_cb_.is_null()) 402 if (completed_ && !preroll_done_cb_.is_null()) {
382 media_task_runner_->PostTask(FROM_HERE, 403 media_task_runner_->PostTask(FROM_HERE,
383 base::ResetAndReturn(&preroll_done_cb_)); 404 base::ResetAndReturn(&preroll_done_cb_));
405 }
406
407 if (eos_encountered && drain_decoder_) {
408 ReleaseMediaCodec();
409 drain_decoder_ = false;
410 eos_enqueued_ = false;
411 preroll_mode_ = kPrerollTillOutputIsPresent;
412 media_task_runner_->PostTask(FROM_HERE, decoder_drained_cb_);
413 }
384 414
385 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 415 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
386 } 416 }
387 417
388 void MediaCodecDecoder::OnPrerollDone() { 418 void MediaCodecDecoder::OnPrerollDone() {
389 DCHECK(media_task_runner_->BelongsToCurrentThread()); 419 DCHECK(media_task_runner_->BelongsToCurrentThread());
390 420
391 DVLOG(1) << class_name() << "::" << __FUNCTION__; 421 DVLOG(1) << class_name() << "::" << __FUNCTION__;
392 422
393 needs_preroll_ = false; 423 preroll_mode_ = kNoPreroll;
394 424
395 // The state might be kStopping. 425 // The state might be kStopping.
396 if (GetState() == kPrerolling) { 426 if (GetState() == kPrerolling) {
397 SetState(kPrerolled); 427 SetState(kPrerolled);
398 media_task_runner_->PostTask(FROM_HERE, 428 media_task_runner_->PostTask(FROM_HERE,
399 base::ResetAndReturn(&preroll_done_cb_)); 429 base::ResetAndReturn(&preroll_done_cb_));
400 } 430 }
401 } 431 }
402 432
403 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 433 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
(...skipping 26 matching lines...) Expand all
430 // data after kAborted and before the OnDemuxerSeekDone. 460 // data after kAborted and before the OnDemuxerSeekDone.
431 if (GetState() == kPrefetching && !aborted_data) 461 if (GetState() == kPrefetching && !aborted_data)
432 PrefetchNextChunk(); 462 PrefetchNextChunk();
433 } 463 }
434 464
435 bool MediaCodecDecoder::IsPrerollingForTests() const { 465 bool MediaCodecDecoder::IsPrerollingForTests() const {
436 // UI task runner. 466 // UI task runner.
437 return GetState() == kPrerolling; 467 return GetState() == kPrerolling;
438 } 468 }
439 469
470 void MediaCodecDecoder::SetAlwaysReconfigureForTests() {
471 // UI task runner.
472 always_reconfigure_for_tests_ = true;
473 }
474
475 void MediaCodecDecoder::SetCodecCreatedCallbackForTests(base::Closure cb) {
476 // UI task runner.
477 codec_created_for_tests_cb_ = cb;
478 }
479
440 int MediaCodecDecoder::NumDelayedRenderTasks() const { 480 int MediaCodecDecoder::NumDelayedRenderTasks() const {
441 return 0; 481 return 0;
442 } 482 }
443 483
444 void MediaCodecDecoder::DoEmergencyStop() { 484 void MediaCodecDecoder::DoEmergencyStop() {
445 DCHECK(media_task_runner_->BelongsToCurrentThread()); 485 DCHECK(media_task_runner_->BelongsToCurrentThread());
446 DVLOG(1) << class_name() << "::" << __FUNCTION__; 486 DVLOG(1) << class_name() << "::" << __FUNCTION__;
447 487
448 // After this method returns, decoder thread will not be running. 488 // After this method returns, decoder thread will not be running.
449 489
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 } 534 }
495 } 535 }
496 536
497 void MediaCodecDecoder::PrefetchNextChunk() { 537 void MediaCodecDecoder::PrefetchNextChunk() {
498 DCHECK(media_task_runner_->BelongsToCurrentThread()); 538 DCHECK(media_task_runner_->BelongsToCurrentThread());
499 539
500 DVLOG(1) << class_name() << "::" << __FUNCTION__; 540 DVLOG(1) << class_name() << "::" << __FUNCTION__;
501 541
502 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 542 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
503 543
504 if (eos_enqueued_ || au_info.length >= kPrefetchLimit || au_info.has_eos) { 544 if (eos_enqueued_ || au_info.data_length >= kPrefetchLimit ||
545 au_info.has_eos) {
505 // We are done prefetching 546 // We are done prefetching
506 SetState(kPrefetched); 547 SetState(kPrefetched);
507 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " posting PrefetchDone"; 548 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " posting PrefetchDone";
508 media_task_runner_->PostTask(FROM_HERE, 549 media_task_runner_->PostTask(FROM_HERE,
509 base::ResetAndReturn(&prefetch_done_cb_)); 550 base::ResetAndReturn(&prefetch_done_cb_));
510 return; 551 return;
511 } 552 }
512 553
513 request_data_cb_.Run(); 554 request_data_cb_.Run();
514 } 555 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 614 }
574 615
575 // Keep the number pending video frames low, ideally maintaining 616 // Keep the number pending video frames low, ideally maintaining
576 // the same audio and video duration after stop request 617 // the same audio and video duration after stop request
577 if (NumDelayedRenderTasks() > 1) { 618 if (NumDelayedRenderTasks() > 1) {
578 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers (" 619 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
579 << NumDelayedRenderTasks() << ") exceeds 1, returning"; 620 << NumDelayedRenderTasks() << ") exceeds 1, returning";
580 return true; // Nothing to do 621 return true; // Nothing to do
581 } 622 }
582 623
583 // Get the next frame from the queue and the queue info 624 // Get the next frame from the queue. As we go, request more data and
625 // consume |kConfigChanged| units.
584 626
585 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 627 // |drain_decoder_| can be already set here if we could not dequeue the input
628 // buffer for it right away.
586 629
587 // Request the data from Demuxer 630 AccessUnitQueue::Info au_info;
588 if (au_info.length <= kPlaybackLowLimit && !au_info.has_eos) 631 if (!drain_decoder_) {
589 media_task_runner_->PostTask(FROM_HERE, request_data_cb_); 632 au_info = AdvanceAccessUnitQueue(&drain_decoder_);
633 if (!au_info.length) {
634 // Report starvation and return, Start() will be called again later.
635 DVLOG(1) << class_name() << "::" << __FUNCTION__
636 << ": starvation detected";
liberato (no reviews please) 2015/08/28 21:42:47 might want to mention |drain_decoder_| in the log.
Tima Vaisburd 2015/08/28 22:28:55 Added the words about the drain inside AdvanceAcce
637 media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
638 return true;
639 }
590 640
591 // Get the next frame from the queue 641 DCHECK(au_info.front_unit);
592
593 if (!au_info.length) {
594 // Report starvation and return, Start() will be called again later.
595 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": starvation detected";
596 media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
597 return true;
598 }
599
600 if (au_info.configs) {
601 DVLOG(1) << class_name() << "::" << __FUNCTION__
602 << ": received new configs, not implemented";
603 // post an error for now?
604 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
605 return false;
606 }
607
608 // We are ready to enqueue the front unit.
609 642
610 #ifndef NDEBUG 643 #ifndef NDEBUG
611 if (verify_next_frame_is_key_) { 644 if (verify_next_frame_is_key_) {
612 verify_next_frame_is_key_ = false; 645 verify_next_frame_is_key_ = false;
613 VerifyUnitIsKeyFrame(au_info.front_unit); 646 VerifyUnitIsKeyFrame(au_info.front_unit);
647 }
648 #endif
614 } 649 }
615 #endif
616 650
617 // Dequeue input buffer 651 // Dequeue input buffer
618 652
619 base::TimeDelta timeout = 653 base::TimeDelta timeout =
620 base::TimeDelta::FromMilliseconds(kInputBufferTimeout); 654 base::TimeDelta::FromMilliseconds(kInputBufferTimeout);
621 int index = -1; 655 int index = -1;
622 MediaCodecStatus status = 656 MediaCodecStatus status =
623 media_codec_bridge_->DequeueInputBuffer(timeout, &index); 657 media_codec_bridge_->DequeueInputBuffer(timeout, &index);
624 658
625 DVLOG(2) << class_name() << ":: DequeueInputBuffer index:" << index; 659 DVLOG(2) << class_name() << ":: DequeueInputBuffer index:" << index;
(...skipping 13 matching lines...) Expand all
639 673
640 default: 674 default:
641 break; 675 break;
642 } 676 }
643 677
644 // We got the buffer 678 // We got the buffer
645 DCHECK_EQ(status, MEDIA_CODEC_OK); 679 DCHECK_EQ(status, MEDIA_CODEC_OK);
646 DCHECK_GE(index, 0); 680 DCHECK_GE(index, 0);
647 681
648 const AccessUnit* unit = au_info.front_unit; 682 const AccessUnit* unit = au_info.front_unit;
649 DCHECK(unit);
650 683
651 if (unit->is_end_of_stream) { 684 if (drain_decoder_ || unit->is_end_of_stream) {
652 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS"; 685 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
653 media_codec_bridge_->QueueEOS(index); 686 media_codec_bridge_->QueueEOS(index);
654 eos_enqueued_ = true; 687 eos_enqueued_ = true;
655 return true; 688 return true;
656 } 689 }
657 690
658 DVLOG(2) << class_name() << ":: QueueInputBuffer pts:" << unit->timestamp; 691 DCHECK(unit);
692
693 DVLOG(2) << class_name() << "::" << __FUNCTION__
694 << ": QueueInputBuffer pts:" << unit->timestamp;
659 695
660 status = media_codec_bridge_->QueueInputBuffer( 696 status = media_codec_bridge_->QueueInputBuffer(
661 index, &unit->data[0], unit->data.size(), unit->timestamp); 697 index, &unit->data[0], unit->data.size(), unit->timestamp);
662 698
663 if (status == MEDIA_CODEC_ERROR) { 699 if (status == MEDIA_CODEC_ERROR) {
664 DVLOG(0) << class_name() << "::" << __FUNCTION__ 700 DVLOG(0) << class_name() << "::" << __FUNCTION__
665 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed"; 701 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
666 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 702 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
667 return false; 703 return false;
668 } 704 }
669 705
670 // Have successfully queued input buffer, go to next access unit. 706 // Have successfully queued input buffer, go to next access unit.
671 au_queue_.Advance(); 707 au_queue_.Advance();
672 return true; 708 return true;
673 } 709 }
674 710
711 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue(
712 bool* drain_decoder) {
713 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
714 DVLOG(2) << class_name() << "::" << __FUNCTION__;
715
716 // Retrieve access units from the |au_queue_| in a loop until we either get
717 // a non-config front unit or until the queue is empty.
718
719 DCHECK(drain_decoder != nullptr);
720
721 AccessUnitQueue::Info au_info;
722
723 do {
724 // Get current frame
liberato (no reviews please) 2015/08/28 21:42:47 without the drain_decoder check here, the behavior
Tima Vaisburd 2015/08/28 22:28:55 Yes, before we would break on first, and consume t
725 au_info = au_queue_.GetInfo();
726
727 // Request the data from Demuxer
728 if (au_info.data_length <= kPlaybackLowLimit && !au_info.has_eos)
729 media_task_runner_->PostTask(FROM_HERE, request_data_cb_);
730
731 if (!au_info.length)
732 break; // Starvation
733
734 if (au_info.configs) {
735 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": received configs "
736 << (*au_info.configs);
737
738 // Compare the new and current configs.
739 if (IsCodecReconfigureNeeded(*au_info.configs)) {
740 DVLOG(1) << class_name() << "::" << __FUNCTION__
741 << ": reconfiguration required";
742 drain_decoder_ = true;
liberato (no reviews please) 2015/08/28 21:42:47 (*drain_decoder)?
Tima Vaisburd 2015/08/28 22:28:55 Yes, indeed. Thank you.
743 }
744
745 // Replace the current configs.
746 SetDemuxerConfigs(*au_info.configs);
747
748 // Move to the next frame
749 au_queue_.Advance();
750 }
751 } while (au_info.configs);
752
753 return au_info;
754 }
755
675 // Returns false if there was MediaCodec error. 756 // Returns false if there was MediaCodec error.
676 bool MediaCodecDecoder::DepleteOutputBufferQueue() { 757 bool MediaCodecDecoder::DepleteOutputBufferQueue() {
677 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 758 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
678 759
679 DVLOG(2) << class_name() << "::" << __FUNCTION__; 760 DVLOG(2) << class_name() << "::" << __FUNCTION__;
680 761
681 int buffer_index = 0; 762 int buffer_index = 0;
682 size_t offset = 0; 763 size_t offset = 0;
683 size_t size = 0; 764 size_t size = 0;
684 base::TimeDelta pts; 765 base::TimeDelta pts;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 if (pts < preroll_timestamp_) 800 if (pts < preroll_timestamp_)
720 render_mode = kRenderSkip; 801 render_mode = kRenderSkip;
721 else if (GetState() == kPrerolling) 802 else if (GetState() == kPrerolling)
722 render_mode = kRenderAfterPreroll; 803 render_mode = kRenderAfterPreroll;
723 else 804 else
724 render_mode = kRenderNow; 805 render_mode = kRenderNow;
725 806
726 Render(buffer_index, offset, size, render_mode, pts, eos_encountered); 807 Render(buffer_index, offset, size, render_mode, pts, eos_encountered);
727 808
728 if (render_mode == kRenderAfterPreroll) { 809 if (render_mode == kRenderAfterPreroll) {
729 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts 810 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts " << pts
811 << " >= preroll timestamp " << preroll_timestamp_
730 << " preroll done, stopping frame processing"; 812 << " preroll done, stopping frame processing";
731 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_); 813 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
732 return false; 814 return false;
733 } 815 }
734 break; 816 break;
735 817
736 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 818 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
737 // Nothing to do. 819 // Nothing to do.
738 break; 820 break;
739 821
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 RETURN_STRING(kStopping); 885 RETURN_STRING(kStopping);
804 RETURN_STRING(kInEmergencyStop); 886 RETURN_STRING(kInEmergencyStop);
805 RETURN_STRING(kError); 887 RETURN_STRING(kError);
806 } 888 }
807 return nullptr; // crash early 889 return nullptr; // crash early
808 } 890 }
809 891
810 #undef RETURN_STRING 892 #undef RETURN_STRING
811 893
812 } // namespace media 894 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698