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

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: Avoid potential frame skipping after decoder drain with a new prerolling mode 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::SetPrerollTillNextFrame() {
170 DCHECK(media_task_runner_->BelongsToCurrentThread());
171 DVLOG(1) << class_name() << "::" << __FUNCTION__;
172
173 preroll_mode_ = kPrerollTillNextFrame;
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
liberato (no reviews please) 2015/08/27 20:42:26 i don't understand this part. in TillNextFrame, i
Tima Vaisburd 2015/08/27 22:04:18 I understood your words as "in the case TillNextFr
Tima Vaisburd 2015/08/27 22:13:11 Actually, now I'm not sure I got your point. In th
liberato (no reviews please) 2015/08/28 15:21:42 thanks for the explanation. the root cause of my
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_ = kPrerollTillNextFrame;
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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 and the queue info
584 625
585 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 626 // Retrieve access units from the |au_queue_| in a loop until we either get
627 // a non-config front unit or until the new config is incompatible and we need
628 // to drain decoder.
586 629
587 // Request the data from Demuxer 630 AccessUnitQueue::Info au_info;
liberato (no reviews please) 2015/08/28 15:21:42 this block can probably be split out into a separa
Tima Vaisburd 2015/08/28 21:26:23 Made a method AdvanceAccessUnitQueue(). After thi
588 if (au_info.length <= kPlaybackLowLimit && !au_info.has_eos) 631 do {
589 media_task_runner_->PostTask(FROM_HERE, request_data_cb_); 632 // |drain_decoder_| can be set here upon the first time we enter the loop if
633 // we could not dequeue the input buffer for it right away.
634 if (drain_decoder_)
635 break;
590 636
591 // Get the next frame from the queue 637 au_info = au_queue_.GetInfo();
592 638
593 if (!au_info.length) { 639 // Request the data from Demuxer
594 // Report starvation and return, Start() will be called again later. 640 if (au_info.data_length <= kPlaybackLowLimit && !au_info.has_eos)
595 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": starvation detected"; 641 media_task_runner_->PostTask(FROM_HERE, request_data_cb_);
596 media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
597 return true;
598 }
599 642
600 if (au_info.configs) { 643 // Get the next frame from the queue
601 DVLOG(1) << class_name() << "::" << __FUNCTION__ 644
602 << ": received new configs, not implemented"; 645 if (!au_info.length) {
603 // post an error for now? 646 // Report starvation and return, Start() will be called again later.
604 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 647 DVLOG(1) << class_name() << "::" << __FUNCTION__
605 return false; 648 << ": starvation detected";
606 } 649 media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
650 return true;
651 }
652
653 if (au_info.configs) {
654 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": received configs "
655 << (*au_info.configs);
656
657 // Compare the new and current configs.
658 if (IsCodecReconfigureNeeded(*au_info.configs)) {
659 DVLOG(1) << class_name() << "::" << __FUNCTION__
660 << ": reconfiguration required";
661 drain_decoder_ = true;
662 }
663
664 // Replace the current configs.
665 SetDemuxerConfigs(*au_info.configs);
666
667 // Remove the configs from the queue.
668 au_queue_.Advance();
669 }
670 } while (au_info.configs);
607 671
608 // We are ready to enqueue the front unit. 672 // We are ready to enqueue the front unit.
609 673
674 DCHECK(drain_decoder_ || au_info.front_unit);
675
610 #ifndef NDEBUG 676 #ifndef NDEBUG
611 if (verify_next_frame_is_key_) { 677 if (verify_next_frame_is_key_ && !drain_decoder_) {
612 verify_next_frame_is_key_ = false; 678 verify_next_frame_is_key_ = false;
613 VerifyUnitIsKeyFrame(au_info.front_unit); 679 VerifyUnitIsKeyFrame(au_info.front_unit);
614 } 680 }
615 #endif 681 #endif
616 682
617 // Dequeue input buffer 683 // Dequeue input buffer
618 684
619 base::TimeDelta timeout = 685 base::TimeDelta timeout =
620 base::TimeDelta::FromMilliseconds(kInputBufferTimeout); 686 base::TimeDelta::FromMilliseconds(kInputBufferTimeout);
621 int index = -1; 687 int index = -1;
(...skipping 17 matching lines...) Expand all
639 705
640 default: 706 default:
641 break; 707 break;
642 } 708 }
643 709
644 // We got the buffer 710 // We got the buffer
645 DCHECK_EQ(status, MEDIA_CODEC_OK); 711 DCHECK_EQ(status, MEDIA_CODEC_OK);
646 DCHECK_GE(index, 0); 712 DCHECK_GE(index, 0);
647 713
648 const AccessUnit* unit = au_info.front_unit; 714 const AccessUnit* unit = au_info.front_unit;
649 DCHECK(unit);
650 715
651 if (unit->is_end_of_stream) { 716 if (drain_decoder_ || unit->is_end_of_stream) {
652 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS"; 717 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
653 media_codec_bridge_->QueueEOS(index); 718 media_codec_bridge_->QueueEOS(index);
654 eos_enqueued_ = true; 719 eos_enqueued_ = true;
655 return true; 720 return true;
656 } 721 }
657 722
658 DVLOG(2) << class_name() << ":: QueueInputBuffer pts:" << unit->timestamp; 723 DCHECK(unit);
724
725 DVLOG(2) << class_name() << "::" << __FUNCTION__
726 << ": QueueInputBuffer pts:" << unit->timestamp;
659 727
660 status = media_codec_bridge_->QueueInputBuffer( 728 status = media_codec_bridge_->QueueInputBuffer(
661 index, &unit->data[0], unit->data.size(), unit->timestamp); 729 index, &unit->data[0], unit->data.size(), unit->timestamp);
662 730
663 if (status == MEDIA_CODEC_ERROR) { 731 if (status == MEDIA_CODEC_ERROR) {
664 DVLOG(0) << class_name() << "::" << __FUNCTION__ 732 DVLOG(0) << class_name() << "::" << __FUNCTION__
665 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed"; 733 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
666 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 734 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
667 return false; 735 return false;
668 } 736 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 if (pts < preroll_timestamp_) 787 if (pts < preroll_timestamp_)
720 render_mode = kRenderSkip; 788 render_mode = kRenderSkip;
721 else if (GetState() == kPrerolling) 789 else if (GetState() == kPrerolling)
722 render_mode = kRenderAfterPreroll; 790 render_mode = kRenderAfterPreroll;
723 else 791 else
724 render_mode = kRenderNow; 792 render_mode = kRenderNow;
725 793
726 Render(buffer_index, offset, size, render_mode, pts, eos_encountered); 794 Render(buffer_index, offset, size, render_mode, pts, eos_encountered);
727 795
728 if (render_mode == kRenderAfterPreroll) { 796 if (render_mode == kRenderAfterPreroll) {
729 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts:" << pts 797 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts " << pts
798 << " >= preroll timestamp " << preroll_timestamp_
730 << " preroll done, stopping frame processing"; 799 << " preroll done, stopping frame processing";
731 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_); 800 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
732 return false; 801 return false;
733 } 802 }
734 break; 803 break;
735 804
736 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 805 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
737 // Nothing to do. 806 // Nothing to do.
738 break; 807 break;
739 808
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 RETURN_STRING(kStopping); 872 RETURN_STRING(kStopping);
804 RETURN_STRING(kInEmergencyStop); 873 RETURN_STRING(kInEmergencyStop);
805 RETURN_STRING(kError); 874 RETURN_STRING(kError);
806 } 875 }
807 return nullptr; // crash early 876 return nullptr; // crash early
808 } 877 }
809 878
810 #undef RETURN_STRING 879 #undef RETURN_STRING
811 880
812 } // namespace media 881 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698