summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMohamed Tarek <mt@rockbox.org>2009-07-25 15:47:13 +0000
committerMohamed Tarek <mt@rockbox.org>2009-07-25 15:47:13 +0000
commitb8cccb5ae18f35ea7d210c513bafe10b19fafbd7 (patch)
tree901a2d75ad40134a005c3bbb68949f551fc9c50e /apps
parent8f572ca525bf3812799e627a4a716300e412c244 (diff)
Adding support for playback of aac audio in rm container, with seeking.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22031 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/codecs.make1
-rw-r--r--apps/codecs/librm/rm.c29
-rw-r--r--apps/codecs/raac.c176
-rw-r--r--apps/metadata.c3
-rw-r--r--apps/metadata.h1
-rw-r--r--apps/metadata/rm.c19
7 files changed, 217 insertions, 13 deletions
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 44a8498fa9..dc6819d272 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -10,6 +10,7 @@ wavpack.c
alac.c
#endif
cook.c
+raac.c
mpc.c
wma.c
sid.c
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make
index fbe3b1c978..b327bd7c69 100644
--- a/apps/codecs/codecs.make
+++ b/apps/codecs/codecs.make
@@ -76,6 +76,7 @@ $(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a
$(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a
$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a
$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a
+$(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a
$(CODECS): $(CODECLIB) # this must be last in codec dependency list
diff --git a/apps/codecs/librm/rm.c b/apps/codecs/librm/rm.c
index c9c40986ba..a48fb51cc6 100644
--- a/apps/codecs/librm/rm.c
+++ b/apps/codecs/librm/rm.c
@@ -529,13 +529,28 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
advance_buffer(src,12);
consumed += 12;
- for(x = 0 ; x < w/sps; x++)
- {
- place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1));
- pkt->frames[place/sps] = *src;
- advance_buffer(src,sps);
- consumed += sps;
- }
+ if (rmctx->codec_type == cook) {
+ for(x = 0 ; x < w/sps; x++)
+ {
+ place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1));
+ pkt->frames[place/sps] = *src;
+ advance_buffer(src,sps);
+ consumed += sps;
+ }
+ }
+ else if (rmctx->codec_type == aac) {
+ rmctx->sub_packet_cnt = (get_uint16be(*src) & 0xf0) >> 4;
+ advance_buffer(src, 2);
+ consumed += 2;
+ if (rmctx->sub_packet_cnt) {
+ for(x = 0; x < rmctx->sub_packet_cnt; x++) {
+ rmctx->sub_packet_lengths[x] = get_uint16be(*src);
+ advance_buffer(src, 2);
+ consumed += 2;
+ }
+ rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt;
+ }
+ }
rmctx->audio_pkt_cnt++;
}while(++(rmctx->sub_packet_cnt) < h);
diff --git a/apps/codecs/raac.c b/apps/codecs/raac.c
new file mode 100644
index 0000000000..cfc5b4a460
--- /dev/null
+++ b/apps/codecs/raac.c
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: aac.c 19743 2009-01-10 21:10:56Z zagor $
+ *
+ * Copyright (C) 2009 Mohamed Tarek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "librm/rm.h"
+#include "libfaad/common.h"
+#include "libfaad/structs.h"
+#include "libfaad/decoder.h"
+#include "libfaad/output.h"
+
+CODEC_HEADER
+#define DATA_HEADER_SIZE 18
+static void init_rm(RMContext *rmctx)
+{
+ memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
+}
+
+RMContext rmctx;
+RMPacket pkt;
+/* this is the codec entry point */
+enum codec_status codec_main(void)
+{
+ static NeAACDecFrameInfo frame_info;
+ NeAACDecHandle decoder;
+ size_t n;
+ int32_t *output;
+ unsigned int i;
+ unsigned char* buffer;
+ int err, consumed, pkt_offset, skipped = 0;
+ uint32_t s = 0; /* sample rate */
+ unsigned char c = 0; /* channels */
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+
+next_track:
+ err = CODEC_OK;
+
+ if (codec_init()) {
+ DEBUGF("FAAD: Codec init error\n");
+ return CODEC_ERROR;
+ }
+
+ while (!*ci->taginfo_ready && !ci->stop_codec)
+ ci->sleep(1);
+
+ ci->memset(&rmctx,0,sizeof(RMContext));
+ ci->memset(&pkt,0,sizeof(RMPacket));
+ init_rm(&rmctx);
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ codec_set_replaygain(ci->id3);
+
+ /* initialise the sound converter */
+ decoder = NeAACDecOpen();
+
+ if (!decoder) {
+ DEBUGF("FAAD: Decode open error\n");
+ err = CODEC_ERROR;
+ goto done;
+ }
+ NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
+ conf->outputFormat = FAAD_FMT_16BIT;
+ NeAACDecSetConfiguration(decoder, conf);
+
+ decoder->config.defObjectType = rmctx.codec_extradata[0];
+ decoder->config.defSampleRate = rmctx.sample_rate;
+ err = NeAACDecInit(decoder, NULL, 0, &s, &c);
+
+ if (err) {
+ DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
+ err = CODEC_ERROR;
+ goto done;
+ }
+ ci->id3->frequency = s;
+ ci->set_elapsed(0);
+ ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+
+ /* The main decoding loop */
+seek_start:
+ while (1) {
+ ci->yield();
+ if (ci->stop_codec || ci->new_track) {
+ break;
+ }
+
+ if (ci->seek_time) {
+
+ /* Do not allow seeking beyond the file's length */
+ if ((unsigned) ci->seek_time > ci->id3->length) {
+ ci->seek_complete();
+ goto done;
+ }
+
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+
+ /* Seek to the start of the track */
+ if (ci->seek_time == 1) {
+ ci->set_elapsed(0);
+ ci->seek_complete();
+ goto seek_start;
+ }
+
+ skipped = 0;
+ while(1) {
+ buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
+ pkt_offset = skipped - pkt.length;
+ consumed = rm_get_packet(&buffer, &rmctx, &pkt);
+ if(consumed < 0) {
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+ skipped += pkt.length;
+ if(pkt.timestamp > (unsigned)ci->seek_time) break;
+ ci->advance_buffer(pkt.length);
+ }
+ ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE);
+ buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
+ ci->seek_complete();
+ }
+
+ /* Request the required number of bytes from the input buffer */
+ buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000);
+ consumed = rm_get_packet(&buffer, &rmctx, &pkt);
+ if(consumed < 0) {
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+
+ if (pkt.timestamp >= ci->id3->length)
+ goto done;
+ /* Decode one block - returned samples will be host-endian */
+ for(i = 0; i < rmctx.sub_packet_cnt; i++) {
+ output = (int32_t *)NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]);
+ buffer += rmctx.sub_packet_lengths[i];
+ if (frame_info.error > 0) {
+ DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
+ err = CODEC_ERROR;
+ goto exit;
+ }
+ output = (int32_t *) output_to_PCM(decoder, decoder->time_out, output,
+ rmctx.nb_channels, decoder->frameLength, decoder->config.outputFormat);
+ ci->pcmbuf_insert(output, NULL, frame_info.samples/rmctx.nb_channels);
+ ci->set_elapsed(pkt.timestamp);
+ }
+
+ ci->advance_buffer(pkt.length);
+ }
+
+ err = CODEC_OK;
+
+done:
+ if (ci->request_next_track())
+ goto next_track;
+
+exit:
+ return err;
+}
+
diff --git a/apps/metadata.c b/apps/metadata.c
index a0409a83ac..80f2c126e2 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -118,6 +118,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
/* Cook in RM/RA */
[AFMT_COOK] =
AFMT_ENTRY("Cook", "cook", NULL, "rm\0ra\0" ),
+ /* AAC in RM/RA */
+ [AFMT_RAAC] =
+ AFMT_ENTRY("RAAC", "raac", NULL, NULL ),
#endif
};
diff --git a/apps/metadata.h b/apps/metadata.h
index f3b50c947d..0125b29e5e 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -62,6 +62,7 @@ enum
AFMT_MOD, /* Amiga MOD File Format */
AFMT_SAP, /* Amiga 8Bit SAP Format */
AFMT_COOK, /* Cook in RM/RA */
+ AFMT_RAAC, /* AAC in RM/RA */
#endif
/* add new formats at any index above this line to have a sensible order -
diff --git a/apps/metadata/rm.c b/apps/metadata/rm.c
index bfaa803be7..95889c35c3 100644
--- a/apps/metadata/rm.c
+++ b/apps/metadata/rm.c
@@ -169,6 +169,11 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
rmctx->codec_type = cook;
break;
+ case FOURCC('r','a','a','c'):
+ case FOURCC('r','a','c','p'):
+ rmctx->codec_type = aac;
+ break;
+
default: /* Not a supported codec */
return -1;
}
@@ -183,7 +188,10 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
DEBUGF(" fourcc = %s\n",fourcc2str(fourcc));
DEBUGF(" codec_extra_data_length = %ld\n",rmctx->extradata_size);
DEBUGF(" codec_extradata :\n");
- print_cook_extradata(rmctx);
+ if(rmctx->codec_type == cook) {
+ DEBUGF(" cook_extradata :\n");
+ print_cook_extradata(rmctx);
+ }
}
@@ -391,12 +399,11 @@ bool get_rm_metadata(int fd, struct mp3entry* id3)
id3->artist = id3->id3v1buf[1];
id3->comment = id3->id3v1buf[3];
- /*switch(rmctx->codec_type)
+ switch(rmctx->codec_type)
{
- case cook:
- id3->codectype = AFMT_COOK;
- break;
- }*/
+ case aac:
+ id3->codectype = AFMT_RAAC;
+ }
id3->bitrate = rmctx->bit_rate / 1000;
id3->frequency = rmctx->sample_rate;