Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: content/common/gpu/media/android_video_decode_accelerator.cc

Issue 1469353010: Configure MediaCodec with CDM in ADVA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed some comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
12 #include "content/common/gpu/gpu_channel.h" 12 #include "content/common/gpu/gpu_channel.h"
13 #include "content/common/gpu/media/avda_return_on_failure.h" 13 #include "content/common/gpu/media/avda_return_on_failure.h"
14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
15 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/bitstream_buffer.h" 16 #include "media/base/bitstream_buffer.h"
16 #include "media/base/limits.h" 17 #include "media/base/limits.h"
17 #include "media/base/timestamp_constants.h" 18 #include "media/base/timestamp_constants.h"
18 #include "media/base/video_decoder_config.h" 19 #include "media/base/video_decoder_config.h"
19 #include "media/video/picture.h" 20 #include "media/video/picture.h"
20 #include "ui/gl/android/scoped_java_surface.h" 21 #include "ui/gl/android/scoped_java_surface.h"
21 #include "ui/gl/android/surface_texture.h" 22 #include "ui/gl/android/surface_texture.h"
22 #include "ui/gl/gl_bindings.h" 23 #include "ui/gl/gl_bindings.h"
23 24
24 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 25 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 const base::Callback<bool(void)>& make_context_current, 80 const base::Callback<bool(void)>& make_context_current,
80 scoped_ptr<BackingStrategy> strategy) 81 scoped_ptr<BackingStrategy> strategy)
81 : client_(NULL), 82 : client_(NULL),
82 make_context_current_(make_context_current), 83 make_context_current_(make_context_current),
83 codec_(media::kCodecH264), 84 codec_(media::kCodecH264),
84 is_encrypted_(false), 85 is_encrypted_(false),
85 state_(NO_ERROR), 86 state_(NO_ERROR),
86 picturebuffers_requested_(false), 87 picturebuffers_requested_(false),
87 gl_decoder_(decoder), 88 gl_decoder_(decoder),
88 strategy_(strategy.Pass()), 89 strategy_(strategy.Pass()),
90 cdm_registration_id_(0),
89 weak_this_factory_(this) {} 91 weak_this_factory_(this) {}
90 92
91 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 93 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
92 DCHECK(thread_checker_.CalledOnValidThread()); 94 DCHECK(thread_checker_.CalledOnValidThread());
95
96 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
97 if (cdm_) {
98 DCHECK(cdm_registration_id_);
99 static_cast<media::MediaDrmBridge*>(cdm_.get())
100 ->UnregisterPlayer(cdm_registration_id_);
101 }
102 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
93 } 103 }
94 104
95 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, 105 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config,
96 Client* client) { 106 Client* client) {
97 DCHECK(!media_codec_); 107 DCHECK(!media_codec_);
98 DCHECK(thread_checker_.CalledOnValidThread()); 108 DCHECK(thread_checker_.CalledOnValidThread());
99 TRACE_EVENT0("media", "AVDA::Initialize"); 109 TRACE_EVENT0("media", "AVDA::Initialize");
100 110
101 DVLOG(1) << __FUNCTION__ << ": profile:" << config.profile 111 DVLOG(1) << __FUNCTION__ << ": profile:" << config.profile
102 << " is_encrypted:" << config.is_encrypted; 112 << " is_encrypted:" << config.is_encrypted;
103 113
114 DCHECK(client);
104 client_ = client; 115 client_ = client;
105 codec_ = VideoCodecProfileToVideoCodec(config.profile); 116 codec_ = VideoCodecProfileToVideoCodec(config.profile);
106 is_encrypted_ = config.is_encrypted; 117 is_encrypted_ = config.is_encrypted;
107 118
108 bool profile_supported = codec_ == media::kCodecVP8; 119 bool profile_supported = codec_ == media::kCodecVP8;
109 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) 120 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID)
110 profile_supported |= 121 profile_supported |=
111 (codec_ == media::kCodecVP9 || codec_ == media::kCodecH264); 122 (codec_ == media::kCodecVP9 || codec_ == media::kCodecH264);
112 #endif 123 #endif
113 124
(...skipping 19 matching lines...) Expand all
133 144
134 if (!gl_decoder_) { 145 if (!gl_decoder_) {
135 LOG(ERROR) << "Failed to get gles2 decoder instance."; 146 LOG(ERROR) << "Failed to get gles2 decoder instance.";
136 return false; 147 return false;
137 } 148 }
138 149
139 strategy_->Initialize(this); 150 strategy_->Initialize(this);
140 151
141 surface_texture_ = strategy_->CreateSurfaceTexture(); 152 surface_texture_ = strategy_->CreateSurfaceTexture();
142 153
143 if (!ConfigureMediaCodec()) { 154 // For encrypted streams we postpone configuration until MediaCrypto is
144 LOG(ERROR) << "Failed to create MediaCodec instance."; 155 // available.
145 return false; 156 if (is_encrypted_)
146 } 157 return true;
147 158
148 return true; 159 return ConfigureMediaCodec();
149 } 160 }
150 161
151 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { 162 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) {
152 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; 163 DVLOG(2) << __FUNCTION__ << ": " << cdm_id;
153 164
154 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 165 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
155 // TODO(timav): Implement CDM setting here. See http://crbug.com/542417 166 using media::MediaDrmBridge;
156 scoped_refptr<media::MediaKeys> cdm = media::MojoCdmService::GetCdm(cdm_id); 167
157 DCHECK(cdm); 168 // This medhod must be called after Initialize().
158 #endif 169 DCHECK(client_);
xhwang 2015/12/04 23:24:09 Put the comment in the DCHECK statement: DCHECK(c
Tima Vaisburd 2015/12/05 01:35:25 Done.
170
171 if (cdm_) {
172 NOTREACHED() << "We do not support resetting CDM.";
173 NotifyCdmAttached(false);
174 return;
175 }
176
177 cdm_ = media::MojoCdmService::GetCdm(cdm_id);
178 DCHECK(cdm_);
179
180 // On Android platform the MediaKeys will be its subclass MediaDrmBridge.
181 MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get());
182
183 // Register CDM callbacks. The callbacks registered will be posted back to
184 // this thread via BindToCurrentLoop.
185
186 // Since |this| holds a reference to the |cdm_|, by the time the CDM is
187 // destructed, UnregisterPlayer() must have been called and |this| has been
188 // destructed as well. So the |cdm_unset_cb| will never have a chance to be
189 // called.
190 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms.
191 cdm_registration_id_ =
192 drm_bridge->RegisterPlayer(media::BindToCurrentLoop(base::Bind(
193 &AndroidVideoDecodeAccelerator::OnKeyAdded,
194 weak_this_factory_.GetWeakPtr())),
195 base::Bind(&base::DoNothing));
xhwang 2015/12/04 23:24:09 add include for DoNothing()?
Tima Vaisburd 2015/12/05 01:35:25 Done.
196
197 drm_bridge->SetMediaCryptoReadyCB(media::BindToCurrentLoop(
198 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady,
199 weak_this_factory_.GetWeakPtr())));
200
201 // Postpone NotifyCdmAttached() call till we create the MediaCodec after
202 // OnMediaCryptoReady().
203
204 #else
159 205
160 NOTIMPLEMENTED(); 206 NOTIMPLEMENTED();
161 NotifyCdmAttached(false); 207 NotifyCdmAttached(false);
208
209 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
162 } 210 }
163 211
164 void AndroidVideoDecodeAccelerator::DoIOTask() { 212 void AndroidVideoDecodeAccelerator::DoIOTask() {
165 DCHECK(thread_checker_.CalledOnValidThread()); 213 DCHECK(thread_checker_.CalledOnValidThread());
166 TRACE_EVENT0("media", "AVDA::DoIOTask"); 214 TRACE_EVENT0("media", "AVDA::DoIOTask");
167 if (state_ == ERROR) { 215 if (state_ == ERROR) {
168 return; 216 return;
169 } 217 }
170 218
171 QueueInput(); 219 QueueInput();
(...skipping 16 matching lines...) Expand all
188 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || 236 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER ||
189 status == media::MEDIA_CODEC_ERROR); 237 status == media::MEDIA_CODEC_ERROR);
190 return; 238 return;
191 } 239 }
192 240
193 base::Time queued_time = pending_bitstream_buffers_.front().second; 241 base::Time queued_time = pending_bitstream_buffers_.front().second;
194 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", 242 UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime",
195 base::Time::Now() - queued_time); 243 base::Time::Now() - queued_time);
196 media::BitstreamBuffer bitstream_buffer = 244 media::BitstreamBuffer bitstream_buffer =
197 pending_bitstream_buffers_.front().first; 245 pending_bitstream_buffers_.front().first;
198 pending_bitstream_buffers_.pop();
199 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
200 pending_bitstream_buffers_.size());
201 246
202 if (bitstream_buffer.id() == -1) { 247 if (bitstream_buffer.id() == -1) {
248 pending_bitstream_buffers_.pop();
249 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
250 pending_bitstream_buffers_.size());
251
203 media_codec_->QueueEOS(input_buf_index); 252 media_codec_->QueueEOS(input_buf_index);
204 return; 253 return;
205 } 254 }
206 255
207 scoped_ptr<base::SharedMemory> shm( 256 scoped_ptr<base::SharedMemory> shm(
208 new base::SharedMemory(bitstream_buffer.handle(), true)); 257 new base::SharedMemory(bitstream_buffer.handle(), true));
209 RETURN_ON_FAILURE(this, shm->Map(bitstream_buffer.size()), 258 RETURN_ON_FAILURE(this, shm->Map(bitstream_buffer.size()),
210 "Failed to SharedMemory::Map()", UNREADABLE_INPUT); 259 "Failed to SharedMemory::Map()", UNREADABLE_INPUT);
211 260
212 const base::TimeDelta presentation_timestamp = 261 const base::TimeDelta presentation_timestamp =
(...skipping 19 matching lines...) Expand all
232 status = media_codec_->QueueInputBuffer(input_buf_index, memory, 281 status = media_codec_->QueueInputBuffer(input_buf_index, memory,
233 bitstream_buffer.size(), 282 bitstream_buffer.size(),
234 presentation_timestamp); 283 presentation_timestamp);
235 } else { 284 } else {
236 status = media_codec_->QueueSecureInputBuffer( 285 status = media_codec_->QueueSecureInputBuffer(
237 input_buf_index, memory, bitstream_buffer.size(), key_id, iv, 286 input_buf_index, memory, bitstream_buffer.size(), key_id, iv,
238 subsamples, presentation_timestamp); 287 subsamples, presentation_timestamp);
239 } 288 }
240 289
241 DVLOG(2) << __FUNCTION__ 290 DVLOG(2) << __FUNCTION__
242 << ": QueueInputBuffer: pts:" << presentation_timestamp 291 << ": Queue(Secure)InputBuffer: pts:" << presentation_timestamp
243 << " status:" << status; 292 << " status:" << status;
244 293
294 if (status == media::MEDIA_CODEC_NO_KEY)
295 return; // keep trying to enqueue the front pending buffer
296
297 pending_bitstream_buffers_.pop();
298 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
299 pending_bitstream_buffers_.size());
300
245 RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK, 301 RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK,
246 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); 302 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE);
247 303
248 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output 304 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output
249 // will be returned from the bitstream buffer. However, MediaCodec API is 305 // will be returned from the bitstream buffer. However, MediaCodec API is
250 // not enough to guarantee it. 306 // not enough to guarantee it.
251 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to 307 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to
252 // keep getting more bitstreams from the client, and throttle them by using 308 // keep getting more bitstreams from the client, and throttle them by using
253 // |bitstreams_notified_in_advance_|. 309 // |bitstreams_notified_in_advance_|.
254 // TODO(dwkang): check if there is a way to remove this workaround. 310 // TODO(dwkang): check if there is a way to remove this workaround.
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); 554 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
499 } 555 }
500 556
501 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { 557 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() {
502 DCHECK(thread_checker_.CalledOnValidThread()); 558 DCHECK(thread_checker_.CalledOnValidThread());
503 DCHECK(surface_texture_.get()); 559 DCHECK(surface_texture_.get());
504 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); 560 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
505 561
506 gfx::ScopedJavaSurface surface(surface_texture_.get()); 562 gfx::ScopedJavaSurface surface(surface_texture_.get());
507 563
564 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr;
565
508 // Pass a dummy 320x240 canvas size and let the codec signal the real size 566 // Pass a dummy 320x240 canvas size and let the codec signal the real size
509 // when it's known from the bitstream. 567 // when it's known from the bitstream.
510 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( 568 media_codec_.reset(media::VideoCodecBridge::CreateDecoder(
511 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL)); 569 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(),
570 media_crypto));
512 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); 571 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_);
513 if (!media_codec_) 572 if (!media_codec_) {
573 LOG(ERROR) << "Failed to create MediaCodec instance.";
514 return false; 574 return false;
575 }
515 576
516 io_timer_.Start(FROM_HERE, 577 io_timer_.Start(FROM_HERE,
517 DecodePollDelay(), 578 DecodePollDelay(),
518 this, 579 this,
519 &AndroidVideoDecodeAccelerator::DoIOTask); 580 &AndroidVideoDecodeAccelerator::DoIOTask);
520 return true; 581 return true;
521 } 582 }
522 583
523 void AndroidVideoDecodeAccelerator::Reset() { 584 void AndroidVideoDecodeAccelerator::Reset() {
524 DCHECK(thread_checker_.CalledOnValidThread()); 585 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 660
600 void AndroidVideoDecodeAccelerator::PostError( 661 void AndroidVideoDecodeAccelerator::PostError(
601 const ::tracked_objects::Location& from_here, 662 const ::tracked_objects::Location& from_here,
602 media::VideoDecodeAccelerator::Error error) { 663 media::VideoDecodeAccelerator::Error error) {
603 base::MessageLoop::current()->PostTask( 664 base::MessageLoop::current()->PostTask(
604 from_here, base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, 665 from_here, base::Bind(&AndroidVideoDecodeAccelerator::NotifyError,
605 weak_this_factory_.GetWeakPtr(), error)); 666 weak_this_factory_.GetWeakPtr(), error));
606 state_ = ERROR; 667 state_ = ERROR;
607 } 668 }
608 669
670 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady(
671 media::MediaDrmBridge::JavaObjectPtr media_crypto,
672 bool needs_protected_surface) {
673 DVLOG(1) << __FUNCTION__;
674
675 if (!media_crypto) {
676 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream.";
677 NotifyCdmAttached(false);
678 return;
679 }
680
681 DCHECK(!media_crypto->is_null());
682
683 // We assume this is a part of the initialization process, thus MediaCodec
684 // is not created yet.
685 DCHECK(!media_codec_);
686
687 if (needs_protected_surface) {
688 LOG(ERROR) << "Protected surface is not supported.";
xhwang 2015/12/04 23:24:09 Is this NOTIMPLEMENTED() as well?
Tima Vaisburd 2015/12/05 01:35:25 Yes, and actually, the codec part is easy to imple
689 NotifyCdmAttached(false);
690 return;
691 }
692
693 media_crypto_ = media_crypto.Pass();
694
695 // After receiving |media_crypto_| we can configure MediaCodec.
696 const bool success = ConfigureMediaCodec();
697 NotifyCdmAttached(success);
698 }
699
700 void AndroidVideoDecodeAccelerator::OnKeyAdded() {
701 DVLOG(1) << __FUNCTION__;
702 }
703
609 void AndroidVideoDecodeAccelerator::NotifyCdmAttached(bool success) { 704 void AndroidVideoDecodeAccelerator::NotifyCdmAttached(bool success) {
610 client_->NotifyCdmAttached(success); 705 client_->NotifyCdmAttached(success);
611 } 706 }
612 707
613 void AndroidVideoDecodeAccelerator::NotifyPictureReady( 708 void AndroidVideoDecodeAccelerator::NotifyPictureReady(
614 const media::Picture& picture) { 709 const media::Picture& picture) {
615 client_->PictureReady(picture); 710 client_->PictureReady(picture);
616 } 711 }
617 712
618 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( 713 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 // software fallback for H264 on Android anyway. 761 // software fallback for H264 on Android anyway.
667 profile.max_resolution.SetSize(3840, 2160); 762 profile.max_resolution.SetSize(3840, 2160);
668 profiles.push_back(profile); 763 profiles.push_back(profile);
669 } 764 }
670 #endif 765 #endif
671 766
672 return profiles; 767 return profiles;
673 } 768 }
674 769
675 } // namespace content 770 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698