| 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" |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 cdm_registration_id_(0), | 168 cdm_registration_id_(0), |
| 169 pending_input_buf_index_(-1), | 169 pending_input_buf_index_(-1), |
| 170 error_sequence_token_(0), | 170 error_sequence_token_(0), |
| 171 defer_errors_(false), | 171 defer_errors_(false), |
| 172 weak_this_factory_(this) { | 172 weak_this_factory_(this) { |
| 173 if (UseDeferredRenderingStrategy()) { | 173 if (UseDeferredRenderingStrategy()) { |
| 174 // TODO(liberato, watk): Figure out what we want to do about zero copy for | 174 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 175 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | 175 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 176 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | 176 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); |
| 177 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | 177 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 178 strategy_.reset(new AndroidDeferredRenderingBackingStrategy()); | 178 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 179 } else { | 179 } else { |
| 180 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | 180 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 181 strategy_.reset(new AndroidCopyingBackingStrategy()); | 181 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 | 184 |
| 185 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 185 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 186 DCHECK(thread_checker_.CalledOnValidThread()); | 186 DCHECK(thread_checker_.CalledOnValidThread()); |
| 187 | 187 |
| 188 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 188 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 189 if (cdm_) { | 189 if (cdm_) { |
| 190 DCHECK(cdm_registration_id_); | 190 DCHECK(cdm_registration_id_); |
| 191 static_cast<media::MediaDrmBridge*>(cdm_.get()) | 191 static_cast<media::MediaDrmBridge*>(cdm_.get()) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 if (!make_context_current_.Run()) { | 232 if (!make_context_current_.Run()) { |
| 233 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 233 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
| 234 return false; | 234 return false; |
| 235 } | 235 } |
| 236 | 236 |
| 237 if (!gl_decoder_) { | 237 if (!gl_decoder_) { |
| 238 LOG(ERROR) << "Failed to get gles2 decoder instance."; | 238 LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| 241 | 241 |
| 242 strategy_->Initialize(this); | 242 surface_ = strategy_->Initialize(config.surface_id); |
| 243 if (surface_.IsEmpty()) { |
| 244 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
| 245 "Java surface is empty."; |
| 246 return false; |
| 247 } |
| 243 | 248 |
| 244 surface_texture_ = strategy_->CreateSurfaceTexture(); | 249 // TODO(watk,liberato): move this into the strategy. |
| 245 on_frame_available_handler_ = | 250 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 246 new OnFrameAvailableHandler(this, surface_texture_); | 251 strategy_->GetSurfaceTexture(); |
| 252 if (surface_texture) { |
| 253 on_frame_available_handler_ = |
| 254 new OnFrameAvailableHandler(this, surface_texture); |
| 255 } |
| 247 | 256 |
| 248 // For encrypted streams we postpone configuration until MediaCrypto is | 257 // For encrypted streams we postpone configuration until MediaCrypto is |
| 249 // available. | 258 // available. |
| 250 if (is_encrypted_) | 259 if (is_encrypted_) |
| 251 return true; | 260 return true; |
| 252 | 261 |
| 253 return ConfigureMediaCodec(); | 262 return ConfigureMediaCodec(); |
| 254 } | 263 } |
| 255 | 264 |
| 256 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { | 265 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 514 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, |
| 506 weak_this_factory_.GetWeakPtr())); | 515 weak_this_factory_.GetWeakPtr())); |
| 507 return false; | 516 return false; |
| 508 } | 517 } |
| 509 | 518 |
| 510 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 519 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
| 511 break; | 520 break; |
| 512 | 521 |
| 513 case media::MEDIA_CODEC_OK: | 522 case media::MEDIA_CODEC_OK: |
| 514 DCHECK_GE(buf_index, 0); | 523 DCHECK_GE(buf_index, 0); |
| 515 DVLOG(3) << "AVDA::DequeueOutput: pts:" << presentation_timestamp | 524 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp |
| 516 << " buf_index:" << buf_index << " offset:" << offset | 525 << " buf_index:" << buf_index << " offset:" << offset |
| 517 << " size:" << size << " eos:" << eos; | 526 << " size:" << size << " eos:" << eos; |
| 518 break; | 527 break; |
| 519 | 528 |
| 520 default: | 529 default: |
| 521 NOTREACHED(); | 530 NOTREACHED(); |
| 522 break; | 531 break; |
| 523 } | 532 } |
| 524 } while (buf_index < 0); | 533 } while (buf_index < 0); |
| 525 | 534 |
| 526 if (eos) { | 535 if (eos) { |
| 527 DVLOG(3) << "AVDA::DequeueOutput: Resetting codec state after EOS"; | 536 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; |
| 528 ResetCodecState(); | 537 ResetCodecState(); |
| 529 | 538 |
| 530 base::MessageLoop::current()->PostTask( | 539 base::MessageLoop::current()->PostTask( |
| 531 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | 540 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 532 weak_this_factory_.GetWeakPtr())); | 541 weak_this_factory_.GetWeakPtr())); |
| 533 return false; | 542 return false; |
| 534 } | 543 } |
| 535 | 544 |
| 536 // Get the bitstream buffer id from the timestamp. | 545 // Get the bitstream buffer id from the timestamp. |
| 537 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); | 546 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 554 bitstreams_notified_in_advance_.begin(), ++bitstream_it); | 563 bitstreams_notified_in_advance_.begin(), ++bitstream_it); |
| 555 break; | 564 break; |
| 556 } | 565 } |
| 557 } | 566 } |
| 558 } else { | 567 } else { |
| 559 // Normally we assume that the decoder makes at most one output frame for | 568 // Normally we assume that the decoder makes at most one output frame for |
| 560 // each distinct input timestamp. However MediaCodecBridge uses timestamp | 569 // each distinct input timestamp. However MediaCodecBridge uses timestamp |
| 561 // correction and provides a non-decreasing timestamp sequence, which might | 570 // correction and provides a non-decreasing timestamp sequence, which might |
| 562 // result in timestamp duplicates. Discard the frame if we cannot get the | 571 // result in timestamp duplicates. Discard the frame if we cannot get the |
| 563 // corresponding buffer id. | 572 // corresponding buffer id. |
| 564 DVLOG(3) << "AVDA::DequeueOutput: Releasing buffer with unexpected PTS: " | 573 DVLOG(3) << __FUNCTION__ << ": Releasing buffer with unexpected PTS: " |
| 565 << presentation_timestamp; | 574 << presentation_timestamp; |
| 566 media_codec_->ReleaseOutputBuffer(buf_index, false); | 575 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 567 } | 576 } |
| 568 | 577 |
| 569 // We got a decoded frame, so try for another. | 578 // We got a decoded frame, so try for another. |
| 570 return true; | 579 return true; |
| 571 } | 580 } |
| 572 | 581 |
| 573 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( | 582 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( |
| 574 int32_t codec_buffer_index, | 583 int32_t codec_buffer_index, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 592 if (i == output_picture_buffers_.end()) { | 601 if (i == output_picture_buffers_.end()) { |
| 593 POST_ERROR(PLATFORM_FAILURE, | 602 POST_ERROR(PLATFORM_FAILURE, |
| 594 "Can't find PictureBuffer id: " << picture_buffer_id); | 603 "Can't find PictureBuffer id: " << picture_buffer_id); |
| 595 return; | 604 return; |
| 596 } | 605 } |
| 597 | 606 |
| 598 // Connect the PictureBuffer to the decoded frame, via whatever | 607 // Connect the PictureBuffer to the decoded frame, via whatever |
| 599 // mechanism the strategy likes. | 608 // mechanism the strategy likes. |
| 600 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); | 609 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); |
| 601 | 610 |
| 611 const bool allow_overlay = strategy_->ArePicturesOverlayable(); |
| 602 base::MessageLoop::current()->PostTask( | 612 base::MessageLoop::current()->PostTask( |
| 603 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 613 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
| 604 weak_this_factory_.GetWeakPtr(), | 614 weak_this_factory_.GetWeakPtr(), |
| 605 media::Picture(picture_buffer_id, bitstream_id, | 615 media::Picture(picture_buffer_id, bitstream_id, |
| 606 gfx::Rect(size_), false))); | 616 gfx::Rect(size_), allow_overlay))); |
| 607 } | 617 } |
| 608 | 618 |
| 609 void AndroidVideoDecodeAccelerator::Decode( | 619 void AndroidVideoDecodeAccelerator::Decode( |
| 610 const media::BitstreamBuffer& bitstream_buffer) { | 620 const media::BitstreamBuffer& bitstream_buffer) { |
| 611 DCHECK(thread_checker_.CalledOnValidThread()); | 621 DCHECK(thread_checker_.CalledOnValidThread()); |
| 612 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { | 622 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { |
| 613 base::MessageLoop::current()->PostTask( | 623 base::MessageLoop::current()->PostTask( |
| 614 FROM_HERE, | 624 FROM_HERE, |
| 615 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 625 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 616 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id())); | 626 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id())); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 } | 702 } |
| 693 | 703 |
| 694 void AndroidVideoDecodeAccelerator::Flush() { | 704 void AndroidVideoDecodeAccelerator::Flush() { |
| 695 DCHECK(thread_checker_.CalledOnValidThread()); | 705 DCHECK(thread_checker_.CalledOnValidThread()); |
| 696 | 706 |
| 697 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 707 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
| 698 } | 708 } |
| 699 | 709 |
| 700 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { | 710 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { |
| 701 DCHECK(thread_checker_.CalledOnValidThread()); | 711 DCHECK(thread_checker_.CalledOnValidThread()); |
| 702 DCHECK(surface_texture_.get()); | |
| 703 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); | 712 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); |
| 704 | 713 |
| 705 gfx::ScopedJavaSurface surface(surface_texture_.get()); | |
| 706 | |
| 707 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; | 714 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; |
| 708 | 715 |
| 709 // |needs_protected_surface_| implies encrypted stream. | 716 // |needs_protected_surface_| implies encrypted stream. |
| 710 DCHECK(!needs_protected_surface_ || media_crypto); | 717 DCHECK(!needs_protected_surface_ || media_crypto); |
| 711 | 718 |
| 712 // Pass a dummy 320x240 canvas size and let the codec signal the real size | 719 // Pass a dummy 320x240 canvas size and let the codec signal the real size |
| 713 // when it's known from the bitstream. | 720 // when it's known from the bitstream. |
| 714 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( | 721 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( |
| 715 codec_, needs_protected_surface_, gfx::Size(320, 240), | 722 codec_, needs_protected_surface_, gfx::Size(320, 240), |
| 716 surface.j_surface().obj(), media_crypto)); | 723 surface_.j_surface().obj(), media_crypto)); |
| 724 |
| 717 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); | 725 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); |
| 718 if (!media_codec_) { | 726 if (!media_codec_) { |
| 719 LOG(ERROR) << "Failed to create MediaCodec instance."; | 727 LOG(ERROR) << "Failed to create MediaCodec instance."; |
| 720 return false; | 728 return false; |
| 721 } | 729 } |
| 722 | 730 |
| 723 ManageTimer(true); | 731 ManageTimer(true); |
| 724 return true; | 732 return true; |
| 725 } | 733 } |
| 726 | 734 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 | 1015 |
| 1008 if (UseDeferredRenderingStrategy()) { | 1016 if (UseDeferredRenderingStrategy()) { |
| 1009 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1017 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 1010 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; | 1018 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; |
| 1011 } | 1019 } |
| 1012 | 1020 |
| 1013 return capabilities; | 1021 return capabilities; |
| 1014 } | 1022 } |
| 1015 | 1023 |
| 1016 } // namespace content | 1024 } // namespace content |
| OLD | NEW |