Commit 4598b1c8 authored by Josh Coalson's avatar Josh Coalson
Browse files

"finalize" Ogg FLAC mapping version 1.0 by prepending "FLAC" magic and a 2...

"finalize" Ogg FLAC mapping version 1.0 by prepending "FLAC" magic and a 2 byte mapping version number to the first packet
parent df964fe3
......@@ -45,6 +45,7 @@ typedef struct OggFLAC__OggDecoderAspect {
/* these are for internal state related to Ogg decoding */
ogg_stream_state stream_state;
ogg_sync_state sync_state;
unsigned version_major, version_minor;
FLAC__bool need_serial_number;
FLAC__bool end_of_stream;
FLAC__bool have_working_page; /* only if true will the following vars be valid */
......@@ -64,6 +65,8 @@ typedef enum {
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK = 0,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR,
OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR
......
......@@ -32,6 +32,7 @@
#include <string.h> /* for memcpy() */
#include "FLAC/assert.h"
#include "private/ogg_decoder_aspect.h"
#include "private/ogg_mapping.h"
#ifdef max
#undef max
......@@ -53,6 +54,9 @@ FLAC__bool OggFLAC__ogg_decoder_aspect_init(OggFLAC__OggDecoderAspect *aspect)
if(ogg_sync_init(&aspect->sync_state) != 0)
return false;
aspect->version_major = ~(0u);
aspect->version_minor = ~(0u);
aspect->need_serial_number = aspect->use_first_serial_number;
aspect->end_of_stream = false;
......@@ -149,6 +153,20 @@ 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 (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))
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];
if (aspect->version_major != 1)
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION;
aspect->working_packet.packet += header_length;
aspect->working_packet.bytes -= header_length;
}
}
else if (ret == 0) {
aspect->have_working_page = false;
......
......@@ -32,6 +32,10 @@
#include <string.h> /* for memset() */
#include "FLAC/assert.h"
#include "private/ogg_encoder_aspect.h"
#include "private/ogg_mapping.h"
static const FLAC__byte OggFLAC__MAPPING_VERSION_MAJOR = 1;
static const FLAC__byte OggFLAC__MAPPING_VERSION_MINOR = 0;
/***********************************************************************
*
......@@ -72,13 +76,14 @@ void OggFLAC__ogg_encoder_aspect_set_defaults(OggFLAC__OggEncoderAspect *aspect)
* The basic FLAC -> Ogg mapping goes like this:
*
* - 'fLaC' magic and STREAMINFO block get combined into the first
* packet
* - 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,
* packet. The packet is prefixed with 'FLAC' magic and the 2
* byte Ogg FLAC mapping version number.
* - 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,
* the mapping only requires that a flush must occur after all
* metadata is written)
* - each subsequent FLAC audio frame goes into its own packet.
* metadata is written).
* - Each subsequent FLAC audio frame goes into its own packet.
*
* WATCHOUT:
* This depends on the behavior of FLAC__StreamEncoder that we get a
......@@ -104,7 +109,15 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
packet.granulepos = aspect->samples_written + samples;
if(aspect->is_first_packet) {
FLAC__byte newbuffer[FLAC__STREAM_SYNC_LENGTH + FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
FLAC__byte newbuffer[
OggFLAC__MAPPING_MAGIC_LENGTH +
OggFLAC__MAPPING_VERSION_MAJOR_LENGTH +
OggFLAC__MAPPING_VERSION_MINOR_LENGTH +
FLAC__STREAM_SYNC_LENGTH +
FLAC__STREAM_METADATA_HEADER_LENGTH +
FLAC__STREAM_METADATA_STREAMINFO_LENGTH
];
FLAC__byte *b = newbuffer;
if(bytes != FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH) {
/*
* If we get here, our assumption about the way write callbacks happen
......@@ -113,8 +126,21 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
FLAC__ASSERT(0);
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
}
memcpy(newbuffer, FLAC__STREAM_SYNC_STRING, FLAC__STREAM_SYNC_LENGTH);
memcpy(newbuffer + FLAC__STREAM_SYNC_LENGTH, buffer, bytes);
/* add 'FLAC' mapping magic */
memcpy(b, OggFLAC__MAPPING_MAGIC, OggFLAC__MAPPING_MAGIC_LENGTH);
b += OggFLAC__MAPPING_MAGIC_LENGTH;
/* add Ogg FLAC mapping major version number */
memcpy(b, &OggFLAC__MAPPING_VERSION_MAJOR, OggFLAC__MAPPING_VERSION_MAJOR_LENGTH);
b += OggFLAC__MAPPING_VERSION_MAJOR_LENGTH;
/* 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 native FLAC 'fLaC' magic */
memcpy(b, FLAC__STREAM_SYNC_STRING, FLAC__STREAM_SYNC_LENGTH);
b += FLAC__STREAM_SYNC_LENGTH;
/* add STREAMINFO */
memcpy(b, buffer, bytes);
FLAC__ASSERT(b + bytes - newbuffer == sizeof(newbuffer));
packet.packet = (unsigned char *)newbuffer;
packet.bytes = sizeof(newbuffer);
......
......@@ -506,6 +506,8 @@ FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused,
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC:
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION:
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR:
decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment