Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Unified Diff: media/base/h264_bitstream_converter.cc

Issue 10690140: Reorganize bitstream converter classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase again Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/h264_bitstream_converter.h ('k') | media/base/h264_bitstream_converter_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/h264_bitstream_converter.cc
diff --git a/media/base/h264_bitstream_converter.cc b/media/base/h264_bitstream_converter.cc
deleted file mode 100644
index 4e154f218d4f4fc17e29c8d09a41e39f904c70fb..0000000000000000000000000000000000000000
--- a/media/base/h264_bitstream_converter.cc
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/base/h264_bitstream_converter.h"
-
-#include "base/logging.h"
-
-namespace media {
-
-static const uint8 kStartCodePrefix[3] = {0, 0, 1};
-
-// Helper function which determines whether NAL unit of given type marks
-// access unit boundary.
-static bool IsAccessUnitBoundaryNal(int nal_unit_type) {
- // Check if this packet marks access unit boundary by checking the
- // packet type.
- if (nal_unit_type == 6 || // Supplemental enhancement information
- nal_unit_type == 7 || // Picture parameter set
- nal_unit_type == 8 || // Sequence parameter set
- nal_unit_type == 9 || // Access unit delimiter
- (nal_unit_type >= 14 && nal_unit_type <= 18)) { // Reserved types
- return true;
- }
- return false;
-}
-
-H264BitstreamConverter::H264BitstreamConverter()
- : configuration_processed_(false),
- first_nal_unit_in_access_unit_(true),
- nal_unit_length_field_width_(0) {
-}
-
-H264BitstreamConverter::~H264BitstreamConverter() {}
-
-uint32 H264BitstreamConverter::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) {
- 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;
- configuration_processed_ = true;
- return parameter_set_size_bytes;
-}
-
-uint32 H264BitstreamConverter::CalculateNeededOutputBufferSize(
- const uint8* input,
- uint32 input_size) 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) {
- return 0; // Error: invalid input data
- }
- if (!configuration_processed_) {
- return 0; // Error: configuration not handled, we don't know nal unit width
- }
- CHECK(nal_unit_length_field_width_ == 1 ||
- nal_unit_length_field_width_ == 2 ||
- nal_unit_length_field_width_ == 4);
-
- // Then add the needed size for the actual packet
- while (data_left > 0) {
- // Read the next NAL unit length from the input buffer
- uint8 size_of_len_field;
- uint32 nal_unit_length;
- for (nal_unit_length = 0, size_of_len_field = nal_unit_length_field_width_;
- size_of_len_field > 0;
- input++, size_of_len_field--, data_left--) {
- nal_unit_length <<= 8;
- nal_unit_length |= *input;
- }
-
- if (nal_unit_length == 0) {
- break; // Signifies that no more data left in the buffer
- } else if (nal_unit_length > data_left) {
- return 0; // Error: Not enough data for correct conversion
- }
- data_left -= nal_unit_length;
-
- // five least significant bits of first NAL unit byte signify nal_unit_type
- int nal_unit_type = *input & 0x1F;
- if (first_nal_in_this_access_unit ||
- IsAccessUnitBoundaryNal(nal_unit_type)) {
- output_size += 1; // Extra zero_byte for these nal units
- first_nal_in_this_access_unit = false;
- }
- // Start code prefix
- output_size += sizeof(kStartCodePrefix);
- // Actual NAL unit size
- output_size += nal_unit_length;
- input += nal_unit_length;
- // No need for trailing zero bits
- }
- return output_size;
-}
-
-bool H264BitstreamConverter::ConvertAVCDecoderConfigurationRecordToByteStream(
- const uint8* input,
- uint32 input_size,
- 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
- }
-
- // 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;
- }
- // 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;
- configuration_processed_ = true;
- *output_size = out_size;
- return true;
-}
-
-bool H264BitstreamConverter::ConvertNalUnitStreamToByteStream(
- const uint8* input, uint32 input_size,
- 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) {
- *output_size = 0;
- return false; // Error: invalid input
- }
-
- // NAL unit width should be known at this point
- CHECK(nal_unit_length_field_width_ == 1 ||
- nal_unit_length_field_width_ == 2 ||
- nal_unit_length_field_width_ == 4);
-
- // Do the actual conversion for the actual input packet
- while (data_left > 0) {
- uint8 i;
- uint32 nal_unit_length;
-
- // Read the next NAL unit length from the input buffer by scanning
- // the input stream with the specific length field width
- for (nal_unit_length = 0, i = nal_unit_length_field_width_;
- i > 0 && data_left > 0;
- inscan++, i--, data_left--) {
- nal_unit_length <<= 8;
- nal_unit_length |= *inscan;
- }
-
- if (nal_unit_length == 0) {
- break; // Successful conversion, end of buffer
- } else if (nal_unit_length > data_left) {
- *output_size = 0;
- return false; // Error: not enough data for correct conversion
- }
-
- uint32 start_code_len;
- first_nal_unit_in_access_unit_ ?
- start_code_len = sizeof(kStartCodePrefix) + 1 :
- start_code_len = sizeof(kStartCodePrefix);
- if (static_cast<uint32>(outscan - output) +
- start_code_len + nal_unit_length > *output_size) {
- *output_size = 0;
- 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)) {
- first_nal_unit_in_access_unit_ = true;
- }
-
- // Write extra zero-byte before start code prefix if this packet
- // signals next access unit.
- if (first_nal_unit_in_access_unit_) {
- *outscan = 0;
- outscan++;
- first_nal_unit_in_access_unit_ = false;
- }
-
- // No need to write leading zero bits.
- // Write start-code prefix.
- memcpy(outscan, kStartCodePrefix, sizeof(kStartCodePrefix));
- outscan += sizeof(kStartCodePrefix);
- // Then write the actual NAL unit from the input buffer.
- memcpy(outscan, inscan, nal_unit_length);
- inscan += nal_unit_length;
- data_left -= nal_unit_length;
- outscan += nal_unit_length;
- // No need for trailing zero bits.
- }
- // Successful conversion, output the freshly allocated bitstream buffer.
- *output_size = static_cast<uint32>(outscan - output);
- return true;
-}
-
-} // namespace media
« no previous file with comments | « media/base/h264_bitstream_converter.h ('k') | media/base/h264_bitstream_converter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698