| OLD | NEW |
| 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/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/callback_helpers.h" |
| 13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 14 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
| 18 #include "base/task_runner_util.h" | 19 #include "base/task_runner_util.h" |
| 19 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
| 20 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
| 21 #include "content/common/gpu/media/android_copying_backing_strategy.h" | 22 #include "content/common/gpu/media/android_copying_backing_strategy.h" |
| 22 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" | 23 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 303 |
| 303 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 304 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
| 304 const MakeGLContextCurrentCallback& make_context_current_cb, | 305 const MakeGLContextCurrentCallback& make_context_current_cb, |
| 305 const GetGLES2DecoderCallback& get_gles2_decoder_cb) | 306 const GetGLES2DecoderCallback& get_gles2_decoder_cb) |
| 306 : client_(NULL), | 307 : client_(NULL), |
| 307 make_context_current_cb_(make_context_current_cb), | 308 make_context_current_cb_(make_context_current_cb), |
| 308 get_gles2_decoder_cb_(get_gles2_decoder_cb), | 309 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
| 309 is_encrypted_(false), | 310 is_encrypted_(false), |
| 310 state_(NO_ERROR), | 311 state_(NO_ERROR), |
| 311 picturebuffers_requested_(false), | 312 picturebuffers_requested_(false), |
| 313 drain_type_(DRAIN_TYPE_NONE), |
| 312 media_drm_bridge_cdm_context_(nullptr), | 314 media_drm_bridge_cdm_context_(nullptr), |
| 313 cdm_registration_id_(0), | 315 cdm_registration_id_(0), |
| 314 pending_input_buf_index_(-1), | 316 pending_input_buf_index_(-1), |
| 315 error_sequence_token_(0), | 317 error_sequence_token_(0), |
| 316 defer_errors_(false), | 318 defer_errors_(false), |
| 317 deferred_initialization_pending_(false), | 319 deferred_initialization_pending_(false), |
| 318 weak_this_factory_(this) {} | 320 weak_this_factory_(this) {} |
| 319 | 321 |
| 320 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 322 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 321 DCHECK(thread_checker_.CalledOnValidThread()); | 323 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 | 490 |
| 489 NOTIMPLEMENTED(); | 491 NOTIMPLEMENTED(); |
| 490 NotifyInitializationComplete(false); | 492 NotifyInitializationComplete(false); |
| 491 | 493 |
| 492 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 494 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 493 } | 495 } |
| 494 | 496 |
| 495 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { | 497 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { |
| 496 DCHECK(thread_checker_.CalledOnValidThread()); | 498 DCHECK(thread_checker_.CalledOnValidThread()); |
| 497 TRACE_EVENT0("media", "AVDA::DoIOTask"); | 499 TRACE_EVENT0("media", "AVDA::DoIOTask"); |
| 498 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) { | 500 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) |
| 499 return; | 501 return; |
| 500 } | |
| 501 | 502 |
| 502 bool did_work = QueueInput(); | 503 strategy_->MaybeRenderEarly(); |
| 503 while (DequeueOutput()) | 504 bool did_work = false, did_input = false, did_output = false; |
| 504 did_work = true; | 505 do { |
| 506 did_input = QueueInput(); |
| 507 did_output = DequeueOutput(); |
| 508 if (did_input || did_output) |
| 509 did_work = true; |
| 510 } while (did_input || did_output); |
| 505 | 511 |
| 506 ManageTimer(did_work || start_timer); | 512 ManageTimer(did_work || start_timer); |
| 507 } | 513 } |
| 508 | 514 |
| 509 bool AndroidVideoDecodeAccelerator::QueueInput() { | 515 bool AndroidVideoDecodeAccelerator::QueueInput() { |
| 510 DCHECK(thread_checker_.CalledOnValidThread()); | 516 DCHECK(thread_checker_.CalledOnValidThread()); |
| 511 TRACE_EVENT0("media", "AVDA::QueueInput"); | 517 TRACE_EVENT0("media", "AVDA::QueueInput"); |
| 512 base::AutoReset<bool> auto_reset(&defer_errors_, true); | 518 base::AutoReset<bool> auto_reset(&defer_errors_, true); |
| 513 if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance) | 519 if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance) |
| 514 return false; | 520 return false; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 541 | 547 |
| 542 DCHECK_NE(input_buf_index, -1); | 548 DCHECK_NE(input_buf_index, -1); |
| 543 | 549 |
| 544 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); | 550 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); |
| 545 | 551 |
| 546 if (bitstream_buffer.id() == -1) { | 552 if (bitstream_buffer.id() == -1) { |
| 547 pending_bitstream_buffers_.pop(); | 553 pending_bitstream_buffers_.pop(); |
| 548 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 554 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| 549 pending_bitstream_buffers_.size()); | 555 pending_bitstream_buffers_.size()); |
| 550 | 556 |
| 551 DCHECK_NE(state_, ERROR); | |
| 552 state_ = WAITING_FOR_EOS; | |
| 553 media_codec_->QueueEOS(input_buf_index); | 557 media_codec_->QueueEOS(input_buf_index); |
| 554 return true; | 558 return true; |
| 555 } | 559 } |
| 556 | 560 |
| 557 scoped_ptr<SharedMemoryRegion> shm; | 561 scoped_ptr<SharedMemoryRegion> shm; |
| 558 | 562 |
| 559 if (pending_input_buf_index_ == -1) { | 563 if (pending_input_buf_index_ == -1) { |
| 560 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued | 564 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued |
| 561 // from MediaCodec, filled with data and bitstream_buffer.handle() is | 565 // from MediaCodec, filled with data and bitstream_buffer.handle() is |
| 562 // closed. | 566 // closed. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); | 665 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); |
| 662 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 666 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
| 663 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, | 667 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, |
| 664 &eos, NULL); | 668 &eos, NULL); |
| 665 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, | 669 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, |
| 666 "presentation_timestamp (ms)", | 670 "presentation_timestamp (ms)", |
| 667 presentation_timestamp.InMilliseconds()); | 671 presentation_timestamp.InMilliseconds()); |
| 668 | 672 |
| 669 switch (status) { | 673 switch (status) { |
| 670 case media::MEDIA_CODEC_ERROR: | 674 case media::MEDIA_CODEC_ERROR: |
| 671 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | 675 // Do not post an error if we are draining for reset and destroy. |
| 676 // Instead, run the drain completion task. |
| 677 if (IsDrainingForResetOrDestroy()) { |
| 678 DVLOG(1) << __FUNCTION__ << ": error while codec draining"; |
| 679 state_ = ERROR; |
| 680 OnDrainCompleted(); |
| 681 } else { |
| 682 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); |
| 683 } |
| 672 return false; | 684 return false; |
| 673 | 685 |
| 674 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 686 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 675 return false; | 687 return false; |
| 676 | 688 |
| 677 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 689 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 690 // An OUTPUT_FORMAT_CHANGED is not reported after flush() if the frame |
| 691 // size does not change. Therefore we have to keep track on the format |
| 692 // even if draining, unless we are draining for destroy. |
| 693 if (drain_type_ == DRAIN_FOR_DESTROY) |
| 694 return true; // ignore |
| 695 |
| 678 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { | 696 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { |
| 679 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); | 697 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); |
| 680 return false; | 698 return false; |
| 681 } | 699 } |
| 700 |
| 682 DVLOG(3) << __FUNCTION__ | 701 DVLOG(3) << __FUNCTION__ |
| 683 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); | 702 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); |
| 684 | 703 |
| 685 // Don't request picture buffers if we already have some. This avoids | 704 // Don't request picture buffers if we already have some. This avoids |
| 686 // having to dismiss the existing buffers which may actively reference | 705 // having to dismiss the existing buffers which may actively reference |
| 687 // decoded images. Breaking their connection to the decoded image will | 706 // decoded images. Breaking their connection to the decoded image will |
| 688 // cause rendering of black frames. Instead, we let the existing | 707 // cause rendering of black frames. Instead, we let the existing |
| 689 // PictureBuffers live on and we simply update their size the next time | 708 // PictureBuffers live on and we simply update their size the next time |
| 690 // they're attachted to an image of the new resolution. See the | 709 // they're attachted to an image of the new resolution. See the |
| 691 // size update in |SendDecodedFrameToClient| and https://crbug/587994. | 710 // size update in |SendDecodedFrameToClient| and https://crbug/587994. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 711 << " size:" << size << " eos:" << eos; | 730 << " size:" << size << " eos:" << eos; |
| 712 break; | 731 break; |
| 713 | 732 |
| 714 default: | 733 default: |
| 715 NOTREACHED(); | 734 NOTREACHED(); |
| 716 break; | 735 break; |
| 717 } | 736 } |
| 718 } while (buf_index < 0); | 737 } while (buf_index < 0); |
| 719 | 738 |
| 720 if (eos) { | 739 if (eos) { |
| 721 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; | 740 OnDrainCompleted(); |
| 741 return false; |
| 742 } |
| 722 | 743 |
| 723 // If we were waiting for an EOS, clear the state and reset the MediaCodec | 744 if (IsDrainingForResetOrDestroy()) { |
| 724 // as normal. Otherwise, enter the ERROR state which will force destruction | 745 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 725 // of MediaCodec during ResetCodecState(). | 746 return true; |
| 726 // | |
| 727 // Some Android platforms seem to send an EOS buffer even when we're not | |
| 728 // expecting it. In this case, destroy and reset the codec but don't notify | |
| 729 // flush done since it violates the state machine. http://crbug.com/585959. | |
| 730 const bool was_waiting_for_eos = state_ == WAITING_FOR_EOS; | |
| 731 state_ = was_waiting_for_eos ? NO_ERROR : ERROR; | |
| 732 | |
| 733 ResetCodecState(); | |
| 734 // |media_codec_| might still be null. | |
| 735 if (was_waiting_for_eos) { | |
| 736 base::MessageLoop::current()->PostTask( | |
| 737 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | |
| 738 weak_this_factory_.GetWeakPtr())); | |
| 739 } | |
| 740 return false; | |
| 741 } | 747 } |
| 742 | 748 |
| 743 if (!picturebuffers_requested_) { | 749 if (!picturebuffers_requested_) { |
| 744 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED | 750 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED |
| 745 // message, then we might not have any picture buffers to use. This | 751 // message, then we might not have any picture buffers to use. This |
| 746 // isn't supposed to happen (see EncodeDecodeTest.java#617). | 752 // isn't supposed to happen (see EncodeDecodeTest.java#617). |
| 747 // Log a metric to see how common this is. | 753 // Log a metric to see how common this is. |
| 748 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); | 754 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); |
| 749 media_codec_->ReleaseOutputBuffer(buf_index, false); | 755 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 750 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); | 756 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 } | 819 } |
| 814 | 820 |
| 815 bool size_changed = false; | 821 bool size_changed = false; |
| 816 if (i->second.size() != size_) { | 822 if (i->second.size() != size_) { |
| 817 // Size may have changed due to resolution change since the last time this | 823 // Size may have changed due to resolution change since the last time this |
| 818 // PictureBuffer was used. | 824 // PictureBuffer was used. |
| 819 strategy_->UpdatePictureBufferSize(&i->second, size_); | 825 strategy_->UpdatePictureBufferSize(&i->second, size_); |
| 820 size_changed = true; | 826 size_changed = true; |
| 821 } | 827 } |
| 822 | 828 |
| 823 // Connect the PictureBuffer to the decoded frame, via whatever | |
| 824 // mechanism the strategy likes. | |
| 825 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); | |
| 826 | |
| 827 const bool allow_overlay = strategy_->ArePicturesOverlayable(); | 829 const bool allow_overlay = strategy_->ArePicturesOverlayable(); |
| 828 | |
| 829 media::Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_), | 830 media::Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_), |
| 830 allow_overlay); | 831 allow_overlay); |
| 831 picture.set_size_changed(size_changed); | 832 picture.set_size_changed(size_changed); |
| 832 | 833 |
| 833 base::MessageLoop::current()->PostTask( | 834 // Notify picture ready before calling UseCodecBufferForPictureBuffer() since |
| 834 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 835 // that process may be slow and shouldn't delay delivery of the frame to the |
| 835 weak_this_factory_.GetWeakPtr(), picture)); | 836 // renderer. The picture is only used on the same thread as this method is |
| 837 // called, so it is safe to do this. |
| 838 NotifyPictureReady(picture); |
| 839 |
| 840 // Connect the PictureBuffer to the decoded frame, via whatever mechanism the |
| 841 // strategy likes. |
| 842 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); |
| 836 } | 843 } |
| 837 | 844 |
| 838 void AndroidVideoDecodeAccelerator::Decode( | 845 void AndroidVideoDecodeAccelerator::Decode( |
| 839 const media::BitstreamBuffer& bitstream_buffer) { | 846 const media::BitstreamBuffer& bitstream_buffer) { |
| 840 DCHECK(thread_checker_.CalledOnValidThread()); | 847 DCHECK(thread_checker_.CalledOnValidThread()); |
| 841 | 848 |
| 842 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { | 849 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { |
| 843 DecodeBuffer(bitstream_buffer); | 850 DecodeBuffer(bitstream_buffer); |
| 844 return; | 851 return; |
| 845 } | 852 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 861 void AndroidVideoDecodeAccelerator::DecodeBuffer( | 868 void AndroidVideoDecodeAccelerator::DecodeBuffer( |
| 862 const media::BitstreamBuffer& bitstream_buffer) { | 869 const media::BitstreamBuffer& bitstream_buffer) { |
| 863 pending_bitstream_buffers_.push(bitstream_buffer); | 870 pending_bitstream_buffers_.push(bitstream_buffer); |
| 864 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 871 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| 865 pending_bitstream_buffers_.size()); | 872 pending_bitstream_buffers_.size()); |
| 866 | 873 |
| 867 DoIOTask(true); | 874 DoIOTask(true); |
| 868 } | 875 } |
| 869 | 876 |
| 870 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 877 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
| 871 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, | 878 if (client_) { |
| 872 strategy_->GetPictureBufferSize(), | 879 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, |
| 873 strategy_->GetTextureTarget()); | 880 strategy_->GetPictureBufferSize(), |
| 881 strategy_->GetTextureTarget()); |
| 882 } |
| 874 } | 883 } |
| 875 | 884 |
| 876 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 885 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
| 877 const std::vector<media::PictureBuffer>& buffers) { | 886 const std::vector<media::PictureBuffer>& buffers) { |
| 878 DCHECK(thread_checker_.CalledOnValidThread()); | 887 DCHECK(thread_checker_.CalledOnValidThread()); |
| 879 DCHECK(output_picture_buffers_.empty()); | 888 DCHECK(output_picture_buffers_.empty()); |
| 880 DCHECK(free_picture_ids_.empty()); | 889 DCHECK(free_picture_ids_.empty()); |
| 881 | 890 |
| 882 if (buffers.size() < kNumPictureBuffers) { | 891 if (buffers.size() < kNumPictureBuffers) { |
| 883 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); | 892 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 POST_ERROR(PLATFORM_FAILURE, "Can't find PictureBuffer id " | 928 POST_ERROR(PLATFORM_FAILURE, "Can't find PictureBuffer id " |
| 920 << picture_buffer_id); | 929 << picture_buffer_id); |
| 921 return; | 930 return; |
| 922 } | 931 } |
| 923 | 932 |
| 924 strategy_->ReuseOnePictureBuffer(i->second); | 933 strategy_->ReuseOnePictureBuffer(i->second); |
| 925 DoIOTask(true); | 934 DoIOTask(true); |
| 926 } | 935 } |
| 927 | 936 |
| 928 void AndroidVideoDecodeAccelerator::Flush() { | 937 void AndroidVideoDecodeAccelerator::Flush() { |
| 938 DVLOG(1) << __FUNCTION__; |
| 929 DCHECK(thread_checker_.CalledOnValidThread()); | 939 DCHECK(thread_checker_.CalledOnValidThread()); |
| 930 | 940 |
| 931 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 941 StartCodecDrain(DRAIN_FOR_FLUSH); |
| 932 } | 942 } |
| 933 | 943 |
| 934 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { | 944 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { |
| 935 DCHECK(thread_checker_.CalledOnValidThread()); | 945 DCHECK(thread_checker_.CalledOnValidThread()); |
| 936 | 946 |
| 937 // It's probably okay just to return here, since the codec will be configured | 947 // It's probably okay just to return here, since the codec will be configured |
| 938 // asynchronously. It's unclear that any state for the new request could | 948 // asynchronously. It's unclear that any state for the new request could |
| 939 // be different, unless somebody modifies |codec_config_| while we're already | 949 // be different, unless somebody modifies |codec_config_| while we're already |
| 940 // waiting for a codec. One shouldn't do that for thread safety. | 950 // waiting for a codec. One shouldn't do that for thread safety. |
| 941 DCHECK_NE(state_, WAITING_FOR_CODEC); | 951 DCHECK_NE(state_, WAITING_FOR_CODEC); |
| 942 | 952 |
| 943 state_ = WAITING_FOR_CODEC; | 953 state_ = WAITING_FOR_CODEC; |
| 944 | 954 |
| 945 // Tell the strategy that we're changing codecs. The codec itself could be | 955 // Tell the strategy that we're changing codecs. The codec itself could be |
| 946 // used normally, since we don't replace it until we're back on the main | 956 // used normally, since we don't replace it until we're back on the main |
| 947 // thread. However, if we're using an output surface, then the incoming codec | 957 // thread. However, if we're using an output surface, then the incoming codec |
| 948 // might access that surface while the main thread is drawing. Telling the | 958 // might access that surface while the main thread is drawing. Telling the |
| 949 // strategy to forget the codec avoids this. | 959 // strategy to forget the codec avoids this. |
| 950 if (media_codec_) { | 960 if (media_codec_) { |
| 951 media_codec_.reset(); | 961 media_codec_.reset(); |
| 952 strategy_->CodecChanged(nullptr, output_picture_buffers_); | 962 strategy_->CodecChanged(nullptr); |
| 953 } | 963 } |
| 954 | 964 |
| 955 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 965 scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| 956 g_avda_timer.Pointer()->ConstructionTaskRunner(); | 966 g_avda_timer.Pointer()->ConstructionTaskRunner(); |
| 957 CHECK(task_runner); | 967 CHECK(task_runner); |
| 958 | 968 |
| 959 base::PostTaskAndReplyWithResult( | 969 base::PostTaskAndReplyWithResult( |
| 960 task_runner.get(), FROM_HERE, | 970 task_runner.get(), FROM_HERE, |
| 961 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, | 971 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, |
| 962 codec_config_), | 972 codec_config_), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 void AndroidVideoDecodeAccelerator::OnCodecConfigured( | 1004 void AndroidVideoDecodeAccelerator::OnCodecConfigured( |
| 995 scoped_ptr<media::VideoCodecBridge> media_codec) { | 1005 scoped_ptr<media::VideoCodecBridge> media_codec) { |
| 996 DCHECK(thread_checker_.CalledOnValidThread()); | 1006 DCHECK(thread_checker_.CalledOnValidThread()); |
| 997 DCHECK_EQ(state_, WAITING_FOR_CODEC); | 1007 DCHECK_EQ(state_, WAITING_FOR_CODEC); |
| 998 | 1008 |
| 999 media_codec_ = std::move(media_codec); | 1009 media_codec_ = std::move(media_codec); |
| 1000 | 1010 |
| 1001 // Record one instance of the codec being initialized. | 1011 // Record one instance of the codec being initialized. |
| 1002 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); | 1012 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); |
| 1003 | 1013 |
| 1004 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); | 1014 strategy_->CodecChanged(media_codec_.get()); |
| 1005 | 1015 |
| 1006 // If we are supposed to notify that initialization is complete, then do so | 1016 // If we are supposed to notify that initialization is complete, then do so |
| 1007 // now. Otherwise, this is a reconfiguration. | 1017 // now. Otherwise, this is a reconfiguration. |
| 1008 if (deferred_initialization_pending_) { | 1018 if (deferred_initialization_pending_) { |
| 1009 NotifyInitializationComplete(!!media_codec_); | 1019 NotifyInitializationComplete(!!media_codec_); |
| 1010 deferred_initialization_pending_ = false; | 1020 deferred_initialization_pending_ = false; |
| 1011 } | 1021 } |
| 1012 | 1022 |
| 1013 if (!media_codec_) { | 1023 if (!media_codec_) { |
| 1014 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); | 1024 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); |
| 1015 return; | 1025 return; |
| 1016 } | 1026 } |
| 1017 | 1027 |
| 1018 state_ = NO_ERROR; | 1028 state_ = NO_ERROR; |
| 1019 | 1029 |
| 1020 ManageTimer(true); | 1030 ManageTimer(true); |
| 1021 } | 1031 } |
| 1022 | 1032 |
| 1023 void AndroidVideoDecodeAccelerator::ResetCodecState() { | 1033 void AndroidVideoDecodeAccelerator::StartCodecDrain(DrainType drain_type) { |
| 1034 DVLOG(2) << __FUNCTION__ << " drain_type:" << drain_type; |
| 1035 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1036 |
| 1037 // We assume that DRAIN_FOR_FLUSH and DRAIN_FOR_RESET cannot come while |
| 1038 // another drain request is present, but DRAIN_FOR_DESTROY can. |
| 1039 DCHECK_NE(drain_type, DRAIN_TYPE_NONE); |
| 1040 DCHECK(drain_type_ == DRAIN_TYPE_NONE || drain_type == DRAIN_FOR_DESTROY) |
| 1041 << "Unexpected StartCodecDrain() with drain type " << drain_type |
| 1042 << " while already draining with drain type " << drain_type_; |
| 1043 |
| 1044 const bool enqueue_eos = drain_type_ == DRAIN_TYPE_NONE; |
| 1045 drain_type_ = drain_type; |
| 1046 |
| 1047 if (enqueue_eos) |
| 1048 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
| 1049 } |
| 1050 |
| 1051 bool AndroidVideoDecodeAccelerator::IsDrainingForResetOrDestroy() const { |
| 1052 return drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY; |
| 1053 } |
| 1054 |
| 1055 void AndroidVideoDecodeAccelerator::OnDrainCompleted() { |
| 1056 DVLOG(2) << __FUNCTION__; |
| 1057 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1058 |
| 1059 // If we were waiting for an EOS, clear the state and reset the MediaCodec |
| 1060 // as normal. Otherwise, enter the ERROR state which will force destruction |
| 1061 // of MediaCodec during ResetCodecState(). |
| 1062 // |
| 1063 // Some Android platforms seem to send an EOS buffer even when we're not |
| 1064 // expecting it. In this case, destroy and reset the codec but don't notify |
| 1065 // flush done since it violates the state machine. http://crbug.com/585959. |
| 1066 |
| 1067 switch (drain_type_) { |
| 1068 case DRAIN_TYPE_NONE: |
| 1069 // Unexpected EOS. |
| 1070 state_ = ERROR; |
| 1071 ResetCodecState(base::Closure()); |
| 1072 break; |
| 1073 case DRAIN_FOR_FLUSH: |
| 1074 ResetCodecState(media::BindToCurrentLoop( |
| 1075 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 1076 weak_this_factory_.GetWeakPtr()))); |
| 1077 break; |
| 1078 case DRAIN_FOR_RESET: |
| 1079 ResetCodecState(media::BindToCurrentLoop( |
| 1080 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 1081 weak_this_factory_.GetWeakPtr()))); |
| 1082 break; |
| 1083 case DRAIN_FOR_DESTROY: |
| 1084 base::MessageLoop::current()->PostTask( |
| 1085 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::ActualDestroy, |
| 1086 weak_this_factory_.GetWeakPtr())); |
| 1087 break; |
| 1088 } |
| 1089 drain_type_ = DRAIN_TYPE_NONE; |
| 1090 } |
| 1091 |
| 1092 void AndroidVideoDecodeAccelerator::ResetCodecState( |
| 1093 const base::Closure& done_cb) { |
| 1024 DCHECK(thread_checker_.CalledOnValidThread()); | 1094 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1025 | 1095 |
| 1026 // If there is already a reset in flight, then that counts. This can really | 1096 // If there is already a reset in flight, then that counts. This can really |
| 1027 // only happen if somebody calls Reset. | 1097 // only happen if somebody calls Reset. |
| 1028 if (state_ == WAITING_FOR_CODEC) | 1098 if (state_ == WAITING_FOR_CODEC) { |
| 1099 if (!done_cb.is_null()) |
| 1100 done_cb.Run(); |
| 1029 return; | 1101 return; |
| 1102 } |
| 1030 | 1103 |
| 1031 bitstream_buffers_in_decoder_.clear(); | 1104 bitstream_buffers_in_decoder_.clear(); |
| 1032 | 1105 |
| 1033 if (pending_input_buf_index_ != -1) { | 1106 if (pending_input_buf_index_ != -1) { |
| 1034 // The data for that index exists in the input buffer, but corresponding | 1107 // The data for that index exists in the input buffer, but corresponding |
| 1035 // shm block been deleted. Check that it is safe to flush the coec, i.e. | 1108 // shm block been deleted. Check that it is safe to flush the coec, i.e. |
| 1036 // |pending_bitstream_buffers_| is empty. | 1109 // |pending_bitstream_buffers_| is empty. |
| 1037 // TODO(timav): keep shm block for that buffer and remove this restriction. | 1110 // TODO(timav): keep shm block for that buffer and remove this restriction. |
| 1038 DCHECK(pending_bitstream_buffers_.empty()); | 1111 DCHECK(pending_bitstream_buffers_.empty()); |
| 1039 pending_input_buf_index_ = -1; | 1112 pending_input_buf_index_ = -1; |
| 1040 } | 1113 } |
| 1041 | 1114 |
| 1042 if (state_ == WAITING_FOR_KEY) | 1115 const bool did_codec_error_happen = state_ == ERROR; |
| 1043 state_ = NO_ERROR; | 1116 state_ = NO_ERROR; |
| 1044 | 1117 |
| 1045 // We might increment error_sequence_token here to cancel any delayed errors, | 1118 // We might increment error_sequence_token here to cancel any delayed errors, |
| 1046 // but right now it's unclear that it's safe to do so. If we are in an error | 1119 // but right now it's unclear that it's safe to do so. If we are in an error |
| 1047 // state because of a codec error, then it would be okay. Otherwise, it's | 1120 // state because of a codec error, then it would be okay. Otherwise, it's |
| 1048 // less obvious that we are exiting the error state. Since deferred errors | 1121 // less obvious that we are exiting the error state. Since deferred errors |
| 1049 // are only intended for fullscreen transitions right now, we take the more | 1122 // are only intended for fullscreen transitions right now, we take the more |
| 1050 // conservative approach and let the errors post. | 1123 // conservative approach and let the errors post. |
| 1051 // TODO(liberato): revisit this once we sort out the error state a bit more. | 1124 // TODO(liberato): revisit this once we sort out the error state a bit more. |
| 1052 | 1125 |
| 1053 // When codec is not in error state we can quickly reset (internally calls | 1126 // When codec is not in error state we can quickly reset (internally calls |
| 1054 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs | 1127 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs |
| 1055 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new | 1128 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new |
| 1056 // one. The full reconfigure is much slower and may cause visible freezing if | 1129 // one. The full reconfigure is much slower and may cause visible freezing if |
| 1057 // done mid-stream. | 1130 // done mid-stream. |
| 1058 if (state_ == NO_ERROR && | 1131 if (!did_codec_error_happen && |
| 1059 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { | 1132 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { |
| 1060 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; | 1133 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; |
| 1061 media_codec_->Reset(); | 1134 media_codec_->Reset(); |
| 1062 // Since we just flushed all the output buffers, make sure that nothing is | 1135 // Since we just flushed all the output buffers, make sure that nothing is |
| 1063 // using them. | 1136 // using them. |
| 1064 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); | 1137 strategy_->CodecChanged(media_codec_.get()); |
| 1065 } else { | 1138 } else { |
| 1066 DVLOG(3) << __FUNCTION__ | 1139 DVLOG(3) << __FUNCTION__ |
| 1067 << " Deleting the MediaCodec and creating a new one."; | 1140 << " Deleting the MediaCodec and creating a new one."; |
| 1068 g_avda_timer.Pointer()->StopTimer(this); | 1141 g_avda_timer.Pointer()->StopTimer(this); |
| 1069 // Changing the codec will also notify the strategy to forget about any | 1142 // Changing the codec will also notify the strategy to forget about any |
| 1070 // output buffers it has currently. | 1143 // output buffers it has currently. |
| 1071 state_ = NO_ERROR; | |
| 1072 ConfigureMediaCodecAsynchronously(); | 1144 ConfigureMediaCodecAsynchronously(); |
| 1073 } | 1145 } |
| 1146 |
| 1147 if (!done_cb.is_null()) |
| 1148 done_cb.Run(); |
| 1074 } | 1149 } |
| 1075 | 1150 |
| 1076 void AndroidVideoDecodeAccelerator::Reset() { | 1151 void AndroidVideoDecodeAccelerator::Reset() { |
| 1152 DVLOG(1) << __FUNCTION__; |
| 1077 DCHECK(thread_checker_.CalledOnValidThread()); | 1153 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1078 TRACE_EVENT0("media", "AVDA::Reset"); | 1154 TRACE_EVENT0("media", "AVDA::Reset"); |
| 1079 | 1155 |
| 1080 while (!pending_bitstream_buffers_.empty()) { | 1156 while (!pending_bitstream_buffers_.empty()) { |
| 1081 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); | 1157 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); |
| 1082 pending_bitstream_buffers_.pop(); | 1158 pending_bitstream_buffers_.pop(); |
| 1083 | 1159 |
| 1084 if (bitstream_buffer_id != -1) { | 1160 if (bitstream_buffer_id != -1) { |
| 1085 base::MessageLoop::current()->PostTask( | 1161 base::MessageLoop::current()->PostTask( |
| 1086 FROM_HERE, | 1162 FROM_HERE, |
| 1087 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 1163 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 1088 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); | 1164 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); |
| 1089 } | 1165 } |
| 1090 } | 1166 } |
| 1091 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); | 1167 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); |
| 1092 bitstreams_notified_in_advance_.clear(); | 1168 bitstreams_notified_in_advance_.clear(); |
| 1093 | 1169 |
| 1094 // Any error that is waiting to post can be ignored. | 1170 // Any error that is waiting to post can be ignored. |
| 1095 error_sequence_token_++; | 1171 error_sequence_token_++; |
| 1096 | 1172 |
| 1097 ResetCodecState(); | 1173 DCHECK(strategy_); |
| 1174 strategy_->ReleaseCodecBuffers(output_picture_buffers_); |
| 1098 | 1175 |
| 1099 // Note that |media_codec_| might not yet be ready, but we can still post | 1176 // Some VP8 files require complete MediaCodec drain before we can call |
| 1100 // this anyway. | 1177 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. |
| 1101 base::MessageLoop::current()->PostTask( | 1178 if (media_codec_ && codec_config_->codec_ == media::kCodecVP8) { |
| 1102 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 1179 // Postpone ResetCodecState() after the drain. |
| 1103 weak_this_factory_.GetWeakPtr())); | 1180 StartCodecDrain(DRAIN_FOR_RESET); |
| 1181 } else { |
| 1182 ResetCodecState(media::BindToCurrentLoop( |
| 1183 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 1184 weak_this_factory_.GetWeakPtr()))); |
| 1185 } |
| 1104 } | 1186 } |
| 1105 | 1187 |
| 1106 void AndroidVideoDecodeAccelerator::Destroy() { | 1188 void AndroidVideoDecodeAccelerator::Destroy() { |
| 1189 DVLOG(1) << __FUNCTION__; |
| 1107 DCHECK(thread_checker_.CalledOnValidThread()); | 1190 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1108 | 1191 |
| 1109 bool have_context = make_context_current_cb_.Run(); | 1192 bool have_context = make_context_current_cb_.Run(); |
| 1110 if (!have_context) | 1193 if (!have_context) |
| 1111 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 1194 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
| 1112 | 1195 |
| 1113 if (strategy_) | 1196 if (strategy_) |
| 1114 strategy_->Cleanup(have_context, output_picture_buffers_); | 1197 strategy_->Cleanup(have_context, output_picture_buffers_); |
| 1115 | 1198 |
| 1116 // If we have an OnFrameAvailable handler, tell it that we're going away. | 1199 // If we have an OnFrameAvailable handler, tell it that we're going away. |
| 1117 if (on_frame_available_handler_) { | 1200 if (on_frame_available_handler_) { |
| 1118 on_frame_available_handler_->ClearOwner(); | 1201 on_frame_available_handler_->ClearOwner(); |
| 1119 on_frame_available_handler_ = nullptr; | 1202 on_frame_available_handler_ = nullptr; |
| 1120 } | 1203 } |
| 1121 | 1204 |
| 1205 client_ = nullptr; |
| 1206 |
| 1207 // Some VP8 files require complete MediaCodec drain before we can call |
| 1208 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. |
| 1209 if (media_codec_ && codec_config_->codec_ == media::kCodecVP8) { |
| 1210 // Clear pending_bitstream_buffers_. |
| 1211 while (!pending_bitstream_buffers_.empty()) |
| 1212 pending_bitstream_buffers_.pop(); |
| 1213 |
| 1214 // Postpone ActualDestroy after the drain. |
| 1215 StartCodecDrain(DRAIN_FOR_DESTROY); |
| 1216 } else { |
| 1217 ActualDestroy(); |
| 1218 } |
| 1219 } |
| 1220 |
| 1221 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
| 1222 DVLOG(1) << __FUNCTION__; |
| 1223 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1224 |
| 1122 // Note that async codec construction might still be in progress. In that | 1225 // Note that async codec construction might still be in progress. In that |
| 1123 // case, the codec will be deleted when it completes once we invalidate all | 1226 // case, the codec will be deleted when it completes once we invalidate all |
| 1124 // our weak refs. | 1227 // our weak refs. |
| 1125 weak_this_factory_.InvalidateWeakPtrs(); | 1228 weak_this_factory_.InvalidateWeakPtrs(); |
| 1126 if (media_codec_) { | 1229 if (media_codec_) { |
| 1127 g_avda_timer.Pointer()->StopTimer(this); | 1230 g_avda_timer.Pointer()->StopTimer(this); |
| 1128 media_codec_.reset(); | 1231 media_codec_.reset(); |
| 1129 } | 1232 } |
| 1130 delete this; | 1233 delete this; |
| 1131 } | 1234 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 void AndroidVideoDecodeAccelerator::OnKeyAdded() { | 1321 void AndroidVideoDecodeAccelerator::OnKeyAdded() { |
| 1219 DVLOG(1) << __FUNCTION__; | 1322 DVLOG(1) << __FUNCTION__; |
| 1220 | 1323 |
| 1221 if (state_ == WAITING_FOR_KEY) | 1324 if (state_ == WAITING_FOR_KEY) |
| 1222 state_ = NO_ERROR; | 1325 state_ = NO_ERROR; |
| 1223 | 1326 |
| 1224 DoIOTask(true); | 1327 DoIOTask(true); |
| 1225 } | 1328 } |
| 1226 | 1329 |
| 1227 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { | 1330 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { |
| 1228 client_->NotifyInitializationComplete(success); | 1331 if (client_) |
| 1332 client_->NotifyInitializationComplete(success); |
| 1229 } | 1333 } |
| 1230 | 1334 |
| 1231 void AndroidVideoDecodeAccelerator::NotifyPictureReady( | 1335 void AndroidVideoDecodeAccelerator::NotifyPictureReady( |
| 1232 const media::Picture& picture) { | 1336 const media::Picture& picture) { |
| 1233 client_->PictureReady(picture); | 1337 if (client_) |
| 1338 client_->PictureReady(picture); |
| 1234 } | 1339 } |
| 1235 | 1340 |
| 1236 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 1341 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
| 1237 int input_buffer_id) { | 1342 int input_buffer_id) { |
| 1238 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | 1343 if (client_) |
| 1344 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); |
| 1239 } | 1345 } |
| 1240 | 1346 |
| 1241 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { | 1347 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { |
| 1242 client_->NotifyFlushDone(); | 1348 if (client_) |
| 1349 client_->NotifyFlushDone(); |
| 1243 } | 1350 } |
| 1244 | 1351 |
| 1245 void AndroidVideoDecodeAccelerator::NotifyResetDone() { | 1352 void AndroidVideoDecodeAccelerator::NotifyResetDone() { |
| 1246 client_->NotifyResetDone(); | 1353 if (client_) |
| 1354 client_->NotifyResetDone(); |
| 1247 } | 1355 } |
| 1248 | 1356 |
| 1249 void AndroidVideoDecodeAccelerator::NotifyError( | 1357 void AndroidVideoDecodeAccelerator::NotifyError( |
| 1250 media::VideoDecodeAccelerator::Error error, | 1358 media::VideoDecodeAccelerator::Error error, |
| 1251 int token) { | 1359 int token) { |
| 1252 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token | 1360 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token |
| 1253 << " current: " << error_sequence_token_; | 1361 << " current: " << error_sequence_token_; |
| 1254 if (token != error_sequence_token_) | 1362 if (token != error_sequence_token_) |
| 1255 return; | 1363 return; |
| 1256 | 1364 |
| 1257 client_->NotifyError(error); | 1365 if (client_) |
| 1366 client_->NotifyError(error); |
| 1258 } | 1367 } |
| 1259 | 1368 |
| 1260 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { | 1369 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { |
| 1261 bool should_be_running = true; | 1370 bool should_be_running = true; |
| 1262 | 1371 |
| 1263 base::TimeTicks now = base::TimeTicks::Now(); | 1372 base::TimeTicks now = base::TimeTicks::Now(); |
| 1264 if (!did_work && !most_recent_work_.is_null()) { | 1373 if (!did_work && !most_recent_work_.is_null()) { |
| 1265 // Make sure that we have done work recently enough, else stop the timer. | 1374 // Make sure that we have done work recently enough, else stop the timer. |
| 1266 if (now - most_recent_work_ > IdleTimerTimeOut()) { | 1375 if (now - most_recent_work_ > IdleTimerTimeOut()) { |
| 1267 most_recent_work_ = base::TimeTicks(); | 1376 most_recent_work_ = base::TimeTicks(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1456 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| 1348 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1457 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
| 1349 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1458 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1350 } | 1459 } |
| 1351 } | 1460 } |
| 1352 | 1461 |
| 1353 return capabilities; | 1462 return capabilities; |
| 1354 } | 1463 } |
| 1355 | 1464 |
| 1356 } // namespace content | 1465 } // namespace content |
| OLD | NEW |