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 "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/android_copying_backing_strategy.h" |
| 14 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" |
13 #include "content/common/gpu/media/avda_return_on_failure.h" | 15 #include "content/common/gpu/media/avda_return_on_failure.h" |
14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 16 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
15 #include "media/base/bitstream_buffer.h" | 17 #include "media/base/bitstream_buffer.h" |
16 #include "media/base/limits.h" | 18 #include "media/base/limits.h" |
17 #include "media/base/timestamp_constants.h" | 19 #include "media/base/timestamp_constants.h" |
18 #include "media/base/video_decoder_config.h" | 20 #include "media/base/video_decoder_config.h" |
19 #include "media/video/picture.h" | 21 #include "media/video/picture.h" |
20 #include "ui/gl/android/scoped_java_surface.h" | 22 #include "ui/gl/android/scoped_java_surface.h" |
21 #include "ui/gl/android/surface_texture.h" | 23 #include "ui/gl/android/surface_texture.h" |
22 #include "ui/gl/gl_bindings.h" | 24 #include "ui/gl/gl_bindings.h" |
23 | 25 |
24 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 26 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
25 #include "media/base/media_keys.h" | 27 #include "media/base/media_keys.h" |
26 #include "media/mojo/services/mojo_cdm_service.h" | 28 #include "media/mojo/services/mojo_cdm_service.h" |
27 #endif | 29 #endif |
28 | 30 |
29 namespace content { | 31 namespace content { |
30 | 32 |
| 33 // TODO(liberato): It is unclear if we have an issue with deadlock during |
| 34 // playback if we lower this. Previously (crbug.com/176036), a deadlock |
| 35 // could occur during preroll. More recent tests have shown some |
| 36 // instability with kNumPictureBuffers==2 with similar symptoms |
| 37 // during playback. crbug.com/531588 . |
| 38 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; |
| 39 |
31 // Max number of bitstreams notified to the client with | 40 // Max number of bitstreams notified to the client with |
32 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. | 41 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
33 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; | 42 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
34 | 43 |
35 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) | 44 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) |
36 // MediaCodec is only guaranteed to support baseline, but some devices may | 45 // MediaCodec is only guaranteed to support baseline, but some devices may |
37 // support others. Advertise support for all H264 profiles and let the | 46 // support others. Advertise support for all H264 profiles and let the |
38 // MediaCodec fail when decoding if it's not actually supported. It's assumed | 47 // MediaCodec fail when decoding if it's not actually supported. It's assumed |
39 // that consumers won't have software fallback for H264 on Android anyway. | 48 // that consumers won't have software fallback for H264 on Android anyway. |
40 static const media::VideoCodecProfile kSupportedH264Profiles[] = { | 49 static const media::VideoCodecProfile kSupportedH264Profiles[] = { |
41 media::H264PROFILE_BASELINE, | 50 media::H264PROFILE_BASELINE, |
42 media::H264PROFILE_MAIN, | 51 media::H264PROFILE_MAIN, |
43 media::H264PROFILE_EXTENDED, | 52 media::H264PROFILE_EXTENDED, |
44 media::H264PROFILE_HIGH, | 53 media::H264PROFILE_HIGH, |
45 media::H264PROFILE_HIGH10PROFILE, | 54 media::H264PROFILE_HIGH10PROFILE, |
46 media::H264PROFILE_HIGH422PROFILE, | 55 media::H264PROFILE_HIGH422PROFILE, |
47 media::H264PROFILE_HIGH444PREDICTIVEPROFILE, | 56 media::H264PROFILE_HIGH444PREDICTIVEPROFILE, |
48 media::H264PROFILE_SCALABLEBASELINE, | 57 media::H264PROFILE_SCALABLEBASELINE, |
49 media::H264PROFILE_SCALABLEHIGH, | 58 media::H264PROFILE_SCALABLEHIGH, |
50 media::H264PROFILE_STEREOHIGH, | 59 media::H264PROFILE_STEREOHIGH, |
51 media::H264PROFILE_MULTIVIEWHIGH | 60 media::H264PROFILE_MULTIVIEWHIGH |
52 }; | 61 }; |
| 62 |
| 63 #define BACKING_STRATEGY AndroidDeferredRenderingBackingStrategy |
| 64 #else |
| 65 #define BACKING_STRATEGY AndroidCopyingBackingStrategy |
53 #endif | 66 #endif |
54 | 67 |
55 // Because MediaCodec is thread-hostile (must be poked on a single thread) and | 68 // Because MediaCodec is thread-hostile (must be poked on a single thread) and |
56 // has no callback mechanism (b/11990118), we must drive it by polling for | 69 // has no callback mechanism (b/11990118), we must drive it by polling for |
57 // complete frames (and available input buffers, when the codec is fully | 70 // complete frames (and available input buffers, when the codec is fully |
58 // saturated). This function defines the polling delay. The value used is an | 71 // saturated). This function defines the polling delay. The value used is an |
59 // arbitrary choice that trades off CPU utilization (spinning) against latency. | 72 // arbitrary choice that trades off CPU utilization (spinning) against latency. |
60 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). | 73 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). |
61 static inline const base::TimeDelta DecodePollDelay() { | 74 static inline const base::TimeDelta DecodePollDelay() { |
62 // An alternative to this polling scheme could be to dedicate a new thread | 75 // An alternative to this polling scheme could be to dedicate a new thread |
63 // (instead of using the ChildThread) to run the MediaCodec, and make that | 76 // (instead of using the ChildThread) to run the MediaCodec, and make that |
64 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it | 77 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it |
65 // believes the codec should complete "soon" (e.g. waiting for an input | 78 // believes the codec should complete "soon" (e.g. waiting for an input |
66 // buffer, or waiting for a picture when it knows enough complete input | 79 // buffer, or waiting for a picture when it knows enough complete input |
67 // pictures have been fed to saturate any internal buffering). This is | 80 // pictures have been fed to saturate any internal buffering). This is |
68 // speculative and it's unclear that this would be a win (nor that there's a | 81 // speculative and it's unclear that this would be a win (nor that there's a |
69 // reasonably device-agnostic way to fill in the "believes" above). | 82 // reasonably device-agnostic way to fill in the "believes" above). |
70 return base::TimeDelta::FromMilliseconds(10); | 83 return base::TimeDelta::FromMilliseconds(10); |
71 } | 84 } |
72 | 85 |
73 static inline const base::TimeDelta NoWaitTimeOut() { | 86 static inline const base::TimeDelta NoWaitTimeOut() { |
74 return base::TimeDelta::FromMicroseconds(0); | 87 return base::TimeDelta::FromMicroseconds(0); |
75 } | 88 } |
76 | 89 |
77 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 90 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
78 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 91 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, |
79 const base::Callback<bool(void)>& make_context_current, | 92 const base::Callback<bool(void)>& make_context_current) |
80 scoped_ptr<BackingStrategy> strategy) | |
81 : client_(NULL), | 93 : client_(NULL), |
82 make_context_current_(make_context_current), | 94 make_context_current_(make_context_current), |
83 codec_(media::kCodecH264), | 95 codec_(media::kCodecH264), |
84 is_encrypted_(false), | 96 is_encrypted_(false), |
85 state_(NO_ERROR), | 97 state_(NO_ERROR), |
86 picturebuffers_requested_(false), | 98 picturebuffers_requested_(false), |
87 gl_decoder_(decoder), | 99 gl_decoder_(decoder), |
88 strategy_(strategy.Pass()), | 100 strategy_(new BACKING_STRATEGY()), |
89 weak_this_factory_(this) {} | 101 weak_this_factory_(this) {} |
90 | 102 |
91 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 103 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
92 DCHECK(thread_checker_.CalledOnValidThread()); | 104 DCHECK(thread_checker_.CalledOnValidThread()); |
93 } | 105 } |
94 | 106 |
95 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 107 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
96 Client* client) { | 108 Client* client) { |
97 DCHECK(!media_codec_); | 109 DCHECK(!media_codec_); |
98 DCHECK(thread_checker_.CalledOnValidThread()); | 110 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 | 439 |
428 pending_bitstream_buffers_.push( | 440 pending_bitstream_buffers_.push( |
429 std::make_pair(bitstream_buffer, base::Time::Now())); | 441 std::make_pair(bitstream_buffer, base::Time::Now())); |
430 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 442 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
431 pending_bitstream_buffers_.size()); | 443 pending_bitstream_buffers_.size()); |
432 | 444 |
433 DoIOTask(); | 445 DoIOTask(); |
434 } | 446 } |
435 | 447 |
436 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 448 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
437 client_->ProvidePictureBuffers(strategy_->GetNumPictureBuffers(), size_, | 449 client_->ProvidePictureBuffers(kNumPictureBuffers, size_, |
438 strategy_->GetTextureTarget()); | 450 strategy_->GetTextureTarget()); |
439 } | 451 } |
440 | 452 |
441 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 453 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
442 const std::vector<media::PictureBuffer>& buffers) { | 454 const std::vector<media::PictureBuffer>& buffers) { |
443 DCHECK(thread_checker_.CalledOnValidThread()); | 455 DCHECK(thread_checker_.CalledOnValidThread()); |
444 DCHECK(output_picture_buffers_.empty()); | 456 DCHECK(output_picture_buffers_.empty()); |
445 DCHECK(free_picture_ids_.empty()); | 457 DCHECK(free_picture_ids_.empty()); |
446 | 458 |
447 for (size_t i = 0; i < buffers.size(); ++i) { | 459 for (size_t i = 0; i < buffers.size(); ++i) { |
448 RETURN_ON_FAILURE(this, buffers[i].size() == size_, | 460 RETURN_ON_FAILURE(this, buffers[i].size() == size_, |
449 "Invalid picture buffer size was passed.", | 461 "Invalid picture buffer size was passed.", |
450 INVALID_ARGUMENT); | 462 INVALID_ARGUMENT); |
451 int32 id = buffers[i].id(); | 463 int32 id = buffers[i].id(); |
452 output_picture_buffers_.insert(std::make_pair(id, buffers[i])); | 464 output_picture_buffers_.insert(std::make_pair(id, buffers[i])); |
453 free_picture_ids_.push(id); | 465 free_picture_ids_.push(id); |
454 // Since the client might be re-using |picture_buffer_id| values, forget | 466 // Since the client might be re-using |picture_buffer_id| values, forget |
455 // about previously-dismissed IDs now. See ReusePictureBuffer() comment | 467 // about previously-dismissed IDs now. See ReusePictureBuffer() comment |
456 // about "zombies" for why we maintain this set in the first place. | 468 // about "zombies" for why we maintain this set in the first place. |
457 dismissed_picture_ids_.erase(id); | 469 dismissed_picture_ids_.erase(id); |
458 | 470 |
459 strategy_->AssignOnePictureBuffer(buffers[i]); | 471 strategy_->AssignOnePictureBuffer(buffers[i]); |
460 } | 472 } |
461 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 473 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
462 | 474 |
463 RETURN_ON_FAILURE( | 475 RETURN_ON_FAILURE(this, output_picture_buffers_.size() >= kNumPictureBuffers, |
464 this, output_picture_buffers_.size() >= strategy_->GetNumPictureBuffers(), | 476 "Invalid picture buffers were passed.", INVALID_ARGUMENT); |
465 "Invalid picture buffers were passed.", INVALID_ARGUMENT); | |
466 | 477 |
467 DoIOTask(); | 478 DoIOTask(); |
468 } | 479 } |
469 | 480 |
470 void AndroidVideoDecodeAccelerator::ReusePictureBuffer( | 481 void AndroidVideoDecodeAccelerator::ReusePictureBuffer( |
471 int32 picture_buffer_id) { | 482 int32 picture_buffer_id) { |
472 DCHECK(thread_checker_.CalledOnValidThread()); | 483 DCHECK(thread_checker_.CalledOnValidThread()); |
473 | 484 |
474 // This ReusePictureBuffer() might have been in a pipe somewhere (queued in | 485 // This ReusePictureBuffer() might have been in a pipe somewhere (queued in |
475 // IPC, or in a PostTask either at the sender or receiver) when we sent a | 486 // IPC, or in a PostTask either at the sender or receiver) when we sent a |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 void AndroidVideoDecodeAccelerator::NotifyResetDone() { | 638 void AndroidVideoDecodeAccelerator::NotifyResetDone() { |
628 client_->NotifyResetDone(); | 639 client_->NotifyResetDone(); |
629 } | 640 } |
630 | 641 |
631 void AndroidVideoDecodeAccelerator::NotifyError( | 642 void AndroidVideoDecodeAccelerator::NotifyError( |
632 media::VideoDecodeAccelerator::Error error) { | 643 media::VideoDecodeAccelerator::Error error) { |
633 client_->NotifyError(error); | 644 client_->NotifyError(error); |
634 } | 645 } |
635 | 646 |
636 // static | 647 // static |
637 media::VideoDecodeAccelerator::SupportedProfiles | 648 media::VideoDecodeAccelerator::Capabilities |
638 AndroidVideoDecodeAccelerator::GetSupportedProfiles() { | 649 AndroidVideoDecodeAccelerator::GetCapabilities() { |
639 SupportedProfiles profiles; | 650 Capabilities capabilities; |
| 651 SupportedProfiles& profiles = capabilities.supported_profiles; |
640 | 652 |
641 if (!media::VideoCodecBridge::IsKnownUnaccelerated( | 653 if (!media::VideoCodecBridge::IsKnownUnaccelerated( |
642 media::kCodecVP8, media::MEDIA_CODEC_DECODER)) { | 654 media::kCodecVP8, media::MEDIA_CODEC_DECODER)) { |
643 SupportedProfile profile; | 655 SupportedProfile profile; |
644 profile.profile = media::VP8PROFILE_ANY; | 656 profile.profile = media::VP8PROFILE_ANY; |
645 profile.min_resolution.SetSize(0, 0); | 657 profile.min_resolution.SetSize(0, 0); |
646 profile.max_resolution.SetSize(1920, 1088); | 658 profile.max_resolution.SetSize(1920, 1088); |
647 profiles.push_back(profile); | 659 profiles.push_back(profile); |
648 } | 660 } |
649 | 661 |
(...skipping 12 matching lines...) Expand all Loading... |
662 profile.profile = supported_profile; | 674 profile.profile = supported_profile; |
663 profile.min_resolution.SetSize(0, 0); | 675 profile.min_resolution.SetSize(0, 0); |
664 // Advertise support for 4k and let the MediaCodec fail when decoding if it | 676 // Advertise support for 4k and let the MediaCodec fail when decoding if it |
665 // doesn't support the resolution. It's assumed that consumers won't have | 677 // doesn't support the resolution. It's assumed that consumers won't have |
666 // software fallback for H264 on Android anyway. | 678 // software fallback for H264 on Android anyway. |
667 profile.max_resolution.SetSize(3840, 2160); | 679 profile.max_resolution.SetSize(3840, 2160); |
668 profiles.push_back(profile); | 680 profiles.push_back(profile); |
669 } | 681 } |
670 #endif | 682 #endif |
671 | 683 |
672 return profiles; | 684 capabilities.flags = BACKING_STRATEGY::GetCapabilitiesFlags(); |
| 685 |
| 686 return capabilities; |
673 } | 687 } |
674 | 688 |
675 } // namespace content | 689 } // namespace content |
OLD | NEW |