From 3692297eeef5d5b38647dcc9bc785d0884bf22fa Mon Sep 17 00:00:00 2001 From: Ian Nartowicz Date: Fri, 13 Jun 2014 22:55:16 +0100 Subject: bitrate calculations --- plugins/flac/flac.c | 111 ++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 64 deletions(-) (limited to 'plugins') diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index 50e82739..4f4e7100 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -47,12 +47,12 @@ #include "../artwork/artwork.h" #include "../liboggedit/oggedit.h" - static DB_decoder_t plugin; - static DB_functions_t *deadbeef; +static DB_decoder_t plugin; +static DB_functions_t *deadbeef; - static DB_artwork_plugin_t *coverart_plugin = NULL; +static DB_artwork_plugin_t *coverart_plugin = NULL; - //#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } #define trace(fmt,...) #define min(x,y) ((x)<(y)?(x):(y)) @@ -60,40 +60,39 @@ #define BUFFERSIZE 100000 - typedef struct { - DB_fileinfo_t info; - FLAC__StreamDecoder *decoder; - char *buffer; // this buffer always has float samples - int remaining; // bytes remaining in buffer from last read - int64_t startsample; - int64_t endsample; - int64_t currentsample; - int64_t totalsamples; - int flac_critical_error; - int init_stop_decoding; - int tagsize; - DB_FILE *file; - - // used only on insert - ddb_playlist_t *plt; - DB_playItem_t *after; - DB_playItem_t *last; - DB_playItem_t *it; - const char *fname; - int bitrate; - FLAC__StreamMetadata *flac_cue_sheet; - } flac_info_t; - - // callbacks - FLAC__StreamDecoderReadStatus flac_read_cb (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { - flac_info_t *info = (flac_info_t *)client_data; - size_t r = deadbeef->fread (buffer, 1, *bytes, info->file); - *bytes = r; - if (r == 0) { - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - } - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +typedef struct { + DB_fileinfo_t info; + FLAC__StreamDecoder *decoder; + char *buffer; // this buffer always has float samples + int remaining; // bytes remaining in buffer from last read + int64_t startsample; + int64_t endsample; + int64_t currentsample; + int64_t totalsamples; + int flac_critical_error; + int init_stop_decoding; + DB_FILE *file; + + // used only on insert + ddb_playlist_t *plt; + DB_playItem_t *after; + DB_playItem_t *last; + DB_playItem_t *it; + const char *fname; + int bitrate; + FLAC__StreamMetadata *flac_cue_sheet; +} flac_info_t; + +// callbacks +FLAC__StreamDecoderReadStatus flac_read_cb (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) { + flac_info_t *info = (flac_info_t *)client_data; + size_t r = deadbeef->fread (buffer, 1, *bytes, info->file); + *bytes = r; + if (r == 0) { + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; } + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} FLAC__StreamDecoderSeekStatus flac_seek_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { flac_info_t *info = (flac_info_t *)client_data; @@ -131,9 +130,6 @@ cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *fra if (frame->header.blocksize == 0) { return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } - if (info->bitrate > 0) { - deadbeef->streamer_set_bitrate (info->bitrate); - } int samplesize = _info->fmt.channels * _info->fmt.bps / 8; int bufsize = BUFFERSIZE - info->remaining; int bufsamples = bufsize / samplesize; @@ -314,26 +310,8 @@ cflac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { fprintf (stderr, "corrupted/invalid flac stream\n"); return -1; } + info->bitrate = deadbeef->pl_find_meta_int(it, ":BITRATE", -1); - // bitrate - size_t fsize = deadbeef->fgetlength (info->file); - FLAC__uint64 position; - FLAC__bool res = FLAC__stream_decoder_get_decode_position (info->decoder, &position); - if (res) { - fsize -= position; - } - int64_t totalsamples = FLAC__stream_decoder_get_total_samples (info->decoder); - if (totalsamples <= 0) { - trace ("flac: totalsamples=%lld\n", totalsamples); -// return -1; - } - float sec = totalsamples / (float)_info->fmt.samplerate; - if (sec > 0) { - info->bitrate = fsize / sec * 8 / 1000; - } - else { - info->bitrate = -1; - } deadbeef->pl_lock (); { const char *channelmask = deadbeef->pl_find_meta (it, "WAVEFORMAT_EXTENSIBLE_CHANNELMASK"); @@ -395,6 +373,9 @@ cflac_free (DB_fileinfo_t *_info) { static int cflac_read (DB_fileinfo_t *_info, char *bytes, int size) { flac_info_t *info = (flac_info_t *)_info; + if (info->bitrate != deadbeef->streamer_get_apx_bitrate()) { + deadbeef->streamer_set_bitrate (info->bitrate); + } int samplesize = _info->fmt.channels * _info->fmt.bps / 8; if (info->endsample >= 0) { if (size / samplesize + info->currentsample > info->endsample) { @@ -592,7 +573,7 @@ cflac_add_metadata (DB_playItem_t *it, const char *s, int length) { static void cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { flac_info_t *info = (flac_info_t *)client_data; - info->tagsize += metadata->length; +// info->tagsize += metadata->length; DB_fileinfo_t *_info = &info->info; if (info->init_stop_decoding) { trace ("error flag is set, ignoring init_metadata callback..\n"); @@ -793,8 +774,6 @@ cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { trace ("flac: FLAC__stream_decoder_process_until_end_of_metadata [2] failed\n"); goto cflac_insert_fail; } - FLAC__stream_decoder_delete(decoder); - decoder = NULL; if (info.info.fmt.samplerate <= 0) { goto cflac_insert_fail; @@ -813,9 +792,13 @@ cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { snprintf (s, sizeof (s), "%d", info.info.fmt.samplerate); deadbeef->pl_add_meta (it, ":SAMPLERATE", s); if ( deadbeef->pl_get_item_duration (it) > 0) { - snprintf (s, sizeof (s), "%d", (int)roundf((fsize-info.tagsize) / deadbeef->pl_get_item_duration (it) * 8 / 1000)); - deadbeef->pl_add_meta (it, ":BITRATE", s); + FLAC__uint64 position; + if (FLAC__stream_decoder_get_decode_position (decoder, &position)) + fsize -= position; + deadbeef->pl_set_meta_int (it, ":BITRATE", (int)roundf(fsize / deadbeef->pl_get_item_duration (it) * 8 / 1000)); } + FLAC__stream_decoder_delete(decoder); + decoder = NULL; // try embedded cue deadbeef->pl_lock (); -- cgit v1.2.3 From 17463ab388e7c2a95db8f19e41a1fad459a63717 Mon Sep 17 00:00:00 2001 From: Ian Nartowicz Date: Fri, 13 Jun 2014 23:02:05 +0100 Subject: tidy up --- plugins/flac/flac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins') diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index 4f4e7100..7cb38458 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -573,7 +573,6 @@ cflac_add_metadata (DB_playItem_t *it, const char *s, int length) { static void cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { flac_info_t *info = (flac_info_t *)client_data; -// info->tagsize += metadata->length; DB_fileinfo_t *_info = &info->info; if (info->init_stop_decoding) { trace ("error flag is set, ignoring init_metadata callback..\n"); -- cgit v1.2.3 From caf400178adbcaaace2a258354b7310067726a04 Mon Sep 17 00:00:00 2001 From: Ian Nartowicz Date: Sat, 14 Jun 2014 00:10:49 +0100 Subject: bitrate for OggFLAC, plus oggedit changes --- plugins/flac/flac.c | 15 ++++++++++++--- plugins/liboggedit/oggedit.h | 1 + plugins/liboggedit/oggedit_flac.c | 11 ++++++++++- plugins/liboggedit/oggedit_internal.c | 32 +++++++++++++++++--------------- plugins/liboggedit/oggedit_internal.h | 2 +- plugins/liboggedit/oggedit_opus.c | 9 ++++----- plugins/liboggedit/oggedit_vorbis.c | 5 ++--- 7 files changed, 47 insertions(+), 28 deletions(-) (limited to 'plugins') diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index 7cb38458..5deab23e 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -791,9 +791,18 @@ cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { snprintf (s, sizeof (s), "%d", info.info.fmt.samplerate); deadbeef->pl_add_meta (it, ":SAMPLERATE", s); if ( deadbeef->pl_get_item_duration (it) > 0) { - FLAC__uint64 position; - if (FLAC__stream_decoder_get_decode_position (decoder, &position)) - fsize -= position; + if (!isogg) { + FLAC__uint64 position; + if (FLAC__stream_decoder_get_decode_position (decoder, &position)) + fsize -= position; + } +#if USE_OGGEDIT + else { + const off_t stream_size = oggedit_flac_stream_info(deadbeef->fopen(fname), 0, 0); + if (stream_size > 0) + fsize = stream_size; + } +#endif deadbeef->pl_set_meta_int (it, ":BITRATE", (int)roundf(fsize / deadbeef->pl_get_item_duration (it) * 8 / 1000)); } FLAC__stream_decoder_delete(decoder); diff --git a/plugins/liboggedit/oggedit.h b/plugins/liboggedit/oggedit.h index b0a4d9b0..94f08e32 100644 --- a/plugins/liboggedit/oggedit.h +++ b/plugins/liboggedit/oggedit.h @@ -79,6 +79,7 @@ const char *oggedit_album_art_type(const int type); char *oggedit_album_art_tag(DB_FILE *fp, int *res); /* oggedit_flac.c */ +off_t oggedit_flac_stream_info(DB_FILE *in, const off_t start_offset, const off_t end_offset); off_t oggedit_write_flac_metadata(DB_FILE *in, const char *fname, const off_t offset, const int num_tags, char **tags); /* oggedit_vorbis.c */ diff --git a/plugins/liboggedit/oggedit_flac.c b/plugins/liboggedit/oggedit_flac.c index 7c4e5653..9aa89716 100644 --- a/plugins/liboggedit/oggedit_flac.c +++ b/plugins/liboggedit/oggedit_flac.c @@ -36,6 +36,15 @@ #define VCTYPE 0x04 #define LASTBLOCK 0x80 +off_t oggedit_flac_stream_info(DB_FILE *in, const off_t start_offset, const off_t end_offset) +{ + ogg_sync_state oy; + ogg_sync_init(&oy); + const off_t stream_size = codec_stream_size(in, &oy, start_offset, end_offset, FLACNAME); + cleanup(in, NULL, &oy, NULL); + return stream_size; +} + static void clear_header_list(ogg_packet **headers) { if (headers) { @@ -196,7 +205,7 @@ off_t oggedit_write_flac_metadata(DB_FILE *in, const char *fname, const off_t of /* If we have tempfile, copy the remaining pages */ if (*tempname) { - if ((res = copy_remaining_pages(in, out, &oy, flac_serial, pageno)) < OGGEDIT_EOF) + if ((res = copy_remaining_pages(in, out, &oy, flac_serial, pageno)) <= OGGEDIT_EOF) goto cleanup; if (rename(tempname, fname)) { res = OGGEDIT_RENAME_FAILED; diff --git a/plugins/liboggedit/oggedit_internal.c b/plugins/liboggedit/oggedit_internal.c index 130a6fed..f3c9b2d9 100644 --- a/plugins/liboggedit/oggedit_internal.c +++ b/plugins/liboggedit/oggedit_internal.c @@ -285,25 +285,21 @@ long flush_stream(FILE *out, ogg_stream_state *os) return pageno; } -char *codec_names(DB_FILE *in, ogg_sync_state *oy, const off_t link_offset, int *res) +char *codec_names(DB_FILE *in, ogg_sync_state *oy, const off_t link_offset) { ogg_page og; - *res = skip_to_bos(in, oy, &og, link_offset); + int serial = skip_to_bos(in, oy, &og, link_offset); char *codecs = strdup("Ogg"); - while (codecs && *res > OGGEDIT_EOF && ogg_page_bos(&og)) { + while (codecs && serial > OGGEDIT_EOF && ogg_page_bos(&og)) { codecs = cat_string(codecs, codec_name(&og), strcmp(codecs, "Ogg") ? "/" : " "); - *res = get_page(in, oy, &og); - } - if (!*codecs) { - *res = OGGEDIT_ALLOCATION_FAILURE; - return NULL; + serial = get_page(in, oy, &og); } - if (*res <= OGGEDIT_EOF) { + + if (serial <= OGGEDIT_EOF) { free(codecs); return NULL; } - *res = OGGEDIT_OK; return codecs; } @@ -324,8 +320,9 @@ off_t codec_stream_size(DB_FILE *in, ogg_sync_state *oy, const off_t start_offse /* Skip to the first codec data page */ while (serial > OGGEDIT_EOF && !(ogg_page_granulepos(&og) > 0 && serial == codec_serial)) - if ((serial = get_page(in, oy, &og)) <= OGGEDIT_EOF) - return serial; + serial = get_page(in, oy, &og); + if (serial <= OGGEDIT_EOF) + return serial; off_t stream_size = 0; if (multiplex) { @@ -465,6 +462,8 @@ int copy_remaining_pages(DB_FILE *in, FILE *out, ogg_sync_state *oy, const int c do serial = get_page(in, oy, &og); while (serial > OGGEDIT_EOF && serial == codec_serial && ogg_page_granulepos(&og) <= 0); + if (serial <= OGGEDIT_EOF) + return serial; /* Renumber the rest of this link */ while (serial > OGGEDIT_EOF && !ogg_page_bos(&og)) { @@ -481,8 +480,10 @@ int copy_remaining_pages(DB_FILE *in, FILE *out, ogg_sync_state *oy, const int c /* Blindly copy remaining links */ while (serial > OGGEDIT_EOF) serial = write_page_and_get_next(in, out, oy, &og); + if (serial < OGGEDIT_EOF) + return serial; - return serial; + return OGGEDIT_OK; } int write_all_streams(DB_FILE *in, FILE *out, ogg_sync_state *oy, const off_t offset) @@ -497,8 +498,9 @@ int write_all_streams(DB_FILE *in, FILE *out, ogg_sync_state *oy, const off_t of /* Copy all pages until EOF or next link */ while (serial > OGGEDIT_EOF && !ogg_page_bos(&og)) - if ((serial = write_page_and_get_next(in, out, oy, &og)) < OGGEDIT_EOF) - return serial; + serial = write_page_and_get_next(in, out, oy, &og); + if (serial < OGGEDIT_EOF) + return serial; return OGGEDIT_OK; } diff --git a/plugins/liboggedit/oggedit_internal.h b/plugins/liboggedit/oggedit_internal.h index a52b2ae4..d050ac72 100644 --- a/plugins/liboggedit/oggedit_internal.h +++ b/plugins/liboggedit/oggedit_internal.h @@ -53,7 +53,7 @@ void cleanup(DB_FILE *in, FILE *out, ogg_sync_state *oy, void *buffer); int copy_up_to_codec(DB_FILE *in, FILE *out, ogg_sync_state *oy, ogg_page *og, const off_t start_offset, const off_t link_offset, const char *codec); int copy_up_to_header(DB_FILE *in, FILE *out, ogg_sync_state *oy, ogg_page *og, const int codec_serial); long flush_stream(FILE *out, ogg_stream_state *os); -char *codec_names(DB_FILE *in, ogg_sync_state *oy, const off_t link_offset, int *res); +char *codec_names(DB_FILE *in, ogg_sync_state *oy, const off_t link_offset); off_t codec_stream_size(DB_FILE *in, ogg_sync_state *oy, const off_t start_offset, const off_t end_offset, const char *codec); char *parse_vendor(const ogg_packet *op, const size_t magic_length); int init_read_stream(DB_FILE *in, ogg_sync_state *oy, ogg_stream_state *os, ogg_page *og, const off_t offset, const char *codec); diff --git a/plugins/liboggedit/oggedit_opus.c b/plugins/liboggedit/oggedit_opus.c index 5533a619..21d75360 100644 --- a/plugins/liboggedit/oggedit_opus.c +++ b/plugins/liboggedit/oggedit_opus.c @@ -60,10 +60,9 @@ int oggedit_write_opus_file(DB_FILE *in, const char *outname, const off_t offset off_t oggedit_opus_stream_info(DB_FILE *in, const off_t start_offset, const off_t end_offset, char **codecs) { - int res; ogg_sync_state oy; ogg_sync_init(&oy); - *codecs = codec_names(in, &oy, start_offset, &res); + *codecs = codec_names(in, &oy, start_offset); const off_t stream_size = codec_stream_size(in, &oy, start_offset, end_offset, OPUSNAME); cleanup(in, NULL, &oy, NULL); return stream_size; @@ -174,7 +173,7 @@ off_t oggedit_write_opus_metadata(DB_FILE *in, const char *fname, const off_t of /* If we have tempfile, copy the remaining pages */ if (*tempname) { - if ((res = copy_remaining_pages(in, out, &oy, opus_serial, pageno)) < OGGEDIT_EOF) + if ((res = copy_remaining_pages(in, out, &oy, opus_serial, pageno)) <= OGGEDIT_EOF) goto cleanup; if (rename(tempname, fname)) { res = OGGEDIT_RENAME_FAILED; @@ -193,8 +192,8 @@ cleanup: /* struct timeval timeval; gettimeofday(&timeval, NULL); -int usecs = timeval.tv_sec* 1000000 + timeval.tv_usec; +int usecs = timeval.tv_sec*1000000 + timeval.tv_usec; gettimeofday(&timeval, NULL); -usecs = timeval.tv_sec* 1000000 + timeval.tv_usec - usecs; +usecs = timeval.tv_sec*1000000 + timeval.tv_usec - usecs; fprintf(stderr, "%d micro-seconds\n", usecs); */ diff --git a/plugins/liboggedit/oggedit_vorbis.c b/plugins/liboggedit/oggedit_vorbis.c index e1252411..9d97b076 100644 --- a/plugins/liboggedit/oggedit_vorbis.c +++ b/plugins/liboggedit/oggedit_vorbis.c @@ -37,10 +37,9 @@ off_t oggedit_vorbis_stream_info(DB_FILE *in, const off_t start_offset, const off_t end_offset, char **codecs) { - int res; ogg_sync_state oy; ogg_sync_init(&oy); - *codecs = codec_names(in, &oy, start_offset, &res); + *codecs = codec_names(in, &oy, start_offset); const off_t stream_size = codec_stream_size(in, &oy, start_offset, end_offset, VORBISNAME); cleanup(in, NULL, &oy, NULL); return stream_size; @@ -152,7 +151,7 @@ off_t oggedit_write_vorbis_metadata(DB_FILE *in, const char *fname, const off_t /* If we have tempfile, copy the remaining pages */ if (*tempname) { - if ((res = copy_remaining_pages(in, out, &oy, vorbis_serial, pageno)) < OGGEDIT_EOF) + if ((res = copy_remaining_pages(in, out, &oy, vorbis_serial, pageno)) <= OGGEDIT_EOF) goto cleanup; if (rename(tempname, fname)) { res = OGGEDIT_RENAME_FAILED; -- cgit v1.2.3