Unit stream to byte stream converter

Change-Id: Iafe1989019e306281f17d80faa348262043cd3b8
This commit is contained in:
Rintaro Kuroiwa 2016-02-18 19:12:52 -08:00
parent 9d67f545ed
commit 90731d79df
4 changed files with 631 additions and 2 deletions

View File

@ -19,14 +19,16 @@
'decoder_configuration.h',
'ec3_audio_util.cc',
'ec3_audio_util.h',
'hevc_decoder_configuration.cc',
'hevc_decoder_configuration.h',
'h264_bit_reader.cc',
'h264_bit_reader.h',
'h264_byte_to_unit_stream_converter.cc',
'h264_byte_to_unit_stream_converter.h',
'h264_parser.cc',
'h264_parser.h',
'hevc_decoder_configuration.cc',
'hevc_decoder_configuration.h',
'nal_unit_to_byte_stream_converter.cc',
'nal_unit_to_byte_stream_converter.h',
'nalu_reader.cc',
'nalu_reader.h',
'vp_codec_configuration.cc',
@ -51,6 +53,7 @@
'h264_byte_to_unit_stream_converter_unittest.cc',
'h264_parser_unittest.cc',
'hevc_decoder_configuration_unittest.cc',
'nal_unit_to_byte_stream_converter_unittest.cc',
'nalu_reader_unittest.cc',
'vp_codec_configuration_unittest.cc',
'vp8_parser_unittest.cc',

View File

@ -0,0 +1,190 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "packager/media/filters/nal_unit_to_byte_stream_converter.h"
#include <list>
#include "packager/base/logging.h"
#include "packager/media/base/bit_reader.h"
#include "packager/media/base/buffer_reader.h"
#include "packager/media/base/buffer_writer.h"
#include "packager/media/base/macros.h"
#include "packager/media/filters/avc_decoder_configuration.h"
#include "packager/media/filters/nalu_reader.h"
namespace edash_packager {
namespace media {
namespace {
const uint8_t kNaluStartCode[] = {0x00, 0x00, 0x00, 0x01};
const uint8_t kEmulationPreventionByte = 0x03;
const uint8_t kAccessUnitDelimiterRbspAnyPrimaryPicType = 0xF0;
// Inserts emulation byte where necessary.
void EscapeRawByteSequencePayload(const uint8_t* input,
size_t input_size,
BufferWriter* output_writer) {
// Keep track of consecutive zeros that it has seen (not including the current
// byte), so that the algorithm doesn't need to go back to check the same
// bytes.
int consecutive_zero_count = 0;
for (size_t i = 0; i < input_size; ++i) {
if (consecutive_zero_count <= 1) {
output_writer->AppendInt(input[i]);
} else if (consecutive_zero_count == 2) {
if (input[i] == 0 || input[i] == 1 || input[i] == 2 || input[i] == 3) {
// Must be escaped.
output_writer->AppendInt(kEmulationPreventionByte);
}
output_writer->AppendInt(input[i]);
// Note that input[i] can be 0.
// 00 00 00 00 00 00 should become
// 00 00 03 00 00 03 00 00 03
// So consecutive_zero_count is reset here and incremented below if
// input[i] is 0.
consecutive_zero_count = 0;
}
consecutive_zero_count = input[i] == 0 ? consecutive_zero_count + 1 : 0;
}
// ISO 14496-10 Section 7.4.1.1 mentions that if the last byte is 0 (which
// only happens if RBSP has cabac_zero_word), 0x03 must be appended.
if (consecutive_zero_count > 0) {
DCHECK_GT(input_size, 0u);
DCHECK_EQ(input[input_size - 1], 0u);
output_writer->AppendInt(kEmulationPreventionByte);
}
}
void AppendNalu(const Nalu& nalu,
int nalu_length_size,
bool escape_data,
BufferWriter* buffer_writer) {
if (escape_data) {
EscapeRawByteSequencePayload(
nalu.data(), nalu.header_size() + nalu.payload_size(), buffer_writer);
} else {
buffer_writer->AppendArray(nalu.data(),
nalu.header_size() + nalu.payload_size());
}
}
void AddAccessUnitDelimiter(BufferWriter* buffer_writer) {
buffer_writer->AppendInt(static_cast<uint8_t>(Nalu::H264_AUD));
// For now, primary_pic_type is 7 which is "anything".
buffer_writer->AppendInt(kAccessUnitDelimiterRbspAnyPrimaryPicType);
}
} // namespace
NalUnitToByteStreamConverter::NalUnitToByteStreamConverter()
: nalu_length_size_(0), escape_data_(false) {}
NalUnitToByteStreamConverter::~NalUnitToByteStreamConverter() {}
bool NalUnitToByteStreamConverter::Initialize(
const uint8_t* decoder_configuration_data,
size_t decoder_configuration_data_size,
bool escape_data) {
escape_data_ = escape_data;
if (!decoder_configuration_data || decoder_configuration_data_size == 0) {
LOG(ERROR) << "Decoder conguration is empty.";
return false;
}
AVCDecoderConfiguration decoder_config;
if (!decoder_config.Parse(std::vector<uint8_t>(
decoder_configuration_data,
decoder_configuration_data + decoder_configuration_data_size))) {
return false;
}
if (decoder_config.nalu_count() < 2) {
LOG(ERROR) << "Cannot find SPS or PPS.";
return false;
}
nalu_length_size_ = decoder_config.nalu_length_size();
BufferWriter buffer_writer(decoder_configuration_data_size);
bool found_sps = false;
bool found_pps = false;
for (uint32_t i = 0; i < decoder_config.nalu_count(); ++i) {
const Nalu& nalu = decoder_config.nalu(i);
if (nalu.type() == Nalu::H264NaluType::H264_SPS) {
buffer_writer.AppendArray(kNaluStartCode, arraysize(kNaluStartCode));
AppendNalu(nalu, nalu_length_size_, escape_data, &buffer_writer);
found_sps = true;
} else if (nalu.type() == Nalu::H264NaluType::H264_PPS) {
buffer_writer.AppendArray(kNaluStartCode, arraysize(kNaluStartCode));
AppendNalu(nalu, nalu_length_size_, escape_data, &buffer_writer);
found_pps = true;
}
}
if (!found_sps || !found_pps) {
LOG(ERROR) << "Failed to find SPS or PPS.";
return false;
}
buffer_writer.SwapBuffer(&decoder_configuration_in_byte_stream_);
return true;
}
// This ignores all AUD, SPS, and PPS in the sample. Instead uses the data
// parsed in Initialize().
bool NalUnitToByteStreamConverter::ConvertUnitToByteStream(
const uint8_t* sample,
size_t sample_size,
bool is_key_frame,
std::vector<uint8_t>* output) {
if (!sample || sample_size == 0) {
LOG(WARNING) << "Sample is empty.";
return true;
}
BufferWriter buffer_writer(sample_size);
buffer_writer.AppendArray(kNaluStartCode, arraysize(kNaluStartCode));
AddAccessUnitDelimiter(&buffer_writer);
if (is_key_frame)
buffer_writer.AppendVector(decoder_configuration_in_byte_stream_);
NaluReader nalu_reader(NaluReader::NaluType::kH264, nalu_length_size_, sample,
sample_size);
Nalu nalu;
NaluReader::Result result = nalu_reader.Advance(&nalu);
while (result == NaluReader::kOk) {
switch (nalu.type()) {
case Nalu::H264_AUD:
FALLTHROUGH_INTENDED;
case Nalu::H264_SPS:
FALLTHROUGH_INTENDED;
case Nalu::H264_PPS:
break;
default:
buffer_writer.AppendArray(kNaluStartCode, arraysize(kNaluStartCode));
AppendNalu(nalu, nalu_length_size_, escape_data_, &buffer_writer);
break;
}
result = nalu_reader.Advance(&nalu);
}
DCHECK_NE(result, NaluReader::kOk);
if (result != NaluReader::kEOStream) {
LOG(ERROR) << "Stopped reading before end of stream.";
return false;
}
buffer_writer.SwapBuffer(output);
return true;
}
} // namespace media
} // namespace edash_packager

View File

@ -0,0 +1,62 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef PACKAGER_MEDIA_FILTERS_NAL_UNIT_TO_BYTE_STREAM_CONVERTER_H_
#define PACKAGER_MEDIA_FILTERS_NAL_UNIT_TO_BYTE_STREAM_CONVERTER_H_
#include <stdint.h>
#include <vector>
#include "packager/base/macros.h"
#include "packager/base/memory/ref_counted.h"
namespace edash_packager {
namespace media {
class VideoStreamInfo;
class NalUnitToByteStreamConverter {
public:
NalUnitToByteStreamConverter();
~NalUnitToByteStreamConverter();
/// This must be called before calling other methods.
/// @param decoder_configuration_data is the pointer to a decoder config data.
/// @param decoder_configuration_data_size is the size of @a
/// decoder_configuration_data.
/// @param escape_data flags whether the decoder configuration and data
/// passed to ConvertUnitToByteStream() should be escaped with
/// emulation prevention byte.
/// @return true on success, false otherwise.
bool Initialize(const uint8_t* decoder_configuration_data,
size_t decoder_configuration_data_size,
bool escape_data);
/// Converts unit stream to byte stream using the data passed to Initialize().
/// The method will function correctly even if @a sample is encrypted using
/// SAMPLE-AES encryption.
/// @param sample is the sample to be converted.
/// @param sample_size is the size of @a sample.
/// @param output is set to the the converted sample, on success.
/// @return true on success, false otherwise.
bool ConvertUnitToByteStream(const uint8_t* sample, size_t sample_size,
bool is_key_frame,
std::vector<uint8_t>* output);
private:
friend class NalUnitToByteStreamConverterTest;
int nalu_length_size_;
std::vector<uint8_t> decoder_configuration_in_byte_stream_;
bool escape_data_;
DISALLOW_COPY_AND_ASSIGN(NalUnitToByteStreamConverter);
};
} // namespace media
} // namespace edash_packager
#endif // PACKAGER_MEDIA_FILTERS_NAL_UNIT_TO_BYTE_STREAM_CONVERTER_H_

View File

@ -0,0 +1,374 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include <gtest/gtest.h>
#include "packager/media/base/media_sample.h"
#include "packager/media/filters/nal_unit_to_byte_stream_converter.h"
namespace edash_packager {
namespace media {
namespace {
// This should be valud AVCDecoderConfigurationRecord that can be parsed by
// NalUnitToByteStreamConverter.
const uint8_t kTestAVCDecoderConfigurationRecord[] = {
0x01, // configuration version (must be 1)
0x00, // AVCProfileIndication (bogus)
0x00, // profile_compatibility (bogus)
0x00, // AVCLevelIndication (bogus)
0xFF, // Length size minus 1 == 3
0xE1, // 1 sps.
0x00, 0x1D, // SPS length == 29
// Some valid SPS data.
0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4,
0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x00, 0xEA,
0x60, 0x0F, 0x16, 0x2D, 0x96,
0x01, // 1 pps.
0x00, 0x0A, // PPS length == 10
// The content of PPS is not checked except the type.
0x68, 0xFE, 0xFD, 0xFC, 0xFB, 0x11, 0x12, 0x13, 0x14, 0x15,
};
const bool kEscapeData = true;
const bool kIsKeyFrame = true;
} // namespace
class NalUnitToByteStreamConverterTest : public ::testing::Test {
public:
NalUnitToByteStreamConverter converter_;
};
// Expect a valid AVCDecoderConfigurationRecord to pass.
TEST(NalUnitToByteStreamConverterTest, ParseAVCDecoderConfigurationRecord) {
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
kEscapeData));
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
!kEscapeData));
}
// Empty AVCDecoderConfigurationRecord should return false.
TEST(NalUnitToByteStreamConverterTest, EmptyAVCDecoderConfigurationRecord) {
NalUnitToByteStreamConverter converter;
EXPECT_FALSE(converter.Initialize(nullptr, 102, kEscapeData));
EXPECT_FALSE(
converter.Initialize(kTestAVCDecoderConfigurationRecord, 0, kEscapeData));
}
// If there is no SPS, Initialize() should fail.
TEST(NalUnitToByteStreamConverterTest, NoSps) {
NalUnitToByteStreamConverter converter;
const uint8_t kNoSps[] = {
0x01, // configuration version (must be 1)
0x00, // AVCProfileIndication (bogus)
0x00, // profile_compatibility (bogus)
0x00, // AVCLevelIndication (bogus)
0xFF, // Length size minus 1 == 3
0xE0, // 0 sps.
// The rest doesn't really matter, Initialize() should fail.
0x01, // 1 pps.
0x00, 0x0A, // PPS length == 10
0x68, 0xFE, 0xFD, 0xFC, 0xFB, 0x11, 0x12, 0x13, 0x14, 0x15,
};
EXPECT_FALSE(converter.Initialize(kNoSps, arraysize(kNoSps), !kEscapeData));
}
// If there is no PPS, Initialize() should fail.
TEST(NalUnitToByteStreamConverterTest, NoPps) {
NalUnitToByteStreamConverter converter;
const uint8_t kNoPps[] = {
0x01, // configuration version (must be 1)
0x00, // AVCProfileIndication (bogus)
0x00, // profile_compatibility (bogus)
0x00, // AVCLevelIndication (bogus)
0xFF, // Length size minus 1 == 3
0xE1, // 1 sps.
0x00, 0x1D, // SPS length == 29
// Some valid SPS data.
0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4,
0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x00, 0xEA,
0x60, 0x0F, 0x16, 0x2D, 0x96,
0x00, // 0 pps.
};
EXPECT_FALSE(converter.Initialize(kNoPps, arraysize(kNoPps), !kEscapeData));
}
// If the length of SPS is 0 then Initialize() should fail.
TEST(NalUnitToByteStreamConverterTest, ZeroLengthSps) {
NalUnitToByteStreamConverter converter;
const uint8_t kZeroLengthSps[] = {
0x01, // configuration version (must be 1)
0x00, // AVCProfileIndication (bogus)
0x00, // profile_compatibility (bogus)
0x00, // AVCLevelIndication (bogus)
0xFF, // Length size minus 1 == 3
0xE1, // 1 sps.
0x00, 0x00, // SPS length == 0
0x01, // 1 pps.
0x00, 0x0A, // PPS length == 10
0x68, 0xFE, 0xFD, 0xFC, 0xFB, 0x11, 0x12, 0x13, 0x14, 0x15,
};
EXPECT_FALSE(converter.Initialize(kZeroLengthSps, arraysize(kZeroLengthSps),
!kEscapeData));
}
// If the length of PPS is 0 then Initialize() should fail.
TEST(NalUnitToByteStreamConverterTest, ZeroLengthPps) {
NalUnitToByteStreamConverter converter;
const uint8_t kZeroLengthPps[] = {
0x01, // configuration version (must be 1)
0x00, // AVCProfileIndication (bogus)
0x00, // profile_compatibility (bogus)
0x00, // AVCLevelIndication (bogus)
0xFF, // Length size minus 1 == 3
0xE1, // 1 sps.
0x00, 0x05, // SPS length == 5
0x00, 0x00, 0x00, 0x01, 0x02,
0x01, // 1 pps.
0x00, 0x00, // PPS length == 0
};
EXPECT_FALSE(converter.Initialize(kZeroLengthPps, arraysize(kZeroLengthPps),
!kEscapeData));
}
TEST(NalUnitToByteStreamConverterTest, ConvertUnitToByteStream) {
// Only the type of the NAL units are checked.
// This does not contain AUD, SPS, nor PPS.
const uint8_t kUnitStreamLikeMediaSample[] = {
0x00, 0x00, 0x00, 0x0A, // Size 10 NALU.
0x00, // Unspecified NAL unit type.
0xFD, 0x78, 0xA4, 0xC3, 0x82, 0x62, 0x11, 0x29, 0x77,
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
!kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(
kUnitStreamLikeMediaSample, arraysize(kUnitStreamLikeMediaSample),
kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // primary pic type is anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// Some valid SPS data.
0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4,
0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x00, 0xEA,
0x60, 0x0F, 0x16, 0x2D, 0x96,
0x00, 0x00, 0x00, 0x01, // Start code.
0x68, 0xFE, 0xFD, 0xFC, 0xFB, 0x11, 0x12, 0x13, 0x14, 0x15, // PPS.
0x00, 0x00, 0x00, 0x01, // Start code.
// The input NALU.
0x00, // Unspecified NALU type.
0xFD, 0x78, 0xA4, 0xC3, 0x82, 0x62, 0x11, 0x29, 0x77,
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
// Verify that escaping works on all data.
TEST(NalUnitToByteStreamConverterTest, ConvertUnitToByteStreamWithEscape) {
// Only the type of the NAL units are checked.
// This does not contain AUD, SPS, nor PPS.
const uint8_t kUnitStreamLikeMediaSample[] = {
0x00, 0x00, 0x00, 0x0A, // Size 10 NALU.
0x00, // Unspecified NAL unit type.
0x06, 0x00, 0x00, 0x00, 0xDF, 0x62, 0x11, 0x29, 0x77,
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(
kUnitStreamLikeMediaSample, arraysize(kUnitStreamLikeMediaSample),
kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // primary pic type is anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// Some valid SPS data.
0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xB4,
0x2F, 0xF9, 0x7F, 0xF0, 0x00, 0x80, 0x00, 0x91,
// Note that extra 0x03 is added.
0x00, 0x00, 0x03, 0x03, 0x03, 0xE9, 0x00, 0x00,
0xEA, 0x60, 0x0F, 0x16, 0x2D, 0x96,
0x00, 0x00, 0x00, 0x01, // Start code.
0x68, 0xFE, 0xFD, 0xFC, 0xFB, 0x11, 0x12, 0x13, 0x14, 0x15, // PPS.
0x00, 0x00, 0x00, 0x01, // Start code.
// The input NALU.
0x00, // Unspecified NALU type.
0x06, 0x00, 0x00, 0x03, 0x00, 0xDF, 0x62, 0x11, 0x29, 0x77,
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
// NALU ending with 0 must have 3 appended.
TEST(NalUnitToByteStreamConverterTest, NaluEndingWithZero) {
const uint8_t kNaluEndingWithZero[] = {
0x00, 0x00, 0x00, 0x03, // Size 10 NALU.
0x00, // Unspecified NAL unit type.
0xAA, 0x00, // Ends with 0.
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(kNaluEndingWithZero,
arraysize(kNaluEndingWithZero),
!kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // primary pic type is anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// The input NALU.
0x00, // Unspecified NALU type.
0xAA, 0x00, 0x03, // 0x03 at the end because the original ends with 0.
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
// Verify that if it is not a key frame then SPS and PPS from decoder
// configuration is not used.
TEST(NalUnitToByteStreamConverterTest, NonKeyFrameSample) {
const uint8_t kNonKeyFrameStream[] = {
0x00, 0x00, 0x00, 0x03, // Size 10 NALU.
0x00, // Unspecified NAL unit type.
0x33, 0x88,
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(kNonKeyFrameStream,
arraysize(kNonKeyFrameStream),
!kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // Anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// The input NALU.
0x00, // Unspecified NALU type.
0x33, 0x88,
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
// Bug found during unit testing.
// The zeros aren't contiguous but the escape byte was inserted.
TEST(NalUnitToByteStreamConverterTest, DispersedZeros) {
const uint8_t kDispersedZeros[] = {
0x00, 0x00, 0x00, 0x08, // Size 10 NALU.
0x00, // Unspecified NAL unit type.
// After 2 zeros (including the first byte of the NALU followed by 0, 1,
// 2, or 3 caused it to insert the escape byte.
0x11, 0x00,
0x01, 0x00, 0x02, 0x00, 0x44,
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(
kDispersedZeros, arraysize(kDispersedZeros), !kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // Anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// The input NALU.
0x00, // Unspecified NAL unit type.
0x11, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44,
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
// Verify that CnovertUnitToByteStream() with escape_data = false works.
TEST(NalUnitToByteStreamConverterTest, DoNotEscape) {
// This has sequences that should be escaped if escape_data = true.
const uint8_t kNotEscaped[] = {
0x00, 0x00, 0x00, 0x0C, // Size 12 NALU.
0x00, // Unspecified NAL unit type.
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
};
NalUnitToByteStreamConverter converter;
EXPECT_TRUE(
converter.Initialize(kTestAVCDecoderConfigurationRecord,
arraysize(kTestAVCDecoderConfigurationRecord),
!kEscapeData));
std::vector<uint8_t> output;
EXPECT_TRUE(converter.ConvertUnitToByteStream(
kNotEscaped, arraysize(kNotEscaped), !kIsKeyFrame, &output));
const uint8_t kExpectedOutput[] = {
0x00, 0x00, 0x00, 0x01, // Start code.
0x09, // AUD type.
0xF0, // Anything.
0x00, 0x00, 0x00, 0x01, // Start code.
// Should be the same as the input.
0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03,
};
EXPECT_EQ(std::vector<uint8_t>(kExpectedOutput,
kExpectedOutput + arraysize(kExpectedOutput)),
output);
}
} // namespace media
} // namespace edash_packager