From cb9d93ad4dd46a4b54bb1690cf12641463d6f53b Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Sun, 25 Aug 2002 05:27:15 +0000 Subject: [PATCH] add vendor string to encoding --- include/FLAC/format.h | 12 ++++++++--- src/libFLAC/format.c | 1 + src/libFLAC/stream_encoder.c | 39 +++++++++++++++++++++++++++++++++++- src/libFLAC/stream_encoder_framing.c | 18 +++++++++++++---- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/include/FLAC/format.h b/include/FLAC/format.h index c274b59..0ac6e3b 100644 --- a/include/FLAC/format.h +++ b/include/FLAC/format.h @@ -131,16 +131,22 @@ extern "C" { #define FLAC__VERSION_STRING VERSION #endif +/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. + * This is a nulL-terminated ASCII string; when inserted into the + * VORBIS_COMMENT the trailing null is stripped. + */ +extern const FLAC__byte *FLAC__VENDOR_STRING; + /** The byte string representation of the beginning of a FLAC stream. */ -extern const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */; +extern const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ /** The 32-bit integer big-endian representation of the beginning of * a FLAC stream. */ -extern const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */; +extern const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ /** The length of the FLAC signature in bits. */ -extern const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */; +extern const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ /** The length of the FLAC signature in bytes. */ #define FLAC__STREAM_SYNC_LENGTH (4u) diff --git a/src/libFLAC/format.c b/src/libFLAC/format.c index f52c38a..cf933cf 100644 --- a/src/libFLAC/format.c +++ b/src/libFLAC/format.c @@ -28,6 +28,7 @@ #endif #define min(a,b) ((a)<(b)?(a):(b)) +const FLAC__byte *FLAC__VENDOR_STRING = "reference libFLAC " FLAC__VERSION_STRING " 20020823"; const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; const unsigned FLAC__STREAM_SYNC = 0x664C6143; const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */; diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c index d8ab93e..3eb43f5 100644 --- a/src/libFLAC/stream_encoder.c +++ b/src/libFLAC/stream_encoder.c @@ -533,6 +533,7 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder) FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) { unsigned i; + FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment; FLAC__ASSERT(0 != encoder); @@ -613,13 +614,23 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) /* validate metadata */ if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA; + metadata_has_seektable = false; + metadata_has_vorbis_comment = false; 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(metadata_has_seektable) /* only one is allowed */ + return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA; + metadata_has_seektable = true; if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table)) return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA; } + else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + if(metadata_has_vorbis_comment) /* only one is allowed */ + return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA; + metadata_has_vorbis_comment = true; + } } encoder->private_->input_capacity = 0; @@ -770,7 +781,7 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) if(encoder->protected_->verify) encoder->private_->verify.state_hint = ENCODER_IN_METADATA; encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO; - encoder->private_->metadata.is_last = (encoder->protected_->num_metadata_blocks == 0); + encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */ 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; @@ -802,6 +813,32 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) encoder->private_->metadata.data.stream_info.total_samples = 0; /* + * Check to see if the supplied metadata contains a VORBIS_COMMENT; + * if not, we will write an empty one (FLAC__add_metadata_block() + * automatically supplies the vendor string). + */ + if(!metadata_has_vorbis_comment) { + FLAC__StreamMetadata vorbis_comment; + vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT; + vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0); + vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */ + vorbis_comment.data.vorbis_comment.vendor_string.length = 0; + vorbis_comment.data.vorbis_comment.vendor_string.entry = 0; + vorbis_comment.data.vorbis_comment.num_comments = 0; + vorbis_comment.data.vorbis_comment.comments = 0; + if(!FLAC__bitbuffer_clear(encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame)) + return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + if(!write_bitbuffer_(encoder, 0)) { + /* the above function sets the state for us in case of an error */ + return encoder->protected_->state; + } + } + + /* * write the user's metadata blocks */ for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { diff --git a/src/libFLAC/stream_encoder_framing.c b/src/libFLAC/stream_encoder_framing.c index 63b72a4..95a701d 100644 --- a/src/libFLAC/stream_encoder_framing.c +++ b/src/libFLAC/stream_encoder_framing.c @@ -18,6 +18,7 @@ */ #include +#include /* for strlen() */ #include "private/stream_encoder_framing.h" #include "private/crc.h" #include "FLAC/assert.h" @@ -33,6 +34,7 @@ static FLAC__bool add_residual_partitioned_rice_(FLAC__BitBuffer *bb, const FLAC FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitBuffer *bb) { unsigned i; + const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING); if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN)) return false; @@ -40,8 +42,16 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN)) return false; - FLAC__ASSERT(metadata->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); - if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->length, FLAC__STREAM_METADATA_LENGTH_LEN)) + /* + * First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string + */ + i = metadata->length; + if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + i -= metadata->data.vorbis_comment.vendor_string.length; + i += vendor_string_length; + } + FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); + if(!FLAC__bitbuffer_write_raw_uint32(bb, i, FLAC__STREAM_METADATA_LENGTH_LEN)) return false; switch(metadata->type) { @@ -95,9 +105,9 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__ } break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: - if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, metadata->data.vorbis_comment.vendor_string.length)) + if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, vendor_string_length)) return false; - if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.vorbis_comment.vendor_string.entry, metadata->data.vorbis_comment.vendor_string.length)) + if(!FLAC__bitbuffer_write_byte_block(bb, FLAC__VENDOR_STRING, vendor_string_length)) return false; if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, metadata->data.vorbis_comment.num_comments)) return false; -- 2.7.4