Chromium Code Reviews| Index: media/gpu/android_video_decode_accelerator.cc |
| diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc |
| index 1b191bafac686755e8445509269c982a82798f9c..a4093f6caad375613cbe336788de47a5a61a02a7 100644 |
| --- a/media/gpu/android_video_decode_accelerator.cc |
| +++ b/media/gpu/android_video_decode_accelerator.cc |
| @@ -6,6 +6,7 @@ |
| #include <stddef.h> |
| +#include <array> |
| #include <memory> |
| #include "base/android/build_info.h" |
| @@ -35,6 +36,7 @@ |
| #include "media/base/media.h" |
| #include "media/base/timestamp_constants.h" |
| #include "media/base/video_decoder_config.h" |
| +#include "media/formats/mp4/box_definitions.h" |
| #include "media/gpu/avda_picture_buffer_manager.h" |
| #include "media/gpu/shared_memory_region.h" |
| #include "media/video/picture.h" |
| @@ -129,6 +131,30 @@ inline void RecordFormatChangedMetric(FormatChangedValue value) { |
| UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value); |
| } |
| +// Extract the SPS and PPS from |extra_data| (which should be an AVCC) and write |
| +// them to |csd0| and |csd1|, respectively, in the format MediaCodec expects. |
| +// Returns true on success. The out parameters are not modified on failure. |
| +bool ExtractSpsAndPps(const std::vector<uint8_t>& extra_data, |
| + std::vector<uint8_t>* csd0, |
| + std::vector<uint8_t>* csd1) { |
| + mp4::AVCDecoderConfigurationRecord record; |
| + if (!record.Parse(extra_data.data(), extra_data.size())) |
| + return false; |
| + |
| + 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.
|
| + for (const std::vector<uint8_t>& sps : record.sps_list) { |
| + csd0->insert(csd0->end(), prefix.begin(), prefix.end()); |
| + csd0->insert(csd0->end(), sps.begin(), sps.end()); |
| + } |
| + |
| + for (const std::vector<uint8_t>& pps : record.pps_list) { |
| + csd1->insert(csd1->end(), prefix.begin(), prefix.end()); |
| + csd1->insert(csd1->end(), pps.begin(), pps.end()); |
| + } |
| + |
| + return true; |
| +} |
| + |
| } // namespace |
| // AVDAManager manages shared resources for a number of AVDA instances. |
| @@ -490,7 +516,7 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| codec_config_->codec_ != kCodecHEVC && |
| #endif |
| codec_config_->codec_ != kCodecH264) { |
| - LOG(ERROR) << "Unsupported profile: " << config.profile; |
| + DLOG(ERROR) << "Unsupported profile: " << config.profile; |
| return false; |
| } |
| @@ -505,9 +531,17 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| return false; |
| } |
| + if (codec_config_->codec_ == kCodecH264 && !config.extra_data.empty()) { |
| + if (!ExtractSpsAndPps(config.extra_data, &codec_config_->csd0_, |
| + &codec_config_->csd1_)) { |
| + DLOG(ERROR) << "Failed to parse extra_data as an AVCC."; |
| + return false; |
| + } |
| + } |
| + |
| auto gles_decoder = get_gles2_decoder_cb_.Run(); |
| if (!gles_decoder) { |
| - LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| + DLOG(ERROR) << "Failed to get gles2 decoder instance."; |
| return false; |
| } |
| @@ -1148,8 +1182,8 @@ AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( |
| std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( |
| codec_config->codec_, codec_config->needs_protected_surface_, |
| codec_config->initial_expected_coded_size_, |
| - codec_config->surface_.j_surface().obj(), media_crypto, true, |
| - require_software_codec)); |
| + codec_config->surface_.j_surface().obj(), media_crypto, |
| + codec_config->csd0_, codec_config->csd1_, true, require_software_codec)); |
| return codec; |
| } |