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 |