mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
add read callback to OggFLAC__SeekableStreamEncoder, necessary for metadata rewriting
This commit is contained in:
@@ -258,6 +258,7 @@ namespace OggFLAC {
|
||||
bool process(const FLAC__int32 * const buffer[], unsigned samples);
|
||||
bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
|
||||
protected:
|
||||
virtual ::OggFLAC__SeekableStreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
|
||||
virtual ::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0;
|
||||
virtual ::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0;
|
||||
virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
|
||||
@@ -268,6 +269,7 @@ namespace OggFLAC {
|
||||
#endif
|
||||
::OggFLAC__SeekableStreamEncoder *encoder_;
|
||||
private:
|
||||
static ::OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static ::FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static ::FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static ::FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
|
||||
@@ -131,6 +131,29 @@ typedef enum {
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[];
|
||||
|
||||
|
||||
/** Return values for the OggFLAC__SeekableStreamEncoder read callback.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE,
|
||||
/**< The read was OK and decoding can continue. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM,
|
||||
/**< The read was attempted at the end of the stream. */
|
||||
|
||||
OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT
|
||||
/**< An unrecoverable error occurred. */
|
||||
|
||||
} OggFLAC__SeekableStreamEncoderReadStatus;
|
||||
|
||||
/** Maps a OggFLAC__SeekableStreamEncoderReadStatus to a C string.
|
||||
*
|
||||
* Using a OggFLAC__SeekableStreamEncoderReadStatus as the index to this array
|
||||
* will give the string equivalent. The contents should not be modified.
|
||||
*/
|
||||
extern OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[];
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* class OggFLAC__StreamEncoder
|
||||
@@ -148,6 +171,25 @@ typedef struct {
|
||||
struct OggFLAC__SeekableStreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
|
||||
} OggFLAC__SeekableStreamEncoder;
|
||||
|
||||
/** Signature for the read callback.
|
||||
* See OggFLAC__seekable_stream_encoder_set_read_callback() for more info.
|
||||
*
|
||||
* \param encoder The encoder instance calling the callback.
|
||||
* \param buffer A pointer to a location for the callee to store
|
||||
* data to be encoded.
|
||||
* \param bytes A pointer to the size of the buffer. On entry
|
||||
* to the callback, it contains the maximum number
|
||||
* of bytes that may be stored in \a buffer. The
|
||||
* callee must set it to the actual number of bytes
|
||||
* stored (0 in case of error or end-of-stream) before
|
||||
* returning.
|
||||
* \param client_data The callee's client data set through
|
||||
* OggFLAC__seekable_stream_encoder_set_client_data().
|
||||
* \retval OggFLAC__SeekableStreamEncoderReadStatus
|
||||
* The callee's return status.
|
||||
*/
|
||||
typedef OggFLAC__SeekableStreamEncoderReadStatus (*OggFLAC__SeekableStreamEncoderReadCallback)(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
|
||||
/** Signature for the seek callback.
|
||||
* See OggFLAC__seekable_stream_encoder_set_seek_callback()
|
||||
* and FLAC__SeekableStreamEncoderSeekCallback for more info.
|
||||
@@ -454,6 +496,30 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estima
|
||||
*/
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
|
||||
|
||||
/** Set the read callback.
|
||||
* The supplied function will be called when the encoder needs to read back
|
||||
* encoded data. This happens during the metadata callback, when the encoder
|
||||
* has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered
|
||||
* while encoding. The address of the buffer to be filled is supplied, along
|
||||
* with the number of bytes the buffer can hold. The callback may choose to
|
||||
* supply less data and modify the byte count but must be careful not to
|
||||
* overflow the buffer. The callback then returns a status code chosen from
|
||||
* OggFLAC__SeekableStreamEncoderReadStatus.
|
||||
*
|
||||
* \note
|
||||
* The callback is mandatory and must be set before initialization.
|
||||
*
|
||||
* \default \c NULL
|
||||
* \param encoder A encoder instance to set.
|
||||
* \param value See above.
|
||||
* \assert
|
||||
* \code encoder != NULL \endcode
|
||||
* \code value != NULL \endcode
|
||||
* \retval FLAC__bool
|
||||
* \c false if the encoder is already initialized, else \c true.
|
||||
*/
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value);
|
||||
|
||||
/** Set the seek callback.
|
||||
* The supplied function will be called when the encoder needs to seek
|
||||
* the output stream. The encoder will pass the absolute byte offset
|
||||
|
||||
@@ -300,6 +300,7 @@ namespace OggFLAC {
|
||||
SeekableStream::State SeekableStream::init()
|
||||
{
|
||||
FLAC__ASSERT(is_valid());
|
||||
::OggFLAC__seekable_stream_encoder_set_read_callback(encoder_, read_callback_);
|
||||
::OggFLAC__seekable_stream_encoder_set_seek_callback(encoder_, seek_callback_);
|
||||
::OggFLAC__seekable_stream_encoder_set_tell_callback(encoder_, tell_callback_);
|
||||
::OggFLAC__seekable_stream_encoder_set_write_callback(encoder_, write_callback_);
|
||||
@@ -325,6 +326,15 @@ namespace OggFLAC {
|
||||
return (bool)::OggFLAC__seekable_stream_encoder_process_interleaved(encoder_, buffer, samples);
|
||||
}
|
||||
|
||||
::OggFLAC__SeekableStreamEncoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)encoder;
|
||||
FLAC__ASSERT(0 != client_data);
|
||||
SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
|
||||
FLAC__ASSERT(0 != instance);
|
||||
return instance->read_callback(buffer, bytes);
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamEncoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
(void)encoder;
|
||||
|
||||
@@ -54,6 +54,7 @@ libOggFLAC_la_SOURCES = \
|
||||
file_encoder.c \
|
||||
ogg_decoder_aspect.c \
|
||||
ogg_encoder_aspect.c \
|
||||
ogg_helper.c \
|
||||
seekable_stream_decoder.c \
|
||||
seekable_stream_encoder.c \
|
||||
stream_decoder.c \
|
||||
|
||||
@@ -52,6 +52,7 @@ SRCS_C = \
|
||||
file_encoder.c \
|
||||
ogg_decoder_aspect.c \
|
||||
ogg_encoder_aspect.c \
|
||||
ogg_helper.c \
|
||||
seekable_stream_decoder.c \
|
||||
seekable_stream_encoder.c \
|
||||
stream_decoder.c \
|
||||
|
||||
@@ -53,6 +53,7 @@ extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFL
|
||||
extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
|
||||
|
||||
static void set_defaults_(OggFLAC__FileEncoder *encoder);
|
||||
static OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
|
||||
static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
|
||||
static FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
@@ -181,6 +182,7 @@ OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEn
|
||||
encoder->private_->samples_written = 0;
|
||||
encoder->private_->frames_written = 0;
|
||||
|
||||
OggFLAC__seekable_stream_encoder_set_read_callback(encoder->private_->seekable_stream_encoder, read_callback_);
|
||||
OggFLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
|
||||
OggFLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_);
|
||||
OggFLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
|
||||
@@ -717,6 +719,24 @@ void set_defaults_(OggFLAC__FileEncoder *encoder)
|
||||
encoder->private_->filename = 0;
|
||||
}
|
||||
|
||||
OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
|
||||
|
||||
(void)encoder;
|
||||
|
||||
FLAC__ASSERT(0 != file_encoder);
|
||||
|
||||
*bytes = (unsigned)fread(buffer, 1, *bytes, file_encoder->private_->file);
|
||||
if (*bytes == 0) {
|
||||
if (feof(file_encoder->private_->file))
|
||||
return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
|
||||
else if (ferror(file_encoder->private_->file))
|
||||
return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT;
|
||||
}
|
||||
return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
|
||||
|
||||
@@ -31,4 +31,5 @@
|
||||
noinst_HEADERS = \
|
||||
all.h \
|
||||
ogg_decoder_aspect.h \
|
||||
ogg_encoder_aspect.h
|
||||
ogg_encoder_aspect.h \
|
||||
ogg_helper.h
|
||||
|
||||
@@ -34,5 +34,6 @@
|
||||
|
||||
#include "ogg_decoder_aspect.h"
|
||||
#include "ogg_encoder_aspect.h"
|
||||
#include "ogg_helper.h"
|
||||
|
||||
#endif
|
||||
|
||||
43
src/libOggFLAC/include/private/ogg_helper.h
Normal file
43
src/libOggFLAC/include/private/ogg_helper.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* libOggFLAC - Free Lossless Audio Codec + Ogg library
|
||||
* Copyright (C) 2002,2003 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef OggFLAC__PRIVATE__OGG_HELPER_H
|
||||
#define OggFLAC__PRIVATE__OGG_HELPER_H
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
#include "OggFLAC/seekable_stream_encoder.h" /* for OggFLAC__SeekableStreamEncoder */
|
||||
|
||||
void simple_ogg_page__init(ogg_page *page);
|
||||
void simple_ogg_page__clear(ogg_page *page);
|
||||
FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data);
|
||||
FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data);
|
||||
|
||||
#endif
|
||||
@@ -108,6 +108,10 @@ SOURCE=.\ogg_encoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_helper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\seekable_stream_decoder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -138,6 +142,10 @@ SOURCE=.\include\private\ogg_decoder_aspect.h
|
||||
|
||||
SOURCE=.\include\private\ogg_encoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_helper.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Protected Header Files"
|
||||
|
||||
|
||||
@@ -101,6 +101,10 @@ SOURCE=.\ogg_encoder_aspect.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ogg_helper.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\seekable_stream_decoder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -131,6 +135,10 @@ SOURCE=.\include\private\ogg_decoder_aspect.h
|
||||
|
||||
SOURCE=.\include\private\ogg_encoder_aspect.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\private\ogg_helper.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Protected Header Files"
|
||||
|
||||
|
||||
189
src/libOggFLAC/ogg_helper.c
Normal file
189
src/libOggFLAC/ogg_helper.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/* libOggFLAC - Free Lossless Audio Codec + Ogg library
|
||||
* Copyright (C) 2002,2003 Josh Coalson
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcmp(), memcpy() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "private/ogg_helper.h"
|
||||
#include "protected/seekable_stream_encoder.h"
|
||||
|
||||
|
||||
static FLAC__bool full_read_(OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
while(bytes > 0) {
|
||||
unsigned bytes_read = bytes;
|
||||
switch(read_callback(encoder, buffer, &bytes_read, client_data)) {
|
||||
case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE:
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
|
||||
if(bytes_read == 0) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT:
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
|
||||
return false;
|
||||
default:
|
||||
/* double protection: */
|
||||
FLAC__ASSERT(0);
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void simple_ogg_page__init(ogg_page *page)
|
||||
{
|
||||
page->header = 0;
|
||||
page->header_len = 0;
|
||||
page->body = 0;
|
||||
page->body_len = 0;
|
||||
}
|
||||
|
||||
void simple_ogg_page__clear(ogg_page *page)
|
||||
{
|
||||
if(page->header)
|
||||
free(page->header);
|
||||
if(page->body)
|
||||
free(page->body);
|
||||
simple_ogg_page__init(page);
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
|
||||
static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
|
||||
FLAC__byte crc[4];
|
||||
|
||||
FLAC__ASSERT(page->header = 0);
|
||||
FLAC__ASSERT(page->header_len = 0);
|
||||
FLAC__ASSERT(page->body = 0);
|
||||
FLAC__ASSERT(page->body_len = 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate space for the page header */
|
||||
if(0 == (page->header = malloc(OGG_MAX_HEADER_LEN))) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the fixed part of the page header (up to but not including
|
||||
* the segment table */
|
||||
if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26];
|
||||
|
||||
/* check to see if it's a correct, "simple" page (one packet only) */
|
||||
if(
|
||||
memcmp(page->header, "OggS", 4) || /* doesn't start with OggS */
|
||||
(page->header[5] & 0x01) || /* continued packet */
|
||||
memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */
|
||||
page->header[26] == 0 /* packet is 0-size */
|
||||
) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the segment table */
|
||||
if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data))
|
||||
return false;
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* check to see that it specifies a single packet */
|
||||
for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
|
||||
if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
page->body_len = 255 * i + page->header[i];
|
||||
}
|
||||
|
||||
/* allocate space for the page body */
|
||||
if(0 == (page->body = malloc(page->body_len))) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the page body */
|
||||
if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
/* check the CRC */
|
||||
memcpy(crc, page->header+22, 4);
|
||||
ogg_page_checksum_set(page);
|
||||
if(memcmp(crc, page->header+22, 4)) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data)
|
||||
{
|
||||
FLAC__ASSERT(page->header != 0);
|
||||
FLAC__ASSERT(page->header_len != 0);
|
||||
FLAC__ASSERT(page->body != 0);
|
||||
FLAC__ASSERT(page->body_len != 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
ogg_page_checksum_set(page);
|
||||
|
||||
/* re-write the page */
|
||||
if(write_callback(encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -31,9 +31,11 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for calloc() */
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "OggFLAC/seekable_stream_encoder.h"
|
||||
#include "protected/seekable_stream_encoder.h"
|
||||
#include "private/ogg_helper.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
@@ -63,6 +65,7 @@ static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__S
|
||||
***********************************************************************/
|
||||
|
||||
typedef struct OggFLAC__SeekableStreamEncoderPrivate {
|
||||
OggFLAC__SeekableStreamEncoderReadCallback read_callback;
|
||||
OggFLAC__SeekableStreamEncoderSeekCallback seek_callback;
|
||||
OggFLAC__SeekableStreamEncoderTellCallback tell_callback;
|
||||
OggFLAC__SeekableStreamEncoderWriteCallback write_callback;
|
||||
@@ -88,6 +91,7 @@ OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED",
|
||||
@@ -96,6 +100,12 @@ OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED"
|
||||
};
|
||||
|
||||
OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[] = {
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
|
||||
"OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT"
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
@@ -444,6 +454,18 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__Se
|
||||
return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
FLAC__ASSERT(0 != encoder->private_);
|
||||
FLAC__ASSERT(0 != encoder->protected_);
|
||||
FLAC__ASSERT(0 != value);
|
||||
if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
|
||||
return false;
|
||||
encoder->private_->read_callback = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_seek_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderSeekCallback value)
|
||||
{
|
||||
FLAC__ASSERT(0 != encoder);
|
||||
@@ -850,7 +872,7 @@ void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMet
|
||||
const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
|
||||
const unsigned min_framesize = metadata->data.stream_info.min_framesize;
|
||||
const unsigned max_framesize = metadata->data.stream_info.max_framesize;
|
||||
const unsigned bps = metadata->data.stream_info.bits_per_sample;
|
||||
ogg_page page;
|
||||
|
||||
FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
|
||||
|
||||
@@ -861,7 +883,6 @@ void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMet
|
||||
|
||||
(void)unused; /* silence compiler warning about unused parameter */
|
||||
FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
|
||||
return;//@@@@@@
|
||||
|
||||
/*@@@ reopen callback here? The docs currently require user to open files in update mode from the start */
|
||||
|
||||
@@ -871,89 +892,85 @@ return;//@@@@@@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write MD5 signature
|
||||
* Write STREAMINFO stats
|
||||
*/
|
||||
simple_ogg_page__init(&page);
|
||||
if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data))
|
||||
return; /* state already set */
|
||||
/*
|
||||
* MD5 signature
|
||||
*/
|
||||
{
|
||||
const unsigned md5_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
|
||||
) / 8;
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
|
||||
) / 8;
|
||||
|
||||
if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + md5_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
return;
|
||||
}
|
||||
if(encoder->private_->write_callback(encoder, metadata->data.stream_info.md5sum, 16, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
if(md5_offset + 16 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return;
|
||||
}
|
||||
memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write total samples
|
||||
* total samples
|
||||
*/
|
||||
{
|
||||
const unsigned total_samples_byte_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
|
||||
- 4
|
||||
) / 8;
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
|
||||
- 4
|
||||
) / 8;
|
||||
|
||||
b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F);
|
||||
if(total_samples_byte_offset + 5 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return;
|
||||
}
|
||||
b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0;
|
||||
b[0] |= (FLAC__byte)((samples >> 32) & 0x0F);
|
||||
b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
|
||||
b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
|
||||
b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
|
||||
b[4] = (FLAC__byte)(samples & 0xFF);
|
||||
if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + total_samples_byte_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
return;
|
||||
}
|
||||
if(encoder->private_->write_callback(encoder, b, 5, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
return;
|
||||
}
|
||||
memcpy(page.body + total_samples_byte_offset, b, 5);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write min/max framesize
|
||||
* min/max framesize
|
||||
*/
|
||||
{
|
||||
const unsigned min_framesize_offset =
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
|
||||
) / 8;
|
||||
FLAC__STREAM_METADATA_HEADER_LENGTH +
|
||||
(
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
|
||||
FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
|
||||
) / 8;
|
||||
|
||||
if(min_framesize_offset + 6 > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return;
|
||||
}
|
||||
b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
|
||||
b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
|
||||
b[2] = (FLAC__byte)(min_framesize & 0xFF);
|
||||
b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
|
||||
b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
|
||||
b[5] = (FLAC__byte)(max_framesize & 0xFF);
|
||||
if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + min_framesize_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
return;
|
||||
}
|
||||
if(encoder->private_->write_callback(encoder, b, 6, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
return;
|
||||
}
|
||||
memcpy(page.body + min_framesize_offset, b, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -961,17 +978,22 @@ return;//@@@@@@
|
||||
*/
|
||||
if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
|
||||
unsigned i;
|
||||
FLAC__byte *p;
|
||||
|
||||
FLAC__format_seektable_sort(encoder->private_->seek_table);
|
||||
|
||||
FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
|
||||
|
||||
if(encoder->private_->seek_callback(encoder, encoder->protected_->seektable_offset + FLAC__STREAM_METADATA_HEADER_LENGTH, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
|
||||
simple_ogg_page__init(&page);
|
||||
if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data))
|
||||
return; /* state already set */
|
||||
|
||||
if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) {
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < encoder->private_->seek_table->num_points; i++) {
|
||||
for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) {
|
||||
FLAC__uint64 xx;
|
||||
unsigned x;
|
||||
xx = encoder->private_->seek_table->points[i].sample_number;
|
||||
@@ -999,6 +1021,11 @@ return;//@@@@@@
|
||||
encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
|
||||
return;
|
||||
}
|
||||
memcpy(p, b, 18);
|
||||
}
|
||||
|
||||
if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data))
|
||||
return; /* state already set */
|
||||
simple_ogg_page__clear(&page);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +387,7 @@ public:
|
||||
~SeekableStreamEncoder() { }
|
||||
|
||||
// from OggFLAC::Encoder::SeekableStream
|
||||
::OggFLAC__SeekableStreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
|
||||
::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
|
||||
::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
|
||||
::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
|
||||
@@ -394,6 +395,13 @@ public:
|
||||
bool die(const char *msg = 0) const;
|
||||
};
|
||||
|
||||
::OggFLAC__SeekableStreamEncoderReadStatus SeekableStreamEncoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
|
||||
{
|
||||
(void)buffer, (void)bytes;
|
||||
|
||||
return ::OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
::FLAC__SeekableStreamEncoderSeekStatus SeekableStreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
|
||||
{
|
||||
(void)absolute_byte_offset;
|
||||
|
||||
@@ -431,6 +431,12 @@ static FLAC__bool test_stream_encoder()
|
||||
return true;
|
||||
}
|
||||
|
||||
OggFLAC__SeekableStreamEncoderReadStatus seekable_stream_encoder_read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)encoder, (void)buffer, (void)bytes, (void)client_data;
|
||||
return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
FLAC__SeekableStreamEncoderSeekStatus seekable_stream_encoder_seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
|
||||
{
|
||||
(void)encoder, (void)absolute_byte_offset, (void)client_data;
|
||||
@@ -567,6 +573,11 @@ static FLAC__bool test_seekable_stream_encoder()
|
||||
return die_ss_("returned false", encoder);
|
||||
printf("OK\n");
|
||||
|
||||
printf("testing OggFLAC__seekable_stream_encoder_set_read_callback()... ");
|
||||
if(!OggFLAC__seekable_stream_encoder_set_read_callback(encoder, seekable_stream_encoder_read_callback_))
|
||||
return die_ss_("returned false", encoder);
|
||||
printf("OK\n");
|
||||
|
||||
printf("testing OggFLAC__seekable_stream_encoder_set_seek_callback()... ");
|
||||
if(!OggFLAC__seekable_stream_encoder_set_seek_callback(encoder, seekable_stream_encoder_seek_callback_))
|
||||
return die_ss_("returned false", encoder);
|
||||
|
||||
Reference in New Issue
Block a user