finish implementation of --add-seekpoint
authorJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 8 Nov 2002 22:24:41 +0000 (22:24 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 8 Nov 2002 22:24:41 +0000 (22:24 +0000)
src/metaflac/operations_shorthand_seektable.c
src/metaflac/usage.c

index 7d20f24..c3ad407 100644 (file)
@@ -79,9 +79,8 @@ FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Me
 
        ok = populate_seekpoint_values(filename, block, needs_write);
 
-       if(ok) {
-               //@@@@ compact it
-       }
+       if(ok)
+               (void) FLAC__format_seektable_sort(&block->data.seek_table);
 
        return ok;
 }
@@ -93,6 +92,7 @@ FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Me
 typedef struct {
        FLAC__StreamMetadata_SeekTable *seektable_template;
        FLAC__uint64 samples_written;
+       FLAC__uint64 audio_offset, last_offset;
        unsigned first_seekpoint_to_check;
        FLAC__bool error_occurred;
        FLAC__StreamDecoderErrorStatus error_status;
@@ -102,48 +102,44 @@ static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *d
 {
        ClientData *cd = (ClientData*)client_data;
 
+       (void)buffer;
        FLAC__ASSERT(0 != cd);
 
        if(!cd->error_occurred && cd->seektable_template->num_points > 0) {
                const unsigned blocksize = frame->header.blocksize;
-               //@@@@
+               const FLAC__uint64 frame_first_sample = cd->samples_written;
+               const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
+               FLAC__uint64 test_sample;
+               unsigned i;
+               for(i = cd->first_seekpoint_to_check; i < cd->seektable_template->num_points; i++) {
+                       test_sample = cd->seektable_template->points[i].sample_number;
+                       if(test_sample > frame_last_sample) {
+                               break;
+                       }
+                       else if(test_sample >= frame_first_sample) {
+                               cd->seektable_template->points[i].sample_number = frame_first_sample;
+                               cd->seektable_template->points[i].stream_offset = cd->last_offset - cd->audio_offset;
+                               cd->seektable_template->points[i].frame_samples = blocksize;
+                               cd->first_seekpoint_to_check++;
+                               /* DO NOT: "break;" and here's why:
+                                * The seektable template may contain more than one target
+                                * sample for any given frame; we will keep looping, generating
+                                * duplicate seekpoints for them, and we'll clean it up later,
+                                * just before writing the seektable back to the metadata.
+                                */
+                       }
+                       else {
+                               cd->first_seekpoint_to_check++;
+                       }
+               }
                cd->samples_written += blocksize;
+               if(!FLAC__file_decoder_get_decode_position(decoder, &cd->last_offset))
+                       return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
                return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
        }
        else
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 }
-#if 0
-@@@@
-{
-       const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder);
-       const FLAC__uint64 frame_first_sample = seekable_stream_encoder->private_->samples_written;
-       const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
-       FLAC__uint64 test_sample;
-       unsigned i;
-       for(i = seekable_stream_encoder->private_->first_seekpoint_to_check; i < seekable_stream_encoder->private_->seek_table->num_points; i++) {
-               test_sample = seekable_stream_encoder->private_->seek_table->points[i].sample_number;
-               if(test_sample > frame_last_sample) {
-                       break;
-               }
-               else if(test_sample >= frame_first_sample) {
-                       seekable_stream_encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
-                       seekable_stream_encoder->private_->seek_table->points[i].stream_offset = seekable_stream_encoder->private_->bytes_written - seekable_stream_encoder->private_->stream_offset;
-                       seekable_stream_encoder->private_->seek_table->points[i].frame_samples = blocksize;
-                       seekable_stream_encoder->private_->first_seekpoint_to_check++;
-                       /* DO NOT: "break;" and here's why:
-                        * The seektable template may contain more than one target
-                        * sample for any given frame; we will keep looping, generating
-                        * duplicate seekpoints for them, and we'll clean it up later,
-                        * just before writing the seektable back to the metadata.
-                        */
-               }
-               else {
-                       seekable_stream_encoder->private_->first_seekpoint_to_check++;
-               }
-       }
-}
-#endif
 
 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
@@ -155,6 +151,7 @@ static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecode
 {
        ClientData *cd = (ClientData*)client_data;
 
+       (void)decoder;
        FLAC__ASSERT(0 != cd);
 
        if(!cd->error_occurred) { /* don't let multiple errors overwrite the first one */
@@ -174,6 +171,7 @@ FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata
 
        client_data.seektable_template = &block->data.seek_table;
        client_data.samples_written = 0;
+       /* client_data.audio_offset must be determined later */
        client_data.first_seekpoint_to_check = 0;
        client_data.error_occurred = false;
 
@@ -197,6 +195,17 @@ FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata
                ok = false;
        }
 
+       if(ok && !FLAC__file_decoder_process_until_end_of_metadata(decoder)) {
+               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__file_decoder_get_resolved_state_string(decoder));
+               ok = false;
+       }
+
+       if(ok && !FLAC__file_decoder_get_decode_position(decoder, &client_data.audio_offset)) {
+               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file\n", filename);
+               ok = false;
+       }
+       client_data.last_offset = client_data.audio_offset;
+
        if(ok && !FLAC__file_decoder_process_until_end_of_file(decoder)) {
                fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__file_decoder_get_resolved_state_string(decoder));
                ok = false;
@@ -207,6 +216,7 @@ FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata
                ok = false;
        }
 
+       *needs_write = true;
        FLAC__file_decoder_delete(decoder);
        return ok;
 }
index b4269b0..eb23954 100644 (file)
@@ -149,6 +149,19 @@ int long_usage(const char *message, ...)
        fprintf(out, "                      must have the same resolution, sample rate, and number\n");
        fprintf(out, "                      of channels.  The sample rate must be one of 8, 11.025,\n");
        fprintf(out, "                      12, 16, 22.05, 24, 32, 44.1, or 48 kHz.\n");
+       fprintf(out, "--add-seekpoint={#|X|#x|#s}  Add seek points to a SEEKTABLE block\n");
+       fprintf(out, "       #  : a specific sample number for a seek point\n");
+       fprintf(out, "       X  : a placeholder point (always goes at the end of the SEEKTABLE)\n");
+       fprintf(out, "       #x : # evenly spaced seekpoints, the first being at sample 0\n");
+       fprintf(out, "       #s : a seekpoint every # seconds; # does not have to be a whole number\n");
+       fprintf(out, "                      If no SEEKTABLE block exists, one will be created.  If\n");
+       fprintf(out, "                      one already exists, points will be added to the existing\n");
+       fprintf(out, "                      table, and duplicates will be turned into placeholder\n");
+       fprintf(out, "                      points.  You may use many --add-seekpoint options; the\n");
+       fprintf(out, "                      resulting SEEKTABLE will be the unique-ified union of\n");
+       fprintf(out, "                      all such values.  Example: --add-seekpoint=100x\n");
+       fprintf(out, "                      --add-seekpoint=3.5s will add 100 evenly spaced\n");
+       fprintf(out, "                      seekpoints and a seekpoint every 3.5 seconds.\n");
        fprintf(out, "--add-padding=length  Add a padding block of the given length (in bytes).\n");
        fprintf(out, "                      The overall length of the new block will be 4 + length;\n");
        fprintf(out, "                      the extra 4 bytes is for the metadata block header.\n");