diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 20:34:14 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-04 20:34:14 +0000 |
commit | 58023bea8fa444c4ac08c12c825dcc79b5954abe (patch) | |
tree | d4d4ce8dc812b8118aaa3e49d6465265cf19aad8 /media/base | |
parent | b781e774ae4f5d579c8e9122ea9baafb1f54261a (diff) | |
download | chromium_src-58023bea8fa444c4ac08c12c825dcc79b5954abe.zip chromium_src-58023bea8fa444c4ac08c12c825dcc79b5954abe.tar.gz chromium_src-58023bea8fa444c4ac08c12c825dcc79b5954abe.tar.bz2 |
Reworked player_x11:
- Turned support for EGL image ON for OpenMAX decoding.
- Added simple fix for compilation issue due to missing definition for MessageLoop.
- Added changes to GLES Video Renderer to use EGL image.
- Added H264BitstreamConverter and H264BitstreamConverterFFmpegAdaptor classes to Chromium.
- Introduced new h264 bitstream converter to FFmpegDemuxer
- Added h264 bitstream converter related classes to media targets and introduced new target for unit testing bitstream converter.
Patch by vmr@chromium.org:
http://codereview.chromium.org/6260010/
BUG=None
TEST=Test H.264 decode clip with player_x11 OpenMAX enabled.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73839 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/h264_bitstream_converter.cc | 314 | ||||
-rw-r--r-- | media/base/h264_bitstream_converter.h | 124 | ||||
-rw-r--r-- | media/base/h264_bitstream_converter_unittest.cc | 472 |
3 files changed, 910 insertions, 0 deletions
diff --git a/media/base/h264_bitstream_converter.cc b/media/base/h264_bitstream_converter.cc new file mode 100644 index 0000000..bdf6363 --- /dev/null +++ b/media/base/h264_bitstream_converter.cc @@ -0,0 +1,314 @@ +// Copyright (c) 2011 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; + first_nal_in_this_access_unit = false; + // 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 + diff --git a/media/base/h264_bitstream_converter.h b/media/base/h264_bitstream_converter.h new file mode 100644 index 0000000..bce1e23b --- /dev/null +++ b/media/base/h264_bitstream_converter.h @@ -0,0 +1,124 @@ +// Copyright (c) 2011 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. + +#ifndef MEDIA_BASE_H264_BITSTREAM_CONVERTER_H_ +#define MEDIA_BASE_H264_BITSTREAM_CONVERTER_H_ + +#include "base/basictypes.h" + +namespace media { + +// H264BitstreamConverter is a class to convert H.264 bitstream from +// MP4 format (as specified in ISO/IEC 14496-15) into H.264 bytestream +// (as specified in ISO/IEC 14496-10 Annex B). +class H264BitstreamConverter { + public: + H264BitstreamConverter(); + ~H264BitstreamConverter(); + + // Parses the global AVCDecoderConfigurationRecord from the file format's + // headers. Converter will remember the field length from the configuration + // headers after this. + // + // Parameters + // configuration_record + // Pointer to buffer containing AVCDecoderConfigurationRecord. + // configuration_record_size + // Size of the buffer in bytes. + // + // Returns + // Required buffer size for AVCDecoderConfigurationRecord when converted + // to bytestream format, or 0 if could not determine the configuration + // from the input buffer. + uint32 ParseConfigurationAndCalculateSize(const uint8* configuration_record, + uint32 configuration_record_size); + + // Calculates needed buffer size for the bitstream converted into bytestream. + // Lightweight implementation that does not do the actual conversion. + // + // Parameters + // configuration_record + // Pointer to buffer containing AVCDecoderConfigurationRecord. + // configuration_record_size + // Size of the buffer in bytes. + // + // Returns + // Required buffer size for the input NAL unit buffer when converted + // to bytestream format, or 0 if could not determine the configuration + // from the input buffer. + uint32 CalculateNeededOutputBufferSize(const uint8* input, + uint32 input_size) const; + + // ConvertParameterSetsToByteStream converts the + // AVCDecoderConfigurationRecord from the MP4 headers to bytestream format. + // Client is responsible for making sure the output buffer is large enough + // to hold the output data. Client can precalculate the needed output buffer + // size by using ParseConfigurationAndCalculateSize. + // + // In case of failed conversion object H264BitstreamConverter may have written + // some bytes to buffer pointed by pinput but user should ignore those bytes. + // None of the outputs should be considered valid. + // + // Parameters + // pinput + // Pointer to buffer containing AVCDecoderConfigurationRecord. + // input_size + // Size of the buffer in bytes. + // poutput + // Pointer to buffer where the output should be written to. + // poutput_size (i/o) + // Pointer to the size of the output buffer. Will contain the number of + // bytes written to output after successful call. + // + // Returns + // true if successful conversion + // false if conversion not successful (poutput_size will hold the amount + // of converted data) + bool ConvertAVCDecoderConfigurationRecordToByteStream(const uint8* input, + uint32 input_size, + uint8* output, + uint32* output_size); + + // ConvertNalUnitStreamToByteStream converts the NAL unit from MP4 format + // to bytestream format. Client is responsible for making sure the output + // buffer is large enough to hold the output data. Client can precalculate the + // needed output buffer size by using CalculateNeededOutputBufferSize. + // + // In case of failed conversion object H264BitstreamConverter may have written + // some bytes to buffer pointed by pinput but user should ignore those bytes. + // None of the outputs should be considered valid. + // + // Parameters + // pinput + // Pointer to buffer containing AVCDecoderConfigurationRecord. + // input_size + // Size of the buffer in bytes. + // poutput + // Pointer to buffer where the output should be written to. + // poutput_size (i/o) + // Pointer to the size of the output buffer. Will contain the number of + // bytes written to output after successful call. + // + // Returns + // true if successful conversion + // false if conversion not successful (poutput_size will hold the amount + // of converted data) + bool ConvertNalUnitStreamToByteStream(const uint8* input, uint32 input_size, + uint8* output, uint32* output_size); + + private: + // Flag for indicating whether global parameter sets have been processed. + bool configuration_processed_; + // Flag for indicating whether next NAL unit starts new access unit. + bool first_nal_unit_in_access_unit_; + // Variable to hold interleaving field's length in bytes. + uint8 nal_unit_length_field_width_; + + DISALLOW_COPY_AND_ASSIGN(H264BitstreamConverter); +}; + +} // namespace media + +#endif // MEDIA_BASE_H264_BITSTREAM_CONVERTER_H_ + diff --git a/media/base/h264_bitstream_converter_unittest.cc b/media/base/h264_bitstream_converter_unittest.cc new file mode 100644 index 0000000..97ccaaf --- /dev/null +++ b/media/base/h264_bitstream_converter_unittest.cc @@ -0,0 +1,472 @@ +// Copyright (c) 2011 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 "base/scoped_ptr.h" +#include "media/base/h264_bitstream_converter.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class H264BitstreamConverterTest : public testing::Test { + protected: + H264BitstreamConverterTest() {} + + virtual ~H264BitstreamConverterTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(H264BitstreamConverterTest); +}; + +static const uint8 kHeaderDataOkWithFieldLen4[] = { + 0x01, 0x42, 0x00, 0x28, 0xFF, 0xE1, 0x00, 0x08, 0x67, 0x42, 0x00, 0x28, + 0xE9, 0x05, 0x89, 0xC8, 0x01, 0x00, 0x04, 0x68, 0xCE, 0x06, 0xF2, 0x00 +}; + +static const uint8 kPacketDataOkWithFieldLen4[] = { + 0x00, 0x00, 0x0B, 0xF7, 0x65, 0xB8, 0x40, 0x57, 0x0B, 0xF0, + 0xDF, 0xF8, 0x00, 0x1F, 0x78, 0x98, 0x54, 0xAC, 0xF2, 0x00, 0x04, 0x9D, 0x26, + 0xE0, 0x3B, 0x5C, 0x00, 0x0A, 0x00, 0x8F, 0x9E, 0x86, 0x63, 0x1B, 0x46, 0xE7, + 0xD6, 0x45, 0x88, 0x88, 0xEA, 0x10, 0x89, 0x79, 0x01, 0x34, 0x30, 0x01, 0x8E, + 0x7D, 0x1A, 0x39, 0x45, 0x4E, 0x69, 0x86, 0x12, 0xF2, 0xE7, 0xCF, 0x50, 0xF8, + 0x26, 0x54, 0x17, 0xBE, 0x3F, 0xC4, 0x80, 0x32, 0xD8, 0x02, 0x32, 0xE4, 0xAE, + 0xDD, 0x39, 0x11, 0x8E, 0x54, 0x42, 0xAE, 0xBD, 0x12, 0xA4, 0xCE, 0xE2, 0x98, + 0x91, 0x05, 0xC4, 0xA8, 0x20, 0xC7, 0xB3, 0xD9, 0x47, 0x73, 0x09, 0xD5, 0xCF, + 0x62, 0x57, 0x3F, 0xFF, 0xFD, 0xB9, 0x94, 0x2B, 0x3D, 0x12, 0x1A, 0x84, 0x0B, + 0x28, 0xAD, 0x5C, 0x9E, 0x5C, 0xC3, 0xBB, 0xBD, 0x7F, 0xFE, 0x09, 0x87, 0x74, + 0x39, 0x1C, 0xA5, 0x0E, 0x44, 0xD8, 0x5D, 0x41, 0xDB, 0xAA, 0xBC, 0x05, 0x16, + 0xA3, 0x98, 0xEE, 0xEE, 0x9C, 0xA0, 0xF1, 0x23, 0x90, 0xF0, 0x5E, 0x9F, 0xF4, + 0xFA, 0x7F, 0x4B, 0x69, 0x66, 0x49, 0x52, 0xDD, 0xD6, 0xC0, 0x0F, 0x8C, 0x6E, + 0x80, 0xDD, 0x7A, 0xDF, 0x10, 0xCD, 0x4B, 0x54, 0x6F, 0xFC, 0x7D, 0x34, 0xBA, + 0x8B, 0xD4, 0xD9, 0x30, 0x18, 0x9F, 0x39, 0x04, 0x9F, 0xCB, 0xDB, 0x1B, 0xA7, + 0x70, 0x96, 0xAF, 0xFF, 0x6F, 0xB5, 0xBF, 0x58, 0x01, 0x98, 0xCD, 0xF2, 0x66, + 0x28, 0x1A, 0xC4, 0x9E, 0x58, 0x40, 0x39, 0xAE, 0x07, 0x11, 0x3F, 0xF2, 0x9B, + 0x06, 0x9C, 0xB8, 0xC9, 0x16, 0x12, 0x09, 0x8E, 0xD2, 0xD4, 0xF5, 0xC6, 0x77, + 0x40, 0x0F, 0xFD, 0x12, 0x19, 0x55, 0x1A, 0x8E, 0x9C, 0x18, 0x8B, 0x0D, 0x18, + 0xFA, 0xBA, 0x7F, 0xBB, 0x83, 0xBB, 0x85, 0xA0, 0xCC, 0xAF, 0xF6, 0xEA, 0x81, + 0x10, 0x18, 0x8E, 0x10, 0x00, 0xCB, 0x7F, 0x27, 0x08, 0x06, 0xDE, 0x3C, 0x20, + 0xE5, 0xFE, 0xCC, 0x4F, 0xB3, 0x41, 0xE0, 0xCC, 0x4C, 0x26, 0xC1, 0xC0, 0x2C, + 0x16, 0x12, 0xAA, 0x04, 0x83, 0x51, 0x4E, 0xCA, 0x00, 0xCF, 0x42, 0x9C, 0x06, + 0x2D, 0x06, 0xDD, 0x1D, 0x08, 0x75, 0xE0, 0x89, 0xC7, 0x62, 0x68, 0x2E, 0xBF, + 0x4D, 0x2D, 0x0A, 0xC4, 0x86, 0xF6, 0x2F, 0xA1, 0x49, 0xA7, 0x0F, 0xDB, 0x1F, + 0x82, 0xEC, 0xC1, 0x62, 0xFB, 0x7F, 0xF1, 0xAE, 0xA6, 0x1A, 0xD5, 0x6B, 0x06, + 0x5E, 0xB6, 0x02, 0x50, 0xAE, 0x2D, 0xF9, 0xD9, 0x95, 0xAD, 0x01, 0x8C, 0x53, + 0x01, 0xAF, 0xCE, 0xE5, 0xA5, 0xBB, 0x95, 0x8A, 0x85, 0x70, 0x77, 0xE3, 0x9A, + 0x68, 0x1B, 0xDF, 0x47, 0xF9, 0xF4, 0xBD, 0x80, 0x7D, 0x76, 0x9A, 0x69, 0xFC, + 0xBE, 0x14, 0x0D, 0x87, 0x09, 0x12, 0x98, 0x20, 0x05, 0x46, 0xB7, 0xAE, 0x10, + 0xB7, 0x01, 0xB7, 0xDE, 0x3B, 0xDD, 0x7A, 0x8A, 0x55, 0x73, 0xAD, 0xDF, 0x69, + 0xDE, 0xD0, 0x51, 0x97, 0xA0, 0xE6, 0x5E, 0xBA, 0xBA, 0x80, 0x0F, 0x4E, 0x9A, + 0x68, 0x36, 0xE6, 0x9F, 0x5B, 0x39, 0xC0, 0x90, 0xA1, 0xC0, 0xC3, 0x82, 0xE4, + 0x50, 0xEA, 0x60, 0x7A, 0xDD, 0x5F, 0x8B, 0x5F, 0xAF, 0xFC, 0x74, 0xAF, 0xDC, + 0x56, 0xF7, 0x2E, 0x3E, 0x97, 0x6E, 0x2B, 0xF3, 0xAF, 0xFE, 0x7D, 0x32, 0xDC, + 0x56, 0xF8, 0xAF, 0xB5, 0xA3, 0xBB, 0x00, 0x5B, 0x84, 0x3D, 0x9F, 0x0B, 0x40, + 0x88, 0x61, 0x5F, 0x4F, 0x4F, 0xB0, 0xB3, 0x07, 0x81, 0x3E, 0xF2, 0xFB, 0x50, + 0xCA, 0x77, 0x40, 0x12, 0xA8, 0xE6, 0x11, 0x8E, 0xD6, 0x8A, 0xC6, 0xD6, 0x8C, + 0x1D, 0x63, 0x55, 0x3D, 0x34, 0xEA, 0xC3, 0xC6, 0x6A, 0xD2, 0x8C, 0xB0, 0x1D, + 0x5E, 0x4A, 0x7A, 0x8B, 0xD5, 0x99, 0x80, 0x84, 0x32, 0xFB, 0xB7, 0x02, 0x6E, + 0x61, 0xFE, 0xAC, 0x1B, 0x5D, 0x10, 0x23, 0x24, 0xC3, 0x8C, 0x7B, 0x58, 0x2C, + 0x4D, 0x04, 0x74, 0x84, 0x25, 0x10, 0x4E, 0x94, 0x29, 0x4D, 0x88, 0xAE, 0x65, + 0x53, 0xB9, 0x95, 0x4E, 0xE7, 0xDD, 0xEE, 0xF2, 0x70, 0x1F, 0x26, 0x4F, 0xA8, + 0xBC, 0x3D, 0x35, 0x02, 0x3B, 0xC0, 0x98, 0x70, 0x38, 0x18, 0xE5, 0x1E, 0x05, + 0xAC, 0x28, 0xAA, 0x46, 0x1A, 0xB0, 0x19, 0x99, 0x18, 0x35, 0x78, 0x1E, 0x41, + 0x60, 0x0D, 0x4F, 0x7E, 0xEC, 0x37, 0xC3, 0x30, 0x73, 0x2A, 0x69, 0xFE, 0xEF, + 0x27, 0xEE, 0x13, 0xCC, 0xD0, 0xDB, 0xE6, 0x45, 0xEC, 0x5C, 0xB5, 0x71, 0x54, + 0x2E, 0xB1, 0xE9, 0x88, 0xB4, 0x3F, 0x6F, 0xFD, 0xF7, 0xFF, 0x9D, 0x2D, 0x52, + 0x2E, 0xAE, 0xC9, 0x95, 0xDE, 0xBF, 0xDF, 0xFF, 0xBF, 0x21, 0xB3, 0x2B, 0xF5, + 0xF7, 0xF7, 0xD1, 0xA0, 0xF0, 0x76, 0x68, 0x37, 0xDB, 0x8F, 0x85, 0x4D, 0xA8, + 0x1A, 0xF9, 0x7F, 0x75, 0xA7, 0x93, 0xF5, 0x03, 0xC1, 0xF2, 0x60, 0x8A, 0x92, + 0x53, 0xF5, 0xD1, 0xC1, 0x56, 0x4B, 0x68, 0x05, 0x16, 0x88, 0x61, 0xE7, 0x14, + 0xC8, 0x0D, 0xF0, 0xDF, 0xEF, 0x46, 0x4A, 0xED, 0x0B, 0xD1, 0xD1, 0xD1, 0xA4, + 0x85, 0xA3, 0x2C, 0x1D, 0xDE, 0x45, 0x14, 0xA1, 0x8E, 0xA8, 0xD9, 0x8C, 0xAB, + 0x47, 0x31, 0xF1, 0x00, 0x15, 0xAD, 0x80, 0x20, 0xAA, 0xE4, 0x57, 0xF8, 0x05, + 0x14, 0x58, 0x0B, 0xD3, 0x63, 0x00, 0x8F, 0x44, 0x15, 0x7F, 0x19, 0xC7, 0x0A, + 0xE0, 0x49, 0x32, 0xFE, 0x36, 0x0E, 0xF3, 0x66, 0x10, 0x2B, 0x11, 0x73, 0x3D, + 0x19, 0x92, 0x22, 0x20, 0x75, 0x1F, 0xF1, 0xDB, 0x96, 0x73, 0xCF, 0x1B, 0x53, + 0xFF, 0xD2, 0x23, 0xF2, 0xB6, 0xAA, 0xB6, 0x44, 0xA3, 0x73, 0x7E, 0x00, 0x2D, + 0x4D, 0x4D, 0x87, 0xE0, 0x84, 0x55, 0xD6, 0x03, 0xB8, 0xD8, 0x90, 0xEF, 0xC0, + 0x76, 0x5D, 0x69, 0x02, 0x00, 0x0E, 0x17, 0xD0, 0x02, 0x96, 0x50, 0xEA, 0xAB, + 0xBF, 0x0D, 0xAF, 0xCB, 0xD3, 0xFF, 0xAA, 0x9D, 0x7F, 0xD6, 0xBD, 0x2C, 0x14, + 0xB4, 0xCD, 0x20, 0x73, 0xB4, 0xF4, 0x38, 0x96, 0xDE, 0xB0, 0x6B, 0xE5, 0x1B, + 0xFD, 0x0E, 0x0B, 0xA4, 0x81, 0xBF, 0xC8, 0xA0, 0x21, 0x76, 0x7B, 0x25, 0x3F, + 0xE6, 0x84, 0x40, 0x1A, 0xDA, 0x25, 0x5A, 0xFF, 0x73, 0x6B, 0x14, 0x1B, 0xF7, + 0x08, 0xFA, 0x26, 0x73, 0x7A, 0x58, 0x02, 0x1A, 0xE6, 0x63, 0xB6, 0x45, 0x7B, + 0xE3, 0xE0, 0x80, 0x14, 0x42, 0xA8, 0x7D, 0xF3, 0x80, 0x9B, 0x01, 0x43, 0x82, + 0x82, 0x8C, 0xBE, 0x0D, 0xFD, 0xAE, 0x88, 0xA8, 0xB9, 0xC3, 0xEE, 0xFF, 0x46, + 0x00, 0x84, 0xE6, 0xB4, 0x0C, 0xA9, 0x66, 0xC6, 0x74, 0x72, 0xAA, 0xA4, 0x3A, + 0xB0, 0x1B, 0x06, 0xB4, 0xDB, 0xE8, 0xC2, 0x17, 0xA2, 0xBC, 0xBE, 0x5C, 0x0F, + 0x2A, 0x76, 0xD5, 0xEE, 0x39, 0x36, 0x7C, 0x25, 0x94, 0x15, 0x3C, 0xC9, 0xB9, + 0x93, 0x07, 0x19, 0xAF, 0xE6, 0x70, 0xC3, 0xF5, 0xD4, 0x17, 0x87, 0x57, 0x77, + 0x7D, 0xCF, 0x0D, 0xDD, 0xDE, 0xB7, 0xFF, 0xB4, 0xDA, 0x20, 0x45, 0x1A, 0x45, + 0xF4, 0x58, 0x01, 0xBC, 0xEB, 0x3F, 0x16, 0x7F, 0x4C, 0x15, 0x84, 0x8C, 0xE5, + 0xF6, 0x96, 0xA6, 0xA1, 0xB9, 0xB2, 0x7F, 0x6B, 0xFF, 0x31, 0xF2, 0xF5, 0xC9, + 0xFF, 0x61, 0xEE, 0xB5, 0x84, 0xAE, 0x68, 0x41, 0xEA, 0xD0, 0xF0, 0xA5, 0xCE, + 0x0C, 0xE6, 0x4C, 0x6D, 0x6D, 0x94, 0x08, 0xC9, 0xA9, 0x4A, 0x60, 0x6D, 0x01, + 0x3B, 0xEF, 0x4D, 0x99, 0x8D, 0x42, 0x2A, 0x6B, 0x8A, 0xC7, 0xFA, 0xA9, 0x90, + 0x40, 0x00, 0x90, 0xF3, 0xA0, 0x75, 0x8E, 0xD5, 0xFE, 0xE7, 0xBD, 0x02, 0x87, + 0x0C, 0x7D, 0xF0, 0xAF, 0x1E, 0x5F, 0x8D, 0xC8, 0xE1, 0xD4, 0x56, 0x08, 0xBF, + 0x76, 0x80, 0xD4, 0x18, 0x89, 0x2D, 0x57, 0xDF, 0x66, 0xD0, 0x46, 0x68, 0x77, + 0x55, 0x47, 0xF5, 0x7C, 0xF7, 0xA6, 0x66, 0xD6, 0x5A, 0x64, 0x55, 0xD4, 0x80, + 0xC4, 0x55, 0xE9, 0x36, 0x3F, 0x5E, 0xE2, 0x5C, 0x7F, 0x5F, 0xCE, 0x7F, 0xE1, + 0x0C, 0x82, 0x3D, 0x6B, 0x6E, 0xA2, 0xEA, 0x3B, 0x1F, 0xE8, 0x9E, 0xC7, 0x4E, + 0x24, 0x3D, 0xDD, 0xFA, 0xEB, 0x71, 0xDF, 0xFE, 0x15, 0xFE, 0x41, 0x9B, 0xB4, + 0x4E, 0xAB, 0x51, 0xE5, 0x1F, 0x7D, 0x2D, 0xAC, 0xD0, 0x66, 0xD9, 0xA1, 0x59, + 0x78, 0xC6, 0xEF, 0xC4, 0x43, 0x08, 0x65, 0x18, 0x73, 0xDE, 0x2A, 0xAD, 0x72, + 0xE7, 0x5A, 0x7E, 0x33, 0x04, 0x72, 0x38, 0x57, 0x47, 0x73, 0x10, 0x1D, 0x88, + 0x57, 0x4C, 0xDF, 0xA7, 0x78, 0x16, 0xFB, 0x01, 0x21, 0x28, 0x2D, 0xB6, 0x7E, + 0x05, 0x18, 0x32, 0x52, 0xC3, 0x49, 0x0B, 0x32, 0x18, 0x12, 0x93, 0x54, 0x15, + 0x3B, 0xC8, 0x6D, 0x4A, 0x77, 0xEF, 0x0A, 0x46, 0x83, 0x89, 0x5C, 0x8B, 0xCB, + 0x18, 0xA6, 0xDC, 0x97, 0x6F, 0xEE, 0xEE, 0x00, 0x6A, 0xF1, 0x10, 0xFE, 0x07, + 0x0C, 0xE0, 0x53, 0xD2, 0xB8, 0x45, 0xF4, 0x6E, 0x16, 0x4B, 0xC9, 0x9C, 0xC7, + 0x93, 0x83, 0x23, 0x1D, 0x4D, 0x00, 0xB9, 0x4F, 0x86, 0x51, 0xF0, 0x29, 0x69, + 0x41, 0x21, 0xC5, 0x4A, 0xC6, 0x6D, 0xD1, 0x81, 0x38, 0xDB, 0x7C, 0x06, 0xA8, + 0x26, 0x8E, 0x71, 0x00, 0x4C, 0x44, 0x14, 0x05, 0xF2, 0x1C, 0x00, 0x49, 0xFC, + 0x29, 0x6A, 0xF9, 0x9E, 0xD1, 0x35, 0x4B, 0xB7, 0xE5, 0xDB, 0xFC, 0x01, 0x04, + 0x3F, 0x70, 0x33, 0x56, 0x87, 0x69, 0x01, 0xB4, 0xCE, 0x1C, 0x4D, 0x2E, 0x83, + 0x51, 0x51, 0xD0, 0x37, 0x3B, 0xB4, 0xBA, 0x47, 0xF5, 0xFF, 0xBF, 0xFA, 0xD5, + 0x03, 0x65, 0xD3, 0x28, 0x9F, 0x38, 0x57, 0xFE, 0x71, 0xD8, 0x9C, 0x16, 0xEE, + 0x72, 0x19, 0x03, 0x17, 0x6E, 0xC0, 0xEC, 0x49, 0x3D, 0x96, 0xE2, 0x30, 0x97, + 0x97, 0x84, 0x38, 0x6B, 0xE8, 0x2E, 0xAB, 0x0E, 0x2E, 0x03, 0x52, 0xBA, 0x68, + 0x55, 0xBA, 0x1D, 0x2C, 0x47, 0xAA, 0x72, 0xAE, 0x02, 0x31, 0x6E, 0xA1, 0xDC, + 0xAD, 0x0F, 0x4A, 0x46, 0xC9, 0xF2, 0xA9, 0xAB, 0xFD, 0x87, 0x89, 0x5C, 0xB3, + 0x75, 0x7E, 0xE3, 0xDE, 0x9F, 0xC4, 0x02, 0x1E, 0xA2, 0xF8, 0x8B, 0xD3, 0x00, + 0x83, 0x96, 0xC4, 0xD0, 0xB9, 0x62, 0xB9, 0x69, 0xEC, 0x56, 0xDF, 0x7D, 0x91, + 0x4B, 0x68, 0x27, 0xA8, 0x61, 0x78, 0xA7, 0x95, 0x66, 0x51, 0x41, 0xF6, 0xCE, + 0x78, 0xD3, 0x9A, 0x91, 0xA0, 0x31, 0x09, 0x47, 0xB8, 0x47, 0xB8, 0x44, 0xE1, + 0x13, 0x86, 0x7E, 0x92, 0x80, 0xC6, 0x1A, 0xF7, 0x79, 0x7E, 0xF1, 0x5D, 0x9F, + 0x17, 0x2D, 0x80, 0x00, 0x79, 0x34, 0x7D, 0xE3, 0xAD, 0x60, 0x00, 0x20, 0x07, + 0x80, 0x00, 0x40, 0x01, 0xF8, 0xA1, 0x86, 0xB1, 0xEE, 0x21, 0x63, 0x85, 0x60, + 0x51, 0x84, 0x90, 0x7E, 0x92, 0x09, 0x39, 0x1C, 0x16, 0x87, 0x5C, 0xA6, 0x09, + 0x90, 0x06, 0x34, 0x6E, 0xB8, 0x8D, 0x5D, 0xAC, 0x77, 0x97, 0xB5, 0x4D, 0x30, + 0xFD, 0x39, 0xD0, 0x50, 0x00, 0xC9, 0x98, 0x04, 0x86, 0x00, 0x0D, 0xD8, 0x3E, + 0x34, 0xC2, 0xA6, 0x25, 0xF8, 0x20, 0xCC, 0x6D, 0x9E, 0x63, 0x05, 0x30, 0xC4, + 0xC6, 0xCC, 0x54, 0x31, 0x9F, 0x3C, 0xF5, 0x86, 0xB9, 0x08, 0x18, 0xC3, 0x1E, + 0xB9, 0xA0, 0x0C, 0x45, 0x2C, 0x54, 0x32, 0x8B, 0x85, 0x86, 0x59, 0xC3, 0xB3, + 0x50, 0x5A, 0xFE, 0xBA, 0xF7, 0x4D, 0xC9, 0x9C, 0x9E, 0x01, 0xDF, 0xD7, 0x6E, + 0xB5, 0x15, 0x53, 0x08, 0x57, 0xA4, 0x71, 0x36, 0x80, 0x46, 0x05, 0x21, 0x48, + 0x7B, 0x91, 0xC8, 0xAA, 0xFF, 0x07, 0x9F, 0x78, 0x68, 0xCF, 0x3C, 0xEF, 0xFF, + 0xBC, 0xB6, 0xA2, 0x36, 0xB7, 0x9F, 0x54, 0xF6, 0x6F, 0x5D, 0xDD, 0x75, 0xD4, + 0x3C, 0x75, 0xE8, 0xCF, 0x15, 0x02, 0x5B, 0x94, 0xC3, 0xA2, 0x41, 0x63, 0xA1, + 0x14, 0xF6, 0xC0, 0x57, 0x15, 0x9F, 0x0C, 0x3F, 0x80, 0xF2, 0x98, 0xEE, 0x41, + 0x85, 0xEE, 0xBC, 0xAA, 0xE9, 0x59, 0xAA, 0xA0, 0x92, 0xCA, 0x00, 0xF3, 0x50, + 0xCC, 0xFF, 0xAD, 0x97, 0x69, 0xA7, 0xF2, 0x0B, 0x8F, 0xD7, 0xD7, 0x82, 0x3A, + 0xBB, 0x98, 0x1D, 0xCB, 0x89, 0x0B, 0x9B, 0x05, 0xF7, 0xD0, 0x1A, 0x60, 0xF3, + 0x29, 0x16, 0x12, 0xF8, 0xF4, 0xF1, 0x4A, 0x05, 0x9B, 0x57, 0x12, 0x7E, 0x3A, + 0x4A, 0x8D, 0xA6, 0xDF, 0xB6, 0xDD, 0xDF, 0xC3, 0xF0, 0xD2, 0xD4, 0xD7, 0x41, + 0xA6, 0x00, 0x76, 0x8C, 0x75, 0x08, 0xF0, 0x19, 0xD8, 0x14, 0x63, 0x55, 0x52, + 0x18, 0x30, 0x98, 0xD0, 0x3F, 0x65, 0x52, 0xB3, 0x88, 0x6D, 0x17, 0x39, 0x93, + 0xCA, 0x3B, 0xB4, 0x1D, 0x8D, 0xDF, 0xDF, 0xAD, 0x72, 0xDA, 0x74, 0xAF, 0xBD, + 0x31, 0xF9, 0x12, 0x61, 0x45, 0x29, 0x4C, 0x2B, 0x61, 0xA1, 0x12, 0x90, 0x53, + 0xE7, 0x5A, 0x9D, 0x44, 0xC8, 0x3A, 0x83, 0xDC, 0x34, 0x4C, 0x07, 0xAF, 0xDB, + 0x90, 0xCD, 0x03, 0xA4, 0x64, 0x78, 0xBD, 0x55, 0xB2, 0x56, 0x59, 0x32, 0xAB, + 0x13, 0x2C, 0xC9, 0x77, 0xF8, 0x3B, 0xDF, 0xFF, 0xAC, 0x07, 0xB9, 0x08, 0x7B, + 0xE9, 0x82, 0xB9, 0x59, 0xC7, 0xFF, 0x86, 0x2C, 0x12, 0x7C, 0xC6, 0x65, 0x3C, + 0x71, 0xB8, 0x98, 0x9F, 0xA2, 0x45, 0x03, 0xA5, 0xD9, 0xC3, 0xCF, 0xFA, 0xEB, + 0x89, 0xAD, 0x03, 0xEE, 0xDD, 0x76, 0xD3, 0x4F, 0x10, 0x6F, 0xF0, 0xC1, 0x60, + 0x0C, 0x00, 0xD4, 0x76, 0x12, 0x0A, 0x8D, 0xDC, 0xFD, 0x5E, 0x0B, 0x26, 0x2F, + 0x01, 0x1D, 0xB9, 0xE7, 0x73, 0xD4, 0xF2, 0xCB, 0xD8, 0x78, 0x21, 0x52, 0x4B, + 0x83, 0x3C, 0x44, 0x72, 0x0E, 0xB1, 0x4E, 0x37, 0xBC, 0xC7, 0x50, 0xFA, 0x07, + 0x80, 0x71, 0x10, 0x0B, 0x24, 0xD1, 0x7E, 0xDA, 0x7F, 0xA7, 0x2F, 0x40, 0xAA, + 0xD3, 0xF5, 0x44, 0x10, 0x56, 0x4E, 0x3B, 0xF1, 0x6E, 0x9A, 0xA0, 0xEA, 0x85, + 0x66, 0x16, 0xFB, 0x5C, 0x0B, 0x2B, 0x74, 0x18, 0xAF, 0x3D, 0x04, 0x3E, 0xCE, + 0x88, 0x9B, 0x3E, 0xF4, 0xB9, 0x00, 0x60, 0x0E, 0xE1, 0xE2, 0xCB, 0x12, 0xB9, + 0x6D, 0x5A, 0xC7, 0x55, 0x1D, 0xB9, 0x79, 0xAC, 0x43, 0x43, 0xE6, 0x3B, 0xDD, + 0x7E, 0x9F, 0x78, 0xD3, 0xEA, 0xA3, 0x11, 0xFF, 0xDB, 0xBB, 0xB8, 0x97, 0x37, + 0x15, 0xDB, 0xF1, 0x97, 0x96, 0xC7, 0xFC, 0xE5, 0xBF, 0xF2, 0x86, 0xC0, 0xFA, + 0x9B, 0x4C, 0x00, 0x04, 0x03, 0xA5, 0xB6, 0xB7, 0x9C, 0xD9, 0xAB, 0x09, 0x77, + 0x51, 0x18, 0x3B, 0xAD, 0x61, 0x6C, 0xFC, 0x51, 0x96, 0xFB, 0x19, 0xC8, 0x52, + 0x35, 0x07, 0x00, 0x63, 0x87, 0x14, 0x04, 0xFA, 0x7A, 0x48, 0x3E, 0x00, 0x47, + 0x29, 0x07, 0x74, 0x97, 0x74, 0x84, 0xEB, 0xB2, 0x16, 0xB2, 0x31, 0x81, 0xCE, + 0x2A, 0x31, 0xA7, 0xB1, 0xEB, 0x83, 0x34, 0x7A, 0x73, 0xD7, 0x2F, 0xFF, 0xBC, + 0xFF, 0xE5, 0xAA, 0xF2, 0xB5, 0x6E, 0x9E, 0xA5, 0x70, 0x8A, 0x8C, 0xDF, 0x6A, + 0x06, 0x16, 0xC1, 0xAB, 0x59, 0x70, 0xD9, 0x3D, 0x47, 0x7C, 0xDD, 0xEF, 0xDF, + 0x2F, 0xFF, 0x42, 0x6B, 0xBA, 0x4B, 0xBF, 0xF8, 0x7F, 0xF2, 0x03, 0x0D, 0x79, + 0xBC, 0x03, 0x76, 0x64, 0x1C, 0x0D, 0x7B, 0xD7, 0xBD, 0xB0, 0x6C, 0xD8, 0x61, + 0x17, 0x17, 0x8C, 0xED, 0x4E, 0x20, 0xEB, 0x55, 0x33, 0x39, 0xE9, 0x7E, 0xBE, + 0x8E, 0x05, 0x4B, 0x78, 0x96, 0x85, 0xCC, 0x68, 0xC9, 0x78, 0xAF, 0xAE, 0x44, + 0x36, 0x61, 0xD3, 0x53, 0xEB, 0xB3, 0x3E, 0x4F, 0x97, 0xE2, 0x8D, 0xAE, 0x90, + 0xED, 0xB5, 0x4F, 0x8E, 0xE4, 0x7A, 0x44, 0xCF, 0x9D, 0xC5, 0x77, 0x4D, 0xAB, + 0x4F, 0xE5, 0xC5, 0x73, 0xA0, 0xC8, 0xA5, 0xBB, 0x4B, 0x7D, 0xD5, 0xFB, 0xFB, + 0xFF, 0x61, 0xFD, 0xAA, 0x1A, 0x62, 0x7E, 0x3C, 0x66, 0x34, 0x15, 0x64, 0x25, + 0xEC, 0x7C, 0x9D, 0x6A, 0x64, 0x4D, 0x80, 0xD5, 0x4F, 0xFE, 0x8E, 0xEE, 0x18, + 0x53, 0xC1, 0x09, 0x51, 0xF7, 0xC0, 0xA6, 0xB2, 0x9B, 0x19, 0x2B, 0x14, 0x66, + 0x66, 0x4B, 0x39, 0x62, 0x1D, 0x84, 0xB9, 0x02, 0x84, 0xAC, 0xC1, 0xDA, 0x6C, + 0x80, 0xCD, 0x40, 0x20, 0x20, 0x19, 0x51, 0xDC, 0x2B, 0x7D, 0x5D, 0x7F, 0xE3, + 0x86, 0x8E, 0xC3, 0x35, 0xFE, 0x5C, 0xF6, 0x1C, 0xFF, 0x05, 0x9E, 0xB5, 0xB6, + 0xBB, 0xBE, 0xF7, 0x2F, 0xB7, 0xE1, 0xF5, 0x33, 0x86, 0xA0, 0x47, 0xDE, 0xF7, + 0xE9, 0x3B, 0xBE, 0x7E, 0x9B, 0x17, 0xFC, 0xFD, 0x2E, 0x40, 0x86, 0x41, 0x75, + 0xF1, 0xB2, 0x18, 0xA9, 0xDE, 0x2D, 0xD6, 0x04, 0x20, 0xA4, 0xBA, 0x81, 0xBC, + 0x1D, 0x5A, 0xD6, 0xF7, 0xF6, 0xB8, 0x42, 0xF7, 0xF5, 0x3D, 0x97, 0xAC, 0xCD, + 0x6F, 0xAD, 0xDB, 0x4F, 0x5A, 0x2E, 0x64, 0xB9, 0x5D, 0xDD, 0x8B, 0x4A, 0x35, + 0x44, 0xFE, 0x3D, 0xC6, 0x77, 0x7A, 0xBF, 0xDA, 0xAC, 0x9E, 0xB0, 0xA2, 0xB9, + 0x6C, 0xAF, 0x02, 0xDD, 0xF2, 0x71, 0x2B, 0xEF, 0xD3, 0x51, 0x0E, 0x07, 0x11, + 0xBD, 0xED, 0x39, 0x7F, 0xD9, 0xB8, 0xBD, 0xEE, 0x35, 0xE9, 0x5C, 0x67, 0x42, + 0xDA, 0x05, 0x6E, 0x39, 0xCE, 0x55, 0xFB, 0x26, 0xB7, 0x90, 0x4B, 0xDA, 0x91, + 0x48, 0xFD, 0xDE, 0xB2, 0xEC, 0x88, 0x9A, 0x46, 0x1A, 0x4C, 0xD4, 0x05, 0x12, + 0x85, 0x57, 0x37, 0x22, 0xD3, 0x0E, 0x4F, 0x79, 0xE3, 0x81, 0xA9, 0x2B, 0x5F, + 0xD7, 0x6D, 0xBD, 0x21, 0x98, 0x6F, 0x7D, 0xF5, 0x32, 0x7A, 0x6E, 0xF8, 0x20, + 0x01, 0x50, 0x90, 0x7A, 0x88, 0x3E, 0x0D, 0x57, 0xB1, 0x58, 0x65, 0xE6, 0x82, + 0xCE, 0x08, 0x69, 0x8B, 0x87, 0x62, 0x36, 0xB1, 0x7B, 0xDE, 0x74, 0xBD, 0xFE, + 0x10, 0xBE, 0x26, 0xAB, 0x7E, 0xB7, 0x8D, 0xF7, 0x83, 0x2E, 0x0F, 0xAF, 0x7E, + 0xBC, 0x17, 0x31, 0xFF, 0xB0, 0x4F, 0x7F, 0x4B, 0x13, 0x83, 0xDF, 0xEE, 0x23, + 0xD3, 0xE7, 0xC8, 0xAF, 0x75, 0xAB, 0xEA, 0xBD, 0x7D, 0xD2, 0x9D, 0xE9, 0xC1, + 0x18, 0x8B, 0x7C, 0x9F, 0x51, 0xDC, 0x37, 0xA3, 0xDB, 0xFC, 0xD4, 0x6A, 0x91, + 0x44, 0x7F, 0x72, 0xC5, 0xD9, 0xC8, 0x37, 0x38, 0x63, 0x0D, 0x59, 0x8B, 0x7F, + 0x7D, 0x96, 0xC1, 0x5F, 0x4C, 0x7C, 0x88, 0xCB, 0x65, 0x07, 0x2B, 0x0E, 0x1D, + 0x24, 0xAA, 0x20, 0x2E, 0x6C, 0x33, 0xAB, 0xEF, 0x23, 0xE5, 0xE3, 0x6C, 0xA3, + 0xA5, 0x2D, 0x01, 0xDF, 0x26, 0x92, 0x52, 0xF5, 0xE6, 0x3E, 0xE3, 0xDD, 0xC6, + 0xED, 0x42, 0x0F, 0x71, 0x7B, 0xD1, 0xF4, 0x06, 0xF6, 0x82, 0xD5, 0x13, 0xB3, + 0x60, 0x31, 0x09, 0x89, 0x63, 0x15, 0xD2, 0xCB, 0xAA, 0x77, 0xFD, 0xF4, 0xEB, + 0xF4, 0xED, 0x2E, 0xE2, 0xBA, 0x27, 0x2E, 0x74, 0xD2, 0x91, 0x7F, 0x0F, 0xDE, + 0x25, 0xFE, 0x78, 0x20, 0x05, 0x0A, 0x6A, 0xFE, 0x89, 0x14, 0x23, 0xF3, 0xF5, + 0x3A, 0x1E, 0xF3, 0x22, 0xCE, 0x12, 0x82, 0x24, 0x11, 0x05, 0x04, 0x71, 0x99, + 0xE5, 0xF0, 0xA6, 0xDB, 0x7B, 0xF5, 0x8F, 0xF9, 0x3C, 0x02, 0x0C, 0x46, 0xFD, + 0xB6, 0xEA, 0x06, 0x11, 0xF4, 0x1E, 0x7A, 0x20, 0x6A, 0x54, 0xBB, 0x4A, 0x60, + 0xB0, 0x30, 0x28, 0x9A, 0xF3, 0x3B, 0xE9, 0xBD, 0xD6, 0x04, 0xCA, 0x3A, 0x33, + 0x37, 0x5F, 0xB7, 0xAD, 0xE7, 0x9C, 0xE2, 0x95, 0x21, 0xF7, 0xB5, 0xC4, 0xF0, + 0xD1, 0x51, 0x09, 0x44, 0x3F, 0x07, 0xFC, 0x5F, 0x37, 0xFD, 0x7D, 0x7E, 0xD5, + 0xF7, 0xEB, 0x69, 0xB9, 0x54, 0x98, 0x5A, 0x2A, 0x56, 0xE3, 0xC0, 0x21, 0x57, + 0xD1, 0xEB, 0x75, 0x15, 0xED, 0xAC, 0xAF, 0x5D, 0xFF, 0xC2, 0xFE, 0x4E, 0xFB, + 0xBA, 0x13, 0xB8, 0x87, 0xFA, 0x4E, 0x5E, 0x5C, 0x24, 0x15, 0x5B, 0x2B, 0x2C, + 0x32, 0x68, 0x1F, 0x30, 0x5F, 0xC1, 0xF7, 0xE7, 0xE1, 0x9C, 0x00, 0xC1, 0x9C, + 0xB1, 0xAB, 0xFA, 0xFF, 0xC1, 0x1E, 0x72, 0xA1, 0x46, 0x9E, 0x2E, 0xCD, 0x76, + 0x96, 0x4F, 0x14, 0xDC, 0x68, 0xC1, 0x10, 0x9F, 0xDF, 0xEB, 0x5A, 0xBA, 0x8D, + 0x91, 0x4E, 0x76, 0xE9, 0x3A, 0x43, 0x2D, 0x88, 0xD2, 0x81, 0x0C, 0xEC, 0x6F, + 0xB7, 0xA4, 0x8B, 0x97, 0x4F, 0xC4, 0x1E, 0xF3, 0x0F, 0xF5, 0x66, 0x66, 0xBF, + 0x6C, 0x3F, 0xFB, 0x6E, 0x2B, 0x48, 0x6C, 0x7B, 0xD1, 0x2E, 0x64, 0xD1, 0x0B, + 0x6E, 0x5B, 0x05, 0x16, 0xDD, 0xCB, 0x1B, 0xDE, 0xA2, 0xB9, 0xA8, 0x94, 0xD6, + 0x5A, 0x5B, 0xE2, 0xC9, 0xBC, 0xD5, 0xAB, 0x64, 0x5B, 0x0F, 0x9A, 0xFD, 0xC7, + 0x2E, 0xB7, 0xEF, 0xAE, 0xE9, 0x1F, 0x32, 0xD2, 0xCA, 0xA0, 0x37, 0x63, 0x86, + 0x72, 0x41, 0x07, 0xBC, 0xAB, 0x6F, 0xFF, 0xB7, 0x16, 0xAA, 0xA9, 0x58, 0x9E, + 0x43, 0x9C, 0x22, 0x8D, 0x48, 0xCE, 0xE5, 0xEF, 0xE0, 0x7D, 0x47, 0x87, 0x5A, + 0xA8, 0x5B, 0x06, 0xA9, 0x47, 0xF0, 0x26, 0xB4, 0x99, 0xD8, 0xA3, 0x64, 0xED, + 0x73, 0xB3, 0x96, 0xB4, 0x21, 0x19, 0xA5, 0xC1, 0xDC, 0x88, 0x2E, 0xEE, 0xF2, + 0x77, 0x91, 0xEC, 0xFB, 0xD5, 0xF9, 0xF8, 0x90, 0x47, 0xAD, 0xF5, 0xEB, 0x96, + 0x6D, 0xF1, 0x1C, 0xE0, 0xDC, 0x74, 0x1C, 0xE6, 0x2E, 0xE1, 0x76, 0x9D, 0xEE, + 0xF4, 0xEF, 0xA5, 0x31, 0x03, 0x87, 0x0E, 0x2C, 0x84, 0xA5, 0xF1, 0x22, 0xBE, + 0x48, 0xA9, 0xCD, 0x09, 0x07, 0xC1, 0xF0, 0xD4, 0xE7, 0x03, 0x82, 0x39, 0xE2, + 0xA0, 0x0B, 0xDE, 0xAC, 0x37, 0xAC, 0x62, 0x97, 0x8E, 0x79, 0xCE, 0x52, 0x24, + 0x78, 0xF9, 0x17, 0xD2, 0xF1, 0x5D, 0x2D, 0xA1, 0xDF, 0x12, 0x2C, 0x83, 0xE5, + 0x1A, 0x28, 0x9A, 0x2D, 0xED, 0x8A, 0xBF, 0xFC, 0x41, 0xC3, 0xEB, 0x0E, 0x91, + 0xDB, 0xF2, 0xA1, 0xC8, 0xA8, 0x01, 0x8B, 0xF2, 0xF3, 0x59, 0xB7, 0xA7, 0x6F, + 0x80, 0xFF, 0x0B, 0x46, 0xE1, 0x63, 0xA7, 0x5F, 0x6B, 0xBE, 0x33, 0x71, 0xBE, + 0x3A, 0xAF, 0xA9, 0x53, 0x5D, 0x3B, 0xB2, 0xF6, 0xEB, 0x42, 0x1C, 0x3E, 0x3F, + 0x1D, 0x6A, 0x34, 0xAE, 0xB1, 0x05, 0xA1, 0x32, 0x6C, 0xB5, 0xE4, 0xD3, 0xBB, + 0xE8, 0x10, 0x14, 0x9E, 0x68, 0x6A, 0x24, 0x51, 0xA5, 0x66, 0x64, 0xCC, 0xC4, + 0x2D, 0x96, 0xA2, 0xC7, 0x2D, 0x1F, 0x0A, 0x0F, 0x6B, 0xD9, 0xAD, 0xA3, 0x11, + 0x8F, 0x00, 0xAA, 0x06, 0xC2, 0x1E, 0xF3, 0xE8, 0x5A, 0x37, 0x4C, 0xD6, 0x4B, + 0x6B, 0x01, 0xC9, 0xB0, 0xB6, 0xB9, 0x92, 0xED, 0x1D, 0x08, 0xB0, 0x80, 0x06, + 0x20, 0xEA, 0xEE, 0xF9, 0x1D, 0xA4, 0x57, 0x73, 0x2E, 0x1B, 0xA5, 0xAF, 0xF6, + 0xAF, 0xAE, 0x04, 0x7C, 0x4C, 0x7E, 0xC8, 0xDB, 0xC0, 0xFB, 0x37, 0xC8, 0x7E, + 0xFE, 0x47, 0x0A, 0x3C, 0xFA, 0x61, 0xE7, 0xEB, 0x1B, 0xF3, 0x7C, 0x32, 0xE3, + 0x7C, 0x37, 0x66, 0x7C, 0x53, 0x07, 0xC2, 0x37, 0xA3, 0xBD, 0xF7, 0xFA, 0xE3, + 0x8A, 0x76, 0xCB, 0x6C, 0xC8, 0x13, 0xC4, 0x53, 0x53, 0xDB, 0xAD, 0x37, 0x1A, + 0xEB, 0xE0 +}; + +TEST_F(H264BitstreamConverterTest, Conversion_Success) { + // Initialize converter. + scoped_array<uint8> output; + H264BitstreamConverter converter; + + // Parse the headers. + uint32 config_size = converter.ParseConfigurationAndCalculateSize( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4)); + EXPECT_GT(config_size, 0U); + + // Go on with converting the headers. + output.reset(new uint8[config_size]); + EXPECT_TRUE(output.get() != NULL); + EXPECT_TRUE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4), + output.get(), + &config_size)); + + // Calculate buffer size for actual NAL unit. + uint32 output_size = converter.CalculateNeededOutputBufferSize( + kPacketDataOkWithFieldLen4, + sizeof(kPacketDataOkWithFieldLen4)); + EXPECT_GT(output_size, 0U); + output_size += config_size; + output.reset(new uint8[output_size]); + EXPECT_TRUE(output.get() != NULL); + + uint32 output_size_left_for_nal_unit = output_size - config_size; + // Do the conversion for actual NAL unit. + EXPECT_TRUE(converter.ConvertNalUnitStreamToByteStream( + kPacketDataOkWithFieldLen4, + sizeof(kPacketDataOkWithFieldLen4), + output.get() + config_size, + &output_size_left_for_nal_unit)); + + // Classes allocated in stack are automatically destroyed. +} + +TEST_F(H264BitstreamConverterTest, Conversion_FailureNullData) { + // Initialize converter. + H264BitstreamConverter converter; + + // Simulate situation where there is no header data. + uint32 config_size = converter.ParseConfigurationAndCalculateSize(NULL, 0); + EXPECT_EQ(config_size, 0U); + + // Go on with converting the headers with NULL parameters. + EXPECT_FALSE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + NULL, + 0, + NULL, + &config_size)); + + // Simulate NULL parameters for buffer calculation. + uint32 output_size = converter.CalculateNeededOutputBufferSize(NULL, 0); + EXPECT_EQ(output_size, 0U); + + // Do the conversion for actual NAL unit with NULL paramaters. + EXPECT_FALSE(converter.ConvertNalUnitStreamToByteStream(NULL, + 0, + NULL, + &output_size)); + + // Classes allocated in stack are automatically destroyed. +} + +TEST_F(H264BitstreamConverterTest, Conversion_FailureHeaderBufferOverflow) { + // Initialize converter + H264BitstreamConverter converter; + + // Simulate 10 sps AVCDecoderConfigurationRecord, + // which would extend beyond the buffer. + uint8 corrupted_header[sizeof(kHeaderDataOkWithFieldLen4)]; + memcpy(corrupted_header, kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4)); + // 6th byte, 5 LSBs contain the number of sps's. + corrupted_header[5] = corrupted_header[5] | 0xA; + + // Parse the headers + uint32 config_size = converter.ParseConfigurationAndCalculateSize( + corrupted_header, + sizeof(corrupted_header)); + EXPECT_EQ(config_size, 0U); // Failure as a result of buffer overflows. + + // Classes allocated in stack are automatically destroyed. +} + +TEST_F(H264BitstreamConverterTest, Conversion_FailureNalUnitBreakage) { + // Initialize converter. + scoped_array<uint8> output; + H264BitstreamConverter converter; + + // Parse the headers. + uint32 config_size = converter.ParseConfigurationAndCalculateSize( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4)); + EXPECT_GT(config_size, 0U); + + // Go on with converting the headers. + output.reset(new uint8[config_size]); + EXPECT_TRUE(output.get() != NULL); + EXPECT_TRUE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4), + output.get(), + &config_size)); + + // Simulate NAL unit broken in middle by writing only some of the data. + uint8 corrupted_nal_unit[sizeof(kPacketDataOkWithFieldLen4) - 100]; + memcpy(corrupted_nal_unit, kPacketDataOkWithFieldLen4, + sizeof(kPacketDataOkWithFieldLen4) - 100); + + // Calculate buffer size for actual NAL unit, should return 0 because of + // incomplete input buffer. + uint32 output_size = converter.CalculateNeededOutputBufferSize( + corrupted_nal_unit, + sizeof(corrupted_nal_unit)); + EXPECT_EQ(output_size, 0U); + + // Ignore the error and try to go on with conversion simulating wrong usage. + output_size = sizeof(kPacketDataOkWithFieldLen4) + config_size; + output.reset(new uint8[output_size]); + EXPECT_TRUE(output.get() != NULL); + + uint32 output_size_left_for_nal_unit = output_size - config_size; + // Do the conversion for actual NAL unit, expecting failure. + EXPECT_FALSE(converter.ConvertNalUnitStreamToByteStream( + corrupted_nal_unit, + sizeof(corrupted_nal_unit), + output.get() + config_size, + &output_size_left_for_nal_unit)); + EXPECT_EQ(output_size_left_for_nal_unit, 0U); + + // Classes allocated in stack are automatically destroyed. +} + +TEST_F(H264BitstreamConverterTest, Conversion_FailureTooSmallOutputBuffer) { + // Initialize converter. + scoped_array<uint8> output; + H264BitstreamConverter converter; + + // Parse the headers. + uint32 config_size = converter.ParseConfigurationAndCalculateSize( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4)); + EXPECT_GT(config_size, 0U); + uint32 real_config_size = config_size; + + // Go on with converting the headers with too small buffer. + config_size -= 10; + output.reset(new uint8[config_size]); + EXPECT_TRUE(output.get() != NULL); + EXPECT_FALSE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4), + output.get(), + &config_size)); + EXPECT_EQ(config_size, 0U); + + // Still too small (but only 1 byte short). + config_size = real_config_size - 1; + output.reset(new uint8[config_size]); + EXPECT_TRUE(output.get() != NULL); + EXPECT_FALSE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4), + output.get(), + &config_size)); + EXPECT_EQ(config_size, 0U); + + // Finally, retry with valid buffer. + config_size = real_config_size; + output.reset(new uint8[config_size]); + EXPECT_TRUE(output.get() != NULL); + EXPECT_TRUE(converter.ConvertAVCDecoderConfigurationRecordToByteStream( + kHeaderDataOkWithFieldLen4, + sizeof(kHeaderDataOkWithFieldLen4), + output.get(), + &config_size)); + + // Calculate buffer size for actual NAL unit. + uint32 output_size = converter.CalculateNeededOutputBufferSize( + kPacketDataOkWithFieldLen4, + sizeof(kPacketDataOkWithFieldLen4)); + EXPECT_GT(output_size, 0U); + output_size += config_size; + // Simulate too small output buffer. + output_size -= 1; + output.reset(new uint8[output_size]); + EXPECT_TRUE(output.get() != NULL); + + uint32 output_size_left_for_nal_unit = output_size - config_size; + // Do the conversion for actual NAL unit (expect failure). + EXPECT_FALSE(converter.ConvertNalUnitStreamToByteStream( + kPacketDataOkWithFieldLen4, + sizeof(kPacketDataOkWithFieldLen4), + output.get() + config_size, + &output_size_left_for_nal_unit)); + EXPECT_EQ(output_size_left_for_nal_unit, 0U); + + // Classes allocated in stack are automatically destroyed. +} + +} // namespace media + |