summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <waker@users.sourceforge.net>2014-06-14 11:41:48 +0200
committerGravatar Alexey Yakovenko <waker@users.sourceforge.net>2014-06-14 11:41:48 +0200
commit8cb015ad395d13043a7a63a0294550dc4bb3afd8 (patch)
tree8fec5211547b4b08849eaa71bbfab056fc008693 /plugins
parent055ca014541453a3a2e07db6902b16f9406bf530 (diff)
parentcaf400178adbcaaace2a258354b7310067726a04 (diff)
Merge pull request #13 from Lithopsian/flac
Flac/oggflac bitrate calculation improvements
Diffstat (limited to 'plugins')
-rw-r--r--plugins/flac/flac.c119
-rw-r--r--plugins/liboggedit/oggedit.h1
-rw-r--r--plugins/liboggedit/oggedit_flac.c11
-rw-r--r--plugins/liboggedit/oggedit_internal.c32
-rw-r--r--plugins/liboggedit/oggedit_internal.h2
-rw-r--r--plugins/liboggedit/oggedit_opus.c9
-rw-r--r--plugins/liboggedit/oggedit_vorbis.c5
7 files changed, 90 insertions, 89 deletions
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index 50e82739..5deab23e 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,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");
@@ -793,8 +773,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 +791,22 @@ 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);
+ 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);
+ decoder = NULL;
// try embedded cue
deadbeef->pl_lock ();
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;