Commit 69cfda7a authored by Josh Coalson's avatar Josh Coalson
Browse files

add new requirements to ogg mapping: vorbis comment block must come second...

add new requirements to ogg mapping: vorbis comment block must come second after streaminfo; first packet must have a packet type byte of 0x7f; packet 0 version must be followed by a 2-byte count of the # of header packets
parent 10c6f0fe
......@@ -98,7 +98,7 @@
In the interest of simplicity and expediency, the second method was chosen for the first official FLAC->Ogg mapping. A mapping version is included in the first packet so that a less redundant mapping can be defined in the future.
</P>
<P>
It should also be noted that support for encapsulating FLAC in Ogg has been present in the FLAC tools since version 1.0.1. However, the mappings used were never formalized and have insurmountable problems. For that reason, Ogg FLAC streams created with <TT>flac</TT> versions before 1.1.1 should be decoded by the corresponding version of <TT>flac</TT>, and re-encoded with <TT>flac</TT> 1.1.1 or later. Since the support for Ogg FLAC before FLAC 1.1.1 was limited, we hope there will not result in too much inconvenience.
It should also be noted that support for encapsulating FLAC in Ogg has been present in the FLAC tools since version 1.0.1. However, the mappings used were never formalized and have insurmountable problems. For that reason, Ogg FLAC streams created with <B><TT>flac</TT></B> versions before 1.1.1 should be decoded by the corresponding version of <B><TT>flac</TT></B>, and re-encoded with <B><TT>flac</TT></B> 1.1.1 or later. Since the support for Ogg FLAC before FLAC 1.1.1 was limited, we hope this will not result in too much inconvenience.
</P>
<P>
Version 1.0 of the FLAC-to-Ogg mapping then is a simple identifying header followed by pure native FLAC data, as follows:
......@@ -106,6 +106,7 @@
<LI>
The first packet of a stream consists of:
<UL>
<LI>The one-byte packet type 0x7F</LI>
<LI>The four-byte ASCII signature "FLAC", i.e. 0x46, 0x4C, 0x41, 0x43</LI>
<LI>A one-byte binary major version number for the mapping, e.g. 0x01 for mapping version 1.0</LI>
<LI>A one-byte binary minor version number for the mapping, e.g. 0x00 for mapping version 1.0</LI>
......@@ -113,13 +114,13 @@
<LI>The four-byte ASCII native FLAC signature "fLaC" according to the <A HREF="format.html#stream">FLAC format specification</A></LI>
<LI>The <A HREF="format.html#metadata_block">STREAMINFO</A> metadata block for the stream.</LI>
</UL>
This first packet is the only packet in the first page of the stream. This results in a first Ogg page of exactly 78 bytes at the very beginning of the logical stream.
This first packet is the only packet in the first page of the stream. This results in a first Ogg page of exactly 79 bytes at the very beginning of the logical stream.
</LI>
<LI>
This first page is marked 'beginning of stream' in the page flags.
</LI>
<LI>
The first packet is followed by one or more header packets. Each such packet will contain a single <A HREF="format.html#metadata_block">native FLAC metadata block</A>. The first of these must be a VORBIS_COMMENT block. These packets may span page boundaries but the last will finish the page on which it ends, so that the first audio packet begins a page.
The first packet is followed by one or more header packets. Each such packet will contain a single <A HREF="format.html#metadata_block">native FLAC metadata block</A>. The first of these must be a VORBIS_COMMENT block. These packets may span page boundaries but the last will finish the page on which it ends, so that the first audio packet begins a page. The first byte of these metadata packets serves also as the packet type, and has a legal range of (0x01-0x7E,0x81-0xFE).
</LI>
<LI>
The granule position of these first pages containing only headers is zero.
......@@ -128,7 +129,7 @@
The first audio packet of the logical stream begins a fresh Ogg page.
</LI>
<LI>
Native FLAC audio frames appear as subsequent packets in the stream. Each packet corresponds to one FLAC audio frame.
Native FLAC audio frames appear as subsequent packets in the stream. Each packet corresponds to one FLAC audio frame. The first byte of each packet serves as the packet type. Since audio packets are native FLAC frames, this first byte will be always 0xFF according to the <A HREF="format.html#frame_header">native FLAC format specification</A>.
</LI>
<LI>
The last page is marked 'end of stream' in the page flags.
......
......@@ -422,6 +422,19 @@ OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC_
/** This is inherited from OggFLAC__SeekableStreamEncoder; see
* OggFLAC__seekable_stream_encoder_set_metadata().
*
* \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be
* the second metadata block of the stream. The encoder already supplies
* the STREAMINFO block automatically. If \a metadata does not contain a
* VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if
* \a metadata does contain a VORBIS_COMMENT block and it is not the
* first, this function will reorder \a metadata by moving the
* VORBIS_COMMENT block to the front; the relative ordering of the other
* blocks will remain as they were.
*
* \note The Ogg FLAC mapping limits the number of metadata blocks per
* stream to \c 65535. If \a num_blocks exceeds this the function will
* return \c false.
*
* \default \c NULL, 0
* \param encoder An encoder instance to set.
* \param metadata See above.
......@@ -429,7 +442,8 @@ OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC_
* \assert
* \code encoder != NULL \endcode
* \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true.
* \c false if the encoder is already initialized, or if
* \a num_blocks > 65535, else \c true.
*/
OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
......
......@@ -485,6 +485,19 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_searc
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value);
/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_metadata()
*
* \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be
* the second metadata block of the stream. The encoder already supplies
* the STREAMINFO block automatically. If \a metadata does not contain a
* VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if
* \a metadata does contain a VORBIS_COMMENT block and it is not the
* first, this function will reorder \a metadata by moving the
* VORBIS_COMMENT block to the front; the relative ordering of the other
* blocks will remain as they were.
*
* \note The Ogg FLAC mapping limits the number of metadata blocks per
* stream to \c 65535. If \a num_blocks exceeds this the function will
* return \c false.
*
* \default \c NULL, 0
* \param encoder An encoder instance to set.
......@@ -493,7 +506,8 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estima
* \assert
* \code encoder != NULL \endcode
* \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true.
* \c false if the encoder is already initialized, or if
* \a num_blocks > 65535, else \c true.
*/
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
......
......@@ -421,6 +421,19 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(Og
OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLAC__StreamEncoder *encoder, FLAC__uint64 value);
/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_metadata()
*
* \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be
* the second metadata block of the stream. The encoder already supplies
* the STREAMINFO block automatically. If \a metadata does not contain a
* VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if
* \a metadata does contain a VORBIS_COMMENT block and it is not the
* first, this function will reorder \a metadata by moving the
* VORBIS_COMMENT block to the front; the relative ordering of the other
* blocks will remain as they were.
*
* \note The Ogg FLAC mapping limits the number of metadata blocks per
* stream to \c 65535. If \a num_blocks exceeds this the function will
* return \c false.
*
* \default \c NULL, 0
* \param encoder An encoder instance to set.
......@@ -429,7 +442,8 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLA
* \assert
* \code encoder != NULL \endcode
* \retval FLAC__bool
* \c false if the encoder is already initialized, else \c true.
* \c false if the encoder is already initialized, or if
* \a num_blocks > 65535, else \c true.
*/
OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
......
......@@ -880,6 +880,11 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
* Check to see if the supplied metadata contains a VORBIS_COMMENT;
* if not, we will write an empty one (FLAC__add_metadata_block()
* automatically supplies the vendor string).
*
* WATCHOUT: libOggFLAC depends on us to write this block after the
* STREAMINFO since that's what the mapping requires. (In the case
* that metadata_has_vorbis_comment it true it will have already
* insured that the metadata list is properly ordered.)
*/
if(!metadata_has_vorbis_comment) {
FLAC__StreamMetadata vorbis_comment;
......
......@@ -40,6 +40,7 @@
typedef struct OggFLAC__OggEncoderAspect {
/* these are storage for values that can be set through the API */
long serial_number;
unsigned num_metadata;
/* these are for internal state related to Ogg encoding */
ogg_stream_state stream_state;
......@@ -50,6 +51,7 @@ typedef struct OggFLAC__OggEncoderAspect {
} OggFLAC__OggEncoderAspect;
void OggFLAC__ogg_encoder_aspect_set_serial_number(OggFLAC__OggEncoderAspect *aspect, long value);
FLAC__bool OggFLAC__ogg_encoder_aspect_set_num_metadata(OggFLAC__OggEncoderAspect *aspect, unsigned value);
void OggFLAC__ogg_encoder_aspect_set_defaults(OggFLAC__OggEncoderAspect *aspect);
FLAC__bool OggFLAC__ogg_encoder_aspect_init(OggFLAC__OggEncoderAspect *aspect);
void OggFLAC__ogg_encoder_aspect_finish(OggFLAC__OggEncoderAspect *aspect);
......
......@@ -34,6 +34,13 @@
#include "FLAC/ordinals.h"
/** The length of the 'FLAC' magic in bytes. */
#define OggFLAC__MAPPING_PACKET_TYPE_LENGTH (1u)
extern const unsigned OggFLAC__MAPPING_PACKET_TYPE_LEN; /* = 8 bits */
extern const FLAC__byte OggFLAC__MAPPING_FIRST_HEADER_PACKET_TYPE; /* = 0x7f */
/** The length of the 'FLAC' magic in bytes. */
#define OggFLAC__MAPPING_MAGIC_LENGTH (4u)
......@@ -48,4 +55,9 @@ extern const unsigned OggFLAC__MAPPING_VERSION_MINOR_LEN; /* = 8 bits */
/** The length of the Ogg FLAC mapping minor version number in bytes. */
#define OggFLAC__MAPPING_VERSION_MINOR_LENGTH (1u)
extern const unsigned OggFLAC__MAPPING_NUM_HEADERS_LEN; /* = 16 bits */
/** The length of the #-of-header-packets number bytes. */
#define OggFLAC__MAPPING_NUM_HEADERS_LENGTH (2u)
#endif
......@@ -83,11 +83,6 @@ void OggFLAC__ogg_decoder_aspect_set_defaults(OggFLAC__OggDecoderAspect *aspect)
}
void OggFLAC__ogg_decoder_aspect_flush(OggFLAC__OggDecoderAspect *aspect)
{
OggFLAC__ogg_decoder_aspect_reset(aspect);
}
void OggFLAC__ogg_decoder_aspect_reset(OggFLAC__OggDecoderAspect *aspect)
{
(void)ogg_stream_reset(&aspect->stream_state);
(void)ogg_sync_reset(&aspect->sync_state);
......@@ -95,6 +90,14 @@ void OggFLAC__ogg_decoder_aspect_reset(OggFLAC__OggDecoderAspect *aspect)
aspect->have_working_page = false;
}
void OggFLAC__ogg_decoder_aspect_reset(OggFLAC__OggDecoderAspect *aspect)
{
OggFLAC__ogg_decoder_aspect_flush(aspect);
if(aspect->use_first_serial_number)
aspect->need_serial_number = true;
}
OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, void *decoder, void *client_data)
{
static const unsigned OGG_BYTES_CHUNK = 8192;
......@@ -153,15 +156,24 @@ OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wr
const int ret = ogg_stream_packetout(&aspect->stream_state, &aspect->working_packet);
if (ret > 0) {
aspect->have_working_packet = true;
/* if it is packet 0, check for magic and a supported Ogg FLAC mapping version */
if (aspect->working_packet.packetno == 0) {
const unsigned header_length = OggFLAC__MAPPING_MAGIC_LENGTH + OggFLAC__MAPPING_VERSION_MAJOR_LENGTH + OggFLAC__MAPPING_VERSION_MINOR_LENGTH;
/* if it is the first header packet, check for magic and a supported Ogg FLAC mapping version */
if (aspect->working_packet.bytes > 0 && aspect->working_packet.packet[0] == OggFLAC__MAPPING_FIRST_HEADER_PACKET_TYPE) {
const FLAC__byte *b = aspect->working_packet.packet;
const unsigned header_length =
OggFLAC__MAPPING_PACKET_TYPE_LENGTH +
OggFLAC__MAPPING_MAGIC_LENGTH +
OggFLAC__MAPPING_VERSION_MAJOR_LENGTH +
OggFLAC__MAPPING_VERSION_MINOR_LENGTH +
OggFLAC__MAPPING_NUM_HEADERS_LENGTH;
if (aspect->working_packet.bytes < (long)header_length)
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
if (memcmp(aspect->working_packet.packet, OggFLAC__MAPPING_MAGIC, OggFLAC__MAPPING_MAGIC_LENGTH))
b += OggFLAC__MAPPING_PACKET_TYPE_LENGTH;
if (memcmp(b, OggFLAC__MAPPING_MAGIC, OggFLAC__MAPPING_MAGIC_LENGTH))
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
aspect->version_major = (unsigned)aspect->working_packet.packet[OggFLAC__MAPPING_MAGIC_LENGTH];
aspect->version_minor = (unsigned)aspect->working_packet.packet[OggFLAC__MAPPING_MAGIC_LENGTH+OggFLAC__MAPPING_VERSION_MAJOR_LENGTH];
b += OggFLAC__MAPPING_MAGIC_LENGTH;
aspect->version_major = (unsigned)(*b);
b += OggFLAC__MAPPING_VERSION_MAJOR_LENGTH;
aspect->version_minor = (unsigned)(*b);
if (aspect->version_major != 1)
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION;
aspect->working_packet.packet += header_length;
......
......@@ -67,17 +67,31 @@ void OggFLAC__ogg_encoder_aspect_set_serial_number(OggFLAC__OggEncoderAspect *as
aspect->serial_number = value;
}
FLAC__bool OggFLAC__ogg_encoder_aspect_set_num_metadata(OggFLAC__OggEncoderAspect *aspect, unsigned value)
{
if(value < (1u << OggFLAC__MAPPING_NUM_HEADERS_LEN)) {
aspect->num_metadata = value;
return true;
}
else
return false;
}
void OggFLAC__ogg_encoder_aspect_set_defaults(OggFLAC__OggEncoderAspect *aspect)
{
aspect->serial_number = 0;
aspect->num_metadata = 0;
}
/*
* The basic FLAC -> Ogg mapping goes like this:
*
* - 'fLaC' magic and STREAMINFO block get combined into the first
* packet. The packet is prefixed with 'FLAC' magic and the 2
* byte Ogg FLAC mapping version number.
* packet. The packet is prefixed with
* + the one-byte packet type 0x7F
* + 'FLAC' magic
* + the 2 byte Ogg FLAC mapping version number
* + tne 2 byte big-endian # of header packets
* - The first packet is flushed to the first page.
* - Each subsequent metadata block goes into its own packet.
* - Each metadata packet is flushed to page (this is not required,
......@@ -110,9 +124,11 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
if(aspect->is_first_packet) {
FLAC__byte newbuffer[
OggFLAC__MAPPING_PACKET_TYPE_LENGTH +
OggFLAC__MAPPING_MAGIC_LENGTH +
OggFLAC__MAPPING_VERSION_MAJOR_LENGTH +
OggFLAC__MAPPING_VERSION_MINOR_LENGTH +
OggFLAC__MAPPING_NUM_HEADERS_LENGTH +
FLAC__STREAM_SYNC_LENGTH +
FLAC__STREAM_METADATA_HEADER_LENGTH +
FLAC__STREAM_METADATA_STREAMINFO_LENGTH
......@@ -126,6 +142,9 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
FLAC__ASSERT(0);
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
}
/* add first header packet type */
*b = OggFLAC__MAPPING_FIRST_HEADER_PACKET_TYPE;
b += OggFLAC__MAPPING_PACKET_TYPE_LENGTH;
/* add 'FLAC' mapping magic */
memcpy(b, OggFLAC__MAPPING_MAGIC, OggFLAC__MAPPING_MAGIC_LENGTH);
b += OggFLAC__MAPPING_MAGIC_LENGTH;
......@@ -135,6 +154,11 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
/* add Ogg FLAC mapping minor version number */
memcpy(b, &OggFLAC__MAPPING_VERSION_MINOR, OggFLAC__MAPPING_VERSION_MINOR_LENGTH);
b += OggFLAC__MAPPING_VERSION_MINOR_LENGTH;
/* add number of header packets */
*b = (FLAC__byte)(aspect->num_metadata >> 8);
b++;
*b = (FLAC__byte)(aspect->num_metadata);
b++;
/* add native FLAC 'fLaC' magic */
memcpy(b, FLAC__STREAM_SYNC_STRING, FLAC__STREAM_SYNC_LENGTH);
b += FLAC__STREAM_SYNC_LENGTH;
......@@ -158,7 +182,7 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
if(ogg_stream_packetin(&aspect->stream_state, &packet) != 0)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
/*@@@@@@ can't figure out a way to pass a useful number for 'samples' to the write_callback, so we'll just pass 0 */
/*@@@ can't figure out a way to pass a useful number for 'samples' to the write_callback, so we'll just pass 0 */
if(is_metadata) {
while(ogg_stream_flush(&aspect->stream_state, &aspect->page) != 0) {
if(write_callback(encoder, aspect->page.header, aspect->page.header_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
......
......@@ -31,7 +31,13 @@
#include "private/ogg_mapping.h"
const unsigned OggFLAC__MAPPING_PACKET_TYPE_LEN = 8; /* bits */
const FLAC__byte OggFLAC__MAPPING_FIRST_HEADER_PACKET_TYPE = 0x7f;
const FLAC__byte * const OggFLAC__MAPPING_MAGIC = "FLAC";
const unsigned OggFLAC__MAPPING_VERSION_MAJOR_LEN = 8; /* bits */
const unsigned OggFLAC__MAPPING_VERSION_MINOR_LEN = 8; /* bits */
const unsigned OggFLAC__MAPPING_NUM_HEADERS_LEN = 16; /* bits */
......@@ -442,15 +442,31 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__Se
FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
return false;
/* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
if(0 != metadata && num_blocks > 1) {
unsigned i;
for(i = 1; i < num_blocks; i++) {
if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
FLAC__StreamMetadata *vc = metadata[i];
for( ; i > 0; i--)
metadata[i] = metadata[i-1];
metadata[0] = vc;
break;
}
}
}
if(0 != metadata && num_blocks > 0) {
unsigned i;
for(i = 0; i < num_blocks; i++) {
/* keep track of any SEEKTABLE block */
if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
encoder->private_->seek_table = &metadata[i]->data.seek_table;
break; /* take only the first one */
}
}
}
if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks))
return false;
return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
}
......
......@@ -397,6 +397,21 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncod
FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
return false;
/* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
if(0 != metadata && num_blocks > 1) {
unsigned i;
for(i = 1; i < num_blocks; i++) {
if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
FLAC__StreamMetadata *vc = metadata[i];
for( ; i > 0; i--)
metadata[i] = metadata[i-1];
metadata[0] = vc;
break;
}
}
}
if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks))
return false;
return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
}
......
......@@ -69,6 +69,7 @@ static bool generate_file_()
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
/* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
if(!file_utils__generate_oggflacfile(oggflacfilename_, &oggflacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
return die_("creating the encoded file");
......@@ -454,11 +455,11 @@ static bool test_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -531,9 +532,9 @@ static bool test_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -560,10 +561,10 @@ static bool test_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -597,9 +598,9 @@ static bool test_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -738,10 +739,10 @@ static bool test_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -782,11 +783,11 @@ static bool test_stream_decoder()
/* done, now leave the sequence the way we found it... */
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1189,11 +1190,11 @@ static bool test_seekable_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1266,9 +1267,9 @@ static bool test_seekable_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1295,10 +1296,10 @@ static bool test_seekable_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1332,9 +1333,9 @@ static bool test_seekable_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1473,10 +1474,10 @@ static bool test_seekable_stream_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1517,11 +1518,11 @@ static bool test_seekable_stream_decoder()
/* done, now leave the sequence the way we found it... */
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1834,11 +1835,11 @@ static bool test_file_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1911,9 +1912,9 @@ static bool test_file_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1940,10 +1941,10 @@ static bool test_file_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -1977,9 +1978,9 @@ static bool test_file_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -2118,10 +2119,10 @@ static bool test_file_decoder()
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......@@ -2162,11 +2163,11 @@ static bool test_file_decoder()
/* done, now leave the sequence the way we found it... */
num_expected_ = 0;
expected_metadata_sequence_[num_expected_++] = &streaminfo_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
......