mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
merge libOggFLAC into libFLAC and libOggFLAC++ into FLAC++; documentation still needs work
This commit is contained in:
@@ -80,6 +80,13 @@ EXTRA_DIST = \
|
||||
libFLAC_static.dsp \
|
||||
libFLAC.m4
|
||||
|
||||
if FLaC__HAS_OGG
|
||||
extra_ogg_sources = \
|
||||
ogg_decoder_aspect.c \
|
||||
ogg_encoder_aspect.c \
|
||||
ogg_helper.c \
|
||||
ogg_mapping.c
|
||||
endif
|
||||
# see 'http://www.gnu.org/software/libtool/manual.html#Libtool-versioning' for numbering convention
|
||||
libFLAC_la_LDFLAGS = -version-info 8:0:0 -lm $(LOCAL_EXTRA_LDFLAGS)
|
||||
libFLAC_la_SOURCES = \
|
||||
@@ -98,4 +105,5 @@ libFLAC_la_SOURCES = \
|
||||
stream_decoder.c \
|
||||
stream_encoder.c \
|
||||
stream_encoder_framing.c \
|
||||
window.c
|
||||
window.c \
|
||||
$(extra_ogg_sources)
|
||||
|
||||
@@ -73,6 +73,10 @@ SRCS_C = \
|
||||
memory.c \
|
||||
metadata_iterators.c \
|
||||
metadata_object.c \
|
||||
ogg_decoder_aspect.c \
|
||||
ogg_encoder_aspect.c \
|
||||
ogg_helper.c \
|
||||
ogg_mapping.c \
|
||||
stream_decoder.c \
|
||||
stream_encoder.c \
|
||||
stream_encoder_framing.c \
|
||||
|
||||
@@ -41,5 +41,9 @@ noinst_HEADERS = \
|
||||
md5.h \
|
||||
memory.h \
|
||||
metadata.h \
|
||||
ogg_decoder_aspect.h \
|
||||
ogg_encoder_aspect.h \
|
||||
ogg_helper.h \
|
||||
ogg_mapping.h \
|
||||
stream_encoder_framing.h \
|
||||
window.h
|
||||
|
||||
79
src/libFLAC/include/private/ogg_decoder_aspect.h
Normal file
79
src/libFLAC/include/private/ogg_decoder_aspect.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__OGG_DECODER_ASPECT_H
|
||||
#define FLAC__PRIVATE__OGG_DECODER_ASPECT_H
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
#include "FLAC/stream_decoder.h" /* for FLAC__StreamDecoderReadStatus */
|
||||
|
||||
typedef struct FLAC__OggDecoderAspect {
|
||||
/* these are storage for values that can be set through the API */
|
||||
FLAC__bool use_first_serial_number;
|
||||
long serial_number;
|
||||
|
||||
/* 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 */
|
||||
ogg_page working_page;
|
||||
FLAC__bool have_working_packet; /* only if true will the following vars be valid */
|
||||
ogg_packet working_packet; /* as we work through the packet we will move working_packet.packet forward and working_packet.bytes down */
|
||||
} FLAC__OggDecoderAspect;
|
||||
|
||||
void FLAC__ogg_decoder_aspect_set_serial_number(FLAC__OggDecoderAspect *aspect, long value);
|
||||
void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect);
|
||||
FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect);
|
||||
void FLAC__ogg_decoder_aspect_finish(FLAC__OggDecoderAspect *aspect);
|
||||
void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect);
|
||||
void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect);
|
||||
|
||||
typedef enum {
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK = 0,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR,
|
||||
FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR
|
||||
} FLAC__OggDecoderAspectReadStatus;
|
||||
|
||||
typedef FLAC__OggDecoderAspectReadStatus (*FLAC__OggDecoderAspectReadCallbackProxy)(const void *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
|
||||
FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data);
|
||||
|
||||
#endif
|
||||
62
src/libFLAC/include/private/ogg_encoder_aspect.h
Normal file
62
src/libFLAC/include/private/ogg_encoder_aspect.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__OGG_ENCODER_ASPECT_H
|
||||
#define FLAC__PRIVATE__OGG_ENCODER_ASPECT_H
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
#include "FLAC/stream_encoder.h" /* for FLAC__StreamEncoderWriteStatus */
|
||||
|
||||
typedef struct FLAC__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;
|
||||
ogg_page page;
|
||||
FLAC__bool seen_magic; /* true if we've seen the fLaC magic in the write callback yet */
|
||||
FLAC__bool is_first_packet;
|
||||
FLAC__uint64 samples_written;
|
||||
} FLAC__OggEncoderAspect;
|
||||
|
||||
void FLAC__ogg_encoder_aspect_set_serial_number(FLAC__OggEncoderAspect *aspect, long value);
|
||||
FLAC__bool FLAC__ogg_encoder_aspect_set_num_metadata(FLAC__OggEncoderAspect *aspect, unsigned value);
|
||||
void FLAC__ogg_encoder_aspect_set_defaults(FLAC__OggEncoderAspect *aspect);
|
||||
FLAC__bool FLAC__ogg_encoder_aspect_init(FLAC__OggEncoderAspect *aspect);
|
||||
void FLAC__ogg_encoder_aspect_finish(FLAC__OggEncoderAspect *aspect);
|
||||
|
||||
typedef FLAC__StreamEncoderWriteStatus (*FLAC__OggEncoderAspectWriteCallbackProxy)(const void *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
|
||||
FLAC__StreamEncoderWriteStatus FLAC__ogg_encoder_aspect_write_callback_wrapper(FLAC__OggEncoderAspect *aspect, const FLAC__uint64 total_samples_estimate, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, FLAC__OggEncoderAspectWriteCallbackProxy write_callback, void *encoder, void *client_data);
|
||||
#endif
|
||||
43
src/libFLAC/include/private/ogg_helper.h
Normal file
43
src/libFLAC/include/private/ogg_helper.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__OGG_HELPER_H
|
||||
#define FLAC__PRIVATE__OGG_HELPER_H
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
#include "FLAC/stream_encoder.h" /* for FLAC__StreamEncoder */
|
||||
|
||||
void simple_ogg_page__init(ogg_page *page);
|
||||
void simple_ogg_page__clear(ogg_page *page);
|
||||
FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data);
|
||||
FLAC__bool simple_ogg_page__set_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data);
|
||||
|
||||
#endif
|
||||
63
src/libFLAC/include/private/ogg_mapping.h
Normal file
63
src/libFLAC/include/private/ogg_mapping.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__OGG_MAPPING_H
|
||||
#define FLAC__PRIVATE__OGG_MAPPING_H
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
/** The length of the 'FLAC' magic in bytes. */
|
||||
#define FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH (1u)
|
||||
|
||||
extern const unsigned FLAC__OGG_MAPPING_PACKET_TYPE_LEN; /* = 8 bits */
|
||||
|
||||
extern const FLAC__byte FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE; /* = 0x7f */
|
||||
|
||||
/** The length of the 'FLAC' magic in bytes. */
|
||||
#define FLAC__OGG_MAPPING_MAGIC_LENGTH (4u)
|
||||
|
||||
extern const FLAC__byte * const FLAC__OGG_MAPPING_MAGIC; /* = "FLAC" */
|
||||
|
||||
extern const unsigned FLAC__OGG_MAPPING_VERSION_MAJOR_LEN; /* = 8 bits */
|
||||
extern const unsigned FLAC__OGG_MAPPING_VERSION_MINOR_LEN; /* = 8 bits */
|
||||
|
||||
/** The length of the Ogg FLAC mapping major version number in bytes. */
|
||||
#define FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH (1u)
|
||||
|
||||
/** The length of the Ogg FLAC mapping minor version number in bytes. */
|
||||
#define FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH (1u)
|
||||
|
||||
extern const unsigned FLAC__OGG_MAPPING_NUM_HEADERS_LEN; /* = 16 bits */
|
||||
|
||||
/** The length of the #-of-header-packets number bytes. */
|
||||
#define FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH (2u)
|
||||
|
||||
#endif
|
||||
@@ -33,6 +33,9 @@
|
||||
#define FLAC__PROTECTED__STREAM_DECODER_H
|
||||
|
||||
#include "FLAC/stream_decoder.h"
|
||||
#ifdef FLAC__HAS_OGG
|
||||
#include "private/ogg_decoder_aspect.h"
|
||||
#endif
|
||||
|
||||
typedef struct FLAC__StreamDecoderProtected {
|
||||
FLAC__StreamDecoderState state;
|
||||
@@ -42,6 +45,9 @@ typedef struct FLAC__StreamDecoderProtected {
|
||||
unsigned sample_rate; /* in Hz */
|
||||
unsigned blocksize; /* in samples (per channel) */
|
||||
FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__OggDecoderAspect ogg_decoder_aspect;
|
||||
#endif
|
||||
} FLAC__StreamDecoderProtected;
|
||||
|
||||
/*
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#define FLAC__PROTECTED__STREAM_ENCODER_H
|
||||
|
||||
#include "FLAC/stream_encoder.h"
|
||||
#ifdef FLAC__HAS_OGG
|
||||
#include "private/ogg_encoder_aspect.h"
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
@@ -98,6 +101,9 @@ typedef struct FLAC__StreamEncoderProtected {
|
||||
FLAC__StreamMetadata **metadata;
|
||||
unsigned num_metadata_blocks;
|
||||
FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__OggEncoderAspect ogg_encoder_aspect;
|
||||
#endif
|
||||
} FLAC__StreamEncoderProtected;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -235,6 +235,22 @@ SOURCE=.\metadata_object.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_decoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_encoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_helper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_mapping.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\stream_decoder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -303,6 +319,22 @@ SOURCE=.\include\private\metadata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_decoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_encoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_helper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_mapping.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\stream_encoder_framing.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -228,6 +228,22 @@ SOURCE=.\metadata_object.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_decoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_encoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_helper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_mapping.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\stream_decoder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -296,6 +312,22 @@ SOURCE=.\include\private\metadata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_decoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_encoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_helper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_mapping.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\stream_encoder_framing.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
253
src/libFLAC/ogg_decoder_aspect.c
Normal file
253
src/libFLAC/ogg_decoder_aspect.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "private/ogg_decoder_aspect.h"
|
||||
#include "private/ogg_mapping.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Public class methods
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect)
|
||||
{
|
||||
/* we will determine the serial number later if necessary */
|
||||
if(ogg_stream_init(&aspect->stream_state, aspect->serial_number) != 0)
|
||||
return false;
|
||||
|
||||
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;
|
||||
aspect->have_working_page = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__ogg_decoder_aspect_finish(FLAC__OggDecoderAspect *aspect)
|
||||
{
|
||||
(void)ogg_sync_clear(&aspect->sync_state);
|
||||
(void)ogg_stream_clear(&aspect->stream_state);
|
||||
}
|
||||
|
||||
void FLAC__ogg_decoder_aspect_set_serial_number(FLAC__OggDecoderAspect *aspect, long value)
|
||||
{
|
||||
aspect->use_first_serial_number = false;
|
||||
aspect->serial_number = value;
|
||||
}
|
||||
|
||||
void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect)
|
||||
{
|
||||
aspect->use_first_serial_number = true;
|
||||
}
|
||||
|
||||
void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect)
|
||||
{
|
||||
(void)ogg_stream_reset(&aspect->stream_state);
|
||||
(void)ogg_sync_reset(&aspect->sync_state);
|
||||
aspect->end_of_stream = false;
|
||||
aspect->have_working_page = false;
|
||||
}
|
||||
|
||||
void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect)
|
||||
{
|
||||
FLAC__ogg_decoder_aspect_flush(aspect);
|
||||
|
||||
if(aspect->use_first_serial_number)
|
||||
aspect->need_serial_number = true;
|
||||
}
|
||||
|
||||
FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data)
|
||||
{
|
||||
static const unsigned OGG_BYTES_CHUNK = 8192;
|
||||
const unsigned bytes_requested = *bytes;
|
||||
|
||||
/*
|
||||
* The FLAC decoding API uses pull-based reads, whereas Ogg decoding
|
||||
* is push-based. In libFLAC, when you ask to decode a frame, the
|
||||
* decoder will eventually call the read callback to supply some data,
|
||||
* but how much it asks for depends on how much free space it has in
|
||||
* its internal buffer. It does not try to grow its internal buffer
|
||||
* to accomodate a whole frame because then the internal buffer size
|
||||
* could not be limited, which is necessary in embedded applications.
|
||||
*
|
||||
* Ogg however grows its internal buffer until a whole page is present;
|
||||
* only then can you get decoded data out. So we can't just ask for
|
||||
* the same number of bytes from Ogg, then pass what's decoded down to
|
||||
* libFLAC. If what libFLAC is asking for will not contain a whole
|
||||
* page, then we will get no data from ogg_sync_pageout(), and at the
|
||||
* same time cannot just read more data from the client for the purpose
|
||||
* of getting a whole decoded page because the decoded size might be
|
||||
* larger than libFLAC's internal buffer.
|
||||
*
|
||||
* Instead, whenever this read callback wrapper is called, we will
|
||||
* continually request data from the client until we have at least one
|
||||
* page, and manage pages internally so that we can send pieces of
|
||||
* pages down to libFLAC in such a way that we obey its size
|
||||
* requirement. To limit the amount of callbacks, we will always try
|
||||
* to read in enough pages to return the full number of bytes
|
||||
* requested.
|
||||
*/
|
||||
*bytes = 0;
|
||||
while (*bytes < bytes_requested && !aspect->end_of_stream) {
|
||||
if (aspect->have_working_page) {
|
||||
if (aspect->have_working_packet) {
|
||||
unsigned n = bytes_requested - *bytes;
|
||||
if ((unsigned)aspect->working_packet.bytes <= n) {
|
||||
/* the rest of the packet will fit in the buffer */
|
||||
n = aspect->working_packet.bytes;
|
||||
memcpy(buffer, aspect->working_packet.packet, n);
|
||||
*bytes += n;
|
||||
buffer += n;
|
||||
aspect->have_working_packet = false;
|
||||
}
|
||||
else {
|
||||
/* only n bytes of the packet will fit in the buffer */
|
||||
memcpy(buffer, aspect->working_packet.packet, n);
|
||||
*bytes += n;
|
||||
buffer += n;
|
||||
aspect->working_packet.packet += n;
|
||||
aspect->working_packet.bytes -= n;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* try and get another packet */
|
||||
const int ret = ogg_stream_packetout(&aspect->stream_state, &aspect->working_packet);
|
||||
if (ret > 0) {
|
||||
aspect->have_working_packet = true;
|
||||
/* 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] == FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE) {
|
||||
const FLAC__byte *b = aspect->working_packet.packet;
|
||||
const unsigned header_length =
|
||||
FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH +
|
||||
FLAC__OGG_MAPPING_MAGIC_LENGTH +
|
||||
FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH +
|
||||
FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH +
|
||||
FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH;
|
||||
if (aspect->working_packet.bytes < (long)header_length)
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
|
||||
b += FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH;
|
||||
if (memcmp(b, FLAC__OGG_MAPPING_MAGIC, FLAC__OGG_MAPPING_MAGIC_LENGTH))
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
|
||||
b += FLAC__OGG_MAPPING_MAGIC_LENGTH;
|
||||
aspect->version_major = (unsigned)(*b);
|
||||
b += FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH;
|
||||
aspect->version_minor = (unsigned)(*b);
|
||||
if (aspect->version_major != 1)
|
||||
return FLAC__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;
|
||||
}
|
||||
else { /* ret < 0 */
|
||||
/* lost sync, we'll leave the working page for the next call */
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* try and get another page */
|
||||
const int ret = ogg_sync_pageout(&aspect->sync_state, &aspect->working_page);
|
||||
if (ret > 0) {
|
||||
/* got a page, grab the serial number if necessary */
|
||||
if(aspect->need_serial_number) {
|
||||
aspect->stream_state.serialno = aspect->serial_number = ogg_page_serialno(&aspect->working_page);
|
||||
aspect->need_serial_number = false;
|
||||
}
|
||||
if(ogg_stream_pagein(&aspect->stream_state, &aspect->working_page) == 0) {
|
||||
aspect->have_working_page = true;
|
||||
aspect->have_working_packet = false;
|
||||
}
|
||||
/* else do nothing, could be a page from another stream */
|
||||
}
|
||||
else if (ret == 0) {
|
||||
/* need more data */
|
||||
const unsigned ogg_bytes_to_read = max(bytes_requested - *bytes, OGG_BYTES_CHUNK);
|
||||
char *oggbuf = ogg_sync_buffer(&aspect->sync_state, ogg_bytes_to_read);
|
||||
|
||||
if(0 == oggbuf) {
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
else {
|
||||
unsigned ogg_bytes_read = ogg_bytes_to_read;
|
||||
|
||||
switch(read_callback(decoder, (FLAC__byte*)oggbuf, &ogg_bytes_read, client_data)) {
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
|
||||
break;
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
|
||||
aspect->end_of_stream = true;
|
||||
break;
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
if(ogg_sync_wrote(&aspect->sync_state, ogg_bytes_read) < 0) {
|
||||
/* double protection; this will happen if the read callback returns more bytes than the max requested, which would overflow Ogg's internal buffer */
|
||||
FLAC__ASSERT(0);
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* ret < 0 */
|
||||
/* lost sync, bail out */
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aspect->end_of_stream && *bytes == 0) {
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
|
||||
}
|
||||
222
src/libFLAC/ogg_encoder_aspect.c
Normal file
222
src/libFLAC/ogg_encoder_aspect.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> /* for memset() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "private/ogg_encoder_aspect.h"
|
||||
#include "private/ogg_mapping.h"
|
||||
|
||||
static const FLAC__byte FLAC__OGG_MAPPING_VERSION_MAJOR = 1;
|
||||
static const FLAC__byte FLAC__OGG_MAPPING_VERSION_MINOR = 0;
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Public class methods
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__bool FLAC__ogg_encoder_aspect_init(FLAC__OggEncoderAspect *aspect)
|
||||
{
|
||||
/* we will determine the serial number later if necessary */
|
||||
if(ogg_stream_init(&aspect->stream_state, aspect->serial_number) != 0)
|
||||
return false;
|
||||
|
||||
aspect->seen_magic = false;
|
||||
aspect->is_first_packet = true;
|
||||
aspect->samples_written = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__ogg_encoder_aspect_finish(FLAC__OggEncoderAspect *aspect)
|
||||
{
|
||||
(void)ogg_stream_clear(&aspect->stream_state);
|
||||
/*@@@ what about the page? */
|
||||
}
|
||||
|
||||
void FLAC__ogg_encoder_aspect_set_serial_number(FLAC__OggEncoderAspect *aspect, long value)
|
||||
{
|
||||
aspect->serial_number = value;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__ogg_encoder_aspect_set_num_metadata(FLAC__OggEncoderAspect *aspect, unsigned value)
|
||||
{
|
||||
if(value < (1u << FLAC__OGG_MAPPING_NUM_HEADERS_LEN)) {
|
||||
aspect->num_metadata = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void FLAC__ogg_encoder_aspect_set_defaults(FLAC__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
|
||||
* + 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,
|
||||
* the mapping only requires that a flush must occur after all
|
||||
* 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
|
||||
* separate write callback for the fLaC magic, and then separate write
|
||||
* callbacks for each metadata block and audio frame.
|
||||
*/
|
||||
FLAC__StreamEncoderWriteStatus FLAC__ogg_encoder_aspect_write_callback_wrapper(FLAC__OggEncoderAspect *aspect, const FLAC__uint64 total_samples_estimate, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, FLAC__OggEncoderAspectWriteCallbackProxy write_callback, void *encoder, void *client_data)
|
||||
{
|
||||
/* WATCHOUT:
|
||||
* This depends on the behavior of FLAC__StreamEncoder that 'samples'
|
||||
* will be 0 for metadata writes.
|
||||
*/
|
||||
const FLAC__bool is_metadata = (samples == 0);
|
||||
|
||||
/*
|
||||
* Treat fLaC magic packet specially. We will note when we see it, then
|
||||
* wait until we get the STREAMINFO and prepend it in that packet
|
||||
*/
|
||||
if(aspect->seen_magic) {
|
||||
ogg_packet packet;
|
||||
FLAC__byte synthetic_first_packet_body[
|
||||
FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH +
|
||||
FLAC__OGG_MAPPING_MAGIC_LENGTH +
|
||||
FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH +
|
||||
FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH +
|
||||
FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH +
|
||||
FLAC__STREAM_SYNC_LENGTH +
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_LENGTH
|
||||
];
|
||||
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.granulepos = aspect->samples_written + samples;
|
||||
|
||||
if(aspect->is_first_packet) {
|
||||
FLAC__byte *b = synthetic_first_packet_body;
|
||||
if(bytes != FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH) {
|
||||
/*
|
||||
* If we get here, our assumption about the way write callbacks happen
|
||||
* (explained above) is wrong
|
||||
*/
|
||||
FLAC__ASSERT(0);
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
/* add first header packet type */
|
||||
*b = FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE;
|
||||
b += FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH;
|
||||
/* add 'FLAC' mapping magic */
|
||||
memcpy(b, FLAC__OGG_MAPPING_MAGIC, FLAC__OGG_MAPPING_MAGIC_LENGTH);
|
||||
b += FLAC__OGG_MAPPING_MAGIC_LENGTH;
|
||||
/* add Ogg FLAC mapping major version number */
|
||||
memcpy(b, &FLAC__OGG_MAPPING_VERSION_MAJOR, FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH);
|
||||
b += FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH;
|
||||
/* add Ogg FLAC mapping minor version number */
|
||||
memcpy(b, &FLAC__OGG_MAPPING_VERSION_MINOR, FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH);
|
||||
b += FLAC__OGG_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;
|
||||
/* add STREAMINFO */
|
||||
memcpy(b, buffer, bytes);
|
||||
FLAC__ASSERT(b + bytes - synthetic_first_packet_body == sizeof(synthetic_first_packet_body));
|
||||
packet.packet = (unsigned char *)synthetic_first_packet_body;
|
||||
packet.bytes = sizeof(synthetic_first_packet_body);
|
||||
|
||||
packet.b_o_s = 1;
|
||||
aspect->is_first_packet = false;
|
||||
}
|
||||
else {
|
||||
packet.packet = (unsigned char *)buffer;
|
||||
packet.bytes = bytes;
|
||||
}
|
||||
|
||||
if(total_samples_estimate > 0 && total_samples_estimate == aspect->samples_written + samples)
|
||||
packet.e_o_s = 1;
|
||||
|
||||
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 */
|
||||
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)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(ogg_stream_pageout(&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)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(is_metadata && current_frame == 0 && samples == 0 && bytes == 4 && 0 == memcmp(buffer, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING))) {
|
||||
aspect->seen_magic = true;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* If we get here, our assumption about the way write callbacks happen
|
||||
* explained above is wrong
|
||||
*/
|
||||
FLAC__ASSERT(0);
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
aspect->samples_written += samples;
|
||||
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
|
||||
}
|
||||
204
src/libFLAC/ogg_helper.c
Normal file
204
src/libFLAC/ogg_helper.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcmp(), memcpy() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "private/ogg_helper.h"
|
||||
#include "protected/stream_encoder.h"
|
||||
|
||||
|
||||
static FLAC__bool full_read_(FLAC__StreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, FLAC__StreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
while(bytes > 0) {
|
||||
unsigned bytes_read = bytes;
|
||||
switch(read_callback(encoder, buffer, &bytes_read, client_data)) {
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE:
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
|
||||
if(bytes_read == 0) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_ABORT:
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED:
|
||||
return false;
|
||||
default:
|
||||
/* double protection: */
|
||||
FLAC__ASSERT(0);
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void simple_ogg_page__init(ogg_page *page)
|
||||
{
|
||||
page->header = 0;
|
||||
page->header_len = 0;
|
||||
page->body = 0;
|
||||
page->body_len = 0;
|
||||
}
|
||||
|
||||
void simple_ogg_page__clear(ogg_page *page)
|
||||
{
|
||||
if(page->header)
|
||||
free(page->header);
|
||||
if(page->body)
|
||||
free(page->body);
|
||||
simple_ogg_page__init(page);
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
|
||||
static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
|
||||
FLAC__byte crc[4];
|
||||
FLAC__StreamEncoderSeekStatus seek_status;
|
||||
|
||||
FLAC__ASSERT(page->header == 0);
|
||||
FLAC__ASSERT(page->header_len == 0);
|
||||
FLAC__ASSERT(page->body == 0);
|
||||
FLAC__ASSERT(page->body_len == 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(0 == seek_callback)
|
||||
return false;
|
||||
if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate space for the page header */
|
||||
if(0 == (page->header = (unsigned char *)malloc(OGG_MAX_HEADER_LEN))) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the fixed part of the page header (up to but not including
|
||||
* the segment table */
|
||||
if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26];
|
||||
|
||||
/* check to see if it's a correct, "simple" page (one packet only) */
|
||||
if(
|
||||
memcmp(page->header, "OggS", 4) || /* doesn't start with OggS */
|
||||
(page->header[5] & 0x01) || /* continued packet */
|
||||
memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */
|
||||
page->header[26] == 0 /* packet is 0-size */
|
||||
) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the segment table */
|
||||
if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data))
|
||||
return false;
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* check to see that it specifies a single packet */
|
||||
for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
|
||||
if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
page->body_len = 255 * i + page->header[i];
|
||||
}
|
||||
|
||||
/* allocate space for the page body */
|
||||
if(0 == (page->body = (unsigned char *)malloc(page->body_len))) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the page body */
|
||||
if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
/* check the CRC */
|
||||
memcpy(crc, page->header+22, 4);
|
||||
ogg_page_checksum_set(page);
|
||||
if(memcmp(crc, page->header+22, 4)) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__set_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data)
|
||||
{
|
||||
FLAC__StreamEncoderSeekStatus seek_status;
|
||||
|
||||
FLAC__ASSERT(page->header != 0);
|
||||
FLAC__ASSERT(page->header_len != 0);
|
||||
FLAC__ASSERT(page->body != 0);
|
||||
FLAC__ASSERT(page->body_len != 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(0 == seek_callback)
|
||||
return false;
|
||||
if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
ogg_page_checksum_set(page);
|
||||
|
||||
/* re-write the page */
|
||||
if(write_callback((FLAC__StreamEncoder*)encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
47
src/libFLAC/ogg_mapping.c
Normal file
47
src/libFLAC/ogg_mapping.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2004,2005,2006 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "private/ogg_mapping.h"
|
||||
|
||||
const unsigned FLAC__OGG_MAPPING_PACKET_TYPE_LEN = 8; /* bits */
|
||||
|
||||
const FLAC__byte FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE = 0x7f;
|
||||
|
||||
const FLAC__byte * const FLAC__OGG_MAPPING_MAGIC = (const FLAC__byte * const)"FLAC";
|
||||
|
||||
const unsigned FLAC__OGG_MAPPING_VERSION_MAJOR_LEN = 8; /* bits */
|
||||
const unsigned FLAC__OGG_MAPPING_VERSION_MINOR_LEN = 8; /* bits */
|
||||
|
||||
const unsigned FLAC__OGG_MAPPING_NUM_HEADERS_LEN = 16; /* bits */
|
||||
@@ -76,6 +76,17 @@
|
||||
#define FLAC__U64L(x) x##LLU
|
||||
#endif
|
||||
|
||||
|
||||
/* technically this should be in an "export.c" but this is convenient enough */
|
||||
int FLAC_API_SUPPORTS_OGG_FLAC =
|
||||
#if FLAC__HAS_OGG
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Private static data
|
||||
@@ -113,9 +124,16 @@ static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned
|
||||
static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual);
|
||||
static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder);
|
||||
static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
static FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes);
|
||||
static FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
#endif
|
||||
static FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
|
||||
static void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status);
|
||||
static FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
static FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
|
||||
#endif
|
||||
static FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
@@ -129,6 +147,9 @@ static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *c
|
||||
***********************************************************************/
|
||||
|
||||
typedef struct FLAC__StreamDecoderPrivate {
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__bool is_ogg;
|
||||
#endif
|
||||
FLAC__StreamDecoderReadCallback read_callback;
|
||||
FLAC__StreamDecoderSeekCallback seek_callback;
|
||||
FLAC__StreamDecoderTellCallback tell_callback;
|
||||
@@ -178,6 +199,9 @@ typedef struct FLAC__StreamDecoderPrivate {
|
||||
FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */
|
||||
FLAC__uint64 target_sample;
|
||||
unsigned unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__bool got_a_frame; /* hack needed in Ogg FLAC seek routine to check when process_single() actually writes a frame */
|
||||
#endif
|
||||
} FLAC__StreamDecoderPrivate;
|
||||
|
||||
/***********************************************************************
|
||||
@@ -192,6 +216,7 @@ FLAC_API const char * const FLAC__StreamDecoderStateString[] = {
|
||||
"FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC",
|
||||
"FLAC__STREAM_DECODER_READ_FRAME",
|
||||
"FLAC__STREAM_DECODER_END_OF_STREAM",
|
||||
"FLAC__STREAM_DECODER_OGG_ERROR",
|
||||
"FLAC__STREAM_DECODER_SEEK_ERROR",
|
||||
"FLAC__STREAM_DECODER_ABORTED",
|
||||
"FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
|
||||
@@ -200,6 +225,7 @@ FLAC_API const char * const FLAC__StreamDecoderStateString[] = {
|
||||
|
||||
FLAC_API const char * const FLAC__StreamDecoderInitStatusString[] = {
|
||||
"FLAC__STREAM_DECODER_INIT_STATUS_OK",
|
||||
"FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
|
||||
"FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS",
|
||||
"FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR",
|
||||
"FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE",
|
||||
@@ -340,7 +366,7 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
static FLAC__StreamDecoderInitStatus init_stream_internal_(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderReadCallback read_callback,
|
||||
FLAC__StreamDecoderSeekCallback seek_callback,
|
||||
@@ -350,7 +376,8 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
@@ -358,6 +385,11 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
|
||||
return FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
|
||||
|
||||
#ifndef FLAC__HAS_OGG
|
||||
if(is_ogg)
|
||||
return FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
|
||||
#endif
|
||||
|
||||
if(
|
||||
0 == read_callback ||
|
||||
0 == write_callback ||
|
||||
@@ -366,6 +398,12 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
)
|
||||
return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
decoder->private_->is_ogg = is_ogg;
|
||||
if(is_ogg && !FLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))
|
||||
return decoder->protected_->state = FLAC__STREAM_DECODER_OGG_ERROR;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get the CPU info and set the function pointers
|
||||
*/
|
||||
@@ -436,13 +474,70 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
return FLAC__STREAM_DECODER_INIT_STATUS_OK;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderReadCallback read_callback,
|
||||
FLAC__StreamDecoderSeekCallback seek_callback,
|
||||
FLAC__StreamDecoderTellCallback tell_callback,
|
||||
FLAC__StreamDecoderLengthCallback length_callback,
|
||||
FLAC__StreamDecoderEofCallback eof_callback,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_stream_internal_(
|
||||
decoder,
|
||||
read_callback,
|
||||
seek_callback,
|
||||
tell_callback,
|
||||
length_callback,
|
||||
eof_callback,
|
||||
write_callback,
|
||||
metadata_callback,
|
||||
error_callback,
|
||||
client_data,
|
||||
/*is_ogg=*/false
|
||||
);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderReadCallback read_callback,
|
||||
FLAC__StreamDecoderSeekCallback seek_callback,
|
||||
FLAC__StreamDecoderTellCallback tell_callback,
|
||||
FLAC__StreamDecoderLengthCallback length_callback,
|
||||
FLAC__StreamDecoderEofCallback eof_callback,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_stream_internal_(
|
||||
decoder,
|
||||
read_callback,
|
||||
seek_callback,
|
||||
tell_callback,
|
||||
length_callback,
|
||||
eof_callback,
|
||||
write_callback,
|
||||
metadata_callback,
|
||||
error_callback,
|
||||
client_data,
|
||||
/*is_ogg=*/true
|
||||
);
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderInitStatus init_FILE_internal_(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FILE *file,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
@@ -464,7 +559,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
|
||||
|
||||
decoder->private_->file = file;
|
||||
|
||||
return FLAC__stream_decoder_init_stream(
|
||||
return init_stream_internal_(
|
||||
decoder,
|
||||
file_read_callback_,
|
||||
decoder->private_->file == stdin? 0: file_seek_callback_,
|
||||
@@ -474,17 +569,43 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
|
||||
write_callback,
|
||||
metadata_callback,
|
||||
error_callback,
|
||||
client_data
|
||||
client_data,
|
||||
is_ogg
|
||||
);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FILE *file,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FILE *file,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true);
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderInitStatus init_file_internal_(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
const char *filename,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
FILE *file;
|
||||
@@ -507,7 +628,31 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
|
||||
if(0 == file)
|
||||
return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE;
|
||||
|
||||
return FLAC__stream_decoder_init_FILE(decoder, file, write_callback, metadata_callback, error_callback, client_data);
|
||||
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, is_ogg);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
const char *filename,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
const char *filename,
|
||||
FLAC__StreamDecoderWriteCallback write_callback,
|
||||
FLAC__StreamDecoderMetadataCallback metadata_callback,
|
||||
FLAC__StreamDecoderErrorCallback error_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
|
||||
@@ -552,6 +697,11 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
|
||||
decoder->private_->output_capacity = 0;
|
||||
decoder->private_->output_channels = 0;
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(decoder->private_->is_ogg)
|
||||
FLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect);
|
||||
#endif
|
||||
|
||||
if(0 != decoder->private_->file) {
|
||||
if(decoder->private_->file != stdin)
|
||||
fclose(decoder->private_->file);
|
||||
@@ -571,6 +721,23 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
|
||||
return !md5_failed;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_set_serial_number(FLAC__StreamDecoder *decoder, long value)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
/* can't check decoder->private_->is_ogg since that's not set until init time */
|
||||
FLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value);
|
||||
return true;
|
||||
#else
|
||||
(void)value;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
@@ -764,6 +931,10 @@ FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamD
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != position);
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(decoder->private_->is_ogg)
|
||||
return false;
|
||||
#endif
|
||||
if(0 == decoder->private_->tell_callback)
|
||||
return false;
|
||||
if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK)
|
||||
@@ -782,6 +953,11 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
|
||||
decoder->private_->samples_decoded = 0;
|
||||
decoder->private_->do_md5_checking = false;
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(decoder->private_->is_ogg)
|
||||
FLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
|
||||
#endif
|
||||
|
||||
if(!FLAC__bitbuffer_clear(decoder->private_->input)) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
@@ -804,6 +980,12 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
/*@@@ could go in !internal_reset_hack block below */
|
||||
if(decoder->private_->is_ogg)
|
||||
FLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect);
|
||||
#endif
|
||||
|
||||
/* Rewind if necessary. If FLAC__stream_decoder_init() is calling us,
|
||||
* (internal_reset_hack) don't try to rewind since we are already at
|
||||
* the beginning of the stream and don't want to fail if the input is
|
||||
@@ -1007,6 +1189,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *deco
|
||||
decoder->private_->is_seeking = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO, SEEK_TABLE, and first_frame_offset */
|
||||
if(
|
||||
decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ||
|
||||
@@ -1025,7 +1208,13 @@ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *deco
|
||||
}
|
||||
|
||||
{
|
||||
FLAC__bool ok = seek_to_absolute_sample_(decoder, length, sample);
|
||||
const FLAC__bool ok =
|
||||
#ifdef FLAC__HAS_OGG
|
||||
decoder->private_->is_ogg?
|
||||
seek_to_absolute_sample_ogg_(decoder, length, sample) :
|
||||
#endif
|
||||
seek_to_absolute_sample_(decoder, length, sample)
|
||||
;
|
||||
decoder->private_->is_seeking = false;
|
||||
return ok;
|
||||
}
|
||||
@@ -1051,6 +1240,9 @@ unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecod
|
||||
|
||||
void set_defaults_(FLAC__StreamDecoder *decoder)
|
||||
{
|
||||
#ifdef FLAC__HAS_OGG
|
||||
decoder->private_->is_ogg = false;
|
||||
#endif
|
||||
decoder->private_->read_callback = 0;
|
||||
decoder->private_->seek_callback = 0;
|
||||
decoder->private_->tell_callback = 0;
|
||||
@@ -1066,6 +1258,10 @@ void set_defaults_(FLAC__StreamDecoder *decoder)
|
||||
decoder->private_->metadata_filter_ids_count = 0;
|
||||
|
||||
decoder->protected_->md5_checking = false;
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1483,7 +1679,7 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_
|
||||
length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH);
|
||||
/* if there is a partial point left, skip over it */
|
||||
if(length > 0) {
|
||||
/*@@@ do an error_callback() here? there's an argument for either way */
|
||||
/*@@@ do a send_error_to_client_() here? there's an argument for either way */
|
||||
if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder))
|
||||
return false; /* read_callback_ sets the state for us */
|
||||
}
|
||||
@@ -2544,7 +2740,8 @@ FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_dat
|
||||
{
|
||||
FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data;
|
||||
|
||||
if(decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data)) {
|
||||
/* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */
|
||||
if(!decoder->private_->is_ogg && decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data)) {
|
||||
*bytes = 0;
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
|
||||
return false;
|
||||
@@ -2565,13 +2762,20 @@ FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_dat
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
const FLAC__StreamDecoderReadStatus status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data);
|
||||
const FLAC__StreamDecoderReadStatus status =
|
||||
#ifdef FLAC__HAS_OGG
|
||||
decoder->private_->is_ogg?
|
||||
read_callback_ogg_aspect_(decoder, buffer, bytes) :
|
||||
#endif
|
||||
decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data)
|
||||
;
|
||||
if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
|
||||
return false;
|
||||
}
|
||||
else if(*bytes == 0) {
|
||||
if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || (decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data))) {
|
||||
/* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */
|
||||
if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || (!decoder->private_->is_ogg && decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data))) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
|
||||
return false;
|
||||
}
|
||||
@@ -2587,8 +2791,63 @@ FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_dat
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
|
||||
return false;
|
||||
}
|
||||
/* [1] @@@ HACK NOTE: The end-of-stream checking has to be hacked around
|
||||
* for Ogg FLAC. This is because the ogg decoder aspect can lose sync
|
||||
* and at the same time hit the end of the stream. There is no way to
|
||||
* report an Ogg sync loss through the callbacks (see note in
|
||||
* read_callback_ogg_aspect_()) so it returns CONTINUE with *bytes==0.
|
||||
* So to keep the decoder from stopping at this point we gate the call
|
||||
* to the eof_callback and let the Ogg decoder aspect set the
|
||||
* end-of-stream state when it is needed.
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes)
|
||||
{
|
||||
switch(FLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) {
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
/* we don't really have a way to handle lost sync via read
|
||||
* callback so we'll let it pass and let the underlying
|
||||
* FLAC decoder catch the error
|
||||
*/
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC:
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC:
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION:
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR:
|
||||
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR:
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
/* double protection */
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder*)void_decoder;
|
||||
|
||||
switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) {
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_ABORT:
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
|
||||
default:
|
||||
/* double protection: */
|
||||
FLAC__ASSERT(0);
|
||||
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
|
||||
{
|
||||
if(decoder->private_->is_seeking) {
|
||||
@@ -2598,6 +2857,9 @@ FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder
|
||||
|
||||
FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
decoder->private_->got_a_frame = true;
|
||||
#endif
|
||||
decoder->private_->last_frame = *frame; /* save the frame */
|
||||
if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
|
||||
unsigned delta = (unsigned)(target_sample - this_frame_sample);
|
||||
@@ -2882,6 +3144,145 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
|
||||
{
|
||||
FLAC__uint64 left_pos = 0, right_pos = stream_length;
|
||||
FLAC__uint64 left_sample = 0, right_sample = FLAC__stream_decoder_get_total_samples(decoder);
|
||||
FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
|
||||
FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
|
||||
FLAC__bool did_a_seek;
|
||||
unsigned iteration = 0;
|
||||
|
||||
/* In the first iterations, we will calculate the target byte position
|
||||
* by the distance from the target sample to left_sample and
|
||||
* right_sample (let's call it "proportional search"). After that, we
|
||||
* will switch to binary search.
|
||||
*/
|
||||
unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
|
||||
|
||||
/* We will switch to a linear search once our current sample is less
|
||||
* than this number of samples ahead of the target sample
|
||||
*/
|
||||
static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
|
||||
|
||||
/* If the total number of samples is unknown, use a large value, and
|
||||
* force binary search immediately.
|
||||
*/
|
||||
if(right_sample == 0) {
|
||||
right_sample = (FLAC__uint64)(-1);
|
||||
BINARY_SEARCH_AFTER_ITERATION = 0;
|
||||
}
|
||||
|
||||
decoder->private_->target_sample = target_sample;
|
||||
for( ; ; iteration++) {
|
||||
if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
|
||||
if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
|
||||
pos = (right_pos + left_pos) / 2;
|
||||
}
|
||||
else {
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
/* with MSVC you have to spoon feed it the casting */
|
||||
pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));
|
||||
#else
|
||||
pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
|
||||
#endif
|
||||
#else
|
||||
/* a little less accurate: */
|
||||
if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
|
||||
pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
|
||||
else /* @@@ WATCHOUT, ~2TB limit */
|
||||
pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
|
||||
#endif
|
||||
/* @@@ TODO: might want to limit pos to some distance
|
||||
* before EOF, to make sure we land before the last frame,
|
||||
* thereby getting a this_frame_sample and so having a better
|
||||
* estimate. @@@@@@DELETE:this would also mostly (or totally if we could
|
||||
* be sure to land before the last frame) avoid the
|
||||
* end-of-stream case we have to check later.
|
||||
*/
|
||||
}
|
||||
|
||||
/* physical seek */
|
||||
if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__stream_decoder_flush(decoder)) {
|
||||
/* above call sets the state for us */
|
||||
return false;
|
||||
}
|
||||
did_a_seek = true;
|
||||
}
|
||||
else
|
||||
did_a_seek = false;
|
||||
|
||||
decoder->private_->got_a_frame = false;
|
||||
if(!FLAC__stream_decoder_process_single(decoder)) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!decoder->private_->got_a_frame) {
|
||||
if(did_a_seek) {
|
||||
/* this can happen if we seek to a point after the last frame; we drop
|
||||
* to binary search right away in this case to avoid any wasted
|
||||
* iterations of proportional search.
|
||||
*/
|
||||
right_pos = pos;
|
||||
BINARY_SEARCH_AFTER_ITERATION = 0;
|
||||
}
|
||||
else {
|
||||
/* this can probably only happen if total_samples is unknown and the
|
||||
* target_sample is past the end of the stream
|
||||
*/
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* our write callback will change the state when it gets to the target frame */
|
||||
else if(!decoder->private_->is_seeking/*@@@@@@ && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM*/) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
|
||||
FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
|
||||
|
||||
if (did_a_seek) {
|
||||
if (this_frame_sample <= target_sample) {
|
||||
/* The 'equal' case should not happen, since
|
||||
* FLAC__stream_decoder_process_single()
|
||||
* should recognize that it has hit the
|
||||
* target sample and we would exit through
|
||||
* the 'break' above.
|
||||
*/
|
||||
FLAC__ASSERT(this_frame_sample != target_sample);
|
||||
|
||||
left_sample = this_frame_sample;
|
||||
/* sanity check to avoid infinite loop */
|
||||
if (left_pos == pos) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
left_pos = pos;
|
||||
}
|
||||
else if(this_frame_sample > target_sample) {
|
||||
right_sample = this_frame_sample;
|
||||
/* sanity check to avoid infinite loop */
|
||||
if (right_pos == pos) {
|
||||
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
right_pos = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
#include "private/lpc.h"
|
||||
#include "private/md5.h"
|
||||
#include "private/memory.h"
|
||||
#ifdef FLAC__HAS_OGG
|
||||
#include "private/ogg_helper.h"
|
||||
#endif
|
||||
#include "private/stream_encoder_framing.h"
|
||||
#include "private/window.h"
|
||||
|
||||
@@ -105,8 +108,9 @@ static void set_defaults_(FLAC__StreamEncoder *encoder);
|
||||
static void free_(FLAC__StreamEncoder *encoder);
|
||||
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
|
||||
static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
|
||||
static FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples);
|
||||
static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples);
|
||||
static void update_metadata_(const FLAC__StreamEncoder *encoder);
|
||||
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
|
||||
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
|
||||
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
|
||||
|
||||
@@ -305,6 +309,7 @@ static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamD
|
||||
static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
|
||||
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
@@ -374,6 +379,10 @@ typedef struct FLAC__StreamEncoderPrivate {
|
||||
FLAC__bool disable_constant_subframes;
|
||||
FLAC__bool disable_fixed_subframes;
|
||||
FLAC__bool disable_verbatim_subframes;
|
||||
#if FLAC__HAS_OGG
|
||||
FLAC__bool is_ogg;
|
||||
#endif
|
||||
FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
|
||||
FLAC__StreamEncoderSeekCallback seek_callback;
|
||||
FLAC__StreamEncoderTellCallback tell_callback;
|
||||
FLAC__StreamEncoderWriteCallback write_callback;
|
||||
@@ -438,6 +447,7 @@ typedef struct FLAC__StreamEncoderPrivate {
|
||||
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
|
||||
"FLAC__STREAM_ENCODER_OK",
|
||||
"FLAC__STREAM_ENCODER_UNINITIALIZED",
|
||||
"FLAC__STREAM_ENCODER_OGG_ERROR",
|
||||
"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
|
||||
"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
|
||||
"FLAC__STREAM_ENCODER_CLIENT_ERROR",
|
||||
@@ -449,6 +459,7 @@ FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
|
||||
FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_OK",
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR",
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS",
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS",
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE",
|
||||
@@ -464,6 +475,13 @@ FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
|
||||
"FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__treamEncoderReadStatusString[] = {
|
||||
"FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE",
|
||||
"FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
|
||||
"FLAC__STREAM_ENCODER_READ_STATUS_ABORT",
|
||||
"FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
|
||||
"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
|
||||
"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
|
||||
@@ -597,7 +615,16 @@ FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data)
|
||||
static FLAC__StreamEncoderInitStatus init_stream_internal_(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FLAC__StreamEncoderReadCallback read_callback,
|
||||
FLAC__StreamEncoderWriteCallback write_callback,
|
||||
FLAC__StreamEncoderSeekCallback seek_callback,
|
||||
FLAC__StreamEncoderTellCallback tell_callback,
|
||||
FLAC__StreamEncoderMetadataCallback metadata_callback,
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
|
||||
@@ -607,6 +634,11 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__St
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
|
||||
|
||||
#ifndef FLAC__HAS_OGG
|
||||
if(is_ogg)
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
|
||||
#endif
|
||||
|
||||
if(0 == write_callback || (seek_callback && 0 == tell_callback))
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
|
||||
|
||||
@@ -725,6 +757,32 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__St
|
||||
if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
|
||||
encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
|
||||
|
||||
#if FLAC__HAS_OGG
|
||||
/* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
|
||||
if(is_ogg && 0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 1) {
|
||||
unsigned i;
|
||||
for(i = 1; i < encoder->protected_->num_metadata_blocks; i++) {
|
||||
if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
|
||||
FLAC__StreamMetadata *vc = encoder->protected_->metadata[i];
|
||||
for( ; i > 0; i--)
|
||||
encoder->protected_->metadata[i] = encoder->protected_->metadata[i-1];
|
||||
encoder->protected_->metadata[0] = vc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* keep track of any SEEKTABLE block */
|
||||
if(0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) {
|
||||
unsigned i;
|
||||
for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
|
||||
if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
|
||||
encoder->private_->seek_table = &encoder->protected_->metadata[i]->data.seek_table;
|
||||
break; /* take only the first one */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* validate metadata */
|
||||
if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
|
||||
@@ -894,6 +952,15 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__St
|
||||
/* set state to OK; from here on, errors are fatal and we'll override the state then */
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
|
||||
|
||||
#if FLAC__HAS_OGG
|
||||
encoder->private_->is_ogg = is_ogg;
|
||||
if(is_ogg && !FLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
encoder->private_->read_callback = read_callback;
|
||||
encoder->private_->write_callback = write_callback;
|
||||
encoder->private_->seek_callback = seek_callback;
|
||||
encoder->private_->tell_callback = tell_callback;
|
||||
@@ -1016,10 +1083,10 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__St
|
||||
* 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 is true it will have already
|
||||
* insured that the metadata list is properly ordered.)
|
||||
* WATCHOUT: the Ogg FLAC mapping requires us to write this block after
|
||||
* the STREAMINFO. (In the case that metadata_has_vorbis_comment is
|
||||
* true it will have already insured that the metadata list is properly
|
||||
* ordered.)
|
||||
*/
|
||||
if(!metadata_has_vorbis_comment) {
|
||||
FLAC__StreamMetadata vorbis_comment;
|
||||
@@ -1075,7 +1142,56 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__St
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_OK;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FLAC__StreamEncoderWriteCallback write_callback,
|
||||
FLAC__StreamEncoderSeekCallback seek_callback,
|
||||
FLAC__StreamEncoderTellCallback tell_callback,
|
||||
FLAC__StreamEncoderMetadataCallback metadata_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_stream_internal_(
|
||||
encoder,
|
||||
/*read_callback=*/0,
|
||||
write_callback,
|
||||
seek_callback,
|
||||
tell_callback,
|
||||
metadata_callback,
|
||||
client_data,
|
||||
/*is_ogg=*/false
|
||||
);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_stream(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FLAC__StreamEncoderReadCallback read_callback,
|
||||
FLAC__StreamEncoderWriteCallback write_callback,
|
||||
FLAC__StreamEncoderSeekCallback seek_callback,
|
||||
FLAC__StreamEncoderTellCallback tell_callback,
|
||||
FLAC__StreamEncoderMetadataCallback metadata_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_stream_internal_(
|
||||
encoder,
|
||||
read_callback,
|
||||
write_callback,
|
||||
seek_callback,
|
||||
tell_callback,
|
||||
metadata_callback,
|
||||
client_data,
|
||||
/*is_ogg=*/true
|
||||
);
|
||||
}
|
||||
|
||||
static FLAC__StreamEncoderInitStatus init_FILE_internal_(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FILE *file,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
FLAC__StreamEncoderInitStatus init_status;
|
||||
|
||||
@@ -1106,7 +1222,16 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__Stre
|
||||
encoder->private_->samples_written = 0;
|
||||
encoder->private_->frames_written = 0;
|
||||
|
||||
init_status = FLAC__stream_encoder_init_stream(encoder, file_write_callback_, file_seek_callback_, file_tell_callback_, /*metadata_callback=*/0, client_data);
|
||||
init_status = init_stream_internal_(
|
||||
encoder,
|
||||
is_ogg? file_read_callback_ : 0,
|
||||
file_write_callback_,
|
||||
file_seek_callback_,
|
||||
file_tell_callback_,
|
||||
/*metadata_callback=*/0,
|
||||
client_data,
|
||||
is_ogg
|
||||
);
|
||||
if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
|
||||
/* the above function sets the state for us in case of an error */
|
||||
return init_status;
|
||||
@@ -1121,8 +1246,34 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__Stre
|
||||
|
||||
return init_status;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FILE *file,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_FILE_internal_(encoder, file, progress_callback, client_data, /*is_ogg=*/false);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_FILE(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
FILE *file,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_FILE_internal_(encoder, file, progress_callback, client_data, /*is_ogg=*/true);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
|
||||
static FLAC__StreamEncoderInitStatus init_file_internal_(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
const char *filename,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data,
|
||||
FLAC__bool is_ogg
|
||||
)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
@@ -1143,7 +1294,27 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__Stre
|
||||
return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
|
||||
}
|
||||
|
||||
return FLAC__stream_encoder_init_FILE(encoder, file, progress_callback, client_data);
|
||||
return init_FILE_internal_(encoder, file, progress_callback, client_data, is_ogg);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
const char *filename,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_file_internal_(encoder, filename, progress_callback, client_data, /*is_ogg=*/false);
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_file(
|
||||
FLAC__StreamEncoder *encoder,
|
||||
const char *filename,
|
||||
FLAC__StreamEncoderProgressCallback progress_callback,
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
return init_file_internal_(encoder, filename, progress_callback, client_data, /*is_ogg=*/true);
|
||||
}
|
||||
|
||||
FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
|
||||
@@ -1165,8 +1336,14 @@ FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
|
||||
FLAC__MD5Final(encoder->private_->streaminfo.data.stream_info.md5sum, &encoder->private_->md5context);
|
||||
|
||||
if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
|
||||
if(encoder->private_->seek_callback)
|
||||
if(encoder->private_->seek_callback) {
|
||||
#if FLAC__HAS_OGG
|
||||
if(encoder->private_->is_ogg)
|
||||
update_ogg_metadata_(encoder);
|
||||
else
|
||||
#endif
|
||||
update_metadata_(encoder);
|
||||
}
|
||||
if(encoder->private_->metadata_callback)
|
||||
encoder->private_->metadata_callback(encoder, &encoder->private_->streaminfo, encoder->private_->client_data);
|
||||
}
|
||||
@@ -1180,15 +1357,39 @@ FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
|
||||
encoder->private_->file = 0;
|
||||
}
|
||||
|
||||
#if FLAC__HAS_OGG
|
||||
if(encoder->private_->is_ogg)
|
||||
FLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect);
|
||||
#endif
|
||||
|
||||
free_(encoder);
|
||||
set_defaults_(encoder);
|
||||
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_serial_number(FLAC__StreamEncoder *encoder, long value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
/* can't check encoder->private_->is_ogg since that's not set until init time */
|
||||
FLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value);
|
||||
return true;
|
||||
#else
|
||||
(void)value;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
#ifndef FLAC__MANDATORY_VERIFY_WHILE_ENCODING
|
||||
@@ -1200,6 +1401,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->streamable_subset = value;
|
||||
@@ -1209,6 +1412,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncod
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->do_mid_side_stereo = value;
|
||||
@@ -1218,6 +1423,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEnco
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->loose_mid_side_stereo = value;
|
||||
@@ -1227,6 +1434,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->channels = value;
|
||||
@@ -1236,6 +1445,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encod
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->bits_per_sample = value;
|
||||
@@ -1245,6 +1456,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->sample_rate = value;
|
||||
@@ -1254,6 +1467,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->blocksize = value;
|
||||
@@ -1263,6 +1478,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *enco
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
FLAC__ASSERT(0 != specification);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
@@ -1332,6 +1549,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->max_lpc_order = value;
|
||||
@@ -1341,6 +1560,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->qlp_coeff_precision = value;
|
||||
@@ -1350,6 +1571,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEnc
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->do_qlp_coeff_prec_search = value;
|
||||
@@ -1359,6 +1582,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__Stre
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
#if 0
|
||||
@@ -1373,6 +1598,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncode
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->do_exhaustive_model_search = value;
|
||||
@@ -1382,6 +1609,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__St
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->min_residual_partition_order = value;
|
||||
@@ -1391,6 +1620,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->max_residual_partition_order = value;
|
||||
@@ -1400,6 +1631,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
#if 0
|
||||
@@ -1414,6 +1647,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__St
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->total_samples_estimate = value;
|
||||
@@ -1423,19 +1658,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->protected_->metadata = metadata;
|
||||
encoder->protected_->num_metadata_blocks = num_blocks;
|
||||
if(0 != metadata && num_blocks > 0) {
|
||||
unsigned i;
|
||||
for(i = 0; i < num_blocks; i++) {
|
||||
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 FLAC__HAS_OGG
|
||||
if(!FLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1446,6 +1678,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->private_->disable_constant_subframes = value;
|
||||
@@ -1455,6 +1689,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__Stream
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->private_->disable_fixed_subframes = value;
|
||||
@@ -1464,6 +1700,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEnc
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->private_->disable_verbatim_subframes = value;
|
||||
@@ -1473,12 +1711,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__Stream
|
||||
FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->state;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->verify)
|
||||
return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder);
|
||||
else
|
||||
@@ -1487,6 +1729,9 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(
|
||||
|
||||
FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR)
|
||||
return FLAC__StreamEncoderStateString[encoder->protected_->state];
|
||||
else
|
||||
@@ -1496,6 +1741,8 @@ FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__
|
||||
FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
if(0 != absolute_sample)
|
||||
*absolute_sample = encoder->private_->verify.error_stats.absolute_sample;
|
||||
if(0 != frame_number)
|
||||
@@ -1513,102 +1760,136 @@ FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__St
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->verify;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->streamable_subset;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->do_mid_side_stereo;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->loose_mid_side_stereo;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->channels;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->bits_per_sample;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->sample_rate;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->blocksize;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->max_lpc_order;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->qlp_coeff_precision;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->do_qlp_coeff_prec_search;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->do_escape_coding;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->do_exhaustive_model_search;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->min_residual_partition_order;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->max_residual_partition_order;
|
||||
}
|
||||
|
||||
FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->rice_parameter_search_dist;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
return encoder->protected_->total_samples_estimate;
|
||||
}
|
||||
|
||||
@@ -1619,6 +1900,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c
|
||||
const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
|
||||
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
|
||||
|
||||
j = 0;
|
||||
@@ -1749,6 +2032,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder
|
||||
const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize;
|
||||
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
|
||||
|
||||
j = k = 0;
|
||||
@@ -1915,12 +2200,20 @@ void set_defaults_(FLAC__StreamEncoder *encoder)
|
||||
encoder->private_->disable_constant_subframes = false;
|
||||
encoder->private_->disable_fixed_subframes = false;
|
||||
encoder->private_->disable_verbatim_subframes = false;
|
||||
#if FLAC__HAS_OGG
|
||||
encoder->private_->is_ogg = false;
|
||||
#endif
|
||||
encoder->private_->read_callback = 0;
|
||||
encoder->private_->write_callback = 0;
|
||||
encoder->private_->seek_callback = 0;
|
||||
encoder->private_->tell_callback = 0;
|
||||
encoder->private_->metadata_callback = 0;
|
||||
encoder->private_->progress_callback = 0;
|
||||
encoder->private_->client_data = 0;
|
||||
|
||||
#if FLAC__HAS_OGG
|
||||
FLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect);
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_(FLAC__StreamEncoder *encoder)
|
||||
@@ -2173,7 +2466,7 @@ FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples)
|
||||
FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples)
|
||||
{
|
||||
FLAC__StreamEncoderWriteStatus status;
|
||||
FLAC__uint64 output_position = 0;
|
||||
@@ -2229,6 +2522,22 @@ FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder,
|
||||
}
|
||||
}
|
||||
|
||||
#if FLAC__HAS_OGG
|
||||
if(encoder->private_->is_ogg) {
|
||||
status = FLAC__ogg_encoder_aspect_write_callback_wrapper(
|
||||
&encoder->protected_->ogg_encoder_aspect,
|
||||
FLAC__stream_encoder_get_total_samples_estimate(encoder),
|
||||
buffer,
|
||||
bytes,
|
||||
samples,
|
||||
encoder->private_->current_frame_number,
|
||||
(FLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback,
|
||||
encoder,
|
||||
encoder->private_->client_data
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
status = encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data);
|
||||
|
||||
if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
@@ -2401,6 +2710,181 @@ void update_metadata_(const FLAC__StreamEncoder *encoder)
|
||||
}
|
||||
}
|
||||
|
||||
/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */
|
||||
void update_ogg_metadata_(FLAC__StreamEncoder *encoder)
|
||||
{
|
||||
FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
|
||||
const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo;
|
||||
const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
|
||||
const unsigned min_framesize = metadata->data.stream_info.min_framesize;
|
||||
const unsigned max_framesize = metadata->data.stream_info.max_framesize;
|
||||
ogg_page page;
|
||||
|
||||
FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
|
||||
|
||||
/* All this is based on intimate knowledge of the stream header
|
||||
* layout, but a change to the header format that would break this
|
||||
* would also break all streams encoded in the previous format.
|
||||
*/
|
||||
|
||||
/**
|
||||
** Write STREAMINFO stats
|
||||
**/
|
||||
simple_ogg_page__init(&page);
|
||||
if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
|
||||
simple_ogg_page__clear(&page);
|
||||
return; /* state already set */
|
||||
}
|
||||
|
||||
/*
|
||||
* Write MD5 signature
|
||||
*/
|
||||
{
|
||||
const unsigned md5_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
|
||||
) / 8;
|
||||
|
||||
if(md5_offset + 16 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
simple_ogg_page__clear(&page);
|
||||
return;
|
||||
}
|
||||
memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write total samples
|
||||
*/
|
||||
{
|
||||
const unsigned total_samples_byte_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
|
||||
- 4
|
||||
) / 8;
|
||||
|
||||
if(total_samples_byte_offset + 5 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
simple_ogg_page__clear(&page);
|
||||
return;
|
||||
}
|
||||
b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0;
|
||||
b[0] |= (FLAC__byte)((samples >> 32) & 0x0F);
|
||||
b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
|
||||
b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
|
||||
b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
|
||||
b[4] = (FLAC__byte)(samples & 0xFF);
|
||||
memcpy(page.body + total_samples_byte_offset, b, 5);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write min/max framesize
|
||||
*/
|
||||
{
|
||||
const unsigned min_framesize_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
|
||||
) / 8;
|
||||
|
||||
if(min_framesize_offset + 6 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
simple_ogg_page__clear(&page);
|
||||
return;
|
||||
}
|
||||
b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
|
||||
b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
|
||||
b[2] = (FLAC__byte)(min_framesize & 0xFF);
|
||||
b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
|
||||
b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
|
||||
b[5] = (FLAC__byte)(max_framesize & 0xFF);
|
||||
memcpy(page.body + min_framesize_offset, b, 6);
|
||||
}
|
||||
if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
|
||||
simple_ogg_page__clear(&page);
|
||||
return; /* state already set */
|
||||
}
|
||||
simple_ogg_page__clear(&page);
|
||||
|
||||
/*
|
||||
* Write seektable
|
||||
*/
|
||||
if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
|
||||
unsigned i;
|
||||
FLAC__byte *p;
|
||||
|
||||
FLAC__format_seektable_sort(encoder->private_->seek_table);
|
||||
|
||||
FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
|
||||
|
||||
simple_ogg_page__init(&page);
|
||||
if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
|
||||
simple_ogg_page__clear(&page);
|
||||
return; /* state already set */
|
||||
}
|
||||
|
||||
if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
simple_ogg_page__clear(&page);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) {
|
||||
FLAC__uint64 xx;
|
||||
unsigned x;
|
||||
xx = encoder->private_->seek_table->points[i].sample_number;
|
||||
b[7] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[6] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[5] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[4] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[3] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[2] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[1] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[0] = (FLAC__byte)xx; xx >>= 8;
|
||||
xx = encoder->private_->seek_table->points[i].stream_offset;
|
||||
b[15] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[14] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[13] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[12] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[11] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[10] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[9] = (FLAC__byte)xx; xx >>= 8;
|
||||
b[8] = (FLAC__byte)xx; xx >>= 8;
|
||||
x = encoder->private_->seek_table->points[i].frame_samples;
|
||||
b[17] = (FLAC__byte)x; x >>= 8;
|
||||
b[16] = (FLAC__byte)x; x >>= 8;
|
||||
if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
simple_ogg_page__clear(&page);
|
||||
return;
|
||||
}
|
||||
memcpy(p, b, 18);
|
||||
}
|
||||
|
||||
if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
|
||||
simple_ogg_page__clear(&page);
|
||||
return; /* state already set */
|
||||
}
|
||||
simple_ogg_page__clear(&page);
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
|
||||
{
|
||||
FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
|
||||
@@ -3908,6 +4392,20 @@ void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDeco
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
|
||||
}
|
||||
|
||||
FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
|
||||
*bytes = (unsigned)fread(buffer, 1, *bytes, encoder->private_->file);
|
||||
if (*bytes == 0) {
|
||||
if (feof(encoder->private_->file))
|
||||
return FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
|
||||
else if (ferror(encoder->private_->file))
|
||||
return FLAC__STREAM_ENCODER_READ_STATUS_ABORT;
|
||||
}
|
||||
return FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
@@ -3952,7 +4450,19 @@ FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *e
|
||||
(void)client_data, (void)current_frame;
|
||||
|
||||
if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) {
|
||||
if(0 != encoder->private_->progress_callback && samples > 0) {
|
||||
FLAC__bool call_it = 0 != encoder->private_->progress_callback && (
|
||||
#if FLAC__HAS_OGG
|
||||
/* We would like to be able to use 'samples > 0' in the
|
||||
* clause here but currently because of the nature of our
|
||||
* Ogg writing implementation, 'samples' is always 0 (see
|
||||
* ogg_encoder_aspect.c). The downside is extra progress
|
||||
* callbacks.
|
||||
*/
|
||||
encoder->private_->is_ogg? true :
|
||||
#endif
|
||||
samples > 0
|
||||
);
|
||||
if(call_it) {
|
||||
/* NOTE: We have to add +bytes, +samples, and +1 to the stats
|
||||
* because at this point in the callback chain, the stats
|
||||
* have not been updated. Only after we return and control
|
||||
|
||||
Reference in New Issue
Block a user