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

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

Issue 2276343005: Delete MediaCodecPlayer, it's time! (Closed)
Patch Set: Created 4 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/android/media_codec_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h"
10 #include "base/logging.h"
11 #include "media/base/android/media_codec_bridge.h"
12
13 namespace media {
14
15 namespace {
16
17 // Stop requesting new data in the kPrefetching state when the queue size
18 // reaches this limit.
19 const int kPrefetchLimit = 8;
20
21 // Request new data in the kRunning state if the queue size is less than this.
22 const int kPlaybackLowLimit = 4;
23
24 // Posting delay of the next frame processing, in milliseconds
25 const int kNextFrameDelay = 1;
26
27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds.
28 const int kInputBufferTimeout = 20;
29
30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds.
31 const int kOutputBufferTimeout = 20;
32
33 } // namespace
34
35 MediaCodecDecoder::MediaCodecDecoder(
36 const char* decoder_thread_name,
37 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
38 FrameStatistics* frame_statistics,
39 const base::Closure& external_request_data_cb,
40 const base::Closure& starvation_cb,
41 const base::Closure& decoder_drained_cb,
42 const base::Closure& stop_done_cb,
43 const base::Closure& waiting_for_decryption_key_cb,
44 const base::Closure& error_cb)
45 : decoder_thread_(decoder_thread_name),
46 media_task_runner_(media_task_runner),
47 frame_statistics_(frame_statistics),
48 needs_reconfigure_(false),
49 drain_decoder_(false),
50 always_reconfigure_for_tests_(false),
51 external_request_data_cb_(external_request_data_cb),
52 starvation_cb_(starvation_cb),
53 decoder_drained_cb_(decoder_drained_cb),
54 stop_done_cb_(stop_done_cb),
55 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb),
56 error_cb_(error_cb),
57 state_(kStopped),
58 pending_input_buf_index_(-1),
59 is_prepared_(false),
60 eos_enqueued_(false),
61 missing_key_reported_(false),
62 completed_(false),
63 last_frame_posted_(false),
64 is_data_request_in_progress_(false),
65 is_incoming_data_invalid_(false),
66 #ifndef NDEBUG
67 verify_next_frame_is_key_(false),
68 #endif
69 weak_factory_(this) {
70 DCHECK(media_task_runner_->BelongsToCurrentThread());
71
72 DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
73
74 internal_error_cb_ =
75 base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
76 internal_preroll_done_cb_ =
77 base::Bind(&MediaCodecDecoder::OnPrerollDone, weak_factory_.GetWeakPtr());
78 request_data_cb_ =
79 base::Bind(&MediaCodecDecoder::RequestData, weak_factory_.GetWeakPtr());
80 }
81
82 MediaCodecDecoder::~MediaCodecDecoder() {}
83
84 const char* MediaCodecDecoder::class_name() const {
85 return "Decoder";
86 }
87
88 void MediaCodecDecoder::Flush() {
89 DCHECK(media_task_runner_->BelongsToCurrentThread());
90
91 DVLOG(1) << class_name() << "::" << __FUNCTION__;
92
93 DCHECK_EQ(GetState(), kStopped);
94
95 // Flush() is a part of the Seek request. Whenever we request a seek we need
96 // to invalidate the current data request.
97 if (is_data_request_in_progress_)
98 is_incoming_data_invalid_ = true;
99
100 eos_enqueued_ = false;
101 missing_key_reported_ = false;
102 completed_ = false;
103 drain_decoder_ = false;
104 au_queue_.Flush();
105
106 // |is_prepared_| is set on the decoder thread, it shouldn't be running now.
107 DCHECK(!decoder_thread_.IsRunning());
108 is_prepared_ = false;
109
110 pending_input_buf_index_ = -1;
111
112 #ifndef NDEBUG
113 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
114 // We have just DCHECKed that decoder thread is not running.
115
116 // For video the first frame after flush must be key frame.
117 verify_next_frame_is_key_ = true;
118 #endif
119
120 if (media_codec_bridge_) {
121 MediaCodecStatus flush_status = media_codec_bridge_->Flush();
122 if (flush_status != MEDIA_CODEC_OK) {
123 DVLOG(0) << class_name() << "::" << __FUNCTION__
124 << "MediaCodecBridge::Flush() failed";
125 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
126 }
127 }
128 }
129
130 void MediaCodecDecoder::ReleaseMediaCodec() {
131 DCHECK(media_task_runner_->BelongsToCurrentThread());
132
133 DVLOG(1) << class_name() << "::" << __FUNCTION__;
134
135 DCHECK(!decoder_thread_.IsRunning());
136
137 media_codec_bridge_.reset();
138
139 // |is_prepared_| is set on the decoder thread, it shouldn't be running now.
140 is_prepared_ = false;
141
142 pending_input_buf_index_ = -1;
143 }
144
145 bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
146 DCHECK(media_task_runner_->BelongsToCurrentThread());
147
148 // Whether decoder needs to be stopped.
149 base::AutoLock lock(state_lock_);
150 switch (state_) {
151 case kPrefetching:
152 case kPrefetched:
153 case kPrerolling:
154 case kPrerolled:
155 case kRunning:
156 return true;
157 case kStopped:
158 case kStopping:
159 case kInEmergencyStop:
160 case kError:
161 return false;
162 }
163 NOTREACHED();
164 return false;
165 }
166
167 bool MediaCodecDecoder::IsStopped() const {
168 DCHECK(media_task_runner_->BelongsToCurrentThread());
169
170 return GetState() == kStopped;
171 }
172
173 bool MediaCodecDecoder::IsCompleted() const {
174 DCHECK(media_task_runner_->BelongsToCurrentThread());
175
176 return completed_;
177 }
178
179 bool MediaCodecDecoder::NotCompletedAndNeedsPreroll() const {
180 DCHECK(media_task_runner_->BelongsToCurrentThread());
181
182 return HasStream() && !completed_ &&
183 (!is_prepared_ || !preroll_timestamp_.is_zero());
184 }
185
186 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) {
187 DCHECK(media_task_runner_->BelongsToCurrentThread());
188 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp;
189
190 preroll_timestamp_ = preroll_timestamp;
191 }
192
193 void MediaCodecDecoder::SetNeedsReconfigure() {
194 DCHECK(media_task_runner_->BelongsToCurrentThread());
195
196 DVLOG(1) << class_name() << "::" << __FUNCTION__;
197
198 needs_reconfigure_ = true;
199 }
200
201 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) {
202 DCHECK(media_task_runner_->BelongsToCurrentThread());
203
204 DVLOG(1) << class_name() << "::" << __FUNCTION__;
205
206 DCHECK(GetState() == kStopped);
207
208 prefetch_done_cb_ = prefetch_done_cb;
209
210 SetState(kPrefetching);
211 PrefetchNextChunk();
212 }
213
214 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure(
215 jobject media_crypto) {
216 DCHECK(media_task_runner_->BelongsToCurrentThread());
217
218 DVLOG(1) << class_name() << "::" << __FUNCTION__;
219
220 if (GetState() == kError) {
221 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
222 return kConfigFailure;
223 }
224
225 if (needs_reconfigure_) {
226 DVLOG(1) << class_name() << "::" << __FUNCTION__
227 << ": needs reconfigure, deleting MediaCodec";
228 needs_reconfigure_ = false;
229 ReleaseMediaCodec();
230 }
231
232 if (media_codec_bridge_) {
233 DVLOG(1) << class_name() << "::" << __FUNCTION__
234 << ": reconfiguration is not required, ignoring";
235 return kConfigOk;
236 }
237
238 // Read all |kConfigChanged| units preceding the data one.
239 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
240 while (au_info.configs) {
241 SetDemuxerConfigs(*au_info.configs);
242 au_queue_.Advance();
243 au_info = au_queue_.GetInfo();
244 }
245
246 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(media_crypto);
247
248 #ifndef NDEBUG
249 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
250 // This DCHECK ensures we won't need to lock this variable.
251 DCHECK(!decoder_thread_.IsRunning());
252
253 // For video the first frame after reconfiguration must be key frame.
254 if (result == kConfigOk)
255 verify_next_frame_is_key_ = true;
256 #endif
257
258 return result;
259 }
260
261 bool MediaCodecDecoder::Preroll(const base::Closure& preroll_done_cb) {
262 DCHECK(media_task_runner_->BelongsToCurrentThread());
263
264 DVLOG(1) << class_name() << "::" << __FUNCTION__
265 << " preroll_timestamp:" << preroll_timestamp_;
266
267 DecoderState state = GetState();
268 if (state != kPrefetched) {
269 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
270 << AsString(state) << ", ignoring";
271 return false;
272 }
273
274 if (!media_codec_bridge_) {
275 DVLOG(0) << class_name() << "::" << __FUNCTION__
276 << ": not configured, ignoring";
277 return false;
278 }
279
280 DCHECK(!decoder_thread_.IsRunning());
281
282 preroll_done_cb_ = preroll_done_cb;
283
284 // We only synchronize video stream.
285 DissociatePTSFromTime(); // associaton will happen after preroll is done.
286
287 last_frame_posted_ = false;
288 missing_key_reported_ = false;
289
290 // Start the decoder thread
291 if (!decoder_thread_.Start()) {
292 DVLOG(0) << class_name() << "::" << __FUNCTION__
293 << ": cannot start decoder thread";
294 return false;
295 }
296
297 SetState(kPrerolling);
298
299 decoder_thread_.task_runner()->PostTask(
300 FROM_HERE,
301 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
302
303 return true;
304 }
305
306 bool MediaCodecDecoder::Start(base::TimeDelta start_timestamp) {
307 DCHECK(media_task_runner_->BelongsToCurrentThread());
308
309 DVLOG(1) << class_name() << "::" << __FUNCTION__
310 << " start_timestamp:" << start_timestamp;
311
312 DecoderState state = GetState();
313
314 if (state != kPrefetched && state != kPrerolled) {
315 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
316 << AsString(state) << ", ignoring";
317 return false;
318 }
319
320 if (!media_codec_bridge_) {
321 DVLOG(0) << class_name() << "::" << __FUNCTION__
322 << ": not configured, ignoring";
323 return false;
324 }
325
326 // We only synchronize video stream.
327 AssociateCurrentTimeWithPTS(start_timestamp);
328
329 DCHECK(preroll_timestamp_.is_zero());
330
331 // Start the decoder thread
332 if (!decoder_thread_.IsRunning()) {
333 last_frame_posted_ = false;
334 missing_key_reported_ = false;
335 if (!decoder_thread_.Start()) {
336 DVLOG(1) << class_name() << "::" << __FUNCTION__
337 << ": cannot start decoder thread";
338 return false;
339 }
340 }
341
342 SetState(kRunning);
343
344 decoder_thread_.task_runner()->PostTask(
345 FROM_HERE,
346 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
347
348 return true;
349 }
350
351 void MediaCodecDecoder::SyncStop() {
352 DCHECK(media_task_runner_->BelongsToCurrentThread());
353
354 DVLOG(1) << class_name() << "::" << __FUNCTION__;
355
356 if (GetState() == kError) {
357 DVLOG(0) << class_name() << "::" << __FUNCTION__
358 << ": wrong state kError, ignoring";
359 return;
360 }
361
362 DoEmergencyStop();
363
364 ReleaseDelayedBuffers();
365 }
366
367 void MediaCodecDecoder::RequestToStop() {
368 DCHECK(media_task_runner_->BelongsToCurrentThread());
369
370 DVLOG(1) << class_name() << "::" << __FUNCTION__;
371
372 DecoderState state = GetState();
373 switch (state) {
374 case kError:
375 DVLOG(0) << class_name() << "::" << __FUNCTION__
376 << ": wrong state kError, ignoring";
377 break;
378 case kRunning:
379 SetState(kStopping);
380 break;
381 case kPrerolling:
382 case kPrerolled:
383 DCHECK(decoder_thread_.IsRunning());
384 // Synchronous stop.
385 decoder_thread_.Stop();
386 SetState(kStopped);
387 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
388 break;
389 case kStopping:
390 case kStopped:
391 break; // ignore
392 case kPrefetching:
393 case kPrefetched:
394 // There is nothing to wait for, we can sent notification right away.
395 DCHECK(!decoder_thread_.IsRunning());
396 SetState(kStopped);
397 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
398 break;
399 default:
400 NOTREACHED();
401 break;
402 }
403 }
404
405 void MediaCodecDecoder::OnLastFrameRendered(bool eos_encountered) {
406 DCHECK(media_task_runner_->BelongsToCurrentThread());
407
408 DVLOG(1) << class_name() << "::" << __FUNCTION__
409 << " eos_encountered:" << eos_encountered;
410
411 decoder_thread_.Stop(); // synchronous
412
413 SetState(kStopped);
414 completed_ = (eos_encountered && !drain_decoder_);
415
416 missing_key_reported_ = false;
417
418 // If the stream is completed during preroll we need to report it since
419 // another stream might be running and the player waits for two callbacks.
420 if (completed_ && !preroll_done_cb_.is_null()) {
421 preroll_timestamp_ = base::TimeDelta();
422 media_task_runner_->PostTask(FROM_HERE,
423 base::ResetAndReturn(&preroll_done_cb_));
424 }
425
426 if (eos_encountered && drain_decoder_) {
427 drain_decoder_ = false;
428 eos_enqueued_ = false;
429 ReleaseMediaCodec();
430 media_task_runner_->PostTask(FROM_HERE, decoder_drained_cb_);
431 }
432
433 media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
434 }
435
436 void MediaCodecDecoder::OnPrerollDone() {
437 DCHECK(media_task_runner_->BelongsToCurrentThread());
438
439 DVLOG(1) << class_name() << "::" << __FUNCTION__
440 << " state:" << AsString(GetState());
441
442 preroll_timestamp_ = base::TimeDelta();
443
444 // The state might be kStopping (?)
445 if (GetState() == kPrerolling)
446 SetState(kPrerolled);
447
448 if (!preroll_done_cb_.is_null())
449 base::ResetAndReturn(&preroll_done_cb_).Run();
450 }
451
452 void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
453 DCHECK(media_task_runner_->BelongsToCurrentThread());
454
455 // If |data| contains an aborted data, the last AU will have kAborted status.
456 bool aborted_data =
457 !data.access_units.empty() &&
458 data.access_units.back().status == DemuxerStream::kAborted;
459
460 #ifndef NDEBUG
461 const char* explain_if_skipped =
462 is_incoming_data_invalid_ ? " skipped as invalid"
463 : (aborted_data ? " skipped as aborted" : "");
464
465 for (const auto& unit : data.access_units)
466 DVLOG(2) << class_name() << "::" << __FUNCTION__ << explain_if_skipped
467 << " au: " << unit;
468 for (const auto& configs : data.demuxer_configs)
469 DVLOG(2) << class_name() << "::" << __FUNCTION__ << " configs: " << configs;
470 #endif
471
472 if (!is_incoming_data_invalid_ && !aborted_data)
473 au_queue_.PushBack(data);
474
475 is_incoming_data_invalid_ = false;
476 is_data_request_in_progress_ = false;
477
478 // Do not request data if we got kAborted. There is no point to request the
479 // data after kAborted and before the OnDemuxerSeekDone.
480 if (GetState() == kPrefetching && !aborted_data)
481 PrefetchNextChunk();
482 }
483
484 bool MediaCodecDecoder::IsPrerollingForTests() const {
485 // UI task runner.
486 return GetState() == kPrerolling;
487 }
488
489 void MediaCodecDecoder::SetAlwaysReconfigureForTests() {
490 // UI task runner.
491 always_reconfigure_for_tests_ = true;
492 }
493
494 void MediaCodecDecoder::SetCodecCreatedCallbackForTests(base::Closure cb) {
495 // UI task runner.
496 codec_created_for_tests_cb_ = cb;
497 }
498
499 int MediaCodecDecoder::NumDelayedRenderTasks() const {
500 return 0;
501 }
502
503 void MediaCodecDecoder::DoEmergencyStop() {
504 DCHECK(media_task_runner_->BelongsToCurrentThread());
505 DVLOG(1) << class_name() << "::" << __FUNCTION__;
506
507 // After this method returns, decoder thread will not be running.
508
509 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
510 SetState(kInEmergencyStop);
511
512 decoder_thread_.Stop(); // synchronous
513
514 SetState(kStopped);
515
516 missing_key_reported_ = false;
517 }
518
519 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
520 bool has_delayed_tasks) {
521 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
522
523 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
524
525 if (last_frame_when_stopping || eos_encountered) {
526 media_task_runner_->PostTask(
527 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
528 weak_factory_.GetWeakPtr(), eos_encountered));
529 last_frame_posted_ = true;
530 }
531 }
532
533 void MediaCodecDecoder::OnCodecError() {
534 DCHECK(media_task_runner_->BelongsToCurrentThread());
535
536 // Ignore codec errors from the moment surface is changed till the
537 // |media_codec_bridge_| is deleted.
538 if (needs_reconfigure_) {
539 DVLOG(1) << class_name() << "::" << __FUNCTION__
540 << ": needs reconfigure, ignoring";
541 return;
542 }
543
544 SetState(kError);
545 error_cb_.Run();
546 }
547
548 void MediaCodecDecoder::RequestData() {
549 DCHECK(media_task_runner_->BelongsToCurrentThread());
550
551 // We request data only in kPrefetching, kPrerolling and kRunning states.
552 // For kPrerolling and kRunning this method is posted from Decoder thread,
553 // and by the time it arrives the player might be doing something else, e.g.
554 // seeking, in which case we should not request more data
555 switch (GetState()) {
556 case kPrefetching:
557 case kPrerolling:
558 case kRunning:
559 break; // continue
560 default:
561 return; // skip
562 }
563
564 // Ensure one data request at a time.
565 if (!is_data_request_in_progress_) {
566 is_data_request_in_progress_ = true;
567 external_request_data_cb_.Run();
568 }
569 }
570
571 void MediaCodecDecoder::PrefetchNextChunk() {
572 DCHECK(media_task_runner_->BelongsToCurrentThread());
573
574 DVLOG(1) << class_name() << "::" << __FUNCTION__;
575
576 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
577
578 if (eos_enqueued_ || au_info.data_length >= kPrefetchLimit ||
579 au_info.has_eos) {
580 // We are done prefetching
581 SetState(kPrefetched);
582 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " posting PrefetchDone";
583 media_task_runner_->PostTask(FROM_HERE,
584 base::ResetAndReturn(&prefetch_done_cb_));
585 return;
586 }
587
588 request_data_cb_.Run();
589 }
590
591 void MediaCodecDecoder::ProcessNextFrame() {
592 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
593
594 DVLOG(2) << class_name() << "::" << __FUNCTION__;
595
596 DecoderState state = GetState();
597
598 if (state != kPrerolling && state != kRunning && state != kStopping) {
599 DVLOG(1) << class_name() << "::" << __FUNCTION__
600 << ": state: " << AsString(state) << " stopping frame processing";
601 return;
602 }
603
604 if (state == kStopping) {
605 if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
606 media_task_runner_->PostTask(
607 FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
608 weak_factory_.GetWeakPtr(), false));
609 last_frame_posted_ = true;
610 }
611
612 // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
613 // We only need to let finish the delayed rendering tasks.
614 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " kStopping, returning";
615 return;
616 }
617
618 DCHECK(state == kPrerolling || state == kRunning);
619
620 if (!EnqueueInputBuffer())
621 return;
622
623 if (!DepleteOutputBufferQueue())
624 return;
625
626 // We need a small delay if we want to stop this thread by
627 // decoder_thread_.Stop() reliably.
628 // The decoder thread message loop processes all pending
629 // (but not delayed) tasks before it can quit; without a delay
630 // the message loop might be forever processing the pendng tasks.
631 decoder_thread_.task_runner()->PostDelayedTask(
632 FROM_HERE,
633 base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)),
634 base::TimeDelta::FromMilliseconds(kNextFrameDelay));
635 }
636
637 // Returns false if we should stop decoding process. Right now
638 // it happens if we got MediaCodec error or detected starvation.
639 bool MediaCodecDecoder::EnqueueInputBuffer() {
640 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
641
642 DVLOG(2) << class_name() << "::" << __FUNCTION__;
643
644 if (eos_enqueued_) {
645 DVLOG(1) << class_name() << "::" << __FUNCTION__
646 << ": EOS enqueued, returning";
647 return true; // Nothing to do
648 }
649
650 if (missing_key_reported_) {
651 DVLOG(1) << class_name() << "::" << __FUNCTION__
652 << ": NO KEY reported, returning";
653 return true; // Nothing to do
654 }
655
656 // Keep the number pending video frames low, ideally maintaining
657 // the same audio and video duration after stop request
658 if (NumDelayedRenderTasks() > 1) {
659 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
660 << NumDelayedRenderTasks() << ") exceeds 1, returning";
661 return true; // Nothing to do
662 }
663
664 // Get the next frame from the queue. As we go, request more data and
665 // consume |kConfigChanged| units.
666
667 // |drain_decoder_| can be already set here if we could not dequeue the input
668 // buffer for it right away.
669
670 AccessUnitQueue::Info au_info;
671 if (!drain_decoder_) {
672 au_info = AdvanceAccessUnitQueue(&drain_decoder_);
673 if (!au_info.length) {
674 // Report starvation and return, Start() will be called again later.
675 DVLOG(1) << class_name() << "::" << __FUNCTION__
676 << ": starvation detected";
677 media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
678 return true;
679 }
680
681 DCHECK(au_info.front_unit);
682
683 #ifndef NDEBUG
684 if (verify_next_frame_is_key_) {
685 verify_next_frame_is_key_ = false;
686 VerifyUnitIsKeyFrame(au_info.front_unit);
687 }
688 #endif
689 }
690
691 // Dequeue input buffer
692
693 int index = pending_input_buf_index_;
694
695 // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY.
696 // That status does not return this buffer back to the pool of
697 // available input buffers. We have to reuse it in QueueSecureInputBuffer().
698 if (index == -1) {
699 base::TimeDelta timeout =
700 base::TimeDelta::FromMilliseconds(kInputBufferTimeout);
701 MediaCodecStatus status =
702 media_codec_bridge_->DequeueInputBuffer(timeout, &index);
703
704 switch (status) {
705 case MEDIA_CODEC_ERROR:
706 DVLOG(0) << class_name() << "::" << __FUNCTION__
707 << ": MEDIA_CODEC_ERROR DequeueInputBuffer failed";
708 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
709 return false;
710
711 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER:
712 DVLOG(2)
713 << class_name() << "::" << __FUNCTION__
714 << ": DequeueInputBuffer returned MediaCodec.INFO_TRY_AGAIN_LATER.";
715 return true;
716
717 default:
718 break;
719 }
720
721 DCHECK_EQ(status, MEDIA_CODEC_OK);
722 }
723
724 DVLOG(2) << class_name() << "::" << __FUNCTION__
725 << ": using input buffer index:" << index;
726
727 // We got the buffer
728 DCHECK_GE(index, 0);
729
730 const AccessUnit* unit = au_info.front_unit;
731
732 if (drain_decoder_ || unit->is_end_of_stream) {
733 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
734
735 // Check that we are not using the pending input buffer to queue EOS
736 DCHECK(pending_input_buf_index_ == -1);
737
738 media_codec_bridge_->QueueEOS(index);
739 eos_enqueued_ = true;
740 return true;
741 }
742
743 DCHECK(unit);
744 DCHECK(!unit->data.empty());
745
746 // Pending input buffer is already filled with data.
747 const uint8_t* memory =
748 (pending_input_buf_index_ == -1) ? &unit->data[0] : nullptr;
749
750 pending_input_buf_index_ = -1;
751 MediaCodecStatus status = MEDIA_CODEC_OK;
752
753 if (unit->key_id.empty() || unit->iv.empty()) {
754 DVLOG(2) << class_name() << "::" << __FUNCTION__
755 << ": QueueInputBuffer pts:" << unit->timestamp;
756
757 status = media_codec_bridge_->QueueInputBuffer(
758 index, memory, unit->data.size(), unit->timestamp);
759 } else {
760 DVLOG(2) << class_name() << "::" << __FUNCTION__
761 << ": QueueSecureInputBuffer pts:" << unit->timestamp
762 << " key_id size:" << unit->key_id.size()
763 << " iv size:" << unit->iv.size()
764 << " subsamples size:" << unit->subsamples.size();
765
766 status = media_codec_bridge_->QueueSecureInputBuffer(
767 index, memory, unit->data.size(), unit->key_id, unit->iv,
768 unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
769 unit->subsamples.size(), unit->timestamp);
770 }
771
772 switch (status) {
773 case MEDIA_CODEC_OK:
774 break;
775
776 case MEDIA_CODEC_ERROR:
777 DVLOG(0) << class_name() << "::" << __FUNCTION__
778 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
779 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
780 return false;
781
782 case MEDIA_CODEC_NO_KEY:
783 DVLOG(1) << class_name() << "::" << __FUNCTION__
784 << ": MEDIA_CODEC_NO_KEY";
785 media_task_runner_->PostTask(FROM_HERE, waiting_for_decryption_key_cb_);
786
787 // We need to enqueue the same input buffer after we get the key.
788 // The buffer is owned by us (not the MediaCodec) and is filled with data.
789 pending_input_buf_index_ = index;
790
791 // In response to the |waiting_for_decryption_key_cb_| the player will
792 // request to stop decoder. We need to keep running to properly perform
793 // the stop, but prevent generating more |waiting_for_decryption_key_cb_|.
794 missing_key_reported_ = true;
795 return true;
796
797 default:
798 NOTREACHED() << class_name() << "::" << __FUNCTION__
799 << ": unexpected error code " << status;
800 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
801 return false;
802 }
803
804 // Have successfully queued input buffer, go to next access unit.
805 au_queue_.Advance();
806 return true;
807 }
808
809 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue(
810 bool* drain_decoder) {
811 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
812 DVLOG(2) << class_name() << "::" << __FUNCTION__;
813
814 // Retrieve access units from the |au_queue_| in a loop until we either get
815 // a non-config front unit or until the queue is empty.
816
817 DCHECK(drain_decoder != nullptr);
818
819 AccessUnitQueue::Info au_info;
820
821 do {
822 // Get current frame
823 au_info = au_queue_.GetInfo();
824
825 // Request the data from Demuxer
826 if (au_info.data_length <= kPlaybackLowLimit && !au_info.has_eos)
827 media_task_runner_->PostTask(FROM_HERE, request_data_cb_);
828
829 if (!au_info.length)
830 break; // Starvation
831
832 if (au_info.configs) {
833 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": received configs "
834 << (*au_info.configs);
835
836 // Compare the new and current configs.
837 if (IsCodecReconfigureNeeded(*au_info.configs)) {
838 DVLOG(1) << class_name() << "::" << __FUNCTION__
839 << ": reconfiguration and decoder drain required";
840 *drain_decoder = true;
841 }
842
843 // Replace the current configs.
844 SetDemuxerConfigs(*au_info.configs);
845
846 // Move to the next frame
847 au_queue_.Advance();
848 }
849 } while (au_info.configs);
850
851 return au_info;
852 }
853
854 // Returns false if there was MediaCodec error.
855 bool MediaCodecDecoder::DepleteOutputBufferQueue() {
856 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
857
858 DVLOG(2) << class_name() << "::" << __FUNCTION__;
859
860 int buffer_index = 0;
861 size_t offset = 0;
862 size_t size = 0;
863 base::TimeDelta pts;
864 MediaCodecStatus status;
865 bool eos_encountered = false;
866
867 RenderMode render_mode;
868
869 base::TimeDelta timeout =
870 base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
871
872 // Extract all output buffers that are available.
873 // Usually there will be only one, but sometimes it is preceeded by
874 // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
875 do {
876 status = media_codec_bridge_->DequeueOutputBuffer(
877 timeout, &buffer_index, &offset, &size, &pts, &eos_encountered,
878 nullptr);
879
880 // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
881 // to quickly break the loop after we got all currently available buffers.
882 timeout = base::TimeDelta::FromMilliseconds(0);
883
884 switch (status) {
885 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
886 // Output buffers are replaced in MediaCodecBridge, nothing to do.
887 DVLOG(2) << class_name() << "::" << __FUNCTION__
888 << " MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED";
889 break;
890
891 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
892 DVLOG(2) << class_name() << "::" << __FUNCTION__
893 << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
894 if (!OnOutputFormatChanged()) {
895 DVLOG(1) << class_name() << "::" << __FUNCTION__
896 << ": OnOutputFormatChanged failed, stopping frame"
897 << " processing";
898 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
899 return false;
900 }
901 break;
902
903 case MEDIA_CODEC_OK:
904 // We got the decoded frame.
905
906 is_prepared_ = true;
907
908 if (pts < preroll_timestamp_)
909 render_mode = kRenderSkip;
910 else if (GetState() == kPrerolling)
911 render_mode = kRenderAfterPreroll;
912 else
913 render_mode = kRenderNow;
914
915 if (!Render(buffer_index, offset, size, render_mode, pts,
916 eos_encountered)) {
917 DVLOG(1) << class_name() << "::" << __FUNCTION__
918 << " Render failed, stopping frame processing";
919 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
920 return false;
921 }
922
923 if (render_mode == kRenderAfterPreroll) {
924 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " pts " << pts
925 << " >= preroll timestamp " << preroll_timestamp_
926 << " preroll done, stopping frame processing";
927 media_task_runner_->PostTask(FROM_HERE, internal_preroll_done_cb_);
928 return false;
929 }
930 break;
931
932 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
933 // Nothing to do.
934 DVLOG(2) << class_name() << "::" << __FUNCTION__
935 << " MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER";
936 break;
937
938 case MEDIA_CODEC_ERROR:
939 DVLOG(0) << class_name() << "::" << __FUNCTION__
940 << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
941 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
942 break;
943
944 default:
945 NOTREACHED();
946 break;
947 }
948 } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
949 status != MEDIA_CODEC_ERROR && !eos_encountered);
950
951 if (eos_encountered) {
952 DVLOG(1) << class_name() << "::" << __FUNCTION__
953 << " EOS dequeued, stopping frame processing";
954 return false;
955 }
956
957 if (status == MEDIA_CODEC_ERROR) {
958 DVLOG(0) << class_name() << "::" << __FUNCTION__
959 << " MediaCodec error, stopping frame processing";
960 return false;
961 }
962
963 return true;
964 }
965
966 MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const {
967 base::AutoLock lock(state_lock_);
968 return state_;
969 }
970
971 void MediaCodecDecoder::SetState(DecoderState state) {
972 DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << AsString(state);
973
974 base::AutoLock lock(state_lock_);
975 state_ = state;
976 }
977
978 #undef RETURN_STRING
979 #define RETURN_STRING(x) \
980 case x: \
981 return #x;
982
983 const char* MediaCodecDecoder::AsString(RenderMode render_mode) {
984 switch (render_mode) {
985 RETURN_STRING(kRenderSkip);
986 RETURN_STRING(kRenderAfterPreroll);
987 RETURN_STRING(kRenderNow);
988 }
989 return nullptr; // crash early
990 }
991
992 const char* MediaCodecDecoder::AsString(DecoderState state) {
993 switch (state) {
994 RETURN_STRING(kStopped);
995 RETURN_STRING(kPrefetching);
996 RETURN_STRING(kPrefetched);
997 RETURN_STRING(kPrerolling);
998 RETURN_STRING(kPrerolled);
999 RETURN_STRING(kRunning);
1000 RETURN_STRING(kStopping);
1001 RETURN_STRING(kInEmergencyStop);
1002 RETURN_STRING(kError);
1003 }
1004 return nullptr; // crash early
1005 }
1006
1007 #undef RETURN_STRING
1008
1009 } // 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