Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/gpu/android_video_decode_accelerator.h" | 5 #include "media/gpu/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <array> | |
| 9 #include <memory> | 10 #include <memory> |
| 10 | 11 |
| 11 #include "base/android/build_info.h" | 12 #include "base/android/build_info.h" |
| 12 #include "base/auto_reset.h" | 13 #include "base/auto_reset.h" |
| 13 #include "base/bind.h" | 14 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 15 #include "base/callback_helpers.h" | 16 #include "base/callback_helpers.h" |
| 16 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 17 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
| 18 #include "base/logging.h" | 19 #include "base/logging.h" |
| 19 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 20 #include "base/metrics/histogram.h" | 21 #include "base/metrics/histogram.h" |
| 21 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
| 22 #include "base/task_runner_util.h" | 23 #include "base/task_runner_util.h" |
| 23 #include "base/threading/thread.h" | 24 #include "base/threading/thread.h" |
| 24 #include "base/threading/thread_checker.h" | 25 #include "base/threading/thread_checker.h" |
| 25 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
| 26 #include "base/trace_event/trace_event.h" | 27 #include "base/trace_event/trace_event.h" |
| 27 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 28 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 28 #include "gpu/command_buffer/service/mailbox_manager.h" | 29 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 29 #include "gpu/ipc/service/gpu_channel.h" | 30 #include "gpu/ipc/service/gpu_channel.h" |
| 30 #include "media/base/android/media_codec_bridge.h" | 31 #include "media/base/android/media_codec_bridge.h" |
| 31 #include "media/base/android/media_codec_util.h" | 32 #include "media/base/android/media_codec_util.h" |
| 32 #include "media/base/bind_to_current_loop.h" | 33 #include "media/base/bind_to_current_loop.h" |
| 33 #include "media/base/bitstream_buffer.h" | 34 #include "media/base/bitstream_buffer.h" |
| 34 #include "media/base/limits.h" | 35 #include "media/base/limits.h" |
| 35 #include "media/base/media.h" | 36 #include "media/base/media.h" |
| 36 #include "media/base/timestamp_constants.h" | 37 #include "media/base/timestamp_constants.h" |
| 37 #include "media/base/video_decoder_config.h" | 38 #include "media/base/video_decoder_config.h" |
| 39 #include "media/formats/mp4/box_definitions.h" | |
| 38 #include "media/gpu/avda_picture_buffer_manager.h" | 40 #include "media/gpu/avda_picture_buffer_manager.h" |
| 39 #include "media/gpu/shared_memory_region.h" | 41 #include "media/gpu/shared_memory_region.h" |
| 40 #include "media/video/picture.h" | 42 #include "media/video/picture.h" |
| 41 #include "ui/gl/android/scoped_java_surface.h" | 43 #include "ui/gl/android/scoped_java_surface.h" |
| 42 #include "ui/gl/android/surface_texture.h" | 44 #include "ui/gl/android/surface_texture.h" |
| 43 #include "ui/gl/gl_bindings.h" | 45 #include "ui/gl/gl_bindings.h" |
| 44 | 46 |
| 45 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 47 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 46 #include "media/mojo/services/mojo_cdm_service.h" | 48 #include "media/mojo/services/mojo_cdm_service.h" |
| 47 #endif | 49 #endif |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 // For RecordFormatChangedMetric. | 124 // For RecordFormatChangedMetric. |
| 123 enum FormatChangedValue { | 125 enum FormatChangedValue { |
| 124 CodecInitialized = false, | 126 CodecInitialized = false, |
| 125 MissingFormatChanged = true | 127 MissingFormatChanged = true |
| 126 }; | 128 }; |
| 127 | 129 |
| 128 inline void RecordFormatChangedMetric(FormatChangedValue value) { | 130 inline void RecordFormatChangedMetric(FormatChangedValue value) { |
| 129 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value); | 131 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value); |
| 130 } | 132 } |
| 131 | 133 |
| 134 // Extract the SPS and PPS from |extra_data| (which should be an AVCC) and write | |
| 135 // them to |csd0| and |csd1|, respectively, in the format MediaCodec expects. | |
| 136 // Returns true on success. The out parameters are not modified on failure. | |
| 137 bool ExtractSpsAndPps(const std::vector<uint8_t>& extra_data, | |
| 138 std::vector<uint8_t>* csd0, | |
| 139 std::vector<uint8_t>* csd1) { | |
| 140 mp4::AVCDecoderConfigurationRecord record; | |
| 141 if (!record.Parse(extra_data.data(), extra_data.size())) | |
| 142 return false; | |
| 143 | |
| 144 const std::array<uint8_t, 4> prefix = {0, 0, 0, 1}; | |
|
dcheng
2016/09/27 22:41:15
constexpr
watk
2016/09/27 22:56:02
Done.
| |
| 145 for (const std::vector<uint8_t>& sps : record.sps_list) { | |
| 146 csd0->insert(csd0->end(), prefix.begin(), prefix.end()); | |
| 147 csd0->insert(csd0->end(), sps.begin(), sps.end()); | |
| 148 } | |
| 149 | |
| 150 for (const std::vector<uint8_t>& pps : record.pps_list) { | |
| 151 csd1->insert(csd1->end(), prefix.begin(), prefix.end()); | |
| 152 csd1->insert(csd1->end(), pps.begin(), pps.end()); | |
| 153 } | |
| 154 | |
| 155 return true; | |
| 156 } | |
| 157 | |
| 132 } // namespace | 158 } // namespace |
| 133 | 159 |
| 134 // AVDAManager manages shared resources for a number of AVDA instances. | 160 // AVDAManager manages shared resources for a number of AVDA instances. |
| 135 // Its responsibilities include: | 161 // Its responsibilities include: |
| 136 // - Starting and stopping a shared "construction" thread for instantiating and | 162 // - Starting and stopping a shared "construction" thread for instantiating and |
| 137 // releasing MediaCodecs. | 163 // releasing MediaCodecs. |
| 138 // - Detecting when a task has hung on the construction thread so AVDAs can | 164 // - Detecting when a task has hung on the construction thread so AVDAs can |
| 139 // stop using it. | 165 // stop using it. |
| 140 // - Running a RepeatingTimer so that AVDAs can get a regular callback to | 166 // - Running a RepeatingTimer so that AVDAs can get a regular callback to |
| 141 // DoIOTask(). | 167 // DoIOTask(). |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); | 509 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); |
| 484 codec_config_->initial_expected_coded_size_ = | 510 codec_config_->initial_expected_coded_size_ = |
| 485 config.initial_expected_coded_size; | 511 config.initial_expected_coded_size; |
| 486 | 512 |
| 487 if (codec_config_->codec_ != kCodecVP8 && | 513 if (codec_config_->codec_ != kCodecVP8 && |
| 488 codec_config_->codec_ != kCodecVP9 && | 514 codec_config_->codec_ != kCodecVP9 && |
| 489 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 515 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 490 codec_config_->codec_ != kCodecHEVC && | 516 codec_config_->codec_ != kCodecHEVC && |
| 491 #endif | 517 #endif |
| 492 codec_config_->codec_ != kCodecH264) { | 518 codec_config_->codec_ != kCodecH264) { |
| 493 LOG(ERROR) << "Unsupported profile: " << config.profile; | 519 DLOG(ERROR) << "Unsupported profile: " << config.profile; |
| 494 return false; | 520 return false; |
| 495 } | 521 } |
| 496 | 522 |
| 497 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 523 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
| 498 // or if the stream is encrypted. | 524 // or if the stream is encrypted. |
| 499 if (IsMediaCodecSoftwareDecodingForbidden() && | 525 if (IsMediaCodecSoftwareDecodingForbidden() && |
| 500 VideoCodecBridge::IsKnownUnaccelerated(codec_config_->codec_, | 526 VideoCodecBridge::IsKnownUnaccelerated(codec_config_->codec_, |
| 501 MEDIA_CODEC_DECODER)) { | 527 MEDIA_CODEC_DECODER)) { |
| 502 DVLOG(1) << "Initialization failed: " | 528 DVLOG(1) << "Initialization failed: " |
| 503 << (codec_config_->codec_ == kCodecVP8 ? "vp8" : "vp9") | 529 << (codec_config_->codec_ == kCodecVP8 ? "vp8" : "vp9") |
| 504 << " is not hardware accelerated"; | 530 << " is not hardware accelerated"; |
| 505 return false; | 531 return false; |
| 506 } | 532 } |
| 507 | 533 |
| 534 if (codec_config_->codec_ == kCodecH264 && !config.extra_data.empty()) { | |
| 535 if (!ExtractSpsAndPps(config.extra_data, &codec_config_->csd0_, | |
| 536 &codec_config_->csd1_)) { | |
| 537 DLOG(ERROR) << "Failed to parse extra_data as an AVCC."; | |
| 538 return false; | |
| 539 } | |
| 540 } | |
| 541 | |
| 508 auto gles_decoder = get_gles2_decoder_cb_.Run(); | 542 auto gles_decoder = get_gles2_decoder_cb_.Run(); |
| 509 if (!gles_decoder) { | 543 if (!gles_decoder) { |
| 510 LOG(ERROR) << "Failed to get gles2 decoder instance."; | 544 DLOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 511 return false; | 545 return false; |
| 512 } | 546 } |
| 513 | 547 |
| 514 // If we're low on resources, we may decide to defer creation of the surface | 548 // If we're low on resources, we may decide to defer creation of the surface |
| 515 // until the codec is actually used. | 549 // until the codec is actually used. |
| 516 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(config_.surface_id, | 550 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(config_.surface_id, |
| 517 codec_config_->codec_)) { | 551 codec_config_->codec_)) { |
| 518 DCHECK(!deferred_initialization_pending_); | 552 DCHECK(!deferred_initialization_pending_); |
| 519 | 553 |
| 520 // We should never be here if a SurfaceView is required. | 554 // We should never be here if a SurfaceView is required. |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 : nullptr; | 1175 : nullptr; |
| 1142 | 1176 |
| 1143 // |needs_protected_surface_| implies encrypted stream. | 1177 // |needs_protected_surface_| implies encrypted stream. |
| 1144 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); | 1178 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); |
| 1145 | 1179 |
| 1146 const bool require_software_codec = !codec_config->allow_autodetection_; | 1180 const bool require_software_codec = !codec_config->allow_autodetection_; |
| 1147 | 1181 |
| 1148 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( | 1182 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( |
| 1149 codec_config->codec_, codec_config->needs_protected_surface_, | 1183 codec_config->codec_, codec_config->needs_protected_surface_, |
| 1150 codec_config->initial_expected_coded_size_, | 1184 codec_config->initial_expected_coded_size_, |
| 1151 codec_config->surface_.j_surface().obj(), media_crypto, true, | 1185 codec_config->surface_.j_surface().obj(), media_crypto, |
| 1152 require_software_codec)); | 1186 codec_config->csd0_, codec_config->csd1_, true, require_software_codec)); |
| 1153 | 1187 |
| 1154 return codec; | 1188 return codec; |
| 1155 } | 1189 } |
| 1156 | 1190 |
| 1157 void AndroidVideoDecodeAccelerator::OnCodecConfigured( | 1191 void AndroidVideoDecodeAccelerator::OnCodecConfigured( |
| 1158 std::unique_ptr<VideoCodecBridge> media_codec) { | 1192 std::unique_ptr<VideoCodecBridge> media_codec) { |
| 1159 DCHECK(thread_checker_.CalledOnValidThread()); | 1193 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1160 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); | 1194 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); |
| 1161 | 1195 |
| 1162 // Record one instance of the codec being initialized. | 1196 // Record one instance of the codec being initialized. |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1701 | 1735 |
| 1702 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() | 1736 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() |
| 1703 const { | 1737 const { |
| 1704 // Prevent MediaCodec from using its internal software decoders when we have | 1738 // Prevent MediaCodec from using its internal software decoders when we have |
| 1705 // more secure and up to date versions in the renderer process. | 1739 // more secure and up to date versions in the renderer process. |
| 1706 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || | 1740 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || |
| 1707 codec_config_->codec_ == kCodecVP9); | 1741 codec_config_->codec_ == kCodecVP9); |
| 1708 } | 1742 } |
| 1709 | 1743 |
| 1710 } // namespace media | 1744 } // namespace media |
| OLD | NEW |