1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Mohamed Tarek 2009-07-25 15:47:13 +00:00
parent 8f572ca525
commit b8cccb5ae1
7 changed files with 217 additions and 13 deletions

View file

@ -10,6 +10,7 @@ wavpack.c
alac.c
#endif
cook.c
raac.c
mpc.c
wma.c
sid.c

View file

@ -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

View file

@ -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);

176
apps/codecs/raac.c Normal file
View file

@ -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;
}

View file

@ -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
};

View file

@ -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 -

View file

@ -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;