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:
parent
8f572ca525
commit
b8cccb5ae1
7 changed files with 217 additions and 13 deletions
|
@ -10,6 +10,7 @@ wavpack.c
|
|||
alac.c
|
||||
#endif
|
||||
cook.c
|
||||
raac.c
|
||||
mpc.c
|
||||
wma.c
|
||||
sid.c
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
176
apps/codecs/raac.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 -
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue