mirror of https://github.com/xiph/flac
revamp OggFLAC__SeekableStreamDecoder to derive from OggFLAC__StreamDecoder instead of FLAC__SeekableStreamDecoder; rewrite seek routine to do a binary search through Ogg pages, instead of the seektable-based search of FLAC__SeekableStreamDecoder
This commit is contained in:
parent
6ebbabfd34
commit
63f8edc69c
|
@ -209,7 +209,7 @@ namespace OggFLAC {
|
|||
bool set_metadata_ignore_all();
|
||||
|
||||
State get_state() const;
|
||||
FLAC::Decoder::SeekableStream::State get_FLAC_seekable_stream_decoder_state() const;
|
||||
OggFLAC::Decoder::Stream::State get_stream_decoder_state() const;
|
||||
FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const;
|
||||
bool get_md5_checking() const;
|
||||
unsigned get_channels() const;
|
||||
|
@ -231,10 +231,10 @@ namespace OggFLAC {
|
|||
|
||||
bool seek_absolute(FLAC__uint64 sample);
|
||||
protected:
|
||||
virtual ::FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
|
||||
virtual ::FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0;
|
||||
virtual ::FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0;
|
||||
virtual ::FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) = 0;
|
||||
virtual ::OggFLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
|
||||
virtual ::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0;
|
||||
virtual ::OggFLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0;
|
||||
virtual ::OggFLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) = 0;
|
||||
virtual bool eof_callback() = 0;
|
||||
virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
|
||||
virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
|
||||
|
@ -246,10 +246,10 @@ namespace OggFLAC {
|
|||
#endif
|
||||
::OggFLAC__SeekableStreamDecoder *decoder_;
|
||||
private:
|
||||
static ::FLAC__SeekableStreamDecoderReadStatus read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static ::FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static ::FLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static ::FLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
static ::OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static ::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static ::OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static ::OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
static FLAC__bool eof_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
|
||||
static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
|
||||
static void metadata_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
|
||||
|
@ -311,7 +311,7 @@ namespace OggFLAC {
|
|||
|
||||
State get_state() const;
|
||||
OggFLAC::Decoder::SeekableStream::State get_seekable_stream_decoder_state() const;
|
||||
FLAC::Decoder::SeekableStream::State get_FLAC_seekable_stream_decoder_state() const;
|
||||
OggFLAC::Decoder::Stream::State get_stream_decoder_state() const;
|
||||
FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const;
|
||||
bool get_md5_checking() const;
|
||||
unsigned get_channels() const;
|
||||
|
|
|
@ -118,7 +118,7 @@ extern OggFLAC_API const char * const OggFLAC__FileDecoderStateString[];
|
|||
|
||||
/***********************************************************************
|
||||
*
|
||||
* class OggFLAC__FileDecoder : public FLAC__FileDecoder
|
||||
* class OggFLAC__FileDecoder : public OggFLAC__SeekableStreamDecoder
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
@ -421,27 +421,27 @@ OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_get_state(const OggF
|
|||
*/
|
||||
OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder);
|
||||
|
||||
/** Get the state of the underlying FLAC seekable stream decoder.
|
||||
/** Get the state of the underlying stream decoder.
|
||||
* Useful when the file decoder state is
|
||||
* \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR
|
||||
* and the seekable stream decoder state is
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR.
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval FLAC__SeekableStreamDecoderState
|
||||
* The FLAC seekable stream decoder state.
|
||||
* \retval OggFLAC__StreamDecoderState
|
||||
* The stream decoder state.
|
||||
*/
|
||||
OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder);
|
||||
OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__file_decoder_get_stream_decoder_state(const OggFLAC__FileDecoder *decoder);
|
||||
|
||||
/** Get the state of the underlying FLAC stream decoder.
|
||||
* Useful when the file decoder state is
|
||||
* \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR
|
||||
* and the seekable stream decoder state is
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR
|
||||
* and the * FLAC seekable stream decoder state is
|
||||
* \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
|
||||
* and the stream decoder state is
|
||||
* \c OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR.
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
|
@ -530,6 +530,8 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_sample_rate(const OggFLAC__FileDe
|
|||
*/
|
||||
OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDecoder *decoder);
|
||||
|
||||
#if 0
|
||||
@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release
|
||||
/** This is inherited from FLAC__FileDecoder; see
|
||||
* FLAC__file_decoder_get_decode_position().
|
||||
*
|
||||
|
@ -543,6 +545,7 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDeco
|
|||
* the 'tell' callback.
|
||||
*/
|
||||
OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_decode_position(const OggFLAC__FileDecoder *decoder, FLAC__uint64 *position);
|
||||
#endif
|
||||
|
||||
/** Initialize the decoder instance.
|
||||
* Should be called after OggFLAC__file_decoder_new() and
|
||||
|
@ -614,8 +617,8 @@ OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_metadata(OggFL
|
|||
*/
|
||||
OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_file(OggFLAC__FileDecoder *decoder);
|
||||
|
||||
/** This is inherited from FLAC__FileDecoder; see
|
||||
* FLAC__file_decoder_seek_absolute().
|
||||
/** This is inherited from OggFLAC__SeekableStreamDecoder; see
|
||||
* OggFLAC__seekable_stream_decoder_seek_absolute().
|
||||
*
|
||||
* \param decoder A decoder instance.
|
||||
* \param sample The target sample number to seek to.
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
#define OggFLAC__SEEKABLE_STREAM_DECODER_H
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "FLAC/seekable_stream_decoder.h"
|
||||
#include "stream_decoder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -77,22 +76,27 @@ typedef enum {
|
|||
OggFLAC__SEEKABLE_STREAM_DECODER_OK = 0,
|
||||
/**< The decoder is in the normal OK state. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING,
|
||||
/**< The decoder is in the process of seeking. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM,
|
||||
/**< The decoder has reached the end of the stream. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR,
|
||||
/**< An error occurred in the underlying Ogg layer. */
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
/**< Memory allocation failed. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR,
|
||||
/**< An error occurred in the underlying FLAC seekable stream decoder;
|
||||
* check OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state().
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR,
|
||||
/**< An error occurred in the underlying stream decoder;
|
||||
* check OggFLAC__seekable_stream_decoder_get_stream_decoder_state().
|
||||
*/
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR,
|
||||
/**< The read callback returned an error. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
/**< Memory allocation failed. */
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR,
|
||||
/**< An error occurred while seeking or the seek or tell
|
||||
* callback returned an error.
|
||||
*/
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED,
|
||||
/**< OggFLAC__seekable_stream_decoder_init() was called when the decoder was
|
||||
|
@ -116,6 +120,86 @@ typedef enum {
|
|||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[];
|
||||
|
||||
|
||||
/** Return values for the OggFLAC__SeekableStreamDecoder read callback.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK,
|
||||
/**< The read was OK and decoding can continue. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
|
||||
/**< An unrecoverable error occurred. The decoder will return from the process call. */
|
||||
|
||||
} OggFLAC__SeekableStreamDecoderReadStatus;
|
||||
|
||||
/** Maps a OggFLAC__SeekableStreamDecoderReadStatus to a C string.
|
||||
*
|
||||
* Using a OggFLAC__SeekableStreamDecoderReadStatus as the index to this array
|
||||
* will give the string equivalent. The contents should not be modified.
|
||||
*/
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[];
|
||||
|
||||
|
||||
/** Return values for the OggFLAC__SeekableStreamDecoder seek callback.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK,
|
||||
/**< The seek was OK and decoding can continue. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
|
||||
/**< An unrecoverable error occurred. The decoder will return from the process call. */
|
||||
|
||||
} OggFLAC__SeekableStreamDecoderSeekStatus;
|
||||
|
||||
/** Maps a OggFLAC__SeekableStreamDecoderSeekStatus to a C string.
|
||||
*
|
||||
* Using a OggFLAC__SeekableStreamDecoderSeekStatus as the index to this array
|
||||
* will give the string equivalent. The contents should not be modified.
|
||||
*/
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[];
|
||||
|
||||
|
||||
/** Return values for the OggFLAC__SeekableStreamDecoder tell callback.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK,
|
||||
/**< The tell was OK and decoding can continue. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
|
||||
/**< An unrecoverable error occurred. The decoder will return from the process call. */
|
||||
|
||||
} OggFLAC__SeekableStreamDecoderTellStatus;
|
||||
|
||||
/** Maps a OggFLAC__SeekableStreamDecoderTellStatus to a C string.
|
||||
*
|
||||
* Using a OggFLAC__SeekableStreamDecoderTellStatus as the index to this array
|
||||
* will give the string equivalent. The contents should not be modified.
|
||||
*/
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[];
|
||||
|
||||
|
||||
/** Return values for the OggFLAC__SeekableStreamDecoder length callback.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK,
|
||||
/**< The length call was OK and decoding can continue. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
|
||||
/**< An unrecoverable error occurred. The decoder will return from the process call. */
|
||||
|
||||
} OggFLAC__SeekableStreamDecoderLengthStatus;
|
||||
|
||||
/** Maps a OggFLAC__SeekableStreamDecoderLengthStatus to a C string.
|
||||
*
|
||||
* Using a OggFLAC__SeekableStreamDecoderLengthStatus as the index to this array
|
||||
* will give the string equivalent. The contents should not be modified.
|
||||
*/
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[];
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* class OggFLAC__SeekableStreamDecoder : public FLAC__StreamDecoder
|
||||
|
@ -147,7 +231,7 @@ typedef struct {
|
|||
* \retval FLAC__SeekableStreamDecoderReadStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef FLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderReadCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
typedef OggFLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderReadCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
|
||||
/** Signature for the seek callback.
|
||||
* See OggFLAC__seekable_stream_decoder_set_seek_callback() for more info.
|
||||
|
@ -160,7 +244,7 @@ typedef FLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderRe
|
|||
* \retval FLAC__SeekableStreamDecoderSeekStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef FLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSeekCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
typedef OggFLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSeekCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
|
||||
/** Signature for the tell callback.
|
||||
* See OggFLAC__seekable_stream_decoder_set_tell_callback() for more info.
|
||||
|
@ -173,7 +257,7 @@ typedef FLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSe
|
|||
* \retval FLAC__SeekableStreamDecoderTellStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef FLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTellCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
typedef OggFLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTellCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
|
||||
/** Signature for the length callback.
|
||||
* See OggFLAC__seekable_stream_decoder_set_length_callback() for more info.
|
||||
|
@ -186,7 +270,7 @@ typedef FLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTe
|
|||
* \retval FLAC__SeekableStreamDecoderLengthStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef FLAC__SeekableStreamDecoderLengthStatus (*OggFLAC__SeekableStreamDecoderLengthCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
typedef OggFLAC__SeekableStreamDecoderLengthStatus (*OggFLAC__SeekableStreamDecoderLengthCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
|
||||
/** Signature for the EOF callback.
|
||||
* See OggFLAC__seekable_stream_decoder_set_eof_callback() for more info.
|
||||
|
@ -550,22 +634,22 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(
|
|||
*/
|
||||
OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder);
|
||||
|
||||
/** Get the state of the underlying FLAC seekable stream decoder.
|
||||
/** Get the state of the underlying stream decoder.
|
||||
* Useful when the seekable stream decoder state is
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR.
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
* \code decoder != NULL \endcode
|
||||
* \retval FLAC__SeekableStreamDecoderState
|
||||
* The FLAC seekable stream decoder state.
|
||||
* \retval OggFLAC__StreamDecoderState
|
||||
* The stream decoder state.
|
||||
*/
|
||||
OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder);
|
||||
OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder);
|
||||
|
||||
/** Get the state of the underlying FLAC seekable stream decoder's stream decoder.
|
||||
/** Get the state of the underlying stream decoder's FLAC stream decoder.
|
||||
* Useful when the seekable stream decoder state is
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR and the
|
||||
* FLAC seekable stream decoder state is \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR and the
|
||||
* stream decoder state is \c OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
|
@ -577,8 +661,8 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_s
|
|||
|
||||
/** Get the current decoder state as a C string.
|
||||
* This version automatically resolves
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR
|
||||
* by getting the FLAC seekable stream decoder's state.
|
||||
* \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
|
||||
* by getting the stream decoder's state.
|
||||
*
|
||||
* \param decoder A decoder instance to query.
|
||||
* \assert
|
||||
|
@ -654,6 +738,8 @@ OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggF
|
|||
*/
|
||||
OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder);
|
||||
|
||||
#if 0
|
||||
@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release
|
||||
/** Returns the decoder's current read position within the stream.
|
||||
* This is inherited from FLAC__SeekableStreamDecoder; see
|
||||
* FLAC__seekable_stream_decoder_get_decode_position().
|
||||
|
@ -667,7 +753,9 @@ OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLA
|
|||
* \c true if successful, \c false if there was an error from
|
||||
* the 'tell' callback.
|
||||
*/
|
||||
/*@@@@@@ probably does not work... is it used? */
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_decode_position(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position);
|
||||
#endif
|
||||
|
||||
/** Initialize the decoder instance.
|
||||
* Should be called after OggFLAC__seekable_stream_decoder_new() and
|
||||
|
|
|
@ -123,10 +123,10 @@ namespace OggFLAC {
|
|||
return OggFLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder_));
|
||||
}
|
||||
|
||||
FLAC::Decoder::SeekableStream::State File::get_FLAC_seekable_stream_decoder_state() const
|
||||
OggFLAC::Decoder::Stream::State File::get_stream_decoder_state() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return FLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder_));
|
||||
return OggFLAC::Decoder::Stream::State(::OggFLAC__file_decoder_get_stream_decoder_state(decoder_));
|
||||
}
|
||||
|
||||
FLAC::Decoder::Stream::State File::get_FLAC_stream_decoder_state() const
|
||||
|
|
|
@ -111,10 +111,10 @@ namespace OggFLAC {
|
|||
return State(::OggFLAC__seekable_stream_decoder_get_state(decoder_));
|
||||
}
|
||||
|
||||
FLAC::Decoder::SeekableStream::State SeekableStream::get_FLAC_seekable_stream_decoder_state() const
|
||||
OggFLAC::Decoder::Stream::State SeekableStream::get_stream_decoder_state() const
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
return FLAC::Decoder::SeekableStream::State(::OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder_));
|
||||
return OggFLAC::Decoder::Stream::State(::OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder_));
|
||||
}
|
||||
|
||||
FLAC::Decoder::Stream::State SeekableStream::get_FLAC_stream_decoder_state() const
|
||||
|
@ -216,7 +216,7 @@ namespace OggFLAC {
|
|||
return (bool)::OggFLAC__seekable_stream_decoder_seek_absolute(decoder_, sample);
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
::OggFLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void) decoder;
|
||||
FLAC__ASSERT(0 != client_data);
|
||||
|
@ -225,7 +225,7 @@ namespace OggFLAC {
|
|||
return instance->read_callback(buffer, bytes);
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
(void) decoder;
|
||||
FLAC__ASSERT(0 != client_data);
|
||||
|
@ -234,7 +234,7 @@ namespace OggFLAC {
|
|||
return instance->seek_callback(absolute_byte_offset);
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
::OggFLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
{
|
||||
(void) decoder;
|
||||
FLAC__ASSERT(0 != client_data);
|
||||
|
@ -243,7 +243,7 @@ namespace OggFLAC {
|
|||
return instance->tell_callback(absolute_byte_offset);
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
{
|
||||
(void) decoder;
|
||||
FLAC__ASSERT(0 != client_data);
|
||||
|
|
|
@ -52,10 +52,10 @@
|
|||
|
||||
static void set_defaults_(OggFLAC__FileDecoder *decoder);
|
||||
static FILE *get_binary_stdin_();
|
||||
static FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
static OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
static FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
|
||||
static void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
|
@ -392,11 +392,11 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekab
|
|||
return OggFLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
|
||||
OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__file_decoder_get_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder->private_->seekable_stream_decoder);
|
||||
return OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->seekable_stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_decoder_get_FLAC_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
|
||||
|
@ -456,12 +456,15 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDeco
|
|||
return OggFLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release
|
||||
OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_decode_position(const OggFLAC__FileDecoder *decoder, FLAC__uint64 *position)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return OggFLAC__seekable_stream_decoder_get_decode_position(decoder->private_->seekable_stream_decoder, position);
|
||||
}
|
||||
#endif
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_single(OggFLAC__FileDecoder *decoder)
|
||||
{
|
||||
|
@ -581,7 +584,7 @@ FILE *get_binary_stdin_()
|
|||
return stdin;
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
@ -589,52 +592,52 @@ FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStre
|
|||
if(*bytes > 0) {
|
||||
*bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
|
||||
if(ferror(file_decoder->private_->file)) {
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
}
|
||||
else {
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(fseek(file_decoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
else
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
{
|
||||
OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
|
||||
long pos;
|
||||
(void)decoder;
|
||||
|
||||
if((pos = ftell(file_decoder->private_->file)) < 0)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
else {
|
||||
*absolute_byte_offset = (FLAC__uint64)pos;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
{
|
||||
OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
|
||||
struct stat filestats;
|
||||
(void)decoder;
|
||||
|
||||
if(0 == file_decoder->private_->filename || stat(file_decoder->private_->filename, &filestats) != 0)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
else {
|
||||
*stream_length = (FLAC__uint64)filestats.st_size;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "private/ogg_decoder_aspect.h"
|
||||
|
||||
typedef struct OggFLAC__SeekableStreamDecoderProtected {
|
||||
FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
|
||||
OggFLAC__SeekableStreamDecoderState state;
|
||||
OggFLAC__OggDecoderAspect ogg_decoder_aspect;
|
||||
} OggFLAC__SeekableStreamDecoderProtected;
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for calloc() */
|
||||
#include <string.h> /* for memcpy()/memcmp() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "protected/seekable_stream_decoder.h"
|
||||
#include "protected/stream_decoder.h"
|
||||
#include "../libFLAC/include/private/md5.h" /* @@@@@@ ugly hack, but how else to do? we need to reuse the md5 code but don't want to expose it */
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
|
@ -40,16 +44,11 @@
|
|||
***********************************************************************/
|
||||
|
||||
static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
|
||||
static FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
|
||||
static FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
|
||||
static void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
|
||||
static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
|
||||
static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
|
@ -67,7 +66,19 @@ typedef struct OggFLAC__SeekableStreamDecoderPrivate {
|
|||
OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
|
||||
OggFLAC__SeekableStreamDecoderErrorCallback error_callback;
|
||||
void *client_data;
|
||||
FLAC__SeekableStreamDecoder *FLAC_seekable_stream_decoder;
|
||||
OggFLAC__StreamDecoder *stream_decoder;
|
||||
FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
|
||||
struct MD5Context md5context;
|
||||
FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
|
||||
FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
|
||||
/* the rest of these are only used for seeking: */
|
||||
FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
|
||||
const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
|
||||
/* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */
|
||||
FLAC__bool ignore_stream_info_block;
|
||||
FLAC__bool ignore_seek_table_block;
|
||||
FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
|
||||
FLAC__uint64 target_sample;
|
||||
} OggFLAC__SeekableStreamDecoderPrivate;
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -78,26 +89,50 @@ typedef struct OggFLAC__SeekableStreamDecoderPrivate {
|
|||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_OK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
|
||||
};
|
||||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
|
||||
};
|
||||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
|
||||
};
|
||||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
|
||||
};
|
||||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
|
||||
"OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Class constructor/destructor
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new()
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder;
|
||||
|
||||
FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
|
||||
|
||||
decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder));
|
||||
if(decoder == 0) {
|
||||
return 0;
|
||||
|
@ -116,8 +151,8 @@ OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new
|
|||
return 0;
|
||||
}
|
||||
|
||||
decoder->private_->FLAC_seekable_stream_decoder = FLAC__seekable_stream_decoder_new();
|
||||
if(0 == decoder->private_->FLAC_seekable_stream_decoder) {
|
||||
decoder->private_->stream_decoder = OggFLAC__stream_decoder_new();
|
||||
if(0 == decoder->private_->stream_decoder) {
|
||||
free(decoder->private_);
|
||||
free(decoder->protected_);
|
||||
free(decoder);
|
||||
|
@ -136,11 +171,11 @@ OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStream
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->private_->FLAC_seekable_stream_decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
|
||||
OggFLAC__seekable_stream_decoder_finish(decoder);
|
||||
(void)OggFLAC__seekable_stream_decoder_finish(decoder);
|
||||
|
||||
FLAC__seekable_stream_decoder_delete(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder);
|
||||
|
||||
free(decoder->private_);
|
||||
free(decoder->protected_);
|
||||
|
@ -160,31 +195,46 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder
|
|||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
|
||||
|
||||
if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
|
||||
if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
|
||||
|
||||
if(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR;
|
||||
if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
|
||||
|
||||
FLAC__seekable_stream_decoder_set_read_callback(decoder->private_->FLAC_seekable_stream_decoder, read_callback_);
|
||||
FLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->FLAC_seekable_stream_decoder, seek_callback_);
|
||||
FLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->FLAC_seekable_stream_decoder, tell_callback_);
|
||||
FLAC__seekable_stream_decoder_set_length_callback(decoder->private_->FLAC_seekable_stream_decoder, length_callback_);
|
||||
FLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->FLAC_seekable_stream_decoder, eof_callback_);
|
||||
FLAC__seekable_stream_decoder_set_write_callback(decoder->private_->FLAC_seekable_stream_decoder, write_callback_);
|
||||
FLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->FLAC_seekable_stream_decoder, metadata_callback_);
|
||||
FLAC__seekable_stream_decoder_set_error_callback(decoder->private_->FLAC_seekable_stream_decoder, error_callback_);
|
||||
FLAC__seekable_stream_decoder_set_client_data(decoder->private_->FLAC_seekable_stream_decoder, decoder);
|
||||
decoder->private_->seek_table = 0;
|
||||
|
||||
if(FLAC__seekable_stream_decoder_init(decoder->private_->FLAC_seekable_stream_decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
|
||||
|
||||
/* We initialize the MD5Context even though we may never use it. This is
|
||||
* because md5 checking may be turned on to start and then turned off if a
|
||||
* seek occurs. So we always init the context here and finalize it in
|
||||
* OggFLAC__seekable_stream_decoder_finish() to make sure things are always
|
||||
* cleaned up properly.
|
||||
*/
|
||||
MD5Init(&decoder->private_->md5context);
|
||||
|
||||
OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
|
||||
OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
|
||||
OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
|
||||
OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
|
||||
OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
|
||||
|
||||
/* We always want to see these blocks. Whether or not we pass them up
|
||||
* through the metadata callback will be determined by flags set in our
|
||||
* implementation of ..._set_metadata_respond/ignore...()
|
||||
*/
|
||||
OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
|
||||
OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
|
||||
if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
|
||||
return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__bool ok;
|
||||
FLAC__bool md5_failed = false;
|
||||
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
|
@ -193,27 +243,35 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__Seekable
|
|||
if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return true;
|
||||
|
||||
FLAC__ASSERT(0 != decoder->private_->FLAC_seekable_stream_decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
|
||||
ok = FLAC__seekable_stream_decoder_finish(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
/* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we
|
||||
* always call MD5Final()
|
||||
*/
|
||||
MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
|
||||
|
||||
OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect);
|
||||
OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder);
|
||||
|
||||
if(decoder->private_->do_md5_checking) {
|
||||
if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
|
||||
md5_failed = true;
|
||||
}
|
||||
|
||||
set_defaults_(decoder);
|
||||
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
|
||||
|
||||
return ok;
|
||||
return !md5_failed;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->FLAC_seekable_stream_decoder, value);
|
||||
decoder->protected_->md5_checking = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value)
|
||||
|
@ -331,9 +389,14 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(Ogg
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->FLAC_seekable_stream_decoder, type);
|
||||
if(type == FLAC__METADATA_TYPE_STREAMINFO)
|
||||
decoder->private_->ignore_stream_info_block = false;
|
||||
else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
|
||||
decoder->private_->ignore_seek_table_block = false;
|
||||
return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
|
||||
|
@ -341,9 +404,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_app
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->FLAC_seekable_stream_decoder, id);
|
||||
return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder)
|
||||
|
@ -351,9 +415,12 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
decoder->private_->ignore_stream_info_block = false;
|
||||
decoder->private_->ignore_seek_table_block = false;
|
||||
return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
|
||||
|
@ -361,9 +428,19 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggF
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->FLAC_seekable_stream_decoder, type);
|
||||
if(type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
decoder->private_->ignore_stream_info_block = true;
|
||||
return true;
|
||||
}
|
||||
else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
|
||||
decoder->private_->ignore_seek_table_block = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
|
||||
|
@ -371,9 +448,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_appl
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->FLAC_seekable_stream_decoder, id);
|
||||
return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder)
|
||||
|
@ -381,9 +459,15 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(
|
|||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
FLAC__ASSERT(0 != decoder->private_->stream_decoder);
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
|
||||
return false;
|
||||
return FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
decoder->private_->ignore_stream_info_block = true;
|
||||
decoder->private_->ignore_seek_table_block = true;
|
||||
return
|
||||
OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
|
||||
OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
|
||||
OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
}
|
||||
|
||||
OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
|
@ -393,76 +477,85 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder
|
|||
return decoder->protected_->state;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR)
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
|
||||
return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
|
||||
else
|
||||
return FLAC__seekable_stream_decoder_get_resolved_state_string(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
return decoder->protected_->md5_checking;
|
||||
}
|
||||
|
||||
OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_channels(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_blocksize(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_decode_position(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position)
|
||||
{
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(0 != decoder->private_);
|
||||
return FLAC__seekable_stream_decoder_get_decode_position(decoder->private_->FLAC_seekable_stream_decoder, position);
|
||||
FLAC__ASSERT(0 != position);
|
||||
|
||||
if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK)
|
||||
return false;
|
||||
FLAC__ASSERT(*position >= OggFLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder));
|
||||
*position -= OggFLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder)
|
||||
{
|
||||
|
@ -470,10 +563,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableS
|
|||
FLAC__ASSERT(0 != decoder->private_);
|
||||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
|
||||
OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
|
||||
decoder->private_->do_md5_checking = false;
|
||||
|
||||
if(!FLAC__seekable_stream_decoder_flush(decoder->private_->FLAC_seekable_stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -489,15 +582,27 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableS
|
|||
FLAC__ASSERT(0 != decoder->protected_);
|
||||
|
||||
if(!OggFLAC__seekable_stream_decoder_flush(decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!FLAC__seekable_stream_decoder_reset(decoder->private_->FLAC_seekable_stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
decoder->private_->seek_table = 0;
|
||||
|
||||
decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
|
||||
|
||||
/* We initialize the MD5Context even though we may never use it. This is
|
||||
* because md5 checking may be turned on to start and then turned off if a
|
||||
* seek occurs. So we always init the context here and finalize it in
|
||||
* OggFLAC__seekable_stream_decoder_finish() to make sure things are always
|
||||
* cleaned up properly.
|
||||
*/
|
||||
MD5Init(&decoder->private_->md5context);
|
||||
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
|
||||
|
||||
return true;
|
||||
|
@ -508,7 +613,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__
|
|||
FLAC__bool ret;
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
|
||||
if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
|
||||
if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
|
@ -516,9 +621,9 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__
|
|||
|
||||
FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
|
||||
|
||||
ret = FLAC__seekable_stream_decoder_process_single(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
|
||||
if(!ret)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -528,7 +633,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_met
|
|||
FLAC__bool ret;
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
|
||||
if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
|
||||
if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
|
@ -536,9 +641,9 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_met
|
|||
|
||||
FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
|
||||
|
||||
ret = FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
|
||||
if(!ret)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -548,7 +653,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_str
|
|||
FLAC__bool ret;
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
|
||||
if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
|
||||
if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
|
||||
|
@ -556,28 +661,50 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_str
|
|||
|
||||
FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
|
||||
|
||||
ret = FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->FLAC_seekable_stream_decoder);
|
||||
ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
|
||||
if(!ret)
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
|
||||
{
|
||||
FLAC__uint64 length;
|
||||
|
||||
FLAC__ASSERT(0 != decoder);
|
||||
FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
|
||||
|
||||
if(!FLAC__seekable_stream_decoder_seek_absolute(decoder->private_->FLAC_seekable_stream_decoder, sample)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;
|
||||
|
||||
/* turn off md5 checking if a seek is attempted */
|
||||
decoder->private_->do_md5_checking = false;
|
||||
|
||||
if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
|
||||
return true;
|
||||
/* get the file length */
|
||||
if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
/* rewind */
|
||||
if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return seek_to_absolute_sample_(decoder, length, sample);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
|
@ -596,108 +723,207 @@ void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder)
|
|||
decoder->private_->metadata_callback = 0;
|
||||
decoder->private_->error_callback = 0;
|
||||
decoder->private_->client_data = 0;
|
||||
OggFLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect);
|
||||
/* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
|
||||
decoder->private_->ignore_stream_info_block = false;
|
||||
decoder->private_->ignore_seek_table_block = true;
|
||||
|
||||
decoder->protected_->md5_checking = false;
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
|
||||
(void)unused;
|
||||
|
||||
switch(OggFLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) {
|
||||
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
/* 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 OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC:
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
|
||||
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR:
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR:
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
/* double protection */
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
|
||||
(void)decoder;
|
||||
if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
|
||||
*bytes = 0;
|
||||
#if 0
|
||||
@@@@@@ verify that this is not needed:
|
||||
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
#endif
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
|
||||
/* need to flush the Ogg state */
|
||||
OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
|
||||
|
||||
return decoder->private_->seek_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
return decoder->private_->tell_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *stream_length, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
return decoder->private_->length_callback(decoder, stream_length, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *unused, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
return decoder->private_->eof_callback(decoder, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
void metadata_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
void error_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
|
||||
(void)unused;
|
||||
decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
|
||||
}
|
||||
|
||||
OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)void_decoder;
|
||||
|
||||
switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) {
|
||||
case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK:
|
||||
if (*bytes == 0)
|
||||
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
|
||||
else if(*bytes > 0) {
|
||||
if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
|
||||
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
||||
}
|
||||
if(*bytes == 0) {
|
||||
if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
|
||||
#if 0
|
||||
@@@@@@ verify that this is not needed:
|
||||
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
|
||||
#endif
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
}
|
||||
else
|
||||
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
|
||||
case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR:
|
||||
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
|
||||
default:
|
||||
/* double protection: */
|
||||
FLAC__ASSERT(0);
|
||||
return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
|
||||
FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
|
||||
FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
|
||||
FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
|
||||
|
||||
FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
|
||||
|
||||
seekable_stream_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);
|
||||
/* kick out of seek mode */
|
||||
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
|
||||
/* shift out the samples before target_sample */
|
||||
if(delta > 0) {
|
||||
unsigned channel;
|
||||
const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
|
||||
for(channel = 0; channel < frame->header.channels; channel++)
|
||||
newbuffer[channel] = buffer[channel] + delta;
|
||||
seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
|
||||
seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
|
||||
/* write the relevant samples */
|
||||
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
|
||||
}
|
||||
else {
|
||||
/* write the relevant samples */
|
||||
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(seekable_stream_decoder->private_->do_md5_checking) {
|
||||
if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
|
||||
}
|
||||
}
|
||||
|
||||
void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
|
||||
/* save the MD5 signature for comparison later */
|
||||
memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
|
||||
if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
|
||||
seekable_stream_decoder->private_->do_md5_checking = false;
|
||||
}
|
||||
else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
|
||||
seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
|
||||
}
|
||||
|
||||
if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
|
||||
FLAC__bool ignore_block = false;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
|
||||
ignore_block = true;
|
||||
else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
|
||||
ignore_block = true;
|
||||
if(!ignore_block)
|
||||
seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
|
||||
}
|
||||
}
|
||||
|
||||
void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
|
||||
seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
|
||||
}
|
||||
|
||||
FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *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 = decoder->private_->stream_info.total_samples;
|
||||
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. After that, we will switch to binary search.
|
||||
*/
|
||||
static const unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
|
||||
|
||||
/* We will switch to a linear search once our current sample is less
|
||||
* that 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
|
||||
* increase 'iteration' to force binary search immediately.
|
||||
*/
|
||||
if(right_sample == 0) {
|
||||
right_sample = (FLAC__uint64)(-1);
|
||||
iteration = BINARY_SEARCH_AFTER_ITERATION;
|
||||
}
|
||||
|
||||
decoder->private_->target_sample = target_sample;
|
||||
for( ; ; iteration++) {
|
||||
if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
/* our write callback will change the state when it gets to the target frame */
|
||||
if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
const FLAC__uint64 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 (this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
|
||||
FLAC__uint64 pos;
|
||||
|
||||
if (iteration >= BINARY_SEARCH_AFTER_ITERATION)
|
||||
pos = (right_pos + left_pos) / 2;
|
||||
else
|
||||
pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_pos - left_pos));
|
||||
|
||||
if (this_frame_sample <= target_sample) {
|
||||
/* The 'equal' case should not happen, since
|
||||
* OggFLAC__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;
|
||||
left_pos = pos;
|
||||
}
|
||||
else if(this_frame_sample > target_sample) {
|
||||
right_sample = this_frame_sample;
|
||||
right_pos = pos;
|
||||
}
|
||||
|
||||
/* physical seek */
|
||||
if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
|
||||
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -802,10 +802,10 @@ public:
|
|||
~SeekableStreamDecoder() { }
|
||||
|
||||
// from OggFLAC::Decoder::SeekableStream
|
||||
::FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
|
||||
::FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
|
||||
::FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
|
||||
::FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
|
||||
::OggFLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
|
||||
::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
|
||||
::OggFLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
|
||||
::OggFLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
|
||||
bool eof_callback();
|
||||
::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
|
||||
void metadata_callback(const ::FLAC__StreamMetadata *metadata);
|
||||
|
@ -816,56 +816,56 @@ public:
|
|||
bool test_respond();
|
||||
};
|
||||
|
||||
::FLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
|
||||
::OggFLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
|
||||
{
|
||||
switch(common_read_callback_(buffer, bytes)) {
|
||||
case ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
|
||||
case ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
case ::FLAC__STREAM_DECODER_READ_STATUS_ABORT:
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
|
||||
::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
|
||||
{
|
||||
if(error_occurred_)
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
|
||||
if(::fseek(file_, (long)absolute_byte_offset, SEEK_SET) < 0) {
|
||||
error_occurred_ = true;
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
|
||||
::OggFLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
|
||||
{
|
||||
if(error_occurred_)
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
|
||||
long offset = ::ftell(file_);
|
||||
*absolute_byte_offset = (FLAC__uint64)offset;
|
||||
|
||||
if(offset < 0) {
|
||||
error_occurred_ = true;
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length)
|
||||
::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length)
|
||||
{
|
||||
if(error_occurred_)
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
|
||||
*stream_length = (FLAC__uint64)oggflacfilesize_;
|
||||
return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
bool SeekableStreamDecoder::eof_callback()
|
||||
|
@ -903,10 +903,10 @@ bool SeekableStreamDecoder::die(const char *msg) const
|
|||
printf("FAILED");
|
||||
|
||||
printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring());
|
||||
if(state == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
FLAC::Decoder::SeekableStream::State state_ = get_FLAC_seekable_stream_decoder_state();
|
||||
printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
|
||||
if(state_ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
if(state == ::OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
OggFLAC::Decoder::Stream::State state_ = get_stream_decoder_state();
|
||||
printf(" stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state_), state_.as_cstring());
|
||||
if(state_ == ::OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
|
||||
FLAC::Decoder::Stream::State state__ = get_FLAC_stream_decoder_state();
|
||||
printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state__), state__.as_cstring());
|
||||
}
|
||||
|
@ -1046,9 +1046,9 @@ static bool test_seekable_stream_decoder()
|
|||
OggFLAC::Decoder::SeekableStream::State state = decoder->get_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring());
|
||||
|
||||
printf("testing get_FLAC_seekable_stream_decoder_state()... ");
|
||||
FLAC::Decoder::SeekableStream::State state_ = decoder->get_FLAC_seekable_stream_decoder_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
|
||||
printf("testing get_stream_decoder_state()... ");
|
||||
OggFLAC::Decoder::Stream::State state_ = decoder->get_stream_decoder_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state_), state_.as_cstring());
|
||||
|
||||
printf("testing get_FLAC_stream_decoder_state()... ");
|
||||
FLAC::Decoder::Stream::State state__ = decoder->get_FLAC_stream_decoder_state();
|
||||
|
@ -1575,10 +1575,10 @@ bool FileDecoder::die(const char *msg) const
|
|||
if(state == ::OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
OggFLAC::Decoder::SeekableStream::State state_ = get_seekable_stream_decoder_state();
|
||||
printf(" seekable stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
|
||||
if(state_ == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
FLAC::Decoder::SeekableStream::State state__ = get_FLAC_seekable_stream_decoder_state();
|
||||
printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring());
|
||||
if(state__ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
if(state_ == ::OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
OggFLAC::Decoder::Stream::State state__ = get_stream_decoder_state();
|
||||
printf(" stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state__), state__.as_cstring());
|
||||
if(state__ == ::OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
|
||||
FLAC::Decoder::Stream::State state___ = get_FLAC_stream_decoder_state();
|
||||
printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state___), state___.as_cstring());
|
||||
}
|
||||
|
@ -1730,9 +1730,9 @@ static bool test_file_decoder()
|
|||
OggFLAC::Decoder::SeekableStream::State state_ = decoder->get_seekable_stream_decoder_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
|
||||
|
||||
printf("testing get_FLAC_seekable_stream_decoder_state()... ");
|
||||
FLAC::Decoder::SeekableStream::State state__ = decoder->get_FLAC_seekable_stream_decoder_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring());
|
||||
printf("testing get_stream_decoder_state()... ");
|
||||
OggFLAC::Decoder::Stream::State state__ = decoder->get_stream_decoder_state();
|
||||
printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state__), state__.as_cstring());
|
||||
|
||||
printf("testing get_FLAC_stream_decoder_state()... ");
|
||||
FLAC::Decoder::Stream::State state___ = decoder->get_FLAC_stream_decoder_state();
|
||||
|
|
|
@ -79,10 +79,10 @@ static FLAC__bool die_ss_(const char *msg, const OggFLAC__SeekableStreamDecoder
|
|||
printf("FAILED");
|
||||
|
||||
printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamDecoderStateString[state]);
|
||||
if(state == OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
FLAC__SeekableStreamDecoderState state_ = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder);
|
||||
printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamDecoderStateString[state_]);
|
||||
if(state_ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
if(state == OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
OggFLAC__StreamDecoderState state_ = OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder);
|
||||
printf(" stream decoder state = %u (%s)\n", (unsigned)state_, OggFLAC__StreamDecoderStateString[state_]);
|
||||
if(state_ == OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
|
||||
FLAC__StreamDecoderState state__ = OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder);
|
||||
printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamDecoderStateString[state__]);
|
||||
}
|
||||
|
@ -104,10 +104,10 @@ static FLAC__bool die_f_(const char *msg, const OggFLAC__FileDecoder *decoder)
|
|||
if(state == OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
OggFLAC__SeekableStreamDecoderState state_ = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
|
||||
printf(" seekable stream decoder state = %u (%s)\n", (unsigned)state_, OggFLAC__SeekableStreamDecoderStateString[state_]);
|
||||
if(state_ == OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) {
|
||||
FLAC__SeekableStreamDecoderState state__ = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder);
|
||||
printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__SeekableStreamDecoderStateString[state__]);
|
||||
if(state__ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
if(state_ == OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
|
||||
OggFLAC__StreamDecoderState state__ = OggFLAC__file_decoder_get_stream_decoder_state(decoder);
|
||||
printf(" stream decoder state = %u (%s)\n", (unsigned)state__, OggFLAC__StreamDecoderStateString[state__]);
|
||||
if(state__ == OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
|
||||
FLAC__StreamDecoderState state___ = OggFLAC__file_decoder_get_FLAC_stream_decoder_state(decoder);
|
||||
printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)state___, FLAC__StreamDecoderStateString[state___]);
|
||||
}
|
||||
|
@ -801,22 +801,22 @@ static FLAC__bool test_stream_decoder()
|
|||
return true;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
static OggFLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)decoder;
|
||||
switch(stream_decoder_read_callback_(0, buffer, bytes, client_data)) {
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
|
||||
case FLAC__STREAM_DECODER_READ_STATUS_ABORT:
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
static OggFLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
|
||||
|
||||
|
@ -824,21 +824,21 @@ static FLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callba
|
|||
|
||||
if(0 == dcd) {
|
||||
printf("ERROR: client_data in seek callback is NULL\n");
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if(dcd->error_occurred)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
|
||||
if(fseek(dcd->file, (long)absolute_byte_offset, SEEK_SET) < 0) {
|
||||
dcd->error_occurred = true;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
static OggFLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
|
||||
{
|
||||
seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
|
||||
long offset;
|
||||
|
@ -847,24 +847,24 @@ static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callba
|
|||
|
||||
if(0 == dcd) {
|
||||
printf("ERROR: client_data in tell callback is NULL\n");
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if(dcd->error_occurred)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
|
||||
offset = ftell(dcd->file);
|
||||
*absolute_byte_offset = (FLAC__uint64)offset;
|
||||
|
||||
if(offset < 0) {
|
||||
dcd->error_occurred = true;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
static OggFLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
|
||||
{
|
||||
seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
|
||||
|
||||
|
@ -872,14 +872,14 @@ static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_ca
|
|||
|
||||
if(0 == dcd) {
|
||||
printf("ERROR: client_data in length callback is NULL\n");
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if(dcd->error_occurred)
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
|
||||
|
||||
*stream_length = (FLAC__uint64)oggflacfilesize_;
|
||||
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__bool seekable_stream_decoder_eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data)
|
||||
|
@ -977,7 +977,7 @@ static FLAC__bool test_seekable_stream_decoder()
|
|||
{
|
||||
OggFLAC__SeekableStreamDecoder *decoder;
|
||||
OggFLAC__SeekableStreamDecoderState state;
|
||||
FLAC__SeekableStreamDecoderState fsstate;
|
||||
OggFLAC__StreamDecoderState sstate;
|
||||
FLAC__StreamDecoderState fstate;
|
||||
seekable_stream_decoder_client_data_struct decoder_client_data;
|
||||
|
||||
|
@ -1087,9 +1087,9 @@ static FLAC__bool test_seekable_stream_decoder()
|
|||
state = OggFLAC__seekable_stream_decoder_get_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", state, OggFLAC__SeekableStreamDecoderStateString[state]);
|
||||
|
||||
printf("testing OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state()... ");
|
||||
fsstate = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]);
|
||||
printf("testing OggFLAC__seekable_stream_decoder_get_stream_decoder_state()... ");
|
||||
sstate = OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__StreamDecoderStateString[sstate]);
|
||||
|
||||
printf("testing OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state()... ");
|
||||
fstate = OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder);
|
||||
|
@ -1581,8 +1581,8 @@ static FLAC__bool test_file_decoder()
|
|||
{
|
||||
OggFLAC__FileDecoder *decoder;
|
||||
OggFLAC__FileDecoderState state;
|
||||
OggFLAC__SeekableStreamDecoderState sstate;
|
||||
FLAC__SeekableStreamDecoderState fsstate;
|
||||
OggFLAC__SeekableStreamDecoderState ssstate;
|
||||
OggFLAC__StreamDecoderState sstate;
|
||||
FLAC__StreamDecoderState fstate;
|
||||
seekable_stream_decoder_client_data_struct decoder_client_data;
|
||||
|
||||
|
@ -1673,12 +1673,12 @@ static FLAC__bool test_file_decoder()
|
|||
printf("returned state = %u (%s)... OK\n", state, OggFLAC__FileDecoderStateString[state]);
|
||||
|
||||
printf("testing OggFLAC__file_decoder_get_seekable_stream_decoder_state()... ");
|
||||
sstate = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__SeekableStreamDecoderStateString[sstate]);
|
||||
ssstate = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", ssstate, OggFLAC__SeekableStreamDecoderStateString[ssstate]);
|
||||
|
||||
printf("testing OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state()... ");
|
||||
fsstate = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]);
|
||||
printf("testing OggFLAC__file_decoder_get_stream_decoder_state()... ");
|
||||
sstate = OggFLAC__file_decoder_get_stream_decoder_state(decoder);
|
||||
printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__StreamDecoderStateString[sstate]);
|
||||
|
||||
printf("testing OggFLAC__file_decoder_get_FLAC_stream_decoder_state()... ");
|
||||
fstate = OggFLAC__file_decoder_get_FLAC_stream_decoder_state(decoder);
|
||||
|
|
Loading…
Reference in New Issue