summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-07-04 19:02:48 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-07-04 19:02:48 +0200
commita1bc3f3c2e60af892c12ed53cb6c2cd1f93a5bec (patch)
tree282b7d13584586db74943fac5d7fd6850f97c38d
parent3879ce9a2def4c6fd6247338e8583e09cd3da48b (diff)
added streaming support to aac plugin
-rw-r--r--plugins/aac/aac.c341
-rw-r--r--plugins/aac/aac_parser.c19
-rw-r--r--streamer.c4
3 files changed, 206 insertions, 158 deletions
diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c
index f59c7308..e4e80619 100644
--- a/plugins/aac/aac.c
+++ b/plugins/aac/aac.c
@@ -37,7 +37,7 @@
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
-#define AAC_BUFFER_SIZE 8192
+#define AAC_BUFFER_SIZE 50000
#define OUT_BUFFER_SIZE 100000
typedef struct {
@@ -71,7 +71,7 @@ aac_open (void) {
static uint32_t
aac_fs_read (void *user_data, void *buffer, uint32_t length) {
-// trace ("aac_fs_read\n");
+// trace ("aac_fs_read %d\n", length);
DB_FILE *fp = (DB_FILE *)user_data;
return deadbeef->fread (buffer, 1, length, fp);
}
@@ -84,16 +84,22 @@ aac_fs_seek (void *user_data, uint64_t position) {
}
static int
-parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, int *totalsamples)
+parse_aac_stream(DB_FILE *fp, int *psamplerate, int *pchannels, float *pduration, int *ptotalsamples)
{
- int skip = deadbeef->junk_get_leading_size (fp);
- if (skip >= 0) {
- deadbeef->fseek (fp, skip, SEEK_SET);
- }
- int offs = deadbeef->ftell (fp);
- int fsize = deadbeef->fgetlength (fp);
- if (skip > 0) {
- fsize -= skip;
+ int framepos = deadbeef->ftell (fp);;
+ int firstframepos = -1;
+ int fsize = -1;
+ int offs = 0;
+ if (!fp->vfs->streaming) {
+ int skip = deadbeef->junk_get_leading_size (fp);
+ if (skip >= 0) {
+ deadbeef->fseek (fp, skip, SEEK_SET);
+ }
+ int offs = deadbeef->ftell (fp);
+ fsize = deadbeef->fgetlength (fp);
+ if (skip > 0) {
+ fsize -= skip;
+ }
}
uint8_t buf[ADTS_HEADER_SIZE*8];
@@ -107,6 +113,10 @@ parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, i
int remaining = 0;
int frame = 0;
+ int scanframes = 1000;
+ if (fp->vfs->streaming) {
+ scanframes = 1;
+ }
do {
int size = sizeof (buf) - bufsize;
@@ -121,10 +131,12 @@ parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, i
if (size == 0) {
memmove (buf, buf+1, sizeof (buf)-1);
bufsize--;
+ trace ("aac_sync fail, framepos: %d\n", framepos);
+ framepos++;
continue;
}
else {
- //trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size);
+ trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size);
frame++;
nsamples += samples;
if (!stream_sr) {
@@ -133,34 +145,42 @@ parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, i
if (!stream_ch) {
stream_ch = channels;
}
+ if (firstframepos == -1) {
+ firstframepos = framepos;
+ }
+// if (fp->vfs->streaming) {
+// *psamplerate = stream_sr;
+// *pchannels = stream_ch;
+// }
+ framepos += size;
if (deadbeef->fseek (fp, size-sizeof(buf), SEEK_CUR) == -1) {
trace ("parse_aac_stream: invalid seek %d\n", size-sizeof(buf));
break;
}
bufsize = 0;
}
- } while (totalsamples || frame < 1000);
+ } while (ptotalsamples || frame < scanframes);
if (!frame || !stream_sr || !nsamples) {
return -1;
}
- *samplerate = stream_sr;
- *channels = stream_ch;
+ *psamplerate = stream_sr;
+ *pchannels = stream_ch;
- if (totalsamples) {
- *totalsamples = nsamples;
- *duration = nsamples / (float)stream_sr;
- trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d, nframes=%d\n", *duration, *totalsamples, stream_sr, fsize, frame);
+ if (ptotalsamples) {
+ *ptotalsamples = nsamples;
+ *pduration = nsamples / (float)stream_sr;
+ trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d, nframes=%d\n", *pduration, *ptotalsamples, stream_sr, fsize, frame);
}
else {
int pos = deadbeef->ftell (fp);
int totalsamples = (double)fsize / (pos-offs) * nsamples;
- *duration = totalsamples / (float)stream_sr;
- trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d\n", *duration, totalsamples, stream_sr, fsize);
+ *pduration = totalsamples / (float)stream_sr;
+ trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d\n", *pduration, totalsamples, stream_sr, fsize);
}
- return 0;
+ return firstframepos;
}
// returns -1 for error, 0 for mp4, 1 for aac
@@ -248,11 +268,14 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
int channels = -1;
int totalsamples = -1;
- int skip = deadbeef->junk_get_leading_size (info->file);
- if (skip >= 0) {
- deadbeef->fseek (info->file, skip, SEEK_SET);
+ int offs = -1;
+ if (!info->file->vfs->streaming) {
+ int skip = deadbeef->junk_get_leading_size (info->file);
+ if (skip >= 0) {
+ deadbeef->fseek (info->file, skip, SEEK_SET);
+ }
+ offs =deadbeef->ftell (info->file);
}
- int offs = deadbeef->ftell (info->file);
info->mp4track = -1;
// int res = aac_probe (info->file, &duration, &samplerate, &channels, &totalsamples, &mp4track);
@@ -265,92 +288,111 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
info->mp4reader.truncate = NULL;
info->mp4reader.user_data = info->file;
- info->mp4file = mp4ff_open_read (&info->mp4reader);
- if (info->mp4file) {
- int ntracks = mp4ff_total_tracks (info->mp4file);
- if (ntracks > 0) {
- trace ("m4a container detected, ntracks=%d\n", ntracks);
- int i = -1;
- trace ("looking for mp4 data...\n");
- unsigned char* buff = 0;
- unsigned int buff_size = 0;
- for (i = 0; i < ntracks; i++) {
- mp4AudioSpecificConfig mp4ASC;
- mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size);
- if(buff){
- int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
- if(rc < 0)
- continue;
- break;
+ trace ("aac_init: mp4ff_open_read %s\n", it->fname);
+ if (!info->file->vfs->streaming) {
+ info->mp4file = mp4ff_open_read (&info->mp4reader);
+ if (info->mp4file) {
+ int ntracks = mp4ff_total_tracks (info->mp4file);
+ if (ntracks > 0) {
+ trace ("m4a container detected, ntracks=%d\n", ntracks);
+ int i = -1;
+ trace ("looking for mp4 data...\n");
+ unsigned char* buff = 0;
+ unsigned int buff_size = 0;
+ for (i = 0; i < ntracks; i++) {
+ mp4AudioSpecificConfig mp4ASC;
+ mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size);
+ if(buff){
+ int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
+ if(rc < 0)
+ continue;
+ break;
+ }
}
- }
- if (i != ntracks && buff)
- {
- trace ("mp4 track: %d\n", i);
- samplerate = mp4ff_get_sample_rate (info->mp4file, i);
- channels = mp4ff_get_channel_count (info->mp4file, i);
- int samples = mp4ff_num_samples(info->mp4file, i);
- trace ("mp4 nsamples=%d, samplerate=%d\n", samples * 1024, samplerate);
- duration = (float)samples * 1024 / samplerate;
- totalsamples = samples * 1024;
- info->mp4track = i;
-
- // init mp4 decoding
- info->dec = NeAACDecOpen ();
- unsigned long srate;
- unsigned char ch;
- if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) {
- trace ("NeAACDecInit2 returned error\n");
- return -1;
- }
- info->faad_channels = ch;
- mp4AudioSpecificConfig mp4ASC;
- if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
+ if (i != ntracks && buff)
{
- info->mp4framesize = 1024;
- if (mp4ASC.frameLengthFlag == 1) {
- info->mp4framesize = 960;
+ trace ("mp4 track: %d\n", i);
+ samplerate = mp4ff_get_sample_rate (info->mp4file, i);
+ channels = mp4ff_get_channel_count (info->mp4file, i);
+ int samples = mp4ff_num_samples(info->mp4file, i);
+ trace ("mp4 nsamples=%d, samplerate=%d\n", samples * 1024, samplerate);
+ duration = (float)samples * 1024 / samplerate;
+ totalsamples = samples * 1024;
+ info->mp4track = i;
+
+ // init mp4 decoding
+ info->dec = NeAACDecOpen ();
+ unsigned long srate;
+ unsigned char ch;
+ if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) {
+ trace ("NeAACDecInit2 returned error\n");
+ return -1;
}
- if (mp4ASC.sbr_present_flag == 1) {
- info->mp4framesize *= 2;
+ info->faad_channels = ch;
+ mp4AudioSpecificConfig mp4ASC;
+ if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
+ {
+ info->mp4framesize = 1024;
+ if (mp4ASC.frameLengthFlag == 1) {
+ info->mp4framesize = 960;
+ }
+ if (mp4ASC.sbr_present_flag == 1) {
+ info->mp4framesize *= 2;
+ }
}
+ free (buff);
+ }
+ else {
+ mp4ff_close (info->mp4file);
+ info->mp4file = NULL;
}
- free (buff);
}
else {
mp4ff_close (info->mp4file);
info->mp4file = NULL;
}
}
- else {
- mp4ff_close (info->mp4file);
- info->mp4file = NULL;
+ if (!info->mp4file) {
+ trace ("mp4 track not found, looking for aac stream...\n");
+
+ // not an mp4, try raw aac
+ deadbeef->rewind (info->file);
+ if (parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples) == -1) {
+ trace ("aac stream not found\n");
+ return -1;
+ }
+ deadbeef->rewind (info->file);
+ trace ("found aac stream\n");
}
- }
- if (!info->mp4file) {
- trace ("mp4 track not found, looking for aac stream...\n");
- // not an mp4, try raw aac
- deadbeef->rewind (info->file);
- if (parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples) == -1) {
- trace ("aac stream not found\n");
+ _info->channels = channels;
+ _info->samplerate = samplerate;
+ }
+ else {
+ // sync before attempting to init
+ int samplerate, channels;
+ float duration;
+ offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL);
+ if (offs < 0) {
+ trace ("aac: parse_aac_stream failed\n");
return -1;
}
- trace ("found aac stream\n");
+ _info->channels = channels;
+ _info->samplerate = samplerate*2;
+ trace("parse_aac_stream returned %x\n", offs);
+ }
+ if (offs >= 0) {
+ deadbeef->fseek (info->file, offs, SEEK_SET);
}
-
// duration = (float)totalsamples / samplerate;
// deadbeef->pl_set_item_duration (it, duration);
_info->bps = 16;
- _info->channels = channels;
- _info->samplerate = samplerate;
_info->plugin = &plugin;
- deadbeef->fseek (info->file, offs, SEEK_SET);
-
if (!info->mp4file) {
+ trace ("NeAACDecOpen\n");
info->dec = NeAACDecOpen ();
info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file);
@@ -360,6 +402,7 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
NeAACDecSetConfiguration (info->dec, conf);
unsigned long srate;
unsigned char ch;
+ trace ("NeAACDecInit\n");
int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch);
if (consumed < 0) {
trace ("NeAACDecInit returned %d\n", consumed);
@@ -377,25 +420,23 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
info->remaining -= consumed;
}
info->faad_channels = ch;
+// _info->channels = ch;
+// _info->samplerate = srate;
+ trace ("NeAACDecInit returned samplerate=%d, channels=%d\n", (int)srate, (int)ch);
}
- if (it->endsample > 0) {
- info->startsample = it->startsample;
- info->endsample = it->endsample;
- plugin.seek_sample (_info, 0);
- }
- else {
- info->startsample = 0;
- info->endsample = totalsamples-1;
+ if (!info->file->vfs->streaming) {
+ if (it->endsample > 0) {
+ info->startsample = it->startsample;
+ info->endsample = it->endsample;
+ plugin.seek_sample (_info, 0);
+ }
+ else {
+ info->startsample = 0;
+ info->endsample = totalsamples-1;
+ }
}
-
-// _info->samplerate = srate;
-
- // recalculate duration
-// trace ("duration=%f, totalsamples = %d\n", duration, totalsamples);
-// trace ("NeAACDecInit returned samplerate=%d, channels=%d\n", (int)srate, (int)ch);
-
return 0;
}
@@ -419,10 +460,12 @@ aac_free (DB_fileinfo_t *_info) {
static int
aac_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) {
aac_info_t *info = (aac_info_t *)_info;
- if (info->currentsample + size / (2 * _info->channels) > info->endsample) {
- size = (info->endsample - info->currentsample + 1) * 2 * _info->channels;
- if (size <= 0) {
- return 0;
+ if (!info->file->vfs->streaming) {
+ if (info->currentsample + size / (2 * _info->channels) > info->endsample) {
+ size = (info->endsample - info->currentsample + 1) * 2 * _info->channels;
+ if (size <= 0) {
+ return 0;
+ }
}
}
@@ -488,7 +531,6 @@ aac_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) {
info->remaining += res;
}
- //trace ("NeAACDecDecode %d bytes %d offs\n", info->remaining, deadbeef->ftell (info->file));
samples = NeAACDecDecode (info->dec, &frame_info, info->buffer, info->remaining);
if (!samples) {
trace ("NeAACDecDecode failed\n");
@@ -616,34 +658,37 @@ aac_insert (DB_playItem_t *after, const char *fname) {
trace ("not found\n");
return NULL;
}
+
+ const char *ftype = NULL;
+ float duration = -1;
+ int totalsamples = 0;
+ int samplerate = 0;
+
if (fp->vfs->streaming) {
- trace ("no streaming aac yet (%s)\n", fname);
- deadbeef->fclose (fp);
- return NULL;
+ trace ("streaming aac (%s)\n", fname);
+ ftype = plugin.filetypes[0];
}
+ else {
- int skip = deadbeef->junk_get_leading_size (fp);
- if (skip >= 0) {
- deadbeef->fseek (fp, skip, SEEK_SET);
- }
+ int skip = deadbeef->junk_get_leading_size (fp);
+ if (skip >= 0) {
+ deadbeef->fseek (fp, skip, SEEK_SET);
+ }
- const char *ftype = NULL;
- float duration;
- int samplerate;
- int channels;
- int totalsamples;
-
- // slowwww!
- int res = aac_probe (fp, &duration, &samplerate, &channels, &totalsamples, NULL);
- if (res == -1) {
- deadbeef->fclose (fp);
- return NULL;
- }
- else if (res == 0) {
- ftype = plugin.filetypes[1];
- }
- else if (res == 1) {
- ftype = plugin.filetypes[0];
+ int channels;
+
+ // slowwww!
+ int res = aac_probe (fp, &duration, &samplerate, &channels, &totalsamples, NULL);
+ if (res == -1) {
+ deadbeef->fclose (fp);
+ return NULL;
+ }
+ else if (res == 0) {
+ ftype = plugin.filetypes[1];
+ }
+ else if (res == 1) {
+ ftype = plugin.filetypes[0];
+ }
}
DB_playItem_t *it = deadbeef->pl_item_alloc ();
@@ -662,28 +707,30 @@ aac_insert (DB_playItem_t *after, const char *fname) {
deadbeef->fclose (fp);
- // embedded cue
- deadbeef->pl_lock ();
- const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
- DB_playItem_t *cue = NULL;
+ if (duration > 0) {
+ // embedded cue
+ deadbeef->pl_lock ();
+ const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
+ DB_playItem_t *cue = NULL;
+
+ if (cuesheet) {
+ cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
+ if (cue) {
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
+ deadbeef->pl_unlock ();
+ return cue;
+ }
+ }
+ deadbeef->pl_unlock ();
- if (cuesheet) {
- cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
+ cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
if (cue) {
deadbeef->pl_item_unref (it);
deadbeef->pl_item_unref (cue);
- deadbeef->pl_unlock ();
return cue;
}
}
- deadbeef->pl_unlock ();
-
- cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
- if (cue) {
- deadbeef->pl_item_unref (it);
- deadbeef->pl_item_unref (cue);
- return cue;
- }
deadbeef->pl_add_meta (it, "title", NULL);
diff --git a/plugins/aac/aac_parser.c b/plugins/aac/aac_parser.c
index 32571aff..a09eca84 100644
--- a/plugins/aac/aac_parser.c
+++ b/plugins/aac/aac_parser.c
@@ -56,20 +56,20 @@ aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int
int profile_objecttype = (buf[2] & 0xC0) >> 6;
- //const char *profiles[4] = {
- // "0 Main profile AAC MAIN",
- // "1 Low Complexity profile (LC)AAC LC",
- // "2 Scalable Sample Rate profile (SSR)AAC SSR",
- // "3 (reserved)AAC LTP"
- //};
- //trace ("profile: %s\n", profiles[profile_objecttype]);
+ const char *profiles[4] = {
+ "0 Main profile AAC MAIN",
+ "1 Low Complexity profile (LC)AAC LC",
+ "2 Scalable Sample Rate profile (SSR)AAC SSR",
+ "3 (reserved)AAC LTP"
+ };
+ trace ("profile: %s\n", profiles[profile_objecttype]);
int sample_freq_index = (buf[2] & 0x3C) >> 2;
if (!aac_sample_rates[sample_freq_index]) {
//trace ("invalid samplerate\n");
return 0;
}
- //trace ("samplerate %d (#%d)\n", aac_sample_rates[sample_freq_index], sample_freq_index);
+ trace ("samplerate %d (#%d)\n", aac_sample_rates[sample_freq_index], sample_freq_index);
int private_bit = (buf[2] & 0x02) >> 1;
int channel_conf = ((buf[2] & 0x01) << 2) | ((buf[3] & 0xC0) >> 6);
@@ -77,7 +77,7 @@ aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int
//trace ("invalid channels\n");
return 0;
}
- //trace ("channels %d\n", aac_channels[channel_conf]);
+ trace ("channels %d\n", aac_channels[channel_conf]);
int orig_copy = (buf[3] & 0x20) >> 5;
int home = (buf[3] & 0x10) >> 4;
int copyright_ident_bit = (buf[3] & 0x08) >> 3;
@@ -89,6 +89,7 @@ aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int
}
int adts_buffer_fullness = ((buf[5] & 0x1F) << 3) | ((buf[6] & 0xFC) >> 2);
rdb = buf[7] & 0x03;
+ trace ("rdb: %d\n", rdb);
*channels = aac_channels[channel_conf];
*sample_rate = aac_sample_rates[sample_freq_index];
diff --git a/streamer.c b/streamer.c
index e5b67526..ee204409 100644
--- a/streamer.c
+++ b/streamer.c
@@ -584,10 +584,10 @@ streamer_set_current (playItem_t *it) {
plug = "stdogg";
}
else if (!strcmp (ct, "audio/aacp")) {
- plug = "ffmpeg";
+ plug = "aac";
}
else if (!strcmp (ct, "audio/aac")) {
- plug = "ffmpeg";
+ plug = "aac";
}
else if (!strcmp (ct, "audio/wma")) {
plug = "ffmpeg";