add ..._get_total_samples_estimate(), add progress callback to file encoder
authorJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 2 Aug 2002 07:40:38 +0000 (07:40 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 2 Aug 2002 07:40:38 +0000 (07:40 +0000)
include/FLAC++/encoder.h
include/FLAC/file_encoder.h
src/libFLAC++/file_encoder.cc
src/libFLAC/file_encoder.c
src/test_libFLAC++/encoders.cc
src/test_libFLAC/encoders.c

index 39eddb0..c5e1709 100644 (file)
@@ -131,6 +131,7 @@ namespace FLAC {
                        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'
@@ -221,6 +222,7 @@ namespace FLAC {
                        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'
@@ -313,6 +315,7 @@ namespace FLAC {
                        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'
@@ -324,11 +327,11 @@ namespace FLAC {
                        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 &);
index 66b3bdf..bf43114 100644 (file)
@@ -150,6 +150,9 @@ typedef struct {
        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);
+
 
 /***********************************************************************
  *
@@ -431,6 +434,41 @@ FLAC__bool FLAC__file_encoder_set_metadata(FLAC__FileEncoder *encoder, FLAC__Str
  */
 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.
@@ -509,7 +547,7 @@ FLAC__bool FLAC__file_encoder_get_loose_mid_side_stereo(const FLAC__FileEncoder
  * \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);
@@ -521,7 +559,7 @@ 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);
@@ -533,7 +571,7 @@ 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);
@@ -545,7 +583,7 @@ 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);
@@ -557,7 +595,7 @@ 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);
@@ -569,7 +607,7 @@ 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);
@@ -617,7 +655,7 @@ FLAC__bool FLAC__file_encoder_get_do_exhaustive_model_search(const FLAC__FileEnc
  * \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);
@@ -629,7 +667,7 @@ unsigned FLAC__file_encoder_get_min_residual_partition_order(const FLAC__FileEnc
  * \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);
@@ -641,11 +679,23 @@ unsigned FLAC__file_encoder_get_max_residual_partition_order(const FLAC__FileEnc
  * \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()
index 9d24cfe..5723ae9 100644 (file)
@@ -256,9 +256,17 @@ namespace FLAC {
                        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_));
                }
 
@@ -280,5 +288,19 @@ namespace FLAC {
                        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);
+               }
+
        };
 };
index 3bfbaab..01bf3c4 100644 (file)
@@ -41,9 +41,12 @@ static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStream
  ***********************************************************************/
 
 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;
 
 /***********************************************************************
@@ -154,6 +157,13 @@ FLAC__FileEncoderState FLAC__file_encoder_init(FLAC__FileEncoder *encoder)
        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;
 }
 
@@ -392,6 +402,28 @@ FLAC__bool FLAC__file_encoder_set_filename(FLAC__FileEncoder *encoder, const cha
        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);
@@ -518,6 +550,13 @@ unsigned FLAC__file_encoder_get_rice_parameter_search_dist(const FLAC__FileEncod
        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);
@@ -545,6 +584,9 @@ void set_defaults_(FLAC__FileEncoder *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;
 }
 
@@ -570,8 +612,11 @@ FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder
 
        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;
 }
index 1175e57..854ed70 100644 (file)
@@ -377,6 +377,13 @@ static bool test_stream_encoder()
        }
        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;
@@ -673,6 +680,13 @@ static bool test_seekable_stream_encoder()
        }
        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;
@@ -706,11 +720,16 @@ public:
        ~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();
@@ -967,6 +986,13 @@ static bool test_file_encoder()
        }
        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;
index 4b6f018..5660b82 100644 (file)
@@ -413,6 +413,13 @@ static FLAC__bool test_stream_encoder()
        }
        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;
@@ -682,6 +689,13 @@ static FLAC__bool test_seekable_stream_encoder()
        }
        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;
@@ -709,6 +723,11 @@ static FLAC__bool test_seekable_stream_encoder()
        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;
@@ -817,6 +836,16 @@ static FLAC__bool test_file_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);
@@ -929,6 +958,13 @@ static FLAC__bool test_file_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;