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

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

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Removed unused var, fixed unit test compilation Created 5 years, 4 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 11 matching lines...) Expand all
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 = 20;
32
33 // Estimated frame period in milliseconds
34 const int kEstimatedFramePeriod = 20;
qinmin 2015/07/28 18:09:46 why we need this variable? If we allow preroll for
32 } 35 }
33 36
34 MediaCodecDecoder::MediaCodecDecoder( 37 MediaCodecDecoder::MediaCodecDecoder(
35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 38 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
36 const base::Closure& external_request_data_cb, 39 const base::Closure& external_request_data_cb,
37 const base::Closure& starvation_cb, 40 const base::Closure& starvation_cb,
41 const base::Closure& preroll_done_cb,
38 const base::Closure& stop_done_cb, 42 const base::Closure& stop_done_cb,
39 const base::Closure& error_cb, 43 const base::Closure& error_cb,
40 const char* decoder_thread_name) 44 const char* decoder_thread_name)
41 : media_task_runner_(media_task_runner), 45 : media_task_runner_(media_task_runner),
42 decoder_thread_(decoder_thread_name), 46 decoder_thread_(decoder_thread_name),
43 needs_reconfigure_(false), 47 needs_reconfigure_(false),
44 external_request_data_cb_(external_request_data_cb), 48 external_request_data_cb_(external_request_data_cb),
45 starvation_cb_(starvation_cb), 49 starvation_cb_(starvation_cb),
50 preroll_done_cb_(preroll_done_cb),
46 stop_done_cb_(stop_done_cb), 51 stop_done_cb_(stop_done_cb),
47 error_cb_(error_cb), 52 error_cb_(error_cb),
48 state_(kStopped), 53 state_(kStopped),
49 eos_enqueued_(false), 54 eos_enqueued_(false),
50 completed_(false), 55 completed_(false),
51 last_frame_posted_(false), 56 last_frame_posted_(false),
52 is_data_request_in_progress_(false), 57 is_data_request_in_progress_(false),
53 is_incoming_data_invalid_(false), 58 is_incoming_data_invalid_(false),
54 #ifndef NDEBUG 59 #ifndef NDEBUG
55 verify_next_frame_is_key_(false), 60 verify_next_frame_is_key_(false),
56 #endif 61 #endif
57 weak_factory_(this) { 62 weak_factory_(this) {
58 DCHECK(media_task_runner_->BelongsToCurrentThread()); 63 DCHECK(media_task_runner_->BelongsToCurrentThread());
59 64
60 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name; 65 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
61 66
67 // For simplicity we use constant value instead of truly measuring the frame
68 // period. As long as it is used for determination of the
69 // kPrerolling -> kPrerolled switch only this simplification seems ok.
70 estimated_frame_period_ =
71 base::TimeDelta::FromMilliseconds(kEstimatedFramePeriod);
72
62 internal_error_cb_ = 73 internal_error_cb_ =
63 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr()); 74 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
75 internal_preroll_done_cb_ =
76 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr());
64 request_data_cb_ = 77 request_data_cb_ =
65 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr()); 78 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr());
66 } 79 }
67 80
68 MediaCodecDecoder::~MediaCodecDecoder() { 81 MediaCodecDecoder::~MediaCodecDecoder() {
69 DCHECK(media_task_runner_->BelongsToCurrentThread()); 82 DCHECK(media_task_runner_->BelongsToCurrentThread());
70 83
71 DVLOG(1) << "Decoder::~Decoder()"; 84 DVLOG(1) << "Decoder::~Decoder()";
72 85
73 // NB: ReleaseDecoderResources() is virtual 86 // NB: ReleaseDecoderResources() is virtual
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 DCHECK(media_task_runner_->BelongsToCurrentThread()); 145 DCHECK(media_task_runner_->BelongsToCurrentThread());
133 146
134 DVLOG(1) << class_name() << "::" << __FUNCTION__; 147 DVLOG(1) << class_name() << "::" << __FUNCTION__;
135 148
136 media_codec_bridge_.reset(); 149 media_codec_bridge_.reset();
137 } 150 }
138 151
139 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const { 152 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
140 DCHECK(media_task_runner_->BelongsToCurrentThread()); 153 DCHECK(media_task_runner_->BelongsToCurrentThread());
141 154
155 // Whether decoder needs to be stopped.
142 base::AutoLock lock(state_lock_); 156 base::AutoLock lock(state_lock_);
143 return state_ == kPrefetching || state_ == kRunning; 157 switch (state_) {
158 case kPrefetching:
159 case kPrefetched:
160 case kPrerolling:
161 case kPrerolled:
162 case kRunning:
163 return true;
164 case kStopped:
165 case kStopping:
166 case kInEmergencyStop:
167 case kError:
168 return false;
169 }
170 NOTREACHED();
171 return false;
172 }
173
174 bool MediaCodecDecoder::IsPrerollDone() const {
175 DCHECK(media_task_runner_->BelongsToCurrentThread());
176
177 return !HasStream() || IsCompleted() || GetState() == kPrerolled;
144 } 178 }
145 179
146 bool MediaCodecDecoder::IsStopped() const { 180 bool MediaCodecDecoder::IsStopped() const {
147 DCHECK(media_task_runner_->BelongsToCurrentThread()); 181 DCHECK(media_task_runner_->BelongsToCurrentThread());
148 182
149 return GetState() == kStopped; 183 return GetState() == kStopped;
150 } 184 }
151 185
152 bool MediaCodecDecoder::IsCompleted() const { 186 bool MediaCodecDecoder::IsCompleted() const {
153 DCHECK(media_task_runner_->BelongsToCurrentThread()); 187 DCHECK(media_task_runner_->BelongsToCurrentThread());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 250
217 // For video the first frame after reconfiguration must be key frame. 251 // For video the first frame after reconfiguration must be key frame.
218 if (result == CONFIG_OK) 252 if (result == CONFIG_OK)
219 verify_next_frame_is_key_ = true; 253 verify_next_frame_is_key_ = true;
220 #endif 254 #endif
221 } 255 }
222 256
223 return result; 257 return result;
224 } 258 }
225 259
226 bool MediaCodecDecoder::Start(base::TimeDelta current_time) { 260 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) {
261 DCHECK(media_task_runner_->BelongsToCurrentThread());
262 DCHECK(!decoder_thread_.IsRunning());
263
264 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp;
265
266 // Do not set preroll timestamp if it's too close to zero.
267 preroll_timestamp_ = (preroll_timestamp < estimated_frame_period_)
268 ? base::TimeDelta()
269 : preroll_timestamp;
270 }
271
272 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) {
227 DCHECK(media_task_runner_->BelongsToCurrentThread()); 273 DCHECK(media_task_runner_->BelongsToCurrentThread());
228 274
229 DVLOG(1) << class_name() << "::" << __FUNCTION__ 275 DVLOG(1) << class_name() << "::" << __FUNCTION__
230 << " current_time:" << current_time; 276 << " start_timestamp:" << start_timestamp;
231 277
232 DecoderState state = GetState(); 278 DecoderState state = GetState();
233 if (state == kRunning) { 279 if (state == kPrerolling || state == kRunning) {
234 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started"; 280 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
235 return true; // already started 281 return true; // already started
236 } 282 }
237 283
238 if (state != kPrefetched) { 284 if (state != kPrefetched) {
239 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state " 285 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
240 << AsString(state) << " ignoring"; 286 << AsString(state) << " ignoring";
241 return false; 287 return false;
242 } 288 }
243 289
244 if (!media_codec_bridge_) { 290 if (!media_codec_bridge_) {
245 DVLOG(0) << class_name() << "::" << __FUNCTION__ 291 DVLOG(0) << class_name() << "::" << __FUNCTION__
246 << ": not configured, ignoring"; 292 << ": not configured, ignoring";
247 return false; 293 return false;
248 } 294 }
249 295
250 DCHECK(!decoder_thread_.IsRunning()); 296 DCHECK(!decoder_thread_.IsRunning());
251 297
298 const bool needs_preroll = (preroll_timestamp_ != base::TimeDelta());
299
252 // We only synchronize video stream. 300 // We only synchronize video stream.
253 // When audio is present, the |current_time| is audio time. 301 if (needs_preroll)
254 SynchronizePTSWithTime(current_time); 302 DissociatePTSFromTime(); // associaton will happen after preroll is done.
303 else
304 AssociateCurrentTimeWithPTS(start_timestamp);
255 305
256 last_frame_posted_ = false; 306 last_frame_posted_ = false;
257 307
258 // Start the decoder thread 308 // Start the decoder thread
259 if (!decoder_thread_.Start()) { 309 if (!decoder_thread_.Start()) {
260 DVLOG(1) << class_name() << "::" << __FUNCTION__ 310 DVLOG(1) << class_name() << "::" << __FUNCTION__
261 << ": cannot start decoder thread"; 311 << ": cannot start decoder thread";
262 return false; 312 return false;
263 } 313 }
264 314
265 SetState(kRunning); 315 SetState(needs_preroll ? kPrerolling : kRunning);
266 316
267 decoder_thread_.task_runner()->PostTask( 317 decoder_thread_.task_runner()->PostTask(
268 FROM_HERE, 318 FROM_HERE,
269 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this))); 319 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
270 320
271 return true; 321 return true;
272 } 322 }
273 323
324 void MediaCodecDecoder::ResumeAfterPreroll() {
325 DCHECK(media_task_runner_->BelongsToCurrentThread());
326
327 DVLOG(1) << class_name() << "::" << __FUNCTION__;
328
329 DCHECK(GetState() == kPrerolled);
330 DCHECK(decoder_thread_.IsRunning());
331
332 SetState(kRunning);
333
334 AssociateCurrentTimeWithPTS(preroll_timestamp_);
335 preroll_timestamp_ = base::TimeDelta();
336
337 decoder_thread_.task_runner()->PostTask(
338 FROM_HERE,
339 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
340 }
341
274 void MediaCodecDecoder::SyncStop() { 342 void MediaCodecDecoder::SyncStop() {
275 DCHECK(media_task_runner_->BelongsToCurrentThread()); 343 DCHECK(media_task_runner_->BelongsToCurrentThread());
276 344
277 DVLOG(1) << class_name() << "::" << __FUNCTION__; 345 DVLOG(1) << class_name() << "::" << __FUNCTION__;
278 346
279 if (GetState() == kError) { 347 if (GetState() == kError) {
280 DVLOG(0) << class_name() << "::" << __FUNCTION__ 348 DVLOG(0) << class_name() << "::" << __FUNCTION__
281 << ": wrong state kError, ignoring"; 349 << ": wrong state kError, ignoring";
282 return; 350 return;
283 } 351 }
(...skipping 18 matching lines...) Expand all
302 370
303 DecoderState state = GetState(); 371 DecoderState state = GetState();
304 switch (state) { 372 switch (state) {
305 case kError: 373 case kError:
306 DVLOG(0) << class_name() << "::" << __FUNCTION__ 374 DVLOG(0) << class_name() << "::" << __FUNCTION__
307 << ": wrong state kError, ignoring"; 375 << ": wrong state kError, ignoring";
308 break; 376 break;
309 case kRunning: 377 case kRunning:
310 SetState(kStopping); 378 SetState(kStopping);
311 break; 379 break;
380 case kPrerolling:
381 case kPrerolled:
382 DCHECK(decoder_thread_.IsRunning());
383 // Synchronous stop.
384 decoder_thread_.Stop();
385 SetState(kStopped);
386 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
387 break;
312 case kStopping: 388 case kStopping:
313 break; // ignore 389 break; // ignore
314 case kStopped: 390 case kStopped:
315 case kPrefetching: 391 case kPrefetching:
316 case kPrefetched: 392 case kPrefetched:
317 // There is nothing to wait for, we can sent nofigication right away. 393 // There is nothing to wait for, we can sent nofigication right away.
318 DCHECK(!decoder_thread_.IsRunning()); 394 DCHECK(!decoder_thread_.IsRunning());
319 SetState(kStopped); 395 SetState(kStopped);
320 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 396 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
321 break; 397 break;
(...skipping 10 matching lines...) Expand all
332 << " completed:" << completed; 408 << " completed:" << completed;
333 409
334 decoder_thread_.Stop(); // synchronous 410 decoder_thread_.Stop(); // synchronous
335 411
336 SetState(kStopped); 412 SetState(kStopped);
337 completed_ = completed; 413 completed_ = completed;
338 414
339 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_); 415 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
340 } 416 }
341 417
418 void MediaCodecDecoder::OnPrerollDone() {
419 DCHECK(media_task_runner_->BelongsToCurrentThread());
420
421 DVLOG(1) << class_name() << "::" << __FUNCTION__;
422
423 if (GetState() == kPrerolling) {
424 SetState(kPrerolled);
425 media_task_runner_->PostTask(FROM_HERE, preroll_done_cb_);
426 }
427 }
428
342 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) { 429 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
343 DCHECK(media_task_runner_->BelongsToCurrentThread()); 430 DCHECK(media_task_runner_->BelongsToCurrentThread());
344 431
345 // If |data| contains an aborted data, the last AU will have kAborted status. 432 // If |data| contains an aborted data, the last AU will have kAborted status.
346 bool aborted_data = 433 bool aborted_data =
347 !data.access_units.empty() && 434 !data.access_units.empty() &&
348 data.access_units.back().status == DemuxerStream::kAborted; 435 data.access_units.back().status == DemuxerStream::kAborted;
349 436
350 #ifndef NDEBUG 437 #ifndef NDEBUG
351 const char* explain_if_skipped = 438 const char* explain_if_skipped =
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 request_data_cb_.Run(); 520 request_data_cb_.Run();
434 } 521 }
435 522
436 void MediaCodecDecoder::ProcessNextFrame() { 523 void MediaCodecDecoder::ProcessNextFrame() {
437 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 524 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
438 525
439 DVLOG(2) << class_name() << "::" << __FUNCTION__; 526 DVLOG(2) << class_name() << "::" << __FUNCTION__;
440 527
441 DecoderState state = GetState(); 528 DecoderState state = GetState();
442 529
443 if (state != kRunning && state != kStopping) { 530 if (state != kPrerolling && state != kRunning && state != kStopping) {
444 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running"; 531 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running";
445 return; 532 return;
446 } 533 }
447 534
448 if (state == kStopping) { 535 if (state == kStopping) {
449 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) { 536 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
450 DVLOG(1) << class_name() << "::" << __FUNCTION__ 537 DVLOG(1) << class_name() << "::" << __FUNCTION__
451 << ": kStopping, posting OnLastFrameRendered"; 538 << ": kStopping, posting OnLastFrameRendered";
452 media_task_runner_->PostTask( 539 media_task_runner_->PostTask(
453 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered, 540 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
454 weak_factory_.GetWeakPtr(), false)); 541 weak_factory_.GetWeakPtr(), false));
455 last_frame_posted_ = true; 542 last_frame_posted_ = true;
456 } 543 }
457 544
458 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze. 545 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
459 // We only need to let finish the delayed rendering tasks. 546 // We only need to let finish the delayed rendering tasks.
460 return; 547 return;
461 } 548 }
462 549
463 DCHECK(state == kRunning); 550 DCHECK(state == kPrerolling || state == kRunning);
464 551
465 if (!EnqueueInputBuffer()) 552 if (!EnqueueInputBuffer())
466 return; 553 return;
467 554
468 if (!DepleteOutputBufferQueue()) 555 if (!DepleteOutputBufferQueue())
469 return; 556 return;
470 557
471 // We need a small delay if we want to stop this thread by 558 // We need a small delay if we want to stop this thread by
472 // decoder_thread_.Stop() reliably. 559 // decoder_thread_.Stop() reliably.
473 // The decoder thread message loop processes all pending 560 // The decoder thread message loop processes all pending
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 681 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
595 682
596 DVLOG(2) << class_name() << "::" << __FUNCTION__; 683 DVLOG(2) << class_name() << "::" << __FUNCTION__;
597 684
598 int buffer_index = 0; 685 int buffer_index = 0;
599 size_t offset = 0; 686 size_t offset = 0;
600 size_t size = 0; 687 size_t size = 0;
601 base::TimeDelta pts; 688 base::TimeDelta pts;
602 MediaCodecStatus status; 689 MediaCodecStatus status;
603 bool eos_encountered = false; 690 bool eos_encountered = false;
691 bool preroll_done = false;
604 692
605 base::TimeDelta timeout = 693 base::TimeDelta timeout =
606 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout); 694 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
607 695
608 // Extract all output buffers that are available. 696 // Extract all output buffers that are available.
609 // Usually there will be only one, but sometimes it is preceeded by 697 // Usually there will be only one, but sometimes it is preceeded by
610 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED. 698 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
611 do { 699 do {
612 status = media_codec_bridge_->DequeueOutputBuffer( 700 status = media_codec_bridge_->DequeueOutputBuffer(
613 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered, 701 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
614 nullptr); 702 nullptr);
615 703
616 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls 704 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
617 // to quickly break the loop after we got all currently available buffers. 705 // to quickly break the loop after we got all currently available buffers.
618 timeout = base::TimeDelta::FromMilliseconds(0); 706 timeout = base::TimeDelta::FromMilliseconds(0);
619 707
620 switch (status) { 708 switch (status) {
621 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 709 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
622 // Output buffers are replaced in MediaCodecBridge, nothing to do. 710 // Output buffers are replaced in MediaCodecBridge, nothing to do.
623 break; 711 break;
624 712
625 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: 713 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
626 DVLOG(2) << class_name() << "::" << __FUNCTION__ 714 DVLOG(2) << class_name() << "::" << __FUNCTION__
627 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED"; 715 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
628 OnOutputFormatChanged(); 716 OnOutputFormatChanged();
629 break; 717 break;
630 718
631 case MEDIA_CODEC_OK: 719 case MEDIA_CODEC_OK: {
632 // We got the decoded frame 720 // We got the decoded frame.
633 Render(buffer_index, size, true, pts, eos_encountered); 721
634 break; 722 // TODO(timav): this code won't render the very first frame in
723 // kPrerolling if it is already behind preroll_timestamp_. A more
724 // precise method would be to stop before Render() and resume after
725 // preroll with the Render(), but it would be more complicated.
726
727 DecoderState state = GetState();
728 const bool do_render = (state == kRunning || state == kStopping);
qinmin 2015/07/28 18:09:46 I think it is ok to render if (state == kPrerollin
Tima Vaisburd 2015/07/28 18:34:04 I believe you mean "in addition to kRunning and kS
qinmin 2015/07/28 18:55:06 You can modify the MediaCodecBridge.playOutputBuff
729
730 Render(buffer_index, size, do_render, pts, eos_encountered);
731
732 // If next pts passes over |preroll_timestamp_| this frame is the last
733 // preroll frame.
734 if (!do_render && preroll_timestamp_ <= pts + estimated_frame_period_) {
735 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
736 preroll_done = true;
737 }
738 } break;
635 739
636 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 740 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
637 // Nothing to do. 741 // Nothing to do.
638 break; 742 break;
639 743
640 case MEDIA_CODEC_ERROR: 744 case MEDIA_CODEC_ERROR:
641 DVLOG(0) << class_name() << "::" << __FUNCTION__ 745 DVLOG(0) << class_name() << "::" << __FUNCTION__
642 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer"; 746 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
643 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 747 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
644 break; 748 break;
645 749
646 default: 750 default:
647 NOTREACHED(); 751 NOTREACHED();
648 break; 752 break;
649 } 753 }
650 754
651 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER && 755 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
652 status != MEDIA_CODEC_ERROR && !eos_encountered); 756 status != MEDIA_CODEC_ERROR && !eos_encountered && !preroll_done);
653 757
654 if (eos_encountered) { 758 if (eos_encountered) {
655 DVLOG(1) << class_name() << "::" << __FUNCTION__ 759 DVLOG(1) << class_name() << "::" << __FUNCTION__
656 << " EOS dequeued, stopping frame processing"; 760 << " EOS dequeued, stopping frame processing";
657 return false; 761 return false;
658 } 762 }
659 763
764 if (preroll_done) {
765 DVLOG(1) << class_name() << "::" << __FUNCTION__
766 << " preroll done, stopping frame processing";
767 return false;
768 }
769
660 if (status == MEDIA_CODEC_ERROR) { 770 if (status == MEDIA_CODEC_ERROR) {
661 DVLOG(1) << class_name() << "::" << __FUNCTION__ 771 DVLOG(1) << class_name() << "::" << __FUNCTION__
662 << " MediaCodec error, stopping frame processing"; 772 << " MediaCodec error, stopping frame processing";
663 return false; 773 return false;
664 } 774 }
665 775
666 return true; 776 return true;
667 } 777 }
668 778
669 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const { 779 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const {
(...skipping 11 matching lines...) Expand all
681 #undef RETURN_STRING 791 #undef RETURN_STRING
682 #define RETURN_STRING(x) \ 792 #define RETURN_STRING(x) \
683 case x: \ 793 case x: \
684 return #x; 794 return #x;
685 795
686 const char* MediaCodecDecoder::AsString(DecoderState state) { 796 const char* MediaCodecDecoder::AsString(DecoderState state) {
687 switch (state) { 797 switch (state) {
688 RETURN_STRING(kStopped); 798 RETURN_STRING(kStopped);
689 RETURN_STRING(kPrefetching); 799 RETURN_STRING(kPrefetching);
690 RETURN_STRING(kPrefetched); 800 RETURN_STRING(kPrefetched);
801 RETURN_STRING(kPrerolling);
802 RETURN_STRING(kPrerolled);
691 RETURN_STRING(kRunning); 803 RETURN_STRING(kRunning);
692 RETURN_STRING(kStopping); 804 RETURN_STRING(kStopping);
693 RETURN_STRING(kInEmergencyStop); 805 RETURN_STRING(kInEmergencyStop);
694 RETURN_STRING(kError); 806 RETURN_STRING(kError);
695 default: 807 default:
696 return "Unknown DecoderState"; 808 return "Unknown DecoderState";
697 } 809 }
698 } 810 }
699 811
700 #undef RETURN_STRING 812 #undef RETURN_STRING
701 813
702 } // namespace media 814 } // 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