| 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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 needs_protected_surface_(false), | 161 needs_protected_surface_(false), |
| 162 state_(NO_ERROR), | 162 state_(NO_ERROR), |
| 163 picturebuffers_requested_(false), | 163 picturebuffers_requested_(false), |
| 164 gl_decoder_(decoder), | 164 gl_decoder_(decoder), |
| 165 cdm_registration_id_(0), | 165 cdm_registration_id_(0), |
| 166 pending_input_buf_index_(-1), | 166 pending_input_buf_index_(-1), |
| 167 error_sequence_token_(0), | 167 error_sequence_token_(0), |
| 168 defer_errors_(false), | 168 defer_errors_(false), |
| 169 weak_this_factory_(this) { | 169 weak_this_factory_(this) { |
| 170 if (UseDeferredRenderingStrategy()) | 170 if (UseDeferredRenderingStrategy()) |
| 171 strategy_.reset(new AndroidDeferredRenderingBackingStrategy()); | 171 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 172 else | 172 else |
| 173 strategy_.reset(new AndroidCopyingBackingStrategy()); | 173 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 174 } | 174 } |
| 175 | 175 |
| 176 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 176 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 177 DCHECK(thread_checker_.CalledOnValidThread()); | 177 DCHECK(thread_checker_.CalledOnValidThread()); |
| 178 | 178 |
| 179 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 179 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 180 if (cdm_) { | 180 if (cdm_) { |
| 181 DCHECK(cdm_registration_id_); | 181 DCHECK(cdm_registration_id_); |
| 182 static_cast<media::MediaDrmBridge*>(cdm_.get()) | 182 static_cast<media::MediaDrmBridge*>(cdm_.get()) |
| 183 ->UnregisterPlayer(cdm_registration_id_); | 183 ->UnregisterPlayer(cdm_registration_id_); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 if (!make_context_current_.Run()) { | 223 if (!make_context_current_.Run()) { |
| 224 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 224 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
| 225 return false; | 225 return false; |
| 226 } | 226 } |
| 227 | 227 |
| 228 if (!gl_decoder_) { | 228 if (!gl_decoder_) { |
| 229 LOG(ERROR) << "Failed to get gles2 decoder instance."; | 229 LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 230 return false; | 230 return false; |
| 231 } | 231 } |
| 232 | 232 |
| 233 strategy_->Initialize(this); | 233 surface_ = strategy_->Initialize(config.surface_id); |
| 234 if (surface_.IsEmpty()) { |
| 235 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
| 236 "Java surface is empty."; |
| 237 return false; |
| 238 } |
| 234 | 239 |
| 235 surface_texture_ = strategy_->CreateSurfaceTexture(); | 240 // TODO(watk,liberato): move this into the strategy. |
| 236 on_frame_available_handler_ = | 241 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 237 new OnFrameAvailableHandler(this, surface_texture_); | 242 strategy_->GetSurfaceTexture(); |
| 243 if (surface_texture) { |
| 244 on_frame_available_handler_ = |
| 245 new OnFrameAvailableHandler(this, surface_texture); |
| 246 } |
| 238 | 247 |
| 239 // For encrypted streams we postpone configuration until MediaCrypto is | 248 // For encrypted streams we postpone configuration until MediaCrypto is |
| 240 // available. | 249 // available. |
| 241 if (is_encrypted_) | 250 if (is_encrypted_) |
| 242 return true; | 251 return true; |
| 243 | 252 |
| 244 return ConfigureMediaCodec(); | 253 return ConfigureMediaCodec(); |
| 245 } | 254 } |
| 246 | 255 |
| 247 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { | 256 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 505 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, |
| 497 weak_this_factory_.GetWeakPtr())); | 506 weak_this_factory_.GetWeakPtr())); |
| 498 return false; | 507 return false; |
| 499 } | 508 } |
| 500 | 509 |
| 501 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 510 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
| 502 break; | 511 break; |
| 503 | 512 |
| 504 case media::MEDIA_CODEC_OK: | 513 case media::MEDIA_CODEC_OK: |
| 505 DCHECK_GE(buf_index, 0); | 514 DCHECK_GE(buf_index, 0); |
| 506 DVLOG(3) << "AVDA::DequeueOutput: pts:" << presentation_timestamp | 515 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp |
| 507 << " buf_index:" << buf_index << " offset:" << offset | 516 << " buf_index:" << buf_index << " offset:" << offset |
| 508 << " size:" << size << " eos:" << eos; | 517 << " size:" << size << " eos:" << eos; |
| 509 break; | 518 break; |
| 510 | 519 |
| 511 default: | 520 default: |
| 512 NOTREACHED(); | 521 NOTREACHED(); |
| 513 break; | 522 break; |
| 514 } | 523 } |
| 515 } while (buf_index < 0); | 524 } while (buf_index < 0); |
| 516 | 525 |
| 517 if (eos) { | 526 if (eos) { |
| 518 DVLOG(3) << "AVDA::DequeueOutput: Resetting codec state after EOS"; | 527 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; |
| 519 ResetCodecState(); | 528 ResetCodecState(); |
| 520 | 529 |
| 521 base::MessageLoop::current()->PostTask( | 530 base::MessageLoop::current()->PostTask( |
| 522 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | 531 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 523 weak_this_factory_.GetWeakPtr())); | 532 weak_this_factory_.GetWeakPtr())); |
| 524 return false; | 533 return false; |
| 525 } | 534 } |
| 526 | 535 |
| 527 // Get the bitstream buffer id from the timestamp. | 536 // Get the bitstream buffer id from the timestamp. |
| 528 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); | 537 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 545 bitstreams_notified_in_advance_.begin(), ++bitstream_it); | 554 bitstreams_notified_in_advance_.begin(), ++bitstream_it); |
| 546 break; | 555 break; |
| 547 } | 556 } |
| 548 } | 557 } |
| 549 } else { | 558 } else { |
| 550 // Normally we assume that the decoder makes at most one output frame for | 559 // Normally we assume that the decoder makes at most one output frame for |
| 551 // each distinct input timestamp. However MediaCodecBridge uses timestamp | 560 // each distinct input timestamp. However MediaCodecBridge uses timestamp |
| 552 // correction and provides a non-decreasing timestamp sequence, which might | 561 // correction and provides a non-decreasing timestamp sequence, which might |
| 553 // result in timestamp duplicates. Discard the frame if we cannot get the | 562 // result in timestamp duplicates. Discard the frame if we cannot get the |
| 554 // corresponding buffer id. | 563 // corresponding buffer id. |
| 555 DVLOG(3) << "AVDA::DequeueOutput: Releasing buffer with unexpected PTS: " | 564 DVLOG(3) << __FUNCTION__ << ": Releasing buffer with unexpected PTS: " |
| 556 << presentation_timestamp; | 565 << presentation_timestamp; |
| 557 media_codec_->ReleaseOutputBuffer(buf_index, false); | 566 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 558 } | 567 } |
| 559 | 568 |
| 560 // We got a decoded frame, so try for another. | 569 // We got a decoded frame, so try for another. |
| 561 return true; | 570 return true; |
| 562 } | 571 } |
| 563 | 572 |
| 564 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( | 573 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( |
| 565 int32_t codec_buffer_index, | 574 int32_t codec_buffer_index, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 583 if (i == output_picture_buffers_.end()) { | 592 if (i == output_picture_buffers_.end()) { |
| 584 POST_ERROR(PLATFORM_FAILURE, | 593 POST_ERROR(PLATFORM_FAILURE, |
| 585 "Can't find PictureBuffer id: " << picture_buffer_id); | 594 "Can't find PictureBuffer id: " << picture_buffer_id); |
| 586 return; | 595 return; |
| 587 } | 596 } |
| 588 | 597 |
| 589 // Connect the PictureBuffer to the decoded frame, via whatever | 598 // Connect the PictureBuffer to the decoded frame, via whatever |
| 590 // mechanism the strategy likes. | 599 // mechanism the strategy likes. |
| 591 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); | 600 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); |
| 592 | 601 |
| 602 const bool allow_overlay = strategy_->ArePicturesOverlayable(); |
| 593 base::MessageLoop::current()->PostTask( | 603 base::MessageLoop::current()->PostTask( |
| 594 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 604 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
| 595 weak_this_factory_.GetWeakPtr(), | 605 weak_this_factory_.GetWeakPtr(), |
| 596 media::Picture(picture_buffer_id, bitstream_id, | 606 media::Picture(picture_buffer_id, bitstream_id, |
| 597 gfx::Rect(size_), false))); | 607 gfx::Rect(size_), allow_overlay))); |
| 598 } | 608 } |
| 599 | 609 |
| 600 void AndroidVideoDecodeAccelerator::Decode( | 610 void AndroidVideoDecodeAccelerator::Decode( |
| 601 const media::BitstreamBuffer& bitstream_buffer) { | 611 const media::BitstreamBuffer& bitstream_buffer) { |
| 602 DCHECK(thread_checker_.CalledOnValidThread()); | 612 DCHECK(thread_checker_.CalledOnValidThread()); |
| 603 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { | 613 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { |
| 604 base::MessageLoop::current()->PostTask( | 614 base::MessageLoop::current()->PostTask( |
| 605 FROM_HERE, | 615 FROM_HERE, |
| 606 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 616 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 607 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id())); | 617 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id())); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 } | 693 } |
| 684 | 694 |
| 685 void AndroidVideoDecodeAccelerator::Flush() { | 695 void AndroidVideoDecodeAccelerator::Flush() { |
| 686 DCHECK(thread_checker_.CalledOnValidThread()); | 696 DCHECK(thread_checker_.CalledOnValidThread()); |
| 687 | 697 |
| 688 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 698 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
| 689 } | 699 } |
| 690 | 700 |
| 691 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { | 701 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { |
| 692 DCHECK(thread_checker_.CalledOnValidThread()); | 702 DCHECK(thread_checker_.CalledOnValidThread()); |
| 693 DCHECK(surface_texture_.get()); | |
| 694 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); | 703 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); |
| 695 | 704 |
| 696 gfx::ScopedJavaSurface surface(surface_texture_.get()); | |
| 697 | |
| 698 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; | 705 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; |
| 699 | 706 |
| 700 // |needs_protected_surface_| implies encrypted stream. | 707 // |needs_protected_surface_| implies encrypted stream. |
| 701 DCHECK(!needs_protected_surface_ || media_crypto); | 708 DCHECK(!needs_protected_surface_ || media_crypto); |
| 702 | 709 |
| 703 // Pass a dummy 320x240 canvas size and let the codec signal the real size | 710 // Pass a dummy 320x240 canvas size and let the codec signal the real size |
| 704 // when it's known from the bitstream. | 711 // when it's known from the bitstream. |
| 705 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( | 712 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( |
| 706 codec_, needs_protected_surface_, gfx::Size(320, 240), | 713 codec_, needs_protected_surface_, gfx::Size(320, 240), |
| 707 surface.j_surface().obj(), media_crypto)); | 714 surface_.j_surface().obj(), media_crypto)); |
| 715 |
| 708 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); | 716 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); |
| 709 if (!media_codec_) { | 717 if (!media_codec_) { |
| 710 LOG(ERROR) << "Failed to create MediaCodec instance."; | 718 LOG(ERROR) << "Failed to create MediaCodec instance."; |
| 711 return false; | 719 return false; |
| 712 } | 720 } |
| 713 | 721 |
| 714 ManageTimer(true); | 722 ManageTimer(true); |
| 715 return true; | 723 return true; |
| 716 } | 724 } |
| 717 | 725 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 | 1003 |
| 996 if (UseDeferredRenderingStrategy()) { | 1004 if (UseDeferredRenderingStrategy()) { |
| 997 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1005 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 998 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; | 1006 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; |
| 999 } | 1007 } |
| 1000 | 1008 |
| 1001 return capabilities; | 1009 return capabilities; |
| 1002 } | 1010 } |
| 1003 | 1011 |
| 1004 } // namespace content | 1012 } // namespace content |
| OLD | NEW |