summaryrefslogtreecommitdiffstats
path: root/media
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
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')
-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
-rw-r--r--media/filters/bitstream_converter.h9
-rw-r--r--media/filters/ffmpeg_demuxer.cc9
-rw-r--r--media/filters/ffmpeg_h264_bitstream_converter.cc101
-rw-r--r--media/filters/ffmpeg_h264_bitstream_converter.h67
-rw-r--r--media/filters/ffmpeg_h264_bitstream_converter_unittest.cc443
-rw-r--r--media/media.gyp10
-rw-r--r--media/tools/player_x11/gles_video_renderer.cc8
-rw-r--r--media/tools/player_x11/gles_video_renderer.h1
11 files changed, 1553 insertions, 5 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
+
diff --git a/media/filters/bitstream_converter.h b/media/filters/bitstream_converter.h
index f19e3f2..a1ca3c6 100644
--- a/media/filters/bitstream_converter.h
+++ b/media/filters/bitstream_converter.h
@@ -27,9 +27,14 @@ class BitstreamConverter {
BitstreamConverter() {}
virtual ~BitstreamConverter() {}
- // Attemps to convert the AVPacket from one format to another, based on the
- // specific type of BitstreamConverter that was instantiated.
+ // Initialize does any preparations needed before doing the actual
+ // conversion.
virtual bool Initialize() = 0;
+
+ // Attemps to convert the AVPacket from one format to another, based on the
+ // specific type of BitstreamConverter that was instantiated. Output will be
+ // stored into the |packet|, but user should be aware that conversion can free
+ // and reallocate the input buffer, if it needs to do so to fit it in.
virtual bool ConvertPacket(AVPacket* packet) = 0;
private:
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 413ff5a..d482c83 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -17,6 +17,7 @@
#include "media/filters/bitstream_converter.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/ffmpeg_glue.h"
+#include "media/filters/ffmpeg_h264_bitstream_converter.h"
namespace media {
@@ -208,7 +209,13 @@ void FFmpegDemuxerStream::EnableBitstreamConverter() {
const char* filter_name = NULL;
if (stream_->codec->codec_id == CODEC_ID_H264) {
filter_name = "h264_mp4toannexb";
- } else if (stream_->codec->codec_id == CODEC_ID_MPEG4) {
+ // Use Chromium bitstream converter in case of H.264
+ bitstream_converter_.reset(
+ new FFmpegH264BitstreamConverter(stream_->codec));
+ CHECK(bitstream_converter_->Initialize());
+ return;
+ }
+ if (stream_->codec->codec_id == CODEC_ID_MPEG4) {
filter_name = "mpeg4video_es";
} else if (stream_->codec->codec_id == CODEC_ID_WMV3) {
filter_name = "vc1_asftorcv";
diff --git a/media/filters/ffmpeg_h264_bitstream_converter.cc b/media/filters/ffmpeg_h264_bitstream_converter.cc
new file mode 100644
index 0000000..6220daf
--- /dev/null
+++ b/media/filters/ffmpeg_h264_bitstream_converter.cc
@@ -0,0 +1,101 @@
+// 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/filters/ffmpeg_h264_bitstream_converter.h"
+
+#include "base/logging.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+
+namespace media {
+
+FFmpegH264BitstreamConverter::FFmpegH264BitstreamConverter(
+ AVCodecContext* stream_context)
+ : configuration_processed_(false),
+ stream_context_(stream_context) {
+ CHECK(stream_context_);
+}
+
+FFmpegH264BitstreamConverter::~FFmpegH264BitstreamConverter() {}
+
+bool FFmpegH264BitstreamConverter::Initialize() {
+ return true;
+}
+
+bool FFmpegH264BitstreamConverter::ConvertPacket(AVPacket* packet) {
+ uint32 output_packet_size = 0;
+ uint32 configuration_size = 0;
+ uint32 io_size = 0;
+ if (packet == NULL) {
+ return false;
+ }
+
+ // Calculate the needed output buffer size.
+ if (!configuration_processed_) {
+ // FFmpeg's AVCodecContext's extradata field contains the Decoder
+ // Specific Information from MP4 headers that contain the H.264 SPS and
+ // PPS members. See ISO/IEC 14496-15 Chapter 5.2.4
+ // AVCDecoderConfigurationRecord for exact specification.
+ // Extradata must be at least 7 bytes long.
+ if (stream_context_->extradata == NULL ||
+ stream_context_->extradata_size <= 7) {
+ return false; // Can't go on with conversion without configuration.
+ }
+ configuration_size += converter_.ParseConfigurationAndCalculateSize(
+ stream_context_->extradata,
+ stream_context_->extradata_size);
+ if (configuration_size == 0) {
+ return false; // Not possible to parse the configuration.
+ }
+ }
+ uint32 output_nal_size =
+ converter_.CalculateNeededOutputBufferSize(packet->data, packet->size);
+ if (output_nal_size == 0) {
+ return false; // Invalid input packet.
+ }
+ output_packet_size = configuration_size + output_nal_size;
+
+ // Allocate new packet for the output.
+ AVPacket dest_packet;
+ if (av_new_packet(&dest_packet, output_packet_size) != 0) {
+ return false; // Memory allocation failure.
+ }
+ // This is a bit tricky: since the interface does not allow us to replace
+ // the pointer of the old packet with a new one, we will initially copy the
+ // metadata from old packet to new bigger packet.
+ dest_packet.pts = packet->pts;
+ dest_packet.dts = packet->dts;
+ dest_packet.pos = packet->pos;
+ dest_packet.duration = packet->duration;
+ dest_packet.convergence_duration = packet->convergence_duration;
+ dest_packet.flags = packet->flags;
+ dest_packet.stream_index = packet->stream_index;
+
+ // Process the configuration if not done earlier.
+ if (!configuration_processed_) {
+ if (!converter_.ConvertAVCDecoderConfigurationRecordToByteStream(
+ stream_context_->extradata, stream_context_->extradata_size,
+ dest_packet.data, &configuration_size)) {
+ return false; // Failed to convert the buffer.
+ }
+ configuration_processed_ = true;
+ }
+
+ // Proceed with the conversion of the actual in-band NAL units, leave room
+ // for configuration in the beginning.
+ io_size = dest_packet.size - configuration_size;
+ if (!converter_.ConvertNalUnitStreamToByteStream(
+ packet->data, packet->size,
+ dest_packet.data + configuration_size, &io_size)) {
+ return false;
+ }
+
+ // At the end we must destroy the old packet.
+ packet->destruct(packet);
+ *packet = dest_packet; // Finally, replace the values in the input packet.
+
+ return true;
+}
+
+} // namespace media
+
diff --git a/media/filters/ffmpeg_h264_bitstream_converter.h b/media/filters/ffmpeg_h264_bitstream_converter.h
new file mode 100644
index 0000000..69d8e4c
--- /dev/null
+++ b/media/filters/ffmpeg_h264_bitstream_converter.h
@@ -0,0 +1,67 @@
+// 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_FILTERS_FFMPEG_H264_BITSTREAM_CONVERTER_H_
+#define MEDIA_FILTERS_FFMPEG_H264_BITSTREAM_CONVERTER_H_
+
+#include "base/basictypes.h"
+#include "media/base/h264_bitstream_converter.h"
+#include "media/filters/bitstream_converter.h"
+
+// Forward declarations for FFmpeg datatypes used.
+struct AVCodecContext;
+struct AVPacket;
+
+namespace media {
+
+// FFmpegH264BitstreamConverter does the conversion on single NAL unit
+// basis which is contained within the AVPacket given to ConvertPacket() member
+// function with the exception of the first packet which is prepended with the
+// AVC decoder configuration record information. For example:
+//
+// NAL unit #1 ==> bytestream buffer #1 (AVC configuraion + NAL unit #1)
+// NAL unit #2 ==> bytestream buffer #2 (NAL unit #2)
+// ...
+// NAL unit #n ==> bytestream buffer #n (NAL unit #n)
+//
+// User of the object can append output into one bigger buffer by the client if
+// efficiency reasons warrants the client to do so.
+//
+// FFmpegH264BitstreamConverter acts as an adapter for the H264 Bitstream
+// converter class by implementing the BitstreamConverter interface expected
+// by media pipeline streams demuxed by FFmpegDemuxer.
+//
+// FFmpegH264BitstreamConverter uses FFmpeg allocation methods for buffer
+// allocation to ensure compatibility with FFmpeg's memory management.
+
+class FFmpegH264BitstreamConverter : public BitstreamConverter {
+ public:
+ // The |stream_context| will be used during conversion and should be the
+ // AVCodecContext for the stream sourcing these packets. A reference to
+ // |stream_context| is retained, so it must outlive this class.
+ explicit FFmpegH264BitstreamConverter(AVCodecContext* stream_context);
+ virtual ~FFmpegH264BitstreamConverter();
+
+ // BitstreamConverter implementation
+ virtual bool Initialize();
+ virtual bool ConvertPacket(AVPacket* packet);
+
+ private:
+ // Actual converter class.
+ H264BitstreamConverter converter_;
+
+ // Flag for indicating whether global parameter sets have been processed.
+ bool configuration_processed_;
+
+ // Variable to hold a pointer to memory where we can access the global
+ // data from the FFmpeg file format's global headers.
+ AVCodecContext* stream_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(FFmpegH264BitstreamConverter);
+};
+
+} // namespace media
+
+#endif // MEDIA_FILTERS_FFMPEG_H264_BITSTREAM_CONVERTER_H_
+
diff --git a/media/filters/ffmpeg_h264_bitstream_converter_unittest.cc b/media/filters/ffmpeg_h264_bitstream_converter_unittest.cc
new file mode 100644
index 0000000..bf582f6
--- /dev/null
+++ b/media/filters/ffmpeg_h264_bitstream_converter_unittest.cc
@@ -0,0 +1,443 @@
+// 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/mock_ffmpeg.h"
+#include "media/filters/ffmpeg_h264_bitstream_converter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+namespace media {
+
+// Forward declarations for fake FFmpeg packet handling functions.
+static void fake_av_destruct_packet(AVPacket* pkt);
+static void fake_av_init_packet(AVPacket* pkt);
+static int fake_av_new_packet(AVPacket* pkt, int size);
+
+// Test data arrays.
+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
+};
+
+// Class for testing the FFmpegH264BitstreamConverter.
+class FFmpegH264BitstreamConverterTest : public testing::Test {
+ protected:
+ FFmpegH264BitstreamConverterTest() {
+ // Set up the ffmpeg mock and use our local fake functions to do the
+ // actual implementation for packet allocation / freeing.
+ MockFFmpeg::set(&ffmpeg_mock_);
+ ON_CALL(ffmpeg_mock_, AVInitPacket(_))
+ .WillByDefault(Invoke(fake_av_init_packet));
+ ON_CALL(ffmpeg_mock_, AVNewPacket(_, _))
+ .WillByDefault(Invoke(fake_av_new_packet));
+ ON_CALL(ffmpeg_mock_, AVDestructPacket(_))
+ .WillByDefault(Invoke(fake_av_destruct_packet));
+ // Set up AVCConfigurationRecord correctly for tests.
+ // It's ok to do const cast here as data in kHeaderDataOkWithFieldLen4 is
+ // never written to.
+ memset(&test_context_, 0, sizeof(AVCodecContext));
+ test_context_.extradata = const_cast<uint8*>(kHeaderDataOkWithFieldLen4);
+ test_context_.extradata_size = sizeof(kHeaderDataOkWithFieldLen4);
+ }
+
+ virtual ~FFmpegH264BitstreamConverterTest() {}
+
+ void CreatePacket(AVPacket* packet, const uint8* data, uint32 data_size) {
+ // Create new packet sized of |data_size| from |data|.
+ EXPECT_CALL(ffmpeg_mock_, AVNewPacket(_, _));
+ EXPECT_CALL(ffmpeg_mock_, AVInitPacket(_));
+ EXPECT_EQ(av_new_packet(packet, data_size), 0);
+ memcpy(packet->data, data, data_size);
+ }
+
+ // FFmpeg mock implementation. We want strict mock since we will strictly
+ // define the order of calls and do not want any extra calls.
+ StrictMock<MockFFmpeg> ffmpeg_mock_;
+
+ // Variable to hold valid dummy context for testing.
+ AVCodecContext test_context_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FFmpegH264BitstreamConverterTest);
+};
+
+TEST_F(FFmpegH264BitstreamConverterTest, Conversion_Success) {
+ FFmpegH264BitstreamConverter converter(&test_context_);
+
+ // Initialization should be always successful.
+ EXPECT_TRUE(converter.Initialize());
+
+ AVPacket test_packet;
+ CreatePacket(&test_packet, kPacketDataOkWithFieldLen4,
+ sizeof(kPacketDataOkWithFieldLen4));
+
+ // Try out the actual conversion (should be successful and allocate new
+ // packet and destroy the old one).
+ EXPECT_CALL(ffmpeg_mock_, AVNewPacket(_, _));
+ EXPECT_CALL(ffmpeg_mock_, AVInitPacket(_));
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ EXPECT_TRUE(converter.ConvertPacket(&test_packet));
+
+ // Clean-up the test packet.
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ av_destruct_packet(&test_packet);
+
+ // Converter will be automatically cleaned up.
+}
+
+TEST_F(FFmpegH264BitstreamConverterTest, Conversion_SuccessBigPacket) {
+ FFmpegH264BitstreamConverter converter(&test_context_);
+
+ // Initialization should be always successful.
+ EXPECT_TRUE(converter.Initialize());
+
+ // Create new packet with 1000 excess bytes.
+ AVPacket test_packet;
+ static uint8 excess_data[sizeof(kPacketDataOkWithFieldLen4) + 1000] = {0};
+ memcpy(excess_data, kPacketDataOkWithFieldLen4,
+ sizeof(kPacketDataOkWithFieldLen4));
+ CreatePacket(&test_packet, excess_data, sizeof(excess_data));
+
+ // Try out the actual conversion (should be successful and allocate new
+ // packet and destroy the old one as we do NOT support in place transform).
+ EXPECT_CALL(ffmpeg_mock_, AVNewPacket(_, _));
+ EXPECT_CALL(ffmpeg_mock_, AVInitPacket(_));
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ EXPECT_TRUE(converter.ConvertPacket(&test_packet));
+
+ // Clean-up the test packet.
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ av_destruct_packet(&test_packet);
+
+ // Converter will be automatically cleaned up.
+}
+
+TEST_F(FFmpegH264BitstreamConverterTest, Conversion_FailureOutOfMem) {
+ FFmpegH264BitstreamConverter converter(&test_context_);
+
+ // Initialization should be always successful.
+ EXPECT_TRUE(converter.Initialize());
+
+ // Create new packet.
+ AVPacket test_packet;
+ CreatePacket(&test_packet, kPacketDataOkWithFieldLen4,
+ sizeof(kPacketDataOkWithFieldLen4));
+
+ // Try out the actual conversion (should be successful and allocate new
+ // packet and destroy the old one).
+ EXPECT_CALL(ffmpeg_mock_, AVNewPacket(_, _))
+ .WillOnce(Return(-1));
+ EXPECT_FALSE(converter.ConvertPacket(&test_packet))
+ << "ConvertPacket() did not return expected failure due to out of mem";
+
+ // Clean-up the test packet.
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ av_destruct_packet(&test_packet);
+
+ // Converter will be automatically cleaned up.
+}
+
+TEST_F(FFmpegH264BitstreamConverterTest, Conversion_FailureNullParams) {
+ // Set up AVCConfigurationRecord to represent NULL data.
+ AVCodecContext dummy_context;
+ dummy_context.extradata = NULL;
+ dummy_context.extradata_size = 0;
+ FFmpegH264BitstreamConverter converter(&dummy_context);
+
+ // Initialization should be always successful.
+ EXPECT_TRUE(converter.Initialize());
+
+ // Try out the actual conversion with NULL parameter.
+ EXPECT_FALSE(converter.ConvertPacket(NULL));
+
+ // Create new packet to test actual conversion.
+ AVPacket test_packet;
+ CreatePacket(&test_packet, kPacketDataOkWithFieldLen4,
+ sizeof(kPacketDataOkWithFieldLen4));
+
+ // Try out the actual conversion (should be successful and allocate new
+ // packet and destroy the old one). This should fail due to missing extradata.
+ EXPECT_FALSE(converter.ConvertPacket(&test_packet));
+
+ // Clean-up the test packet.
+ EXPECT_CALL(ffmpeg_mock_, AVDestructPacket(_));
+ av_destruct_packet(&test_packet);
+
+ // Converted will be automatically cleaned up.
+}
+
+static void fake_av_destruct_packet(AVPacket* pkt) {
+ free(pkt->data);
+ pkt->data = NULL;
+ pkt->size = 0;
+}
+
+static void fake_av_init_packet(AVPacket* pkt) {
+ pkt->pts = AV_NOPTS_VALUE;
+ pkt->dts = AV_NOPTS_VALUE;
+ pkt->pos = -1;
+ pkt->duration = 0;
+ pkt->convergence_duration = 0;
+ pkt->flags = 0;
+ pkt->stream_index = 0;
+ pkt->destruct= NULL;
+}
+
+static int fake_av_new_packet(AVPacket* pkt, int size) {
+ uint8* data = reinterpret_cast<uint8*>(malloc(size));
+ av_init_packet(pkt);
+ pkt->data = data;
+ pkt->size = size;
+ pkt->destruct = av_destruct_packet;
+ if (data == NULL)
+ return AVERROR(ENOMEM);
+ return 0;
+}
+
+} // namespace media
+
diff --git a/media/media.gyp b/media/media.gyp
index 7533cd1..f33d191 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -89,6 +89,8 @@
'base/filter_host.h',
'base/filters.cc',
'base/filters.h',
+ 'base/h264_bitstream_converter.cc',
+ 'base/h264_bitstream_converter.h',
'base/media.h',
'base/media_format.cc',
'base/media_format.h',
@@ -144,6 +146,8 @@
'filters/ffmpeg_audio_decoder.h',
'filters/ffmpeg_demuxer.cc',
'filters/ffmpeg_demuxer.h',
+ 'filters/ffmpeg_h264_bitstream_converter.cc',
+ 'filters/ffmpeg_h264_bitstream_converter.h',
'filters/ffmpeg_glue.cc',
'filters/ffmpeg_glue.h',
'filters/ffmpeg_interfaces.cc',
@@ -289,6 +293,7 @@
'base/data_buffer_unittest.cc',
'base/djb2_unittest.cc',
'base/filter_collection_unittest.cc',
+ 'base/h264_bitstream_converter_unittest.cc',
'base/mock_ffmpeg.cc',
'base/mock_ffmpeg.h',
'base/mock_reader.h',
@@ -307,6 +312,7 @@
'filters/decoder_base_unittest.cc',
'filters/ffmpeg_demuxer_unittest.cc',
'filters/ffmpeg_glue_unittest.cc',
+ 'filters/ffmpeg_h264_bitstream_converter_unittest.cc',
'filters/ffmpeg_video_decoder_unittest.cc',
'filters/file_data_source_unittest.cc',
'filters/video_renderer_base_unittest.cc',
@@ -457,7 +463,7 @@
],
'sources': [
'tools/mfplayer/mfplayer.h',
- 'tools/mfplayer/mfplayer.cc',
+ 'tools/mfplayer/mfplayer.cc',
'tools/mfplayer/mf_playback_main.cc',
],
'msvs_settings': {
@@ -478,7 +484,7 @@
],
'sources': [
'tools/mfdecoder/main.cc',
- 'tools/mfdecoder/mfdecoder.h',
+ 'tools/mfdecoder/mfdecoder.h',
'tools/mfdecoder/mfdecoder.cc',
],
'msvs_settings': {
diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc
index 104de5f..3ccc065 100644
--- a/media/tools/player_x11/gles_video_renderer.cc
+++ b/media/tools/player_x11/gles_video_renderer.cc
@@ -18,6 +18,12 @@
GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL;
+// TODO(vmr): Refactor this parameter to work either through environment
+// variable or dynamically sniff whether EGL support is available.
+static inline int uses_egl_image() {
+ return 1;
+}
+
GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window,
MessageLoop* message_loop)
: egl_create_image_khr_(NULL),
@@ -129,6 +135,8 @@ static const char kFragmentShader[] =
// Color shader for EGLImage.
static const char kFragmentShaderEgl[] =
+ "precision mediump float;\n"
+ "precision mediump int;\n"
"varying vec2 interp_tc;\n"
"\n"
"uniform sampler2D tex;\n"
diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h
index 3fcb89a..25c7dbb 100644
--- a/media/tools/player_x11/gles_video_renderer.h
+++ b/media/tools/player_x11/gles_video_renderer.h
@@ -13,6 +13,7 @@
#include <utility>
#include <vector>
+#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "media/base/filters.h"
#include "media/base/video_frame.h"