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