X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmedia%2Ffilters%2Fh264_to_annex_b_bitstream_converter.cc;h=49456dd33722d57761c2c7181b3cdbd30e0860bd;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=fc45607a0b1dc0c36194491383ac49e0c3f2edcc;hpb=2f108dbacb161091e42a3479f4e171339b7e7623;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/media/filters/h264_to_annex_b_bitstream_converter.cc b/src/media/filters/h264_to_annex_b_bitstream_converter.cc index fc45607..49456dd 100644 --- a/src/media/filters/h264_to_annex_b_bitstream_converter.cc +++ b/src/media/filters/h264_to_annex_b_bitstream_converter.cc @@ -5,10 +5,13 @@ #include "media/filters/h264_to_annex_b_bitstream_converter.h" #include "base/logging.h" +#include "media/filters/h264_parser.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. @@ -33,80 +36,55 @@ H264ToAnnexBBitstreamConverter::H264ToAnnexBBitstreamConverter() H264ToAnnexBBitstreamConverter::~H264ToAnnexBBitstreamConverter() {} -uint32 H264ToAnnexBBitstreamConverter::ParseConfigurationAndCalculateSize( +bool H264ToAnnexBBitstreamConverter::ParseConfiguration( 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) { - 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(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(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; - } + 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 false; // Error: invalid input + // 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 true; +} + +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( const uint8* input, - uint32 input_size) const { + uint32 input_size, + const mp4::AVCDecoderConfigurationRecord* avc_config) const { uint32 output_size = 0; 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 } + + if (avc_config) + output_size += GetConfigSize(*avc_config); + CHECK(nal_unit_length_field_width_ == 1 || nal_unit_length_field_width_ == 2 || nal_unit_length_field_width_ == 4); @@ -152,93 +130,37 @@ 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 - } - 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; + for (size_t i = 0; i < avc_config.pps_list.size(); ++i) { + if (!WriteParamSet(avc_config.pps_list[i], &out, &out_size)) + return false; } - // 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; } bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream( const uint8* input, uint32 input_size, + const mp4::AVCDecoderConfigurationRecord* avc_config, uint8* output, uint32* output_size) { const uint8* inscan = input; // We read the input from here progressively 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 } @@ -249,6 +171,7 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream( nal_unit_length_field_width_ == 4); // Do the actual conversion for the actual input packet + int nal_unit_count = 0; while (data_left > 0) { uint8 i; uint32 nal_unit_length; @@ -269,6 +192,30 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream( return false; // Error: not enough data for correct conversion } + // Five least significant bits of first NAL unit byte signify + // nal_unit_type. + int nal_unit_type = *inscan & 0x1F; + nal_unit_count++; + + // Insert the config after the AUD if an AUD is the first NAL unit or + // before all NAL units if the first one isn't an AUD. + if (avc_config && + (nal_unit_type != H264NALU::kAUD || nal_unit_count > 1)) { + uint32 output_bytes_used = outscan - output; + + DCHECK_GE(*output_size, output_bytes_used); + + uint32 config_size = *output_size - output_bytes_used; + if (!ConvertAVCDecoderConfigToByteStream(*avc_config, + outscan, + &config_size)) { + DVLOG(1) << "Failed to insert parameter sets."; + *output_size = 0; + return false; // Failed to convert the buffer. + } + outscan += config_size; + avc_config = NULL; + } uint32 start_code_len; first_nal_unit_in_access_unit_ ? start_code_len = sizeof(kStartCodePrefix) + 1 : @@ -279,10 +226,6 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream( return false; // Error: too small output buffer } - // Five least significant bits of first NAL unit byte signify - // nal_unit_type. - int nal_unit_type = *inscan & 0x1F; - // Check if this packet marks access unit boundary by checking the // packet type. if (IsAccessUnitBoundaryNal(nal_unit_type)) { @@ -313,4 +256,30 @@ bool H264ToAnnexBBitstreamConverter::ConvertNalUnitStreamToByteStream( return true; } +bool H264ToAnnexBBitstreamConverter::WriteParamSet( + const std::vector& 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