unsigned get_min_residual_partition_order() const;
unsigned get_max_residual_partition_order() const;
unsigned get_rice_parameter_search_dist() const;
+ FLAC__uint64 get_total_samples_estimate() const;
// Initialize the instance; as with the C interface,
// init() should be called after construction and 'set'
unsigned get_min_residual_partition_order() const;
unsigned get_max_residual_partition_order() const;
unsigned get_rice_parameter_search_dist() const;
+ FLAC__uint64 get_total_samples_estimate() const;
// Initialize the instance; as with the C interface,
// init() should be called after construction and 'set'
unsigned get_min_residual_partition_order() const;
unsigned get_max_residual_partition_order() const;
unsigned get_rice_parameter_search_dist() const;
+ FLAC__uint64 get_total_samples_estimate() const;
// Initialize the instance; as with the C interface,
// init() should be called after construction and 'set'
bool process(const FLAC__int32 * const buffer[], unsigned samples);
bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
protected:
- //@@@@ progress callback
+ virtual void progress_callback(unsigned current_frame, unsigned total_frames_estimate);
::FLAC__FileEncoder *encoder_;
private:
- //@@@@ progress callback
+ static void progress_callback_(const ::FLAC__FileEncoder *encoder, unsigned current_frame, unsigned total_frames_estimate, void *client_data);
// Private and undefined so you can't use them:
File(const Stream &);
struct FLAC__FileEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
} FLAC__FileEncoder;
+/*@@@ document: */
+typedef void (*FLAC__FileEncoderProgressCallback)(const FLAC__FileEncoder *encoder, unsigned current_frame, unsigned total_frames_estimate, void *client_data);
+
/***********************************************************************
*
*/
FLAC__bool FLAC__file_encoder_set_filename(FLAC__FileEncoder *encoder, const char *value);
+/** Set the progress callback.
+ * The supplied function will be called when the encoder has finished
+ * writing a frame. The \c total_frames_estimate argument to the callback
+ * will be based on the value from
+ * FLAC__file_encoder_set_total_samples_estimate().
+ *
+ * \note
+ * Unlike most other callbacks, the progress callback is \b not mandatory
+ * and need not be set before initialization.
+ *
+ * \default \c NULL
+ * \param encoder An 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.
+ */
+FLAC__bool FLAC__file_encoder_set_progress_callback(FLAC__FileEncoder *encoder, FLAC__FileEncoderProgressCallback value);
+
+/** Set the client data to be passed back to callbacks.
+ * This value will be supplied to callbacks in their \a client_data
+ * argument.
+ *
+ * \default \c NULL
+ * \param encoder An encoder instance to set.
+ * \param value See above.
+ * \assert
+ * \code encoder != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if the encoder is already initialized, else \c true.
+ */
+FLAC__bool FLAC__file_encoder_set_client_data(FLAC__FileEncoder *encoder, void *value);
+
/** Get the current encoder state.
*
* \param encoder An encoder instance to query.
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_channels().
*/
unsigned FLAC__file_encoder_get_channels(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_bits_per_sample().
*/
unsigned FLAC__file_encoder_get_bits_per_sample(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_sample_rate().
*/
unsigned FLAC__file_encoder_get_sample_rate(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_blocksize().
*/
unsigned FLAC__file_encoder_get_blocksize(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_max_lpc_order().
*/
unsigned FLAC__file_encoder_get_max_lpc_order(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_qlp_coeff_precision().
*/
unsigned FLAC__file_encoder_get_qlp_coeff_precision(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_min_residual_partition_order().
*/
unsigned FLAC__file_encoder_get_min_residual_partition_order(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_max_residual_partition_order().
*/
unsigned FLAC__file_encoder_get_max_residual_partition_order(const FLAC__FileEncoder *encoder);
* \param encoder An encoder instance to query.
* \assert
* \code encoder != NULL \endcode
- * \retval FLAC__bool
+ * \retval unsigned
* See FLAC__file_encoder_set_rice_parameter_search_dist().
*/
unsigned FLAC__file_encoder_get_rice_parameter_search_dist(const FLAC__FileEncoder *encoder);
+/** Get the previously set estimate of the total samples to be encoded.
+ * This is inherited from FLAC__SeekableStreamEncoder; see
+ * FLAC__seekable_stream_encoder_get_total_samples_estimate().
+ *
+ * \param encoder An encoder instance to query.
+ * \assert
+ * \code encoder != NULL \endcode
+ * \retval FLAC__uint64
+ * See FLAC__file_encoder_set_total_samples_estimate().
+ */
+FLAC__uint64 FLAC__file_encoder_get_total_samples_estimate(const FLAC__FileEncoder *encoder);
+
/** Initialize the encoder instance.
* Should be called after FLAC__file_encoder_new() and
* FLAC__file_encoder_set_*() but before FLAC__file_encoder_process()
return ::FLAC__file_encoder_get_rice_parameter_search_dist(encoder_);
}
+ FLAC__uint64 File::get_total_samples_estimate() const
+ {
+ FLAC__ASSERT(is_valid());
+ return ::FLAC__file_encoder_get_total_samples_estimate(encoder_);
+ }
+
File::State File::init()
{
FLAC__ASSERT(is_valid());
+ ::FLAC__file_encoder_set_progress_callback(encoder_, progress_callback_);
+ ::FLAC__file_encoder_set_client_data(encoder_, (void*)this);
return State(::FLAC__file_encoder_init(encoder_));
}
return (bool)::FLAC__file_encoder_process_interleaved(encoder_, buffer, samples);
}
+ void File::progress_callback(unsigned current_frame, unsigned total_frames_estimate)
+ {
+ (void)current_frame, (void)total_frames_estimate;
+ }
+
+ void File::progress_callback_(const ::FLAC__FileEncoder *encoder, unsigned current_frame, unsigned total_frames_estimate, void *client_data)
+ {
+ (void)encoder;
+ FLAC__ASSERT(0 != client_data);
+ File *instance = reinterpret_cast<File *>(client_data);
+ FLAC__ASSERT(0 != instance);
+ instance->progress_callback(current_frame, total_frames_estimate);
+ }
+
};
};
***********************************************************************/
typedef struct FLAC__FileEncoderPrivate {
- FILE *file;
+ FLAC__FileEncoderProgressCallback progress_callback;
+ void *client_data;
char *filename;
+ unsigned total_frames_estimate;
FLAC__SeekableStreamEncoder *seekable_stream_encoder;
+ FILE *file;
} FLAC__FileEncoderPrivate;
/***********************************************************************
if(FLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != FLAC__SEEKABLE_STREAM_ENCODER_OK)
return encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
+ {
+ unsigned blocksize = FLAC__file_encoder_get_blocksize(encoder);
+
+ FLAC__ASSERT(blocksize != 0);
+ encoder->private_->total_frames_estimate = (FLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize;
+ }
+
return encoder->protected_->state = FLAC__FILE_ENCODER_OK;
}
return true;
}
+FLAC__bool FLAC__file_encoder_set_progress_callback(FLAC__FileEncoder *encoder, FLAC__FileEncoderProgressCallback value)
+{
+ FLAC__ASSERT(0 != encoder);
+ FLAC__ASSERT(0 != encoder->private_);
+ FLAC__ASSERT(0 != encoder->protected_);
+ if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
+ return false;
+ encoder->private_->progress_callback = value;
+ return true;
+}
+
+FLAC__bool FLAC__file_encoder_set_client_data(FLAC__FileEncoder *encoder, void *value)
+{
+ FLAC__ASSERT(0 != encoder);
+ FLAC__ASSERT(0 != encoder->private_);
+ FLAC__ASSERT(0 != encoder->protected_);
+ if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
+ return false;
+ encoder->private_->client_data = value;
+ return true;
+}
+
FLAC__FileEncoderState FLAC__file_encoder_get_state(const FLAC__FileEncoder *encoder)
{
FLAC__ASSERT(0 != encoder);
return FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
}
+FLAC__uint64 FLAC__file_encoder_get_total_samples_estimate(const FLAC__FileEncoder *encoder)
+{
+ FLAC__ASSERT(0 != encoder);
+ FLAC__ASSERT(0 != encoder->private_);
+ return FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
+}
+
FLAC__bool FLAC__file_encoder_process(FLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
{
FLAC__ASSERT(0 != encoder);
FLAC__ASSERT(0 != encoder);
FLAC__ASSERT(0 != encoder->private_);
+ encoder->private_->progress_callback = 0;
+ encoder->private_->client_data = 0;
+ encoder->private_->total_frames_estimate = 0;
encoder->private_->filename = 0;
}
FLAC__ASSERT(0 != file_encoder);
- if(fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes)
+ if(fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
+ if(0 != file_encoder->private_->progress_callback)
+ file_encoder->private_->progress_callback(file_encoder, current_frame, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+ }
else
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
}
}
printf("OK\n");
+ printf("testing get_total_samples_estimate()... ");
+ if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;
}
printf("OK\n");
+ printf("testing get_total_samples_estimate()... ");
+ if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;
~FileEncoder() { }
// from FLAC::Encoder::File
- //@@@@ progress callback
+ void progress_callback(unsigned current_frame, unsigned total_frames_estimate);
bool die(const char *msg = 0) const;
};
+void FileEncoder::progress_callback(unsigned current_frame, unsigned total_frames_estimate)
+{
+ (void)current_frame, (void)total_frames_estimate;
+}
+
bool FileEncoder::die(const char *msg) const
{
State state = get_state();
}
printf("OK\n");
+ printf("testing get_total_samples_estimate()... ");
+ if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;
}
printf("OK\n");
+ printf("testing FLAC__stream_encoder_get_total_samples_estimate()... ");
+ if(FLAC__stream_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, FLAC__stream_encoder_get_total_samples_estimate(encoder));
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;
}
printf("OK\n");
+ printf("testing FLAC__seekable_stream_encoder_get_total_samples_estimate()... ");
+ if(FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder));
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;
return true;
}
+static void file_encoder_progress_callback_(const FLAC__FileEncoder *encoder, unsigned current_frame, unsigned total_frames_estimate, void *client_data)
+{
+ (void)encoder, (void)current_frame, (void)total_frames_estimate, (void)client_data;
+}
+
static FLAC__bool test_file_encoder()
{
FLAC__FileEncoder *encoder;
return die_f_("returned false", encoder);
printf("OK\n");
+ printf("testing FLAC__file_encoder_set_progress_callback()... ");
+ if(!FLAC__file_encoder_set_progress_callback(encoder, file_encoder_progress_callback_))
+ return die_f_("returned false", encoder);
+ printf("OK\n");
+
+ printf("testing FLAC__file_encoder_set_client_data()... ");
+ if(!FLAC__file_encoder_set_client_data(encoder, 0))
+ return die_f_("returned false", encoder);
+ printf("OK\n");
+
printf("testing FLAC__file_encoder_init()... ");
if(FLAC__file_encoder_init(encoder) != FLAC__FILE_ENCODER_OK)
return die_f_(0, encoder);
}
printf("OK\n");
+ printf("testing FLAC__file_encoder_get_total_samples_estimate()... ");
+ if(FLAC__file_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
+ printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, FLAC__file_encoder_get_total_samples_estimate(encoder));
+ return false;
+ }
+ printf("OK\n");
+
/* init the dummy sample buffer */
for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
samples[i] = i & 7;