| Index: media/filters/h264_to_annex_b_bitstream_converter.cc
|
| diff --git a/media/filters/h264_to_annex_b_bitstream_converter.cc b/media/filters/h264_to_annex_b_bitstream_converter.cc
|
| index fc45607a0b1dc0c36194491383ac49e0c3f2edcc..5a667f4de43df8e77d7e0145751ed07f4106e2a6 100644
|
| --- a/media/filters/h264_to_annex_b_bitstream_converter.cc
|
| +++ b/media/filters/h264_to_annex_b_bitstream_converter.cc
|
| @@ -5,10 +5,12 @@
|
| #include "media/filters/h264_to_annex_b_bitstream_converter.h"
|
|
|
| #include "base/logging.h"
|
| +#include "media/formats/mp4/box_definitions.h"
|
|
|
| namespace media {
|
|
|
| static const uint8 kStartCodePrefix[3] = {0, 0, 1};
|
| +static const uint32 kParamSetStartCodeSize = 1 + sizeof(kStartCodePrefix);
|
|
|
| // Helper function which determines whether NAL unit of given type marks
|
| // access unit boundary.
|
| @@ -35,63 +37,33 @@ H264ToAnnexBBitstreamConverter::~H264ToAnnexBBitstreamConverter() {}
|
|
|
| uint32 H264ToAnnexBBitstreamConverter::ParseConfigurationAndCalculateSize(
|
| const uint8* configuration_record,
|
| - uint32 configuration_record_size) {
|
| - // FFmpeg's AVCodecContext's extradata field contains the Decoder Specific
|
| - // Information from MP4 headers that contain the H.264 SPS and PPS members.
|
| - // ISO 14496-15 Chapter 5.2.4 AVCDecoderConfigurationRecord.
|
| - // AVCConfigurationRecord must be at least 7 bytes long.
|
| - if (configuration_record == NULL || configuration_record_size < 7) {
|
| + int configuration_record_size,
|
| + mp4::AVCDecoderConfigurationRecord* avc_config) {
|
| + DCHECK(configuration_record);
|
| + DCHECK_GT(configuration_record_size, 0);
|
| + DCHECK(avc_config);
|
| +
|
| + if (!avc_config->Parse(configuration_record, configuration_record_size))
|
| return 0; // Error: invalid input
|
| - }
|
| - const uint8* decoder_configuration = configuration_record;
|
| - uint32 parameter_set_size_bytes = 0;
|
| -
|
| - // We can skip the four first bytes as they're only profile information
|
| - decoder_configuration += 4;
|
| - // Fifth byte's two LSBs contain the interleaving field's size minus one
|
| - uint8 size_of_len_field = (*decoder_configuration & 0x3) + 1;
|
| - if (size_of_len_field != 1 && size_of_len_field != 2 &&
|
| - size_of_len_field != 4) {
|
| - return 0; // Error: invalid input, NAL unit field len is not correct
|
| - }
|
| - decoder_configuration++;
|
| - // Sixth byte's five LSBs contain the number of SPSs
|
| - uint8 sps_count = *decoder_configuration & 0x1F;
|
| - decoder_configuration++;
|
| - // Then we have N * SPS's with two byte length field and actual SPS
|
| - while (sps_count-- > 0) {
|
| - if ((decoder_configuration - configuration_record) + 2 >
|
| - static_cast<int32>(configuration_record_size)) {
|
| - return 0; // Error: ran out of data
|
| - }
|
| - uint16 sps_len = decoder_configuration[0] << 8 | decoder_configuration[1];
|
| - decoder_configuration += 2;
|
| - // write the SPS to output, always with zero byte + start code prefix
|
| - parameter_set_size_bytes += 1 + sizeof(kStartCodePrefix);
|
| - decoder_configuration += sps_len;
|
| - parameter_set_size_bytes += sps_len;
|
| - }
|
| - // Then we have the numner of pps in one byte
|
| - uint8 pps_count = *decoder_configuration;
|
| - decoder_configuration++;
|
| - // And finally, we have N * PPS with two byte length field and actual PPS
|
| - while (pps_count-- > 0) {
|
| - if ((decoder_configuration - configuration_record) + 2 >
|
| - static_cast<int32>(configuration_record_size)) {
|
| - return 0; // Error: ran out of data
|
| - }
|
| - uint16 pps_len = decoder_configuration[0] << 8 | decoder_configuration[1];
|
| - decoder_configuration += 2;
|
| - // write the SPS to output, always with zero byte + start code prefix
|
| - parameter_set_size_bytes += 1 + sizeof(kStartCodePrefix);
|
| - decoder_configuration += pps_len;
|
| - parameter_set_size_bytes += pps_len;
|
| - }
|
| +
|
| // We're done processing the AVCDecoderConfigurationRecord,
|
| // store the needed information for parsing actual payload
|
| - nal_unit_length_field_width_ = size_of_len_field;
|
| + nal_unit_length_field_width_ = avc_config->length_size;
|
| configuration_processed_ = true;
|
| - return parameter_set_size_bytes;
|
| + return GetConfigSize(*avc_config);
|
| +}
|
| +
|
| +uint32 H264ToAnnexBBitstreamConverter::GetConfigSize(
|
| + const mp4::AVCDecoderConfigurationRecord& avc_config) const {
|
| + uint32 config_size = 0;
|
| +
|
| + for (size_t i = 0; i < avc_config.sps_list.size(); ++i)
|
| + config_size += kParamSetStartCodeSize + avc_config.sps_list[i].size();
|
| +
|
| + for (size_t i = 0; i < avc_config.pps_list.size(); ++i)
|
| + config_size += kParamSetStartCodeSize + avc_config.pps_list[i].size();
|
| +
|
| + return config_size;
|
| }
|
|
|
| uint32 H264ToAnnexBBitstreamConverter::CalculateNeededOutputBufferSize(
|
| @@ -101,9 +73,9 @@ uint32 H264ToAnnexBBitstreamConverter::CalculateNeededOutputBufferSize(
|
| uint32 data_left = input_size;
|
| bool first_nal_in_this_access_unit = first_nal_unit_in_access_unit_;
|
|
|
| - if (input == NULL || input_size == 0) {
|
| + if (input_size == 0)
|
| return 0; // Error: invalid input data
|
| - }
|
| +
|
| if (!configuration_processed_) {
|
| return 0; // Error: configuration not handled, we don't know nal unit width
|
| }
|
| @@ -152,81 +124,25 @@ uint32 H264ToAnnexBBitstreamConverter::CalculateNeededOutputBufferSize(
|
| }
|
|
|
| bool H264ToAnnexBBitstreamConverter::ConvertAVCDecoderConfigToByteStream(
|
| - const uint8* input,
|
| - uint32 input_size,
|
| + const mp4::AVCDecoderConfigurationRecord& avc_config,
|
| uint8* output,
|
| uint32* output_size) {
|
| - uint8* outscan = output;
|
| - // FFmpeg's AVCodecContext's extradata field contains the Decoder Specific
|
| - // Information from MP4 headers that contain the H.264 SPS and PPS members.
|
| - // ISO 14496-15 Chapter 5.2.4 AVCDecoderConfigurationRecord.
|
| - const uint8* decoder_configuration = input;
|
| - uint32 decoderconfiguration_size = input_size;
|
| - uint32 out_size = 0;
|
| -
|
| - if (decoder_configuration == NULL || decoderconfiguration_size == 0) {
|
| - return 0; // Error: input invalid
|
| + uint8* out = output;
|
| + uint32 out_size = *output_size;
|
| + *output_size = 0;
|
| + for (size_t i = 0; i < avc_config.sps_list.size(); ++i) {
|
| + if (!WriteParamSet(avc_config.sps_list[i], &out, &out_size))
|
| + return false;
|
| }
|
|
|
| - // We can skip the four first bytes as they're only profile information.
|
| - decoder_configuration += 4;
|
| - // Fifth byte's two LSBs contain the interleaving field's size minus one
|
| - uint8 size_of_len_field = (*decoder_configuration & 0x3) + 1;
|
| - if (size_of_len_field != 1 && size_of_len_field != 2 &&
|
| - size_of_len_field != 4) {
|
| - return 0; // Error: invalid input, NAL unit field len is not correct
|
| + for (size_t i = 0; i < avc_config.pps_list.size(); ++i) {
|
| + if (!WriteParamSet(avc_config.pps_list[i], &out, &out_size))
|
| + return false;
|
| }
|
| - decoder_configuration++;
|
| - // Sixth byte's five LSBs contain the number of SPSs
|
| - uint8 sps_count = *decoder_configuration & 0x1F;
|
| - decoder_configuration++;
|
| - // Then we have N * SPS's with two byte length field and actual SPS
|
| - while (sps_count-- > 0) {
|
| - uint16 sps_len = decoder_configuration[0] << 8 |
|
| - decoder_configuration[1];
|
| - decoder_configuration += 2;
|
| - if (out_size + 1 + sizeof(kStartCodePrefix) + sps_len >
|
| - *output_size) {
|
| - *output_size = 0;
|
| - return 0; // too small output buffer;
|
| - }
|
| - // write the SPS to output, always with zero byte + start code prefix
|
| - *outscan = 0; // zero byte
|
| - outscan += 1;
|
| - memcpy(outscan, kStartCodePrefix, sizeof(kStartCodePrefix));
|
| - outscan += sizeof(kStartCodePrefix);
|
| - memcpy(outscan, decoder_configuration, sps_len);
|
| - decoder_configuration += sps_len;
|
| - outscan += sps_len;
|
| - out_size += 1 + sizeof(kStartCodePrefix) + sps_len;
|
| - }
|
| - // Then we have the numner of pps in one byte
|
| - uint8 pps_count = *decoder_configuration;
|
| - decoder_configuration++;
|
| - // And finally, we have N * PPS with two byte length field and actual PPS
|
| - while (pps_count-- > 0) {
|
| - uint16 pps_len = decoder_configuration[0] << 8 | decoder_configuration[1];
|
| - decoder_configuration += 2;
|
| - if (out_size + 1 + sizeof(kStartCodePrefix) + pps_len >
|
| - *output_size) {
|
| - *output_size = 0;
|
| - return 0; // too small output buffer;
|
| - }
|
| - // write the SPS to output, always with zero byte + start code prefix
|
| - *outscan = 0; // zero byte
|
| - outscan += 1;
|
| - memcpy(outscan, kStartCodePrefix, sizeof(kStartCodePrefix));
|
| - outscan += sizeof(kStartCodePrefix);
|
| - memcpy(outscan, decoder_configuration, pps_len);
|
| - decoder_configuration += pps_len;
|
| - outscan += pps_len;
|
| - out_size += 1 + sizeof(kStartCodePrefix) + pps_len;
|
| - }
|
| - // We're done processing the AVCDecoderConfigurationRecord, store the needed
|
| - // information
|
| - nal_unit_length_field_width_ = size_of_len_field;
|
| +
|
| + nal_unit_length_field_width_ = avc_config.length_size;
|
| configuration_processed_ = true;
|
| - *output_size = out_size;
|
| + *output_size = out - output;
|
| return true;
|
| }
|
|
|
| @@ -237,8 +153,7 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream(
|
| uint8* outscan = output; // We write the output to here progressively
|
| uint32 data_left = input_size;
|
|
|
| - if (inscan == NULL || input_size == 0 ||
|
| - outscan == NULL || *output_size == 0) {
|
| + if (input_size == 0 || *output_size == 0) {
|
| *output_size = 0;
|
| return false; // Error: invalid input
|
| }
|
| @@ -313,4 +228,30 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream(
|
| return true;
|
| }
|
|
|
| +bool H264ToAnnexBBitstreamConverter::WriteParamSet(
|
| + const std::vector<uint8>& param_set,
|
| + uint8** out,
|
| + uint32* out_size) const {
|
| + uint32 bytes_left = *out_size;
|
| + if (bytes_left < kParamSetStartCodeSize ||
|
| + bytes_left - kParamSetStartCodeSize < param_set.size()) {
|
| + return false;
|
| + }
|
| +
|
| + uint8* start = *out;
|
| + uint8* buf = start;
|
| +
|
| + // Write the 4 byte Annex B start code.
|
| + *buf++ = 0; // zero byte
|
| + memcpy(buf, kStartCodePrefix, sizeof(kStartCodePrefix));
|
| + buf += sizeof(kStartCodePrefix);
|
| +
|
| + memcpy(buf, ¶m_set[0], param_set.size());
|
| + buf += param_set.size();
|
| +
|
| + *out = buf;
|
| + *out_size -= buf - start;
|
| + return true;
|
| +}
|
| +
|
| } // namespace media
|
|
|