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

Side by Side Diff: media/gpu/android/media_codec_video_decoder.cc

Issue 2552883003: media: Pare MCVD down to a minimal media::VideoDecoder (Closed)
Patch Set: Created 4 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 | « media/gpu/android/media_codec_video_decoder.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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "media/gpu/android/media_codec_video_decoder.h" 5 #include "media/gpu/android/media_codec_video_decoder.h"
6 6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/android/build_info.h"
12 #include "base/auto_reset.h"
13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
15 #include "base/callback_helpers.h"
16 #include "base/command_line.h"
17 #include "base/lazy_instance.h"
18 #include "base/logging.h" 7 #include "base/logging.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/metrics/histogram.h"
21 #include "base/sys_info.h"
22 #include "base/task_runner_util.h"
23 #include "base/threading/thread.h"
24 #include "base/threading/thread_checker.h"
25 #include "base/threading/thread_task_runner_handle.h"
26 #include "base/trace_event/trace_event.h"
27 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
28 #include "gpu/command_buffer/service/mailbox_manager.h"
29 #include "gpu/ipc/service/gpu_channel.h"
30 #include "media/base/android/media_codec_bridge.h"
31 #include "media/base/android/media_codec_util.h" 8 #include "media/base/android/media_codec_util.h"
32 #include "media/base/bind_to_current_loop.h" 9 #include "media/base/android/sdk_media_codec_bridge.h"
33 #include "media/base/bitstream_buffer.h" 10 #include "media/base/video_codecs.h"
34 #include "media/base/limits.h"
35 #include "media/base/media.h"
36 #include "media/base/timestamp_constants.h"
37 #include "media/base/video_decoder_config.h" 11 #include "media/base/video_decoder_config.h"
38 #include "media/gpu/avda_picture_buffer_manager.h"
39 #include "media/gpu/shared_memory_region.h"
40 #include "media/video/picture.h"
41 #include "ui/gl/android/scoped_java_surface.h"
42 #include "ui/gl/android/surface_texture.h"
43 #include "ui/gl/gl_bindings.h"
44
45 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
46 #include "media/mojo/services/mojo_cdm_service.h"
47 #endif
48
49 #define NOTIFY_ERROR(error_code, error_message) \
50 do { \
51 DLOG(ERROR) << error_message; \
52 NotifyError(VideoDecodeAccelerator::error_code); \
53 } while (0)
54 12
55 namespace media { 13 namespace media {
56
57 namespace { 14 namespace {
58 15
59 // Max number of bitstreams notified to the client with 16 // Don't use MediaCodec's internal software decoders when we have more secure
60 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. 17 // and up to date versions in the renderer process.
61 enum { kMaxBitstreamsNotifiedInAdvance = 32 };
62
63 // Because MediaCodec is thread-hostile (must be poked on a single thread) and
64 // has no callback mechanism (b/11990118), we must drive it by polling for
65 // complete frames (and available input buffers, when the codec is fully
66 // saturated). This function defines the polling delay. The value used is an
67 // arbitrary choice that trades off CPU utilization (spinning) against latency.
68 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay().
69 //
70 // An alternative to this polling scheme could be to dedicate a new thread
71 // (instead of using the ChildThread) to run the MediaCodec, and make that
72 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it
73 // believes the codec should complete "soon" (e.g. waiting for an input
74 // buffer, or waiting for a picture when it knows enough complete input
75 // pictures have been fed to saturate any internal buffering). This is
76 // speculative and it's unclear that this would be a win (nor that there's a
77 // reasonably device-agnostic way to fill in the "believes" above).
78 constexpr base::TimeDelta DecodePollDelay =
79 base::TimeDelta::FromMilliseconds(10);
80
81 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0);
82
83 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1);
84
85 // On low end devices (< KitKat is always low-end due to buggy MediaCodec),
86 // defer the surface creation until the codec is actually used if we know no
87 // software fallback exists.
88 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) {
89 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 &&
90 AVDACodecAllocator::Instance()->IsAnyRegisteredAVDA() &&
91 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 ||
92 base::SysInfo::IsLowEndDevice());
93 }
94
95 // Don't use MediaCodecs internal software decoders when we have more secure and
96 // up to date versions in the renderer process.
97 bool IsMediaCodecSoftwareDecodingForbidden(const VideoDecoderConfig& config) { 18 bool IsMediaCodecSoftwareDecodingForbidden(const VideoDecoderConfig& config) {
98 return !config.is_encrypted() && 19 return !config.is_encrypted() &&
99 (config.codec() == kCodecVP8 || _config.codec() == kCodecVP9); 20 (config.codec() == kCodecVP8 || config.codec() == kCodecVP9);
100 } 21 }
101 22
102 bool ConfigSupported(const VideoDecoderConfig& config) { 23 bool ConfigSupported(const VideoDecoderConfig& config) {
103 const auto codec = config.codec(); 24 // Don't support larger than 4k because it won't perform well on many devices.
25 const auto size = config.coded_size();
26 if (size.width() > 3840 || size.height() > 2160)
27 return false;
104 28
105 // Only use MediaCodec for VP8 or VP9 if it's likely backed by hardware or if 29 // Only use MediaCodec for VP8 or VP9 if it's likely backed by hardware or if
106 // the stream is encrypted. 30 // the stream is encrypted.
31 const auto codec = config.codec();
107 if (IsMediaCodecSoftwareDecodingForbidden(config) && 32 if (IsMediaCodecSoftwareDecodingForbidden(config) &&
108 VideoCodecBridge::IsKnownUnaccelerated(codec, MEDIA_CODEC_DECODER)) { 33 VideoCodecBridge::IsKnownUnaccelerated(codec, MEDIA_CODEC_DECODER)) {
109 DVLOG(1) << "Config not supported: " << GetCodecName(codec) 34 DVLOG(1) << "Config not supported: " << GetCodecName(codec)
110 << " is not hardware accelerated"; 35 << " is not hardware accelerated";
111 return false; 36 return false;
112 } 37 }
113 38
114 // Don't support larger than 4k because it won't perform well on many devices.
115 const auto size = config.coded_size();
116 if (size.width() > 3840 || size.height() > 2160)
117 return false;
118
119 switch (codec) { 39 switch (codec) {
120 case kCodecVP8: 40 case kCodecVP8:
121 case kCodecVP9: { 41 case kCodecVP9: {
122 if ((codec == kCodecVP8 && !MediaCodecUtil::IsVp8DecoderAvailable()) || 42 if ((codec == kCodecVP8 && !MediaCodecUtil::IsVp8DecoderAvailable()) ||
123 (codec == kCodecVP9 && !MediaCodecUtil::IsVp9DecoderAvailable())) { 43 (codec == kCodecVP9 && !MediaCodecUtil::IsVp9DecoderAvailable())) {
124 return false; 44 return false;
125 } 45 }
126 46
127 // There's no fallback for encrypted content so we support all sizes. 47 // There's no fallback for encrypted content so we support all sizes.
128 if (config.is_encrypted()) 48 if (config.is_encrypted())
(...skipping 13 matching lines...) Expand all
142 case kCodecHEVC: 62 case kCodecHEVC:
143 return true; 63 return true;
144 #endif 64 #endif
145 default: 65 default:
146 return false; 66 return false;
147 } 67 }
148 } 68 }
149 69
150 } // namespace 70 } // namespace
151 71
152 // MCVDManager manages shared resources for a number of MCVD instances. 72 MediaCodecVideoDecoder::MediaCodecVideoDecoder() {}
153 // Its responsibilities include:
154 // - Starting and stopping a shared "construction" thread for instantiating and
155 // releasing MediaCodecs.
156 // - Detecting when a task has hung on the construction thread so MCVDs can
157 // stop using it.
158 // - Running a RepeatingTimer so that MCVDs can get a regular callback to
159 // DoIOTask().
160 // - Tracking the allocation of surfaces to MCVDs and delivering callbacks when
161 // surfaces are released.
162 class MCVDManager {
163 public:
164 // Request periodic callback of |mcvd|->DoIOTask(). Does nothing if the
165 // instance is already registered and the timer started. The first request
166 // will start the repeating timer on an interval of DecodePollDelay.
167 void StartTimer(MediaCodecVideoDecoder* mcvd) {
168 DCHECK(thread_checker_.CalledOnValidThread());
169 73
170 timer_mcvd_instances_.insert(mcvd); 74 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {}
171 75
172 // If the timer is running, StopTimer() might have been called earlier, if 76 void MediaCodecVideoDecoder::Initialize(const VideoDecoderConfig& config,
173 // so remove the instance from the pending erasures. 77 bool low_delay,
174 if (timer_running_) 78 CdmContext* cdm_context,
175 pending_erase_.erase(mcvd); 79 const InitCB& init_cb,
176 80 const OutputCB& output_cb) {
177 if (io_timer_.IsRunning()) 81 init_cb.Run(ConfigSupported(config));
178 return;
179 io_timer_.Start(FROM_HERE, DecodePollDelay, this, &MCVDManager::RunTimer);
180 }
181
182 // Stop callbacks to |mcvd|->DoIOTask(). Does nothing if the instance is not
183 // registered. If there are no instances left, the repeating timer will be
184 // stopped.
185 void StopTimer(MediaCodecVideoDecoder* mcvd) {
186 DCHECK(thread_checker_.CalledOnValidThread());
187
188 // If the timer is running, defer erasures to avoid iterator invalidation.
189 if (timer_running_) {
190 pending_erase_.insert(mcvd);
191 return;
192 }
193
194 timer_mcvd_instances_.erase(mcvd);
195 if (timer_mcvd_instances_.empty())
196 io_timer_.Stop();
197 }
198
199 private:
200 friend struct base::DefaultLazyInstanceTraits<MCVDManager>;
201
202 MCVDManager() {}
203 ~MCVDManager() { NOTREACHED(); }
204
205 void RunTimer() {
206 {
207 // Call out to all MCVD instances, some of which may attempt to remove
208 // themselves from the list during this operation; those removals will be
209 // deferred until after all iterations are complete.
210 base::AutoReset<bool> scoper(&timer_running_, true);
211 for (auto* mcvd : timer_mcvd_instances_)
212 mcvd->DoIOTask(false);
213 }
214
215 // Take care of any deferred erasures.
216 for (auto* mcvd : pending_erase_)
217 StopTimer(mcvd);
218 pending_erase_.clear();
219
220 // TODO(dalecurtis): We may want to consider chunking this if task execution
221 // takes too long for the combined timer.
222 }
223
224 // All MCVD instances that would like us to poll DoIOTask.
225 std::set<MediaCodecVideoDecoder*> timer_mcvd_instances_;
226
227 // Since we can't delete while iterating when using a set, defer erasure until
228 // after iteration complete.
229 bool timer_running_ = false;
230 std::set<MediaCodecVideoDecoder*> pending_erase_;
231
232 // Repeating timer responsible for draining pending IO to the codecs.
233 base::RepeatingTimer io_timer_;
234
235 base::ThreadChecker thread_checker_;
236
237 DISALLOW_COPY_AND_ASSIGN(MCVDManager);
238 };
239
240 static base::LazyInstance<MCVDManager>::Leaky g_mcvd_manager =
241 LAZY_INSTANCE_INITIALIZER;
242
243 MediaCodecVideoDecoder::BitstreamRecord::BitstreamRecord(
244 const BitstreamBuffer& bitstream_buffer)
245 : buffer(bitstream_buffer) {
246 if (buffer.id() != -1)
247 memory.reset(new SharedMemoryRegion(buffer, true));
248 } 82 }
249 83
250 MediaCodecVideoDecoder::BitstreamRecord::BitstreamRecord( 84 void MediaCodecVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
251 BitstreamRecord&& other) 85 const DecodeCB& decode_cb) {
252 : buffer(std::move(other.buffer)), memory(std::move(other.memory)) {} 86 NOTIMPLEMENTED();
253
254 MediaCodecVideoDecoder::BitstreamRecord::~BitstreamRecord() {}
255
256 MediaCodecVideoDecoder::MediaCodecVideoDecoder(
257 const MakeGLContextCurrentCallback& make_context_current_cb,
258 const GetGLES2DecoderCallback& get_gles2_decoder_cb)
259 : client_(NULL),
260 make_context_current_cb_(make_context_current_cb),
261 get_gles2_decoder_cb_(get_gles2_decoder_cb),
262 state_(NO_ERROR),
263 picture_buffer_manager_(get_gles2_decoder_cb),
264 drain_type_(DRAIN_TYPE_NONE),
265 media_drm_bridge_cdm_context_(nullptr),
266 cdm_registration_id_(0),
267 pending_input_buf_index_(-1),
268 deferred_initialization_pending_(false),
269 codec_needs_reset_(false),
270 defer_surface_creation_(false),
271 weak_this_factory_(this) {}
272
273 MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
274 DCHECK(thread_checker_.CalledOnValidThread());
275 g_mcvd_manager.Get().StopTimer(this);
276 AVDACodecAllocator::Instance()->StopThread(this);
277
278 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
279 if (!media_drm_bridge_cdm_context_)
280 return;
281
282 DCHECK(cdm_registration_id_);
283
284 // Cancel previously registered callback (if any).
285 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(
286 MediaDrmBridgeCdmContext::MediaCryptoReadyCB());
287
288 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_);
289 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
290 } 87 }
291 88
292 bool MediaCodecVideoDecoder::Initialize(const Config& config, Client* client) { 89 void MediaCodecVideoDecoder::Reset(const base::Closure& closure) {
293 DVLOG(1) << __func__ << ": " << config.AsHumanReadableString(); 90 NOTIMPLEMENTED();
294 TRACE_EVENT0("media", "MCVD::Initialize"); 91 }
295 DCHECK(!media_codec_);
296 DCHECK(thread_checker_.CalledOnValidThread());
297 92
298 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { 93 std::string MediaCodecVideoDecoder::GetDisplayName() const {
299 DLOG(ERROR) << "GL callbacks are required for this VDA"; 94 return "MediaCodecVideoDecoder";
300 return false; 95 }
301 }
302 96
303 if (config.output_mode != Config::OutputMode::ALLOCATE) { 97 bool MediaCodecVideoDecoder::NeedsBitstreamConversion() const {
304 DLOG(ERROR) << "Only ALLOCATE OutputMode is supported by this VDA";
305 return false;
306 }
307
308 DCHECK(client);
309 client_ = client;
310 config_ = config;
311 codec_config_ = new CodecConfig();
312 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile);
313 codec_config_->initial_expected_coded_size_ =
314 config.initial_expected_coded_size;
315
316 if (codec_config_->codec_ != kCodecVP8 &&
317 codec_config_->codec_ != kCodecVP9 &&
318 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
319 codec_config_->codec_ != kCodecHEVC &&
320 #endif
321 codec_config_->codec_ != kCodecH264) {
322 DLOG(ERROR) << "Unsupported profile: " << config.profile;
323 return false;
324 }
325
326 if (codec_config_->codec_ == kCodecH264) {
327 codec_config_->csd0_ = config.sps;
328 codec_config_->csd1_ = config.pps;
329 }
330
331 // Only use MediaCodec for VP8/9 if it's likely backed by hardware
332 // or if the stream is encrypted.
333 if (IsMediaCodecSoftwareDecodingForbidden() &&
334 VideoCodecBridge::IsKnownUnaccelerated(codec_config_->codec_,
335 MEDIA_CODEC_DECODER)) {
336 DVLOG(1) << "Initialization failed: "
337 << (codec_config_->codec_ == kCodecVP8 ? "vp8" : "vp9")
338 << " is not hardware accelerated";
339 return false;
340 }
341
342 auto gles_decoder = get_gles2_decoder_cb_.Run();
343 if (!gles_decoder) {
344 DLOG(ERROR) << "Failed to get gles2 decoder instance.";
345 return false;
346 }
347
348 // SetSurface() can't be called before Initialize(), so we pick up our first
349 // surface ID from the codec configuration.
350 DCHECK(!pending_surface_id_);
351
352 // If we're low on resources, we may decide to defer creation of the surface
353 // until the codec is actually used.
354 if (ShouldDeferSurfaceCreation(config_.surface_id, codec_config_->codec_)) {
355 DCHECK(!deferred_initialization_pending_);
356 // We should never be here if a SurfaceView is required.
357 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID);
358 defer_surface_creation_ = true;
359 NotifyInitializationComplete(true);
360 return true;
361 }
362
363 // We signaled that we support deferred initialization, so see if the client
364 // does also.
365 deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
366 if (config_.is_encrypted && !deferred_initialization_pending_) {
367 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams";
368 return false;
369 }
370
371 if (AVDACodecAllocator::Instance()->AllocateSurface(this,
372 config_.surface_id)) {
373 // We now own the surface, so finish initialization.
374 return InitializePictureBufferManager();
375 }
376
377 // We have to wait for some other MCVD instance to free up the surface.
378 // OnSurfaceAvailable will be called when it's available.
379 return true; 98 return true;
380 } 99 }
381 100
382 void MediaCodecVideoDecoder::OnSurfaceAvailable(bool success) { 101 bool MediaCodecVideoDecoder::CanReadWithoutStalling() const {
383 DCHECK(deferred_initialization_pending_); 102 NOTIMPLEMENTED();
384 DCHECK(!defer_surface_creation_); 103 return false;
385
386 if (!success || !InitializePictureBufferManager()) {
387 NotifyInitializationComplete(false);
388 deferred_initialization_pending_ = false;
389 }
390 } 104 }
391 105
392 bool MediaCodecVideoDecoder::InitializePictureBufferManager() { 106 int MediaCodecVideoDecoder::GetMaxDecodeRequests() const {
393 if (!make_context_current_cb_.Run()) { 107 return 4;
394 LOG(ERROR) << "Failed to make this decoder's GL context current.";
395 return false;
396 }
397
398 codec_config_->surface_ =
399 picture_buffer_manager_.Initialize(config_.surface_id);
400 if (codec_config_->surface_.IsEmpty())
401 return false;
402
403 if (!AVDACodecAllocator::Instance()->StartThread(this))
404 return false;
405
406 // If we are encrypted, then we aren't able to create the codec yet.
407 if (config_.is_encrypted) {
408 InitializeCdm();
409 return true;
410 }
411
412 if (deferred_initialization_pending_ || defer_surface_creation_) {
413 defer_surface_creation_ = false;
414 ConfigureMediaCodecAsynchronously();
415 return true;
416 }
417 }
418
419 void MediaCodecVideoDecoder::DoIOTask(bool start_timer) {
420 DCHECK(thread_checker_.CalledOnValidThread());
421 TRACE_EVENT0("media", "MCVD::DoIOTask");
422 if (state_ == ERROR || state_ == WAITING_FOR_CODEC ||
423 state_ == SURFACE_DESTROYED) {
424 return;
425 }
426
427 picture_buffer_manager_.MaybeRenderEarly();
428 bool did_work = false, did_input = false, did_output = false;
429 do {
430 did_input = QueueInput();
431 did_output = DequeueOutput();
432 if (did_input || did_output)
433 did_work = true;
434 } while (did_input || did_output);
435
436 ManageTimer(did_work || start_timer);
437 }
438
439 bool MediaCodecVideoDecoder::QueueInput() {
440 DCHECK(thread_checker_.CalledOnValidThread());
441 TRACE_EVENT0("media", "MCVD::QueueInput");
442 if (state_ == ERROR || state_ == WAITING_FOR_CODEC ||
443 state_ == WAITING_FOR_KEY) {
444 return false;
445 }
446 if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance)
447 return false;
448 if (pending_bitstream_records_.empty())
449 return false;
450
451 int input_buf_index = pending_input_buf_index_;
452
453 // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY.
454 // That status does not return this buffer back to the pool of
455 // available input buffers. We have to reuse it in QueueSecureInputBuffer().
456 if (input_buf_index == -1) {
457 MediaCodecStatus status =
458 media_codec_->DequeueInputBuffer(NoWaitTimeOut, &input_buf_index);
459 switch (status) {
460 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER:
461 return false;
462 case MEDIA_CODEC_ERROR:
463 NOTIFY_ERROR(PLATFORM_FAILURE, "DequeueInputBuffer failed");
464 return false;
465 case MEDIA_CODEC_OK:
466 break;
467 default:
468 NOTREACHED();
469 return false;
470 }
471 }
472
473 DCHECK_NE(input_buf_index, -1);
474
475 BitstreamBuffer bitstream_buffer = pending_bitstream_records_.front().buffer;
476
477 if (bitstream_buffer.id() == -1) {
478 pending_bitstream_records_.pop();
479 TRACE_COUNTER1("media", "MCVD::PendingBitstreamBufferCount",
480 pending_bitstream_records_.size());
481
482 media_codec_->QueueEOS(input_buf_index);
483 return true;
484 }
485
486 std::unique_ptr<SharedMemoryRegion> shm;
487
488 if (pending_input_buf_index_ == -1) {
489 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued
490 // from MediaCodec, filled with data and bitstream_buffer.handle() is
491 // closed.
492 shm = std::move(pending_bitstream_records_.front().memory);
493
494 if (!shm->Map()) {
495 NOTIFY_ERROR(UNREADABLE_INPUT, "SharedMemoryRegion::Map() failed");
496 return false;
497 }
498 }
499
500 const base::TimeDelta presentation_timestamp =
501 bitstream_buffer.presentation_timestamp();
502 DCHECK(presentation_timestamp != kNoTimestamp)
503 << "Bitstream buffers must have valid presentation timestamps";
504
505 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt
506 // ref frames, but it's OK to overwrite it because we only expect a single
507 // output frame to have that timestamp. MCVD clients only use the bitstream
508 // buffer id in the returned Pictures to map a bitstream buffer back to a
509 // timestamp on their side, so either one of the bitstream buffer ids will
510 // result in them finding the right timestamp.
511 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id();
512
513 // Notice that |memory| will be null if we repeatedly enqueue the same buffer,
514 // this happens after MEDIA_CODEC_NO_KEY.
515 const uint8_t* memory =
516 shm ? static_cast<const uint8_t*>(shm->memory()) : nullptr;
517 const std::string& key_id = bitstream_buffer.key_id();
518 const std::string& iv = bitstream_buffer.iv();
519 const std::vector<SubsampleEntry>& subsamples = bitstream_buffer.subsamples();
520
521 MediaCodecStatus status;
522 if (key_id.empty() || iv.empty()) {
523 status = media_codec_->QueueInputBuffer(input_buf_index, memory,
524 bitstream_buffer.size(),
525 presentation_timestamp);
526 } else {
527 status = media_codec_->QueueSecureInputBuffer(
528 input_buf_index, memory, bitstream_buffer.size(), key_id, iv,
529 subsamples, presentation_timestamp);
530 }
531
532 DVLOG(2) << __func__
533 << ": Queue(Secure)InputBuffer: pts:" << presentation_timestamp
534 << " status:" << status;
535
536 if (status == MEDIA_CODEC_NO_KEY) {
537 // Keep trying to enqueue the same input buffer.
538 // The buffer is owned by us (not the MediaCodec) and is filled with data.
539 DVLOG(1) << "QueueSecureInputBuffer failed: NO_KEY";
540 pending_input_buf_index_ = input_buf_index;
541 state_ = WAITING_FOR_KEY;
542 return false;
543 }
544
545 pending_input_buf_index_ = -1;
546 pending_bitstream_records_.pop();
547 TRACE_COUNTER1("media", "MCVD::PendingBitstreamBufferCount",
548 pending_bitstream_records_.size());
549 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output
550 // will be returned from the bitstream buffer. However, MediaCodec API is
551 // not enough to guarantee it.
552 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to
553 // keep getting more bitstreams from the client, and throttle them by using
554 // |bitstreams_notified_in_advance_|.
555 // TODO(dwkang): check if there is a way to remove this workaround.
556 base::ThreadTaskRunnerHandle::Get()->PostTask(
557 FROM_HERE,
558 base::Bind(&MediaCodecVideoDecoder::NotifyEndOfBitstreamBuffer,
559 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id()));
560 bitstreams_notified_in_advance_.push_back(bitstream_buffer.id());
561
562 if (status != MEDIA_CODEC_OK) {
563 NOTIFY_ERROR(PLATFORM_FAILURE, "QueueInputBuffer failed:" << status);
564 return false;
565 }
566
567 return true;
568 }
569
570 bool MediaCodecVideoDecoder::DequeueOutput() {
571 DCHECK(thread_checker_.CalledOnValidThread());
572 TRACE_EVENT0("media", "MCVD::DequeueOutput");
573 if (state_ == ERROR || state_ == WAITING_FOR_CODEC)
574 return false;
575 if (!output_picture_buffers_.empty() && free_picture_ids_.empty() &&
576 !IsDrainingForResetOrDestroy()) {
577 // Don't have any picture buffer to send. Need to wait.
578 return false;
579 }
580
581 // If we're waiting to switch surfaces pause output release until we have all
582 // picture buffers returned. This is so we can ensure the right flags are set
583 // on the picture buffers returned to the client.
584 if (pending_surface_id_) {
585 if (picture_buffer_manager_.HasUnrenderedPictures())
586 return false;
587 if (!UpdateSurface())
588 return false;
589 }
590
591 bool eos = false;
592 base::TimeDelta presentation_timestamp;
593 int32_t buf_index = 0;
594 do {
595 size_t offset = 0;
596 size_t size = 0;
597
598 TRACE_EVENT_BEGIN0("media", "MCVD::DequeueOutput");
599 MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
600 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp,
601 &eos, NULL);
602 TRACE_EVENT_END2("media", "MCVD::DequeueOutput", "status", status,
603 "presentation_timestamp (ms)",
604 presentation_timestamp.InMilliseconds());
605
606 switch (status) {
607 case MEDIA_CODEC_ERROR:
608 // Do not post an error if we are draining for reset and destroy.
609 // Instead, run the drain completion task.
610 if (IsDrainingForResetOrDestroy()) {
611 DVLOG(1) << __func__ << ": error while codec draining";
612 state_ = ERROR;
613 OnDrainCompleted();
614 } else {
615 NOTIFY_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed.");
616 }
617 return false;
618
619 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
620 return false;
621
622 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: {
623 // An OUTPUT_FORMAT_CHANGED is not reported after flush() if the frame
624 // size does not change. Therefore we have to keep track on the format
625 // even if draining, unless we are draining for destroy.
626 if (drain_type_ == DRAIN_FOR_DESTROY)
627 return true; // ignore
628
629 if (media_codec_->GetOutputSize(&size_) != MEDIA_CODEC_OK) {
630 NOTIFY_ERROR(PLATFORM_FAILURE, "GetOutputSize failed.");
631 return false;
632 }
633
634 DVLOG(3) << __func__
635 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString();
636 return true;
637 }
638
639 case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
640 break;
641
642 case MEDIA_CODEC_OK:
643 DCHECK_GE(buf_index, 0);
644 DVLOG(3) << __func__ << ": pts:" << presentation_timestamp
645 << " buf_index:" << buf_index << " offset:" << offset
646 << " size:" << size << " eos:" << eos;
647 break;
648
649 default:
650 NOTREACHED();
651 break;
652 }
653 } while (buf_index < 0);
654
655 if (eos) {
656 OnDrainCompleted();
657 return false;
658 }
659
660 if (IsDrainingForResetOrDestroy()) {
661 media_codec_->ReleaseOutputBuffer(buf_index, false);
662 return true;
663 }
664
665 // TODO(watk): Handle the case where we get a decoded buffer before
666 // FORMAT_CHANGED.
667 // In 0.01% of playbacks MediaCodec returns a frame before FORMAT_CHANGED.
668 // Occurs on JB and M. (See the Media.MCVD.MissingFormatChanged histogram.)
669
670 // Get the bitstream buffer id from the timestamp.
671 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp);
672
673 if (it != bitstream_buffers_in_decoder_.end()) {
674 const int32_t bitstream_buffer_id = it->second;
675 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(),
676 ++it);
677 SendDecodedFrameToClient(buf_index, bitstream_buffer_id);
678
679 // Removes ids former or equal than the id from decoder. Note that
680 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder
681 // because of frame reordering issue. We just maintain this roughly and use
682 // it for throttling.
683 for (auto bitstream_it = bitstreams_notified_in_advance_.begin();
684 bitstream_it != bitstreams_notified_in_advance_.end();
685 ++bitstream_it) {
686 if (*bitstream_it == bitstream_buffer_id) {
687 bitstreams_notified_in_advance_.erase(
688 bitstreams_notified_in_advance_.begin(), ++bitstream_it);
689 break;
690 }
691 }
692 } else {
693 // Normally we assume that the decoder makes at most one output frame for
694 // each distinct input timestamp. However MediaCodecBridge uses timestamp
695 // correction and provides a non-decreasing timestamp sequence, which might
696 // result in timestamp duplicates. Discard the frame if we cannot get the
697 // corresponding buffer id.
698 DVLOG(3) << __func__ << ": Releasing buffer with unexpected PTS: "
699 << presentation_timestamp;
700 media_codec_->ReleaseOutputBuffer(buf_index, false);
701 }
702
703 // We got a decoded frame, so try for another.
704 return true;
705 }
706
707 void MediaCodecVideoDecoder::SendDecodedFrameToClient(
708 int32_t codec_buffer_index,
709 int32_t bitstream_id) {
710 DCHECK(thread_checker_.CalledOnValidThread());
711 DCHECK_NE(bitstream_id, -1);
712 DCHECK(!free_picture_ids_.empty());
713 TRACE_EVENT0("media", "MCVD::SendDecodedFrameToClient");
714
715 if (!make_context_current_cb_.Run()) {
716 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current.");
717 return;
718 }
719
720 int32_t picture_buffer_id = free_picture_ids_.front();
721 free_picture_ids_.pop();
722 TRACE_COUNTER1("media", "MCVD::FreePictureIds", free_picture_ids_.size());
723
724 const auto it = output_picture_buffers_.find(picture_buffer_id);
725 if (it == output_picture_buffers_.end()) {
726 NOTIFY_ERROR(PLATFORM_FAILURE,
727 "Can't find PictureBuffer id: " << picture_buffer_id);
728 return;
729 }
730
731 PictureBuffer& picture_buffer = it->second;
732 const bool size_changed = picture_buffer.size() != size_;
733 if (size_changed)
734 picture_buffer.set_size(size_);
735
736 const bool allow_overlay = picture_buffer_manager_.ArePicturesOverlayable();
737 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.FrameSentAsOverlay", allow_overlay);
738 // TODO(hubbe): Insert the correct color space. http://crbug.com/647725
739 Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_),
740 gfx::ColorSpace(), allow_overlay);
741 picture.set_size_changed(size_changed);
742
743 // Notify picture ready before calling UseCodecBufferForPictureBuffer() since
744 // that process may be slow and shouldn't delay delivery of the frame to the
745 // renderer. The picture is only used on the same thread as this method is
746 // called, so it is safe to do this.
747 NotifyPictureReady(picture);
748
749 // Connect the PictureBuffer to the decoded frame.
750 if (!picture_buffer_manager_.UseCodecBufferForPictureBuffer(
751 codec_buffer_index, picture_buffer, size_)) {
752 NOTIFY_ERROR(PLATFORM_FAILURE,
753 "Failed to attach the codec buffer to a picture buffer.");
754 }
755 }
756
757 void MediaCodecVideoDecoder::Decode(const BitstreamBuffer& bitstream_buffer) {
758 DCHECK(thread_checker_.CalledOnValidThread());
759
760 if (defer_surface_creation_ && !InitializePictureBufferManager()) {
761 NOTIFY_ERROR(PLATFORM_FAILURE,
762 "Failed deferred surface and MediaCodec initialization.");
763 return;
764 }
765
766 // If we previously deferred a codec restart, take care of it now. This can
767 // happen on older devices where configuration changes require a codec reset.
768 if (codec_needs_reset_) {
769 DCHECK_EQ(drain_type_, DRAIN_TYPE_NONE);
770 ResetCodecState();
771 }
772
773 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) {
774 DecodeBuffer(bitstream_buffer);
775 return;
776 }
777
778 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
779 base::SharedMemory::CloseHandle(bitstream_buffer.handle());
780
781 if (bitstream_buffer.id() < 0) {
782 NOTIFY_ERROR(INVALID_ARGUMENT,
783 "Invalid bistream_buffer, id: " << bitstream_buffer.id());
784 } else {
785 base::ThreadTaskRunnerHandle::Get()->PostTask(
786 FROM_HERE,
787 base::Bind(&MediaCodecVideoDecoder::NotifyEndOfBitstreamBuffer,
788 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id()));
789 }
790 }
791
792 void MediaCodecVideoDecoder::DecodeBuffer(
793 const BitstreamBuffer& bitstream_buffer) {
794 pending_bitstream_records_.push(BitstreamRecord(bitstream_buffer));
795 TRACE_COUNTER1("media", "MCVD::PendingBitstreamBufferCount",
796 pending_bitstream_records_.size());
797
798 DoIOTask(true);
799 }
800
801 void MediaCodecVideoDecoder::Flush() {
802 DVLOG(1) << __func__;
803 DCHECK(thread_checker_.CalledOnValidThread());
804
805 if (state_ == SURFACE_DESTROYED || defer_surface_creation_)
806 NotifyFlushDone();
807 else
808 StartCodecDrain(DRAIN_FOR_FLUSH);
809 }
810
811 void MediaCodecVideoDecoder::ConfigureMediaCodecAsynchronously() {
812 DCHECK(thread_checker_.CalledOnValidThread());
813
814 DCHECK_NE(state_, WAITING_FOR_CODEC);
815 state_ = WAITING_FOR_CODEC;
816
817 if (media_codec_) {
818 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
819 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
820 picture_buffer_manager_.CodecChanged(nullptr);
821 }
822
823 codec_config_->task_type_ =
824 AVDACodecAllocator::Instance()->TaskTypeForAllocation();
825 if (codec_config_->task_type_ == TaskType::FAILED_CODEC) {
826 // If there is no free thread, then just fail.
827 OnCodecConfigured(nullptr);
828 return;
829 }
830
831 // If autodetection is disallowed, fall back to Chrome's software decoders
832 // instead of using the software decoders provided by MediaCodec.
833 if (codec_config_->task_type_ == TaskType::SW_CODEC &&
834 IsMediaCodecSoftwareDecodingForbidden()) {
835 OnCodecConfigured(nullptr);
836 return;
837 }
838
839 AVDACodecAllocator::Instance()->CreateMediaCodecAsync(
840 weak_this_factory_.GetWeakPtr(), codec_config_);
841 }
842
843 void MediaCodecVideoDecoder::OnCodecConfigured(
844 std::unique_ptr<VideoCodecBridge> media_codec) {
845 DCHECK(thread_checker_.CalledOnValidThread());
846 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
847
848 // If we are supposed to notify that initialization is complete, then do so
849 // now. Otherwise, this is a reconfiguration.
850 if (deferred_initialization_pending_) {
851 // Losing the output surface is not considered an error state, so notify
852 // success. The client will destroy this soon.
853 NotifyInitializationComplete(state_ == SURFACE_DESTROYED ? true
854 : !!media_codec);
855 deferred_initialization_pending_ = false;
856 }
857
858 // If |state_| changed to SURFACE_DESTROYED while we were configuring a codec,
859 // then the codec is already invalid so we return early and drop it.
860 if (state_ == SURFACE_DESTROYED)
861 return;
862
863 DCHECK(!media_codec_);
864 media_codec_ = std::move(media_codec);
865 picture_buffer_manager_.CodecChanged(media_codec_.get());
866 if (!media_codec_) {
867 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec");
868 return;
869 }
870
871 state_ = NO_ERROR;
872
873 ManageTimer(true);
874 }
875
876 void MediaCodecVideoDecoder::StartCodecDrain(DrainType drain_type) {
877 DVLOG(2) << __func__ << " drain_type:" << drain_type;
878 DCHECK(thread_checker_.CalledOnValidThread());
879
880 // We assume that DRAIN_FOR_FLUSH and DRAIN_FOR_RESET cannot come while
881 // another drain request is present, but DRAIN_FOR_DESTROY can.
882 DCHECK_NE(drain_type, DRAIN_TYPE_NONE);
883 DCHECK(drain_type_ == DRAIN_TYPE_NONE || drain_type == DRAIN_FOR_DESTROY)
884 << "Unexpected StartCodecDrain() with drain type " << drain_type
885 << " while already draining with drain type " << drain_type_;
886
887 const bool enqueue_eos = drain_type_ == DRAIN_TYPE_NONE;
888 drain_type_ = drain_type;
889
890 if (enqueue_eos)
891 DecodeBuffer(BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
892 }
893
894 bool MediaCodecVideoDecoder::IsDrainingForResetOrDestroy() const {
895 return drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY;
896 }
897
898 void MediaCodecVideoDecoder::OnDrainCompleted() {
899 DVLOG(2) << __func__;
900 DCHECK(thread_checker_.CalledOnValidThread());
901
902 // If we were waiting for an EOS, clear the state and reset the MediaCodec
903 // as normal.
904 //
905 // Some Android platforms seem to send an EOS buffer even when we're not
906 // expecting it. In this case, destroy and reset the codec but don't notify
907 // flush done since it violates the state machine. http://crbug.com/585959.
908
909 switch (drain_type_) {
910 case DRAIN_TYPE_NONE:
911 // Unexpected EOS.
912 state_ = ERROR;
913 ResetCodecState();
914 break;
915 case DRAIN_FOR_FLUSH:
916 ResetCodecState();
917 base::ThreadTaskRunnerHandle::Get()->PostTask(
918 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::NotifyFlushDone,
919 weak_this_factory_.GetWeakPtr()));
920 break;
921 case DRAIN_FOR_RESET:
922 ResetCodecState();
923 base::ThreadTaskRunnerHandle::Get()->PostTask(
924 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::NotifyResetDone,
925 weak_this_factory_.GetWeakPtr()));
926 break;
927 case DRAIN_FOR_DESTROY:
928 ResetCodecState();
929 base::ThreadTaskRunnerHandle::Get()->PostTask(
930 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::ActualDestroy,
931 weak_this_factory_.GetWeakPtr()));
932 break;
933 }
934 drain_type_ = DRAIN_TYPE_NONE;
935 }
936
937 void MediaCodecVideoDecoder::ResetCodecState() {
938 DCHECK(thread_checker_.CalledOnValidThread());
939
940 // If there is already a reset in flight, then that counts. This can really
941 // only happen if somebody calls Reset.
942 // If the surface is destroyed there's nothing to do.
943 if (state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED)
944 return;
945
946 bitstream_buffers_in_decoder_.clear();
947
948 if (pending_input_buf_index_ != -1) {
949 // The data for that index exists in the input buffer, but corresponding
950 // shm block been deleted. Check that it is safe to flush the codec, i.e.
951 // |pending_bitstream_records_| is empty.
952 // TODO(timav): keep shm block for that buffer and remove this restriction.
953 DCHECK(pending_bitstream_records_.empty());
954 pending_input_buf_index_ = -1;
955 }
956
957 const bool did_codec_error_happen = state_ == ERROR;
958 state_ = NO_ERROR;
959
960 // Don't reset the codec here if there's no error and we're only flushing;
961 // instead defer until the next decode call; this prevents us from unbacking
962 // frames that might be out for display at end of stream.
963 codec_needs_reset_ = false;
964 if (drain_type_ == DRAIN_FOR_FLUSH && !did_codec_error_happen) {
965 codec_needs_reset_ = true;
966 return;
967 }
968
969 // Flush the codec if possible, or create a new one if not.
970 if (!did_codec_error_happen &&
971 !MediaCodecUtil::CodecNeedsFlushWorkaround(media_codec_.get())) {
972 DVLOG(3) << __func__ << " Flushing MediaCodec.";
973 media_codec_->Flush();
974 // Since we just flushed all the output buffers, make sure that nothing is
975 // using them.
976 picture_buffer_manager_.CodecChanged(media_codec_.get());
977 } else {
978 DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one.";
979 g_mcvd_manager.Get().StopTimer(this);
980 ConfigureMediaCodecAsynchronously();
981 }
982 }
983
984 void MediaCodecVideoDecoder::Reset() {
985 DVLOG(1) << __func__;
986 DCHECK(thread_checker_.CalledOnValidThread());
987 TRACE_EVENT0("media", "MCVD::Reset");
988
989 if (defer_surface_creation_) {
990 DCHECK(!media_codec_);
991 DCHECK(pending_bitstream_records_.empty());
992 DCHECK_EQ(state_, NO_ERROR);
993 base::ThreadTaskRunnerHandle::Get()->PostTask(
994 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::NotifyResetDone,
995 weak_this_factory_.GetWeakPtr()));
996 return;
997 }
998
999 while (!pending_bitstream_records_.empty()) {
1000 int32_t bitstream_buffer_id =
1001 pending_bitstream_records_.front().buffer.id();
1002 pending_bitstream_records_.pop();
1003
1004 if (bitstream_buffer_id != -1) {
1005 base::ThreadTaskRunnerHandle::Get()->PostTask(
1006 FROM_HERE,
1007 base::Bind(&MediaCodecVideoDecoder::NotifyEndOfBitstreamBuffer,
1008 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id));
1009 }
1010 }
1011 TRACE_COUNTER1("media", "MCVD::PendingBitstreamBufferCount", 0);
1012 bitstreams_notified_in_advance_.clear();
1013
1014 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1015
1016 // Some VP8 files require complete MediaCodec drain before we can call
1017 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963.
1018 if (media_codec_ && codec_config_->codec_ == kCodecVP8 &&
1019 !bitstream_buffers_in_decoder_.empty()) {
1020 // Postpone ResetCodecState() after the drain.
1021 StartCodecDrain(DRAIN_FOR_RESET);
1022 } else {
1023 ResetCodecState();
1024 base::ThreadTaskRunnerHandle::Get()->PostTask(
1025 FROM_HERE, base::Bind(&MediaCodecVideoDecoder::NotifyResetDone,
1026 weak_this_factory_.GetWeakPtr()));
1027 }
1028 }
1029
1030 void MediaCodecVideoDecoder::SetSurface(int32_t surface_id) {
1031 DVLOG(1) << __func__;
1032 DCHECK(thread_checker_.CalledOnValidThread());
1033
1034 if (surface_id == config_.surface_id) {
1035 pending_surface_id_.reset();
1036 return;
1037 }
1038
1039 // Surface changes never take effect immediately, they will be handled during
1040 // DequeOutput() once we get to a good switch point or immediately during an
1041 // OnSurfaceDestroyed() call.
1042 pending_surface_id_ = surface_id;
1043 }
1044
1045 void MediaCodecVideoDecoder::Destroy() {
1046 DVLOG(1) << __func__;
1047 DCHECK(thread_checker_.CalledOnValidThread());
1048
1049 picture_buffer_manager_.Destroy(output_picture_buffers_);
1050
1051 client_ = nullptr;
1052
1053 // Some VP8 files require a complete MediaCodec drain before we can call
1054 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In
1055 // that case, postpone ActualDestroy() until after the drain.
1056 if (media_codec_ && codec_config_->codec_ == kCodecVP8) {
1057 // Clear |pending_bitstream_records_|.
1058 while (!pending_bitstream_records_.empty())
1059 pending_bitstream_records_.pop();
1060
1061 StartCodecDrain(DRAIN_FOR_DESTROY);
1062 } else {
1063 ActualDestroy();
1064 }
1065 }
1066
1067 void MediaCodecVideoDecoder::ActualDestroy() {
1068 DVLOG(1) << __func__;
1069 DCHECK(thread_checker_.CalledOnValidThread());
1070
1071 // Note that async codec construction might still be in progress. In that
1072 // case, the codec will be deleted when it completes once we invalidate all
1073 // our weak refs.
1074 weak_this_factory_.InvalidateWeakPtrs();
1075 g_mcvd_manager.Get().StopTimer(this);
1076 if (media_codec_) {
1077 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1078 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
1079 }
1080
1081 // We no longer care about |surface_id|, in case we did before. It's okay
1082 // if we have no surface and/or weren't the owner or a waiter.
1083 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id);
1084
1085 delete this;
1086 }
1087
1088 void MediaCodecVideoDecoder::OnSurfaceDestroyed() {
1089 DVLOG(1) << __func__;
1090 TRACE_EVENT0("media", "MCVD::OnSurfaceDestroyed");
1091 DCHECK(thread_checker_.CalledOnValidThread());
1092
1093 // If the API is available avoid having to restart the decoder in order to
1094 // leave fullscreen. If we don't clear the surface immediately during this
1095 // callback, the MediaCodec will throw an error as the surface is destroyed.
1096 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) {
1097 // Since we can't wait for a transition, we must invalidate all outstanding
1098 // picture buffers to avoid putting the GL system in a broken state.
1099 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1100
1101 // Switch away from the surface being destroyed to a surface texture.
1102 DCHECK_NE(config_.surface_id, SurfaceManager::kNoSurfaceID);
1103
1104 // The leaving fullscreen notification may come in before this point.
1105 if (pending_surface_id_)
1106 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID);
1107
1108 pending_surface_id_ = SurfaceManager::kNoSurfaceID;
1109 UpdateSurface();
1110 return;
1111 }
1112
1113 // If we're currently asynchronously configuring a codec, it will be destroyed
1114 // when configuration completes and it notices that |state_| has changed to
1115 // SURFACE_DESTROYED.
1116 state_ = SURFACE_DESTROYED;
1117 if (media_codec_) {
1118 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1119 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
1120 picture_buffer_manager_.CodecChanged(nullptr);
1121 }
1122
1123 // If we're draining, signal completion now because the drain can no longer
1124 // proceed.
1125 if (drain_type_ != DRAIN_TYPE_NONE)
1126 OnDrainCompleted();
1127 }
1128
1129 void MediaCodecVideoDecoder::InitializeCdm() {
1130 DVLOG(2) << __func__ << ": " << config_.cdm_id;
1131
1132 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
1133 NOTIMPLEMENTED();
1134 NotifyInitializationComplete(false);
1135 #else
1136 // Store the CDM to hold a reference to it.
1137 cdm_for_reference_holding_only_ =
1138 MojoCdmService::LegacyGetCdm(config_.cdm_id);
1139 DCHECK(cdm_for_reference_holding_only_);
1140
1141 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext.
1142 media_drm_bridge_cdm_context_ = static_cast<MediaDrmBridgeCdmContext*>(
1143 cdm_for_reference_holding_only_->GetCdmContext());
1144 DCHECK(media_drm_bridge_cdm_context_);
1145
1146 // Register CDM callbacks. The callbacks registered will be posted back to
1147 // this thread via BindToCurrentLoop.
1148
1149 // Since |this| holds a reference to the |cdm_|, by the time the CDM is
1150 // destructed, UnregisterPlayer() must have been called and |this| has been
1151 // destructed as well. So the |cdm_unset_cb| will never have a chance to be
1152 // called.
1153 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms.
1154 cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer(
1155 BindToCurrentLoop(base::Bind(&MediaCodecVideoDecoder::OnKeyAdded,
1156 weak_this_factory_.GetWeakPtr())),
1157 base::Bind(&base::DoNothing));
1158
1159 // Deferred initialization will continue in OnMediaCryptoReady().
1160 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(
1161 BindToCurrentLoop(base::Bind(&MediaCodecVideoDecoder::OnMediaCryptoReady,
1162 weak_this_factory_.GetWeakPtr())));
1163 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
1164 }
1165
1166 void MediaCodecVideoDecoder::OnMediaCryptoReady(
1167 MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
1168 bool needs_protected_surface) {
1169 DVLOG(1) << __func__;
1170
1171 if (!media_crypto) {
1172 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream.";
1173 cdm_for_reference_holding_only_ = nullptr;
1174 media_drm_bridge_cdm_context_ = nullptr;
1175 NotifyInitializationComplete(false);
1176 return;
1177 }
1178
1179 DCHECK(!media_crypto->is_null());
1180
1181 // We assume this is a part of the initialization process, thus MediaCodec
1182 // is not created yet.
1183 DCHECK(!media_codec_);
1184
1185 codec_config_->media_crypto_ = std::move(media_crypto);
1186 codec_config_->needs_protected_surface_ = needs_protected_surface;
1187
1188 // After receiving |media_crypto_| we can configure MediaCodec.
1189 ConfigureMediaCodecAsynchronously();
1190 }
1191
1192 void MediaCodecVideoDecoder::OnKeyAdded() {
1193 DVLOG(1) << __func__;
1194
1195 if (state_ == WAITING_FOR_KEY)
1196 state_ = NO_ERROR;
1197
1198 DoIOTask(true);
1199 }
1200
1201 void MediaCodecVideoDecoder::NotifyError(Error error) {
1202 state_ = ERROR;
1203 if (client_)
1204 client_->NotifyError(error);
1205 }
1206
1207 void MediaCodecVideoDecoder::ManageTimer(bool did_work) {
1208 bool should_be_running = true;
1209
1210 base::TimeTicks now = base::TimeTicks::Now();
1211 if (!did_work && !most_recent_work_.is_null()) {
1212 // Make sure that we have done work recently enough, else stop the timer.
1213 if (now - most_recent_work_ > IdleTimerTimeOut) {
1214 most_recent_work_ = base::TimeTicks();
1215 should_be_running = false;
1216 }
1217 } else {
1218 most_recent_work_ = now;
1219 }
1220
1221 if (should_be_running)
1222 g_mcvd_manager.Get().StartTimer(this);
1223 else
1224 g_mcvd_manager.Get().StopTimer(this);
1225 }
1226
1227
1228 bool MediaCodecVideoDecoder::UpdateSurface() {
1229 DCHECK(pending_surface_id_);
1230 DCHECK_NE(config_.surface_id, pending_surface_id_.value());
1231 DCHECK(config_.surface_id == SurfaceManager::kNoSurfaceID ||
1232 pending_surface_id_.value() == SurfaceManager::kNoSurfaceID);
1233
1234 const int previous_surface_id = config_.surface_id;
1235 const int new_surface_id = pending_surface_id_.value();
1236 pending_surface_id_.reset();
1237 bool success = true;
1238
1239 // TODO(watk): Fix this so we can wait for the new surface to be allocated.
1240 if (!AVDACodecAllocator::Instance()->AllocateSurface(this, new_surface_id)) {
1241 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to allocate the new surface");
1242 success = false;
1243 }
1244
1245 // Ensure the current context is active when switching surfaces; we may need
1246 // to create a new texture.
1247 if (success && !make_context_current_cb_.Run()) {
1248 NOTIFY_ERROR(PLATFORM_FAILURE,
1249 "Failed to make this decoder's GL context current when "
1250 "switching surfaces.");
1251 success = false;
1252 }
1253
1254 if (success) {
1255 codec_config_->surface_ =
1256 picture_buffer_manager_.Initialize(new_surface_id);
1257 if (codec_config_->surface_.IsEmpty()) {
1258 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces.");
1259 success = false;
1260 }
1261 }
1262
1263 if (success && media_codec_ &&
1264 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) {
1265 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces.");
1266 success = false;
1267 }
1268
1269 if (success) {
1270 config_.surface_id = new_surface_id;
1271 } else {
1272 // This might be called from OnSurfaceDestroyed(), so we have to release the
1273 // MediaCodec if we failed to switch the surface.
1274 if (media_codec_) {
1275 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1276 std::move(media_codec_), codec_config_->task_type_,
1277 previous_surface_id);
1278 picture_buffer_manager_.CodecChanged(nullptr);
1279 }
1280 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id);
1281 }
1282
1283 // Regardless of whether we succeeded, we no longer own the previous surface.
1284 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id);
1285
1286 return success;
1287 } 108 }
1288 109
1289 } // namespace media 110 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android/media_codec_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698