summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 20:34:14 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 20:34:14 +0000
commit58023bea8fa444c4ac08c12c825dcc79b5954abe (patch)
treed4d4ce8dc812b8118aaa3e49d6465265cf19aad8 /media/base
parentb781e774ae4f5d579c8e9122ea9baafb1f54261a (diff)
downloadchromium_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.cc314
-rw-r--r--media/base/h264_bitstream_converter.h124
-rw-r--r--media/base/h264_bitstream_converter_unittest.cc472
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
+