new more flexible way of passing metadata to stream encoder
authorJosh Coalson <jcoalson@users.sourceforce.net>
Sat, 1 Jun 2002 05:39:38 +0000 (05:39 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Sat, 1 Jun 2002 05:39:38 +0000 (05:39 +0000)
include/FLAC/stream_encoder.h
src/libFLAC/include/protected/stream_encoder.h
src/libFLAC/stream_encoder.c

index fe2f35c..9c0a013 100644 (file)
@@ -41,7 +41,7 @@ typedef enum {
        FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER,
        FLAC__STREAM_ENCODER_NOT_STREAMABLE,
        FLAC__STREAM_ENCODER_FRAMING_ERROR,
-       FLAC__STREAM_ENCODER_INVALID_SEEK_TABLE,
+       FLAC__STREAM_ENCODER_INVALID_METADATA,
        FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING,
        FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING, /* that is, the write_callback returned an error */
        FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR,
@@ -80,30 +80,28 @@ typedef struct {
  * will take on the defaults from the constructor, shown below.
  * For more on what the parameters mean, see the documentation.
  *
- * FLAC__bool   streamable_subset              (DEFAULT: true ) true to limit encoder to generating a Subset stream, else false
- * FLAC__bool   do_mid_side_stereo             (DEFAULT: false) if true then channels must be 2
- * FLAC__bool   loose_mid_side_stereo          (DEFAULT: false) if true then do_mid_side_stereo must be true
- * unsigned     channels                       (DEFAULT: 2    ) must be <= FLAC__MAX_CHANNELS
- * unsigned     bits_per_sample                (DEFAULT: 16   ) do not give the encoder wider data than what you specify here or bad things will happen!
- * unsigned     sample_rate                    (DEFAULT: 44100)
- * unsigned     blocksize                      (DEFAULT: 1152 )
- * unsigned     max_lpc_order                  (DEFAULT: 0    ) 0 => encoder will not try general LPC, only fixed predictors; must be <= FLAC__MAX_LPC_ORDER
- * unsigned     qlp_coeff_precision            (DEFAULT: 0    ) >= FLAC__MIN_QLP_COEFF_PRECISION, or 0 to let encoder select based on blocksize;
- *                                                          qlp_coeff_precision+bits_per_sample must be < 32
- * FLAC__bool   do_qlp_coeff_prec_search       (DEFAULT: false) false => use qlp_coeff_precision, true => search around qlp_coeff_precision, take best
- * FLAC__bool   do_escape_coding               (DEFAULT: false) true => search for escape codes in the entropy coding stage for slightly better compression
- * FLAC__bool   do_exhaustive_model_search     (DEFAULT: false) false => use estimated bits per residual for scoring, true => generate all, take shortest
- * unsigned     min_residual_partition_order   (DEFAULT: 0    ) 0 => estimate Rice parameter based on residual variance; >0 => partition residual, use parameter
- * unsigned     max_residual_partition_order   (DEFAULT: 0    )      for each based on mean; min_ and max_ specify the min and max Rice partition order
- * unsigned     rice_parameter_search_dist     (DEFAULT: 0    ) 0 => try only calc'd parameter k; else try all [k-dist..k+dist] parameters, use best
- * FLAC__uint64 total_samples_estimate         (DEFAULT: 0    ) may be 0 if unknown.  acts as a placeholder in the STREAMINFO until the actual total is calculated
- * const FLAC__StreamMetaData_SeekTable *seek_table  (DEFAULT: NULL) optional seek_table to prepend, NULL => no seek table
- * int          padding                        (DEFAULT: -1   ) length of PADDING block to add (goes after seek table); -1 => do not add a PADDING block
- * FLAC__bool   last_metadata_is_last          (DEFAULT: true ) the value the encoder will use for the 'is_last' flag of the last metadata block it writes; set
- *                                                          this to false if you will be adding more metadata blocks before the audio frames, else true
- *            (*write_callback)()              (DEFAULT: NULL ) The callbacks are the only values that MUST be set before FLAC__stream_encoder_init()
- *            (*metadata_callback)()           (DEFAULT: NULL )
- * void*        client_data                    (DEFAULT: NULL ) passed back through the callbacks
+ * FLAC__bool   streamable_subset             (DEFAULT: true  ) true to limit encoder to generating a Subset stream, else false
+ * FLAC__bool   do_mid_side_stereo            (DEFAULT: false ) if true then channels must be 2
+ * FLAC__bool   loose_mid_side_stereo         (DEFAULT: false ) if true then do_mid_side_stereo must be true
+ * unsigned     channels                      (DEFAULT: 2     ) must be <= FLAC__MAX_CHANNELS
+ * unsigned     bits_per_sample               (DEFAULT: 16    ) do not give the encoder wider data than what you specify here or bad things will happen!
+ * unsigned     sample_rate                   (DEFAULT: 44100 )
+ * unsigned     blocksize                     (DEFAULT: 1152  )
+ * unsigned     max_lpc_order                 (DEFAULT: 0     ) 0 => encoder will not try general LPC, only fixed predictors; must be <= FLAC__MAX_LPC_ORDER
+ * unsigned     qlp_coeff_precision           (DEFAULT: 0     ) >= FLAC__MIN_QLP_COEFF_PRECISION, or 0 to let encoder select based on blocksize;
+ *                                                              qlp_coeff_precision+bits_per_sample must be < 32
+ * FLAC__bool   do_qlp_coeff_prec_search      (DEFAULT: false ) false => use qlp_coeff_precision, true => search around qlp_coeff_precision, take best
+ * FLAC__bool   do_escape_coding              (DEFAULT: false ) true => search for escape codes in the entropy coding stage for slightly better compression
+ * FLAC__bool   do_exhaustive_model_search    (DEFAULT: false ) false => use estimated bits per residual for scoring, true => generate all, take shortest
+ * unsigned     min_residual_partition_order  (DEFAULT: 0     ) 0 => estimate Rice parameter based on residual variance; >0 => partition residual, use parameter
+ * unsigned     max_residual_partition_order  (DEFAULT: 0     )      for each based on mean; min_ and max_ specify the min and max Rice partition order
+ * unsigned     rice_parameter_search_dist    (DEFAULT: 0     ) 0 => try only calc'd parameter k; else try all [k-dist..k+dist] parameters, use best
+ * FLAC__uint64 total_samples_estimate        (DEFAULT: 0     ) may be 0 if unknown.  acts as a placeholder in the STREAMINFO until the actual total is calculated
+ * FLAC__StreamMetaData **metadata            (DEFAULT: NULL,0) optional metadata blocks to prepend.  STREAMINFO is not allowed since it is done internally.
+ * + unsigned num_blocks
+ *            (*write_callback)()             (DEFAULT: NULL  ) The callbacks are the only values that MUST be set before FLAC__stream_encoder_init()
+ *            (*metadata_callback)()          (DEFAULT: NULL  )
+ * void*        client_data                   (DEFAULT: NULL  ) passed back through the callbacks
  */
 FLAC__StreamEncoder *FLAC__stream_encoder_new();
 void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder);
@@ -148,9 +146,7 @@ FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEnc
 FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value);
 FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value);
 FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value);
-FLAC__bool FLAC__stream_encoder_set_seek_table(FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData_SeekTable *value);
-FLAC__bool FLAC__stream_encoder_set_padding(FLAC__StreamEncoder *encoder, int value);
-FLAC__bool FLAC__stream_encoder_set_last_metadata_is_last(FLAC__StreamEncoder *encoder, FLAC__bool value);
+FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetaData **metadata, unsigned num_blocks);
 FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteStatus (*value)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data));
 FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, void (*value)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data));
 FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value);
index a900bbe..5d4dcd2 100644 (file)
@@ -40,9 +40,8 @@ typedef struct FLAC__StreamEncoderProtected {
        unsigned max_residual_partition_order;
        unsigned rice_parameter_search_dist;
        FLAC__uint64 total_samples_estimate;
-       const FLAC__StreamMetaData_SeekTable *seek_table;
-       int padding;
-       FLAC__bool last_metadata_is_last;
+       FLAC__StreamMetaData **metadata;
+       unsigned num_metadata_blocks;
 } FLAC__StreamEncoderProtected;
 
 #endif
index 4efa20c..b34176d 100644 (file)
@@ -156,7 +156,7 @@ const char *FLAC__StreamEncoderStateString[] = {
        "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
        "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
        "FLAC__STREAM_ENCODER_FRAMING_ERROR",
-       "FLAC__STREAM_ENCODER_INVALID_SEEK_TABLE",
+       "FLAC__STREAM_ENCODER_INVALID_METADATA",
        "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
        "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
        "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
@@ -221,9 +221,8 @@ FLAC__StreamEncoder *FLAC__stream_encoder_new()
        encoder->protected_->max_residual_partition_order = 0;
        encoder->protected_->rice_parameter_search_dist = 0;
        encoder->protected_->total_samples_estimate = 0;
-       encoder->protected_->seek_table = 0;
-       encoder->protected_->padding = -1;
-       encoder->protected_->last_metadata_is_last = true;
+       encoder->protected_->metadata = 0;
+       encoder->protected_->num_metadata_blocks = 0;
 
        encoder->private_->write_callback = 0;
        encoder->private_->metadata_callback = 0;
@@ -254,8 +253,6 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
 FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
 {
        unsigned i;
-       FLAC__StreamMetaData padding_block;
-       FLAC__StreamMetaData seek_table_block;
 
        FLAC__ASSERT(encoder != 0);
 
@@ -333,6 +330,18 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
                encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
 
+       /* validate metadata */
+       if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
+               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+       for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
+               if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
+                       return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+               else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
+                       if(!FLAC__seek_table_is_valid(&encoder->protected_->metadata[i]->data.seek_table))
+                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+               }
+       }
+
        encoder->private_->input_capacity = 0;
        for(i = 0; i < encoder->protected_->channels; i++) {
                encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
@@ -441,7 +450,7 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
                return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
 
        encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
-       encoder->private_->metadata.is_last = (encoder->protected_->seek_table == 0 && encoder->protected_->padding < 0 && encoder->protected_->last_metadata_is_last);
+       encoder->private_->metadata.is_last = (encoder->protected_->num_metadata_blocks == 0);
        encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
        encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
        encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
@@ -456,23 +465,9 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
                return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
 
-       if(0 != encoder->protected_->seek_table) {
-               if(!FLAC__seek_table_is_valid(encoder->protected_->seek_table))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SEEK_TABLE;
-               seek_table_block.type = FLAC__METADATA_TYPE_SEEKTABLE;
-               seek_table_block.is_last = (encoder->protected_->padding < 0 && encoder->protected_->last_metadata_is_last);
-               seek_table_block.length = encoder->protected_->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
-               seek_table_block.data.seek_table = *encoder->protected_->seek_table;
-               if(!FLAC__add_metadata_block(&seek_table_block, encoder->private_->frame))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
-       }
-
-       /* add a PADDING block if requested */
-       if(encoder->protected_->padding >= 0) {
-               padding_block.type = FLAC__METADATA_TYPE_PADDING;
-               padding_block.is_last = encoder->protected_->last_metadata_is_last;
-               padding_block.length = (unsigned)encoder->protected_->padding;
-               if(!FLAC__add_metadata_block(&padding_block, encoder->private_->frame))
+       for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
+               encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
+               if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
                        return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
        }
 
@@ -691,27 +686,12 @@ FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *
        return true;
 }
 
-FLAC__bool FLAC__stream_encoder_set_seek_table(FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData_SeekTable *value)
-{
-       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->protected_->seek_table = value;
-       return true;
-}
-
-FLAC__bool FLAC__stream_encoder_set_padding(FLAC__StreamEncoder *encoder, int value)
-{
-       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->protected_->padding = value;
-       return true;
-}
-
-FLAC__bool FLAC__stream_encoder_set_last_metadata_is_last(FLAC__StreamEncoder *encoder, FLAC__bool value)
+FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetaData **metadata, unsigned num_blocks)
 {
        if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       encoder->protected_->last_metadata_is_last = value;
+       encoder->protected_->metadata = metadata;
+       encoder->protected_->num_metadata_blocks = num_blocks;
        return true;
 }