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

Side by Side Diff: content/common/gpu/media/android_video_decode_accelerator.cc

Issue 1560983002: Fix MP4 mid-stream resolution changes for MSE on android spitzer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase + TODO comment in ResetCodecState Created 4 years, 11 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "content/common/gpu/media/android_video_decode_accelerator.h" 5 #include "content/common/gpu/media/android_video_decode_accelerator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/android/build_info.h"
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
14 #include "base/trace_event/trace_event.h" 15 #include "base/trace_event/trace_event.h"
15 #include "content/common/gpu/gpu_channel.h" 16 #include "content/common/gpu/gpu_channel.h"
16 #include "content/common/gpu/media/android_copying_backing_strategy.h" 17 #include "content/common/gpu/media/android_copying_backing_strategy.h"
17 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h " 18 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h "
18 #include "content/common/gpu/media/avda_return_on_failure.h" 19 #include "content/common/gpu/media/avda_return_on_failure.h"
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 347 }
347 348
348 bool eos = false; 349 bool eos = false;
349 base::TimeDelta presentation_timestamp; 350 base::TimeDelta presentation_timestamp;
350 int32_t buf_index = 0; 351 int32_t buf_index = 0;
351 bool should_try_again = false; 352 bool should_try_again = false;
352 do { 353 do {
353 size_t offset = 0; 354 size_t offset = 0;
354 size_t size = 0; 355 size_t size = 0;
355 356
356 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutputBuffer"); 357 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput");
357 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 358 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
358 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, 359 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp,
359 &eos, NULL); 360 &eos, NULL);
360 TRACE_EVENT_END2("media", "AVDA::DequeueOutputBuffer", "status", status, 361 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status,
361 "presentation_timestamp (ms)", 362 "presentation_timestamp (ms)",
362 presentation_timestamp.InMilliseconds()); 363 presentation_timestamp.InMilliseconds());
363 364
364 DVLOG(3) << "AVDA::DequeueOutputBuffer: pts:" << presentation_timestamp 365 DVLOG(3) << "AVDA::DequeueOutput: pts:" << presentation_timestamp
365 << " buf_index:" << buf_index << " offset:" << offset 366 << " buf_index:" << buf_index << " offset:" << offset
366 << " size:" << size << " eos:" << eos; 367 << " size:" << size << " eos:" << eos;
367 368
368 switch (status) { 369 switch (status) {
369 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 370 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
370 case media::MEDIA_CODEC_ERROR: 371 case media::MEDIA_CODEC_ERROR:
371 return false; 372 return false;
372 373
373 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { 374 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: {
374 int32_t width, height; 375 int32_t width, height;
375 media_codec_->GetOutputFormat(&width, &height); 376 media_codec_->GetOutputFormat(&width, &height);
376 377
377 if (!picturebuffers_requested_) { 378 if (!picturebuffers_requested_) {
378 picturebuffers_requested_ = true; 379 picturebuffers_requested_ = true;
379 size_ = gfx::Size(width, height); 380 size_ = gfx::Size(width, height);
380 base::MessageLoop::current()->PostTask( 381 base::MessageLoop::current()->PostTask(
381 FROM_HERE, 382 FROM_HERE,
382 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, 383 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers,
383 weak_this_factory_.GetWeakPtr())); 384 weak_this_factory_.GetWeakPtr()));
384 } else { 385 } else {
385 // Dynamic resolution change support is not specified by the Android 386 // Dynamic resolution change support is not specified by the Android
386 // platform at and before JB-MR1, so it's not possible to smoothly 387 // platform at and before JB-MR1, so it's not possible to smoothly
387 // continue playback at this point. Instead, error out immediately, 388 // continue playback at this point. Instead, error out immediately,
388 // expecting clients to Reset() as appropriate to avoid this. 389 // expecting clients to Flush() or Reset() as appropriate to avoid
389 // b/7093648 390 // this. b/7093648
390 RETURN_ON_FAILURE(this, size_ == gfx::Size(width, height), 391 RETURN_ON_FAILURE(this, size_ == gfx::Size(width, height),
391 "Dynamic resolution change is not supported.", 392 "Dynamic resolution change is not supported.",
392 PLATFORM_FAILURE, false); 393 PLATFORM_FAILURE, false);
393 } 394 }
394 return false; 395 return false;
395 } 396 }
396 397
397 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: 398 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
398 break; 399 break;
399 400
(...skipping 13 matching lines...) Expand all
413 // corresponding output frame. 414 // corresponding output frame.
414 415
415 // However MediaCodecBridge uses timestamp correction and provides 416 // However MediaCodecBridge uses timestamp correction and provides
416 // non-decreasing timestamp sequence, which might result in timestamp 417 // non-decreasing timestamp sequence, which might result in timestamp
417 // duplicates. Discard the frame if we cannot get corresponding buffer id. 418 // duplicates. Discard the frame if we cannot get corresponding buffer id.
418 419
419 // Get the bitstream buffer id from the timestamp. 420 // Get the bitstream buffer id from the timestamp.
420 auto it = eos ? bitstream_buffers_in_decoder_.end() 421 auto it = eos ? bitstream_buffers_in_decoder_.end()
421 : bitstream_buffers_in_decoder_.find(presentation_timestamp); 422 : bitstream_buffers_in_decoder_.find(presentation_timestamp);
422 423
423 if (it == bitstream_buffers_in_decoder_.end()) { 424 if (eos) {
424 media_codec_->ReleaseOutputBuffer(buf_index, false); 425 DVLOG(3) << "AVDA::DequeueOutput: Resetting output state after EOS";
426 ResetCodecState();
427
425 base::MessageLoop::current()->PostTask( 428 base::MessageLoop::current()->PostTask(
426 FROM_HERE, 429 FROM_HERE,
427 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, 430 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone,
428 weak_this_factory_.GetWeakPtr())); 431 weak_this_factory_.GetWeakPtr()));
429 } else { 432 } else if (it != bitstream_buffers_in_decoder_.end()) {
430 const int32_t bitstream_buffer_id = it->second; 433 const int32_t bitstream_buffer_id = it->second;
431 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(), 434 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(),
432 ++it); 435 ++it);
433 SendCurrentSurfaceToClient(buf_index, bitstream_buffer_id); 436 SendCurrentSurfaceToClient(buf_index, bitstream_buffer_id);
434 437
435 // If we decoded a frame this time, then try for another. 438 // If we decoded a frame this time, then try for another.
436 should_try_again = true; 439 should_try_again = true;
437 440
438 // Removes ids former or equal than the id from decoder. Note that 441 // Removes ids former or equal than the id from decoder. Note that
439 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder 442 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder
440 // because of frame reordering issue. We just maintain this roughly and use 443 // because of frame reordering issue. We just maintain this roughly and use
441 // for the throttling purpose. 444 // for the throttling purpose.
442 for (auto bitstream_it = bitstreams_notified_in_advance_.begin(); 445 for (auto bitstream_it = bitstreams_notified_in_advance_.begin();
443 bitstream_it != bitstreams_notified_in_advance_.end(); 446 bitstream_it != bitstreams_notified_in_advance_.end();
444 ++bitstream_it) { 447 ++bitstream_it) {
445 if (*bitstream_it == bitstream_buffer_id) { 448 if (*bitstream_it == bitstream_buffer_id) {
446 bitstreams_notified_in_advance_.erase( 449 bitstreams_notified_in_advance_.erase(
447 bitstreams_notified_in_advance_.begin(), ++bitstream_it); 450 bitstreams_notified_in_advance_.begin(), ++bitstream_it);
448 break; 451 break;
449 } 452 }
450 } 453 }
454 } else {
455 DVLOG(3) << "AVDA::DequeueOutput: Releasing buffer with unexpected PTS: "
456 << presentation_timestamp;
457 media_codec_->ReleaseOutputBuffer(buf_index, false);
458 should_try_again = true;
451 } 459 }
452 460
453 return should_try_again; 461 return should_try_again;
454 } 462 }
455 463
456 void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient( 464 void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient(
457 int32_t codec_buffer_index, 465 int32_t codec_buffer_index,
458 int32_t bitstream_id) { 466 int32_t bitstream_id) {
459 DCHECK(thread_checker_.CalledOnValidThread()); 467 DCHECK(thread_checker_.CalledOnValidThread());
460 DCHECK_NE(bitstream_id, -1); 468 DCHECK_NE(bitstream_id, -1);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( 591 media_codec_.reset(media::VideoCodecBridge::CreateDecoder(
584 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL)); 592 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL));
585 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); 593 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_);
586 if (!media_codec_) 594 if (!media_codec_)
587 return false; 595 return false;
588 596
589 ManageTimer(true); 597 ManageTimer(true);
590 return true; 598 return true;
591 } 599 }
592 600
601 void AndroidVideoDecodeAccelerator::ResetCodecState() {
602 // TODO(chcunningham): This will likely dismiss a handful of decoded frames
603 // that have not yet been drawn and returned to us for re-use. Consider
604 // a more complicated design that would wait for these to be drawn before
605 // dismissing.
606 for (const auto& it : output_picture_buffers_) {
607 strategy_->DismissOnePictureBuffer(it.second);
608 client_->DismissPictureBuffer(it.first);
609 dismissed_picture_ids_.insert(it.first);
610 }
611 output_picture_buffers_.clear();
612 std::queue<int32_t> empty;
613 std::swap(free_picture_ids_, empty);
614 CHECK(free_picture_ids_.empty());
615 picturebuffers_requested_ = false;
616 bitstream_buffers_in_decoder_.clear();
617
618 // When codec is not in error state we can quickly reset (internally calls
619 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs
620 // (b/8125974, b/8347958) so we must stop() and reconfigure MediaCodec. The
621 // full reconfigure is much slower and may cause visible freezing if done
622 // mid-stream.
623 if (state_ == NO_ERROR &&
624 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) {
625 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush).";
626 media_codec_->Reset();
627 } else {
628 DVLOG(3) << __FUNCTION__
629 << " Doing slow MediaCodec reset (stop/re-configure).";
630 io_timer_.Stop();
631 media_codec_->Stop();
632 ConfigureMediaCodec();
633 state_ = NO_ERROR;
634 }
635 }
636
593 void AndroidVideoDecodeAccelerator::Reset() { 637 void AndroidVideoDecodeAccelerator::Reset() {
594 DCHECK(thread_checker_.CalledOnValidThread()); 638 DCHECK(thread_checker_.CalledOnValidThread());
595 TRACE_EVENT0("media", "AVDA::Reset"); 639 TRACE_EVENT0("media", "AVDA::Reset");
596 640
597 while (!pending_bitstream_buffers_.empty()) { 641 while (!pending_bitstream_buffers_.empty()) {
598 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().first.id(); 642 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().first.id();
599 pending_bitstream_buffers_.pop(); 643 pending_bitstream_buffers_.pop();
600 644
601 if (bitstream_buffer_id != -1) { 645 if (bitstream_buffer_id != -1) {
602 base::MessageLoop::current()->PostTask( 646 base::MessageLoop::current()->PostTask(
603 FROM_HERE, 647 FROM_HERE,
604 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, 648 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
605 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); 649 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id));
606 } 650 }
607 } 651 }
608 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); 652 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0);
609 bitstreams_notified_in_advance_.clear(); 653 bitstreams_notified_in_advance_.clear();
610 654
611 for (OutputBufferMap::iterator it = output_picture_buffers_.begin(); 655 ResetCodecState();
612 it != output_picture_buffers_.end();
613 ++it) {
614 strategy_->DismissOnePictureBuffer(it->second);
615 client_->DismissPictureBuffer(it->first);
616 dismissed_picture_ids_.insert(it->first);
617 }
618 output_picture_buffers_.clear();
619 std::queue<int32_t> empty;
620 std::swap(free_picture_ids_, empty);
621 CHECK(free_picture_ids_.empty());
622 picturebuffers_requested_ = false;
623 bitstream_buffers_in_decoder_.clear();
624
625 // On some devices, and up to at least JB-MR1,
626 // - flush() can fail after EOS (b/8125974); and
627 // - mid-stream resolution change is unsupported (b/7093648).
628 // To cope with these facts, we always stop & restart the codec on Reset().
629 io_timer_.Stop();
630 media_codec_->Stop();
631 ConfigureMediaCodec();
632 state_ = NO_ERROR;
633 656
634 base::MessageLoop::current()->PostTask( 657 base::MessageLoop::current()->PostTask(
635 FROM_HERE, 658 FROM_HERE,
636 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, 659 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
637 weak_this_factory_.GetWeakPtr())); 660 weak_this_factory_.GetWeakPtr()));
638 } 661 }
639 662
640 void AndroidVideoDecodeAccelerator::Destroy() { 663 void AndroidVideoDecodeAccelerator::Destroy() {
641 DCHECK(thread_checker_.CalledOnValidThread()); 664 DCHECK(thread_checker_.CalledOnValidThread());
642 665
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 802
780 if (UseDeferredRenderingStrategy()) { 803 if (UseDeferredRenderingStrategy()) {
781 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: 804 capabilities.flags = media::VideoDecodeAccelerator::Capabilities::
782 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; 805 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
783 } 806 }
784 807
785 return capabilities; 808 return capabilities;
786 } 809 }
787 810
788 } // namespace content 811 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/android_video_decode_accelerator.h ('k') | media/filters/gpu_video_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698