Chromium Code Reviews| Index: content/common/gpu/media/android_video_decode_accelerator.cc |
| diff --git a/content/common/gpu/media/android_video_decode_accelerator.cc b/content/common/gpu/media/android_video_decode_accelerator.cc |
| index 00e1bb67856e14163ea5da84a6d04a37607335de..42d9a46fd65ddb63463d6818f61affc7a3398492 100644 |
| --- a/content/common/gpu/media/android_video_decode_accelerator.cc |
| +++ b/content/common/gpu/media/android_video_decode_accelerator.cc |
| @@ -12,6 +12,7 @@ |
| #include "content/common/gpu/gpu_channel.h" |
| #include "content/common/gpu/media/avda_return_on_failure.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| +#include "media/base/bind_to_current_loop.h" |
| #include "media/base/bitstream_buffer.h" |
| #include "media/base/limits.h" |
| #include "media/base/timestamp_constants.h" |
| @@ -86,10 +87,19 @@ AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
| picturebuffers_requested_(false), |
| gl_decoder_(decoder), |
| strategy_(strategy.Pass()), |
| + cdm_registration_id_(0), |
| weak_this_factory_(this) {} |
| AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| +#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| + if (cdm_) { |
| + DCHECK(cdm_registration_id_); |
| + static_cast<media::MediaDrmBridge*>(cdm_.get()) |
| + ->UnregisterPlayer(cdm_registration_id_); |
| + } |
| +#endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| } |
| bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| @@ -140,25 +150,59 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| surface_texture_ = strategy_->CreateSurfaceTexture(); |
|
liberato (no reviews please)
2015/12/04 16:20:11
how does this fit with |needs_protected_surface|?
Tima Vaisburd
2015/12/04 20:12:01
Can the protected surface be deferred in the subse
liberato (no reviews please)
2015/12/04 21:40:13
sure, i didn't mean that protected surfaces have t
|
| - if (!ConfigureMediaCodec()) { |
| - LOG(ERROR) << "Failed to create MediaCodec instance."; |
| - return false; |
| - } |
| + // For encrypted streams we postpone configuration until MediaCrypto is |
|
liberato (no reviews please)
2015/12/04 16:20:11
all of this would become a call to FinishInitializ
|
| + // available. |
| + if (is_encrypted_) |
| + return true; |
| - return true; |
| + return ConfigureMediaCodec(); |
| } |
| void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { |
|
xhwang
2015/12/04 20:22:03
This should only be called after Initialize(), oth
liberato (no reviews please)
2015/12/04 21:40:13
maybe additional values for |state_| are useful he
Tima Vaisburd
2015/12/04 22:54:51
Yes, I agree. For now I DCHECKed client_, I'll try
|
| DVLOG(2) << __FUNCTION__ << ": " << cdm_id; |
| #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| - // TODO(timav): Implement CDM setting here. See http://crbug.com/542417 |
| - scoped_refptr<media::MediaKeys> cdm = media::MojoCdmService::GetCdm(cdm_id); |
| - DCHECK(cdm); |
| -#endif |
| + using media::MediaDrmBridge; |
| + |
| + if (cdm_) { |
| + NOTREACHED() << "We do not support resetting CDM."; |
| + NotifyCdmAttached(false); |
| + return; |
| + } |
| + |
| + cdm_ = media::MojoCdmService::GetCdm(cdm_id); |
| + DCHECK(cdm_); |
| + |
| + // On Android platform the MediaKeys fill be its subclass MediaDrmBridge. |
|
liberato (no reviews please)
2015/12/04 16:20:11
s/fill/will
Tima Vaisburd
2015/12/04 20:12:01
Done.
|
| + MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get()); |
| + |
| + // Register CDM callbacks. The callbacks registered will be posted back to |
| + // this thread via BindToCurrentLoop. |
| + |
| + // Since |this| holds a reference to the |cdm_|, by the time the CDM is |
| + // destructed, UnregisterPlayer() must have been called and |this| has been |
| + // destructed as well. So the |cdm_unset_cb| will never have a chance to be |
| + // called. |
| + // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. |
| + cdm_registration_id_ = drm_bridge->RegisterPlayer( |
| + media::BindToCurrentLoop( |
| + base::Bind(&AndroidVideoDecodeAccelerator::OnCdmKeyAdded, |
| + weak_this_factory_.GetWeakPtr())), |
| + base::Bind(&base::DoNothing)); |
| + |
| + drm_bridge->SetMediaCryptoReadyCB(media::BindToCurrentLoop( |
| + base::Bind(&AndroidVideoDecodeAccelerator::OnCdmMediaCryptoReady, |
| + weak_this_factory_.GetWeakPtr()))); |
| + |
| + // Postpone NotifyCdmAttached() call till we create the MediaCodec after |
| + // OnCdmMediaCryptoReady(). |
| + |
| +#else |
| NOTIMPLEMENTED(); |
| NotifyCdmAttached(false); |
| + |
| +#endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| } |
| void AndroidVideoDecodeAccelerator::DoIOTask() { |
| @@ -195,11 +239,12 @@ void AndroidVideoDecodeAccelerator::QueueInput() { |
| base::Time::Now() - queued_time); |
| media::BitstreamBuffer bitstream_buffer = |
| pending_bitstream_buffers_.front().first; |
| - pending_bitstream_buffers_.pop(); |
| - TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| - pending_bitstream_buffers_.size()); |
| if (bitstream_buffer.id() == -1) { |
| + pending_bitstream_buffers_.pop(); |
| + TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| + pending_bitstream_buffers_.size()); |
| + |
| media_codec_->QueueEOS(input_buf_index); |
| return; |
| } |
| @@ -242,6 +287,13 @@ void AndroidVideoDecodeAccelerator::QueueInput() { |
| << ": QueueInputBuffer: pts:" << presentation_timestamp |
| << " status:" << status; |
| + if (status == media::MEDIA_CODEC_NO_KEY) |
| + return; // keep trying to enqueue the front pending buffer |
|
xhwang
2015/12/04 20:22:03
This is an important event. Add a log here.
Tima Vaisburd
2015/12/04 22:54:51
The log line above already prints the status, unle
xhwang
2015/12/04 23:24:09
We need a log with higher level for unexpected eve
Tima Vaisburd
2015/12/05 01:35:25
Done, but it would be better to have states and ha
|
| + |
| + pending_bitstream_buffers_.pop(); |
| + TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| + pending_bitstream_buffers_.size()); |
| + |
| RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK, |
| "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); |
| @@ -505,13 +557,18 @@ bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { |
| gfx::ScopedJavaSurface surface(surface_texture_.get()); |
| + jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; |
| + |
| // Pass a dummy 320x240 canvas size and let the codec signal the real size |
| // when it's known from the bitstream. |
| media_codec_.reset(media::VideoCodecBridge::CreateDecoder( |
| - codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL)); |
| + codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), |
| + media_crypto)); |
| strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); |
| - if (!media_codec_) |
| + if (!media_codec_) { |
| + LOG(ERROR) << "Failed to create MediaCodec instance."; |
| return false; |
| + } |
| io_timer_.Start(FROM_HERE, |
| DecodePollDelay(), |
| @@ -606,6 +663,25 @@ void AndroidVideoDecodeAccelerator::PostError( |
| state_ = ERROR; |
| } |
| +void AndroidVideoDecodeAccelerator::OnCdmMediaCryptoReady( |
| + media::MediaDrmBridge::JavaObjectPtr media_crypto, |
| + bool needs_protected_surface) { |
| + DVLOG(1) << __FUNCTION__; |
| + |
| + DCHECK(media_crypto); |
|
xhwang
2015/12/04 20:22:03
With my CL, |media_crypto| can actually be null if
Tima Vaisburd
2015/12/04 22:54:51
Done.
|
| + DCHECK(!media_crypto->is_null()); |
|
liberato (no reviews please)
2015/12/04 16:20:11
DCHECK(!media_codec)
Tima Vaisburd
2015/12/04 20:12:01
I added this DCHECK, but ConfigureMediaCodec() doe
liberato (no reviews please)
2015/12/04 21:40:13
it depends if we've sent in any buffers.
|
| + |
| + media_crypto_ = media_crypto.Pass(); |
| + |
| + // Configure here instead of in Initialize() |
| + const bool success = ConfigureMediaCodec(); |
| + NotifyCdmAttached(success); |
|
liberato (no reviews please)
2015/12/04 16:20:11
outside the scope of this CL, but NotifyInitializa
Tima Vaisburd
2015/12/04 20:12:01
I heard that there is a work on Version 2 which wi
liberato (no reviews please)
2015/12/04 21:40:13
yes, that's why i think it's outside the scope of
|
| +} |
| + |
| +void AndroidVideoDecodeAccelerator::OnCdmKeyAdded() { |
| + DVLOG(1) << __FUNCTION__; |
|
xhwang
2015/12/04 20:22:03
NOTIMPLEMENTED()
Also add a TODO to finish this p
Tima Vaisburd
2015/12/04 22:54:51
Since in this CL we do not try to stop the decodin
xhwang
2015/12/04 23:24:09
I don't fully understand how this works. What's th
Tima Vaisburd
2015/12/05 01:35:25
Added some comments, please take a look.
|
| +} |
| + |
| void AndroidVideoDecodeAccelerator::NotifyCdmAttached(bool success) { |
| client_->NotifyCdmAttached(success); |
| } |