Index: apps/codecs/libasf/asf.h =================================================================== --- apps/codecs/libasf/asf.h (revision 25992) +++ apps/codecs/libasf/asf.h (working copy) @@ -32,7 +32,8 @@ uint16_t blockalign; uint16_t bitspersample; uint16_t datalen; - uint8_t data[6]; + uint16_t numpackets; + uint8_t data[18]; }; typedef struct asf_waveformatex_s asf_waveformatex_t; Index: apps/codecs/codecs.make =================================================================== --- apps/codecs/codecs.make (revision 25992) +++ apps/codecs/codecs.make (working copy) @@ -37,6 +37,7 @@ include $(APPSDIR)/codecs/libtremor/libtremor.make include $(APPSDIR)/codecs/libwavpack/libwavpack.make include $(APPSDIR)/codecs/libwma/libwma.make +include $(APPSDIR)/codecs/libwmapro/libwmapro.make include $(APPSDIR)/codecs/libcook/libcook.make include $(APPSDIR)/codecs/librm/librm.make include $(APPSDIR)/codecs/libatrac/libatrac.make @@ -82,7 +83,7 @@ $(CODECDIR)/ape-pre.map : $(CODECDIR)/libdemac-pre.a $(CODECDIR)/ape.codec : $(CODECDIR)/libdemac.a $(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a $(CODECDIR)/libasf.a -$(CODECDIR)/wmapro.codec : $(CODECDIR)/libwma.a $(CODECDIR)/libasf.a +$(CODECDIR)/wmapro.codec : $(CODECDIR)/libwmapro.a $(CODECDIR)/libasf.a $(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a $(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a $(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a Index: apps/codecs/wmapro.c =================================================================== --- apps/codecs/wmapro.c (revision 25992) +++ apps/codecs/wmapro.c (working copy) @@ -20,14 +20,148 @@ ****************************************************************************/ #include "codeclib.h" +#include "libasf/asf.h" +#include "libwmapro/wmaprodec.h" CODEC_HEADER +#define MAXSAMPLES (1L << 12) /* Max number of samples in a wma pro subframe */ +#define MAXCHANNELS 8 +#define BUFSIZE MAXCHANNELS * MAXSAMPLES +static int16_t decoded[BUFSIZE] IBSS_ATTR; + +AVCodecContext avctx; +AVPacket avpkt; + +/* This function initialises AVCodecContext with the data needed for the wmapro + * decoder to work. The required data is taken from asf_waveformatex_t because that's + * what the rockbox asf metadata parser fill/work with. In the future, when the + * codec is being optimised for on-target playback this function should not be needed, + * as we will be working directly with WMAProDecodeCtx (declared in wmaprodec.c) */ +static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx) +{ + /* Copy the extra-data */ + avctx->extradata_size = wfx->datalen; + avctx->extradata = (uint8_t *)malloc(wfx->datalen*sizeof(uint8_t)); + memcpy(avctx->extradata, wfx->data, wfx->datalen*sizeof(uint8_t)); + + avctx->block_align = wfx->blockalign; + avctx->sample_rate = wfx->rate; + avctx->channels = wfx->channels; + +} + /* this is the codec entry point */ enum codec_status codec_main(void) { - DEBUGF("WMA: WMA Professional has not been implemented yet\n"); + uint32_t elapsedtime; + int retval; + asf_waveformatex_t wfx; /* Holds the stream properties */ + size_t resume_offset; + int res; /* Return values from asf_read_packet() and decode_packet() */ + uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */ + int audiobufsize; /* Payload size */ + int packetlength = 0; /* Logical packet size (minus the header size) */ + int outlen = 0; /* Number of bytes written to the output buffer */ + int pktcnt = 0; /* Count of the packets played */ + + /* Generic codec initialisation */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); - return CODEC_ERROR; + +next_track: + + /* Wait for the metadata to be read */ + while (!*ci->taginfo_ready && !ci->stop_codec) + ci->sleep(1); + + retval = CODEC_OK; + + /* Remember the resume position */ + resume_offset = ci->id3->offset; + + if (codec_init()) { + LOGF("(WMA PRO) Error: Error initialising codec\n"); + retval = CODEC_ERROR; + goto done; + } + + /* Copy the format metadata we've stored in the id3 TOC field. This + saves us from parsing it again here. */ + memcpy(&wfx, ci->id3->toc, sizeof(wfx)); + + ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate); + ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? + STEREO_MONO : STEREO_INTERLEAVED); + codec_set_replaygain(ci->id3); + + /* Initialise the AVCodecContext */ + init_codec_ctx(&avctx, &wfx); + + if (decode_init(&avctx) < 0) { + LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); + retval = CODEC_ERROR; + goto done; + } + + /* Now advance the file position to the first frame */ + ci->seek_buffer(ci->id3->first_frame_offset); + + elapsedtime = 0; + resume_offset = 0; + + /* The main decoding loop */ + + while (pktcnt < wfx.numpackets) + { + ci->yield(); + if (ci->stop_codec || ci->new_track) { + goto done; + } + + res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); + + if (res < 0) { + LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); + goto done; + } else { + avpkt.data = audiobuf; + avpkt.size = audiobufsize; + pktcnt++; + + /* We now loop on the packet, decoding and outputting the subframes + * one-by-one. For more information about how wma pro structures its + * audio frames, see libwmapro/wmaprodec.c */ + while(avpkt.size > 0) + { + outlen = BUFSIZE; /* decode_packet needs to know the size of the output buffer */ + res = decode_packet(&avctx, decoded, &outlen, &avpkt); + avpkt.data += res; + avpkt.size -= res; + avctx.frame_number++; + if(outlen) { + ci->yield (); + /* outlen now holds the size of the data in bytes - we want the + * number of samples. */ + outlen /= 4; //XXX: Why 4 ? + ci->pcmbuf_insert(decoded, NULL, outlen); + elapsedtime += outlen*10/(wfx.rate/100); + ci->set_elapsed(elapsedtime); + ci->yield (); + } + } + + } + + /* Advance to the next logical packet */ + ci->advance_buffer(packetlength); + } + retval = CODEC_OK; + +done: + if (ci->request_next_track()) + goto next_track; + + return retval; } Property changes on: apps/codecs/wmapro.c ___________________________________________________________________ Name: svn:keywords + Id Index: apps/codecs/libwmapro/SOURCES =================================================================== --- apps/codecs/libwmapro/SOURCES (revision 0) +++ apps/codecs/libwmapro/SOURCES (revision 0) @@ -0,0 +1,9 @@ +wmaprodec.c +wma.c +dsputil.c +mdct.c +fft.c +bitstream.c +libavutil/log.c +libavutil/mem.c +libavutil/mathematics.c Index: apps/codecs/libwmapro/libavutil/mathematics.c =================================================================== --- apps/codecs/libwmapro/libavutil/mathematics.c (revision 25992) +++ apps/codecs/libwmapro/libavutil/mathematics.c (working copy) @@ -23,7 +23,7 @@ * miscellaneous math routines and tables */ -#include +//#include #include #include #include "mathematics.h" @@ -76,9 +76,9 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd){ int64_t r=0; - assert(c > 0); - assert(b >=0); - assert(rnd >=0 && rnd<=5 && rnd!=4); + //assert(c > 0); + //assert(b >=0); + //assert(rnd >=0 && rnd<=5 && rnd!=4); if(a<0 && a != INT64_MIN) return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd>>1)&1)); Index: apps/codecs/libwmapro/libavutil/internal.h =================================================================== --- apps/codecs/libwmapro/libavutil/internal.h (revision 25992) +++ apps/codecs/libwmapro/libavutil/internal.h (working copy) @@ -142,8 +142,8 @@ #endif /* avoid usage of dangerous/inappropriate system functions */ -#undef malloc -#define malloc please_use_av_malloc +//#undef malloc +//#define malloc please_use_av_malloc #undef free #define free please_use_av_free #undef realloc @@ -163,8 +163,8 @@ #undef exit #define exit exit_is_forbidden #ifndef LIBAVFORMAT_BUILD -#undef printf -#define printf please_use_av_log_instead_of_printf +//#undef printf +//#define printf please_use_av_log_instead_of_printf #undef fprintf #define fprintf please_use_av_log_instead_of_fprintf #undef puts Index: apps/codecs/libwmapro/libavutil/log.c =================================================================== --- apps/codecs/libwmapro/libavutil/log.c (revision 25992) +++ apps/codecs/libwmapro/libavutil/log.c (working copy) @@ -54,10 +54,10 @@ return; } if(count>0){ - fprintf(stderr, " Last message repeated %d times\n", count); + //fprintf(stderr, " Last message repeated %d times\n", count); count=0; } - fputs(line, stderr); + //fputs(line, stderr); strcpy(prev, line); } Index: apps/codecs/libwmapro/libavutil/mathematics.h =================================================================== --- apps/codecs/libwmapro/libavutil/mathematics.h (revision 25992) +++ apps/codecs/libwmapro/libavutil/mathematics.h (working copy) @@ -22,7 +22,7 @@ #define AVUTIL_MATHEMATICS_H #include -#include +#include "/usr/include/math.h" #include "attributes.h" //#include "rational.h" Index: apps/codecs/libwmapro/fft.c =================================================================== --- apps/codecs/libwmapro/fft.c (revision 25992) +++ apps/codecs/libwmapro/fft.c (working copy) @@ -102,11 +102,11 @@ s->fft_permute = ff_fft_permute_c; s->fft_calc = ff_fft_calc_c; -#if CONFIG_MDCT +//#if CONFIG_MDCT s->imdct_calc = ff_imdct_calc_c; s->imdct_half = ff_imdct_half_c; s->mdct_calc = ff_mdct_calc_c; -#endif +//#endif s->exptab1 = NULL; s->split_radix = 1; #if 0 Index: apps/codecs/libwmapro/wmaprodec.c =================================================================== --- apps/codecs/libwmapro/wmaprodec.c (revision 25992) +++ apps/codecs/libwmapro/wmaprodec.c (working copy) @@ -93,13 +93,11 @@ #include "wmaprodata.h" #include "dsputil.h" #include "wma.h" +#include "wmaprodec.h" /* Some defines to make it compile */ #define AVERROR_INVALIDDATA -1 #define AVERROR_PATCHWELCOME -2 -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif #define av_log_ask_for_sample(...) /** current decoder limitations */ @@ -238,8 +236,8 @@ */ static void av_cold dump_context(WMAProDecodeCtx *s) { -#define PRINT(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %d\n", a, b); -#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %x\n", a, b); +#define PRINT(a, b) printf(" %s = %d\n", a, b); +#define PRINT_HEX(a, b) printf(" %s = %x\n", a, b); PRINT("ed sample bit depth", s->bits_per_sample); PRINT_HEX("ed decode flags", s->decode_flags); @@ -255,7 +253,7 @@ *@param avctx codec context *@return 0 on success, < 0 otherwise */ -static av_cold int decode_end(AVCodecContext *avctx) +av_cold int decode_end(AVCodecContext *avctx) { WMAProDecodeCtx *s = avctx->priv_data; int i; @@ -271,8 +269,10 @@ *@param avctx codec context *@return 0 on success, -1 otherwise */ -static av_cold int decode_init(AVCodecContext *avctx) +av_cold int decode_init(AVCodecContext *avctx) { + avctx->priv_data = malloc(sizeof(WMAProDecodeCtx)); + memset(avctx->priv_data, 0, sizeof(WMAProDecodeCtx)); WMAProDecodeCtx *s = avctx->priv_data; uint8_t *edata_ptr = avctx->extradata; unsigned int channel_mask; @@ -452,8 +452,8 @@ /** calculate sine values for the decorrelation matrix */ for (i = 0; i < 33; i++) sin64[i] = sin(i*M_PI / 64.0); -#if 0 - if (avctx->debug & FF_DEBUG_BITSTREAM) +#if 1 + //if (avctx->debug & FF_DEBUG_BITSTREAM) dump_context(s); #endif @@ -1379,7 +1379,7 @@ if (len != (get_bits_count(gb) - s->frame_offset) + 2) { /** FIXME: not sure if this is always an error */ av_log(s->avctx, AV_LOG_ERROR, "frame[%i] would have to skip %i bits\n", - s->frame_num, len - (get_bits_count(gb) - s->frame_offset) - 1); + (int)s->frame_num, len - (get_bits_count(gb) - s->frame_offset) - 1); s->packet_loss = 1; return 0; } @@ -1465,7 +1465,7 @@ *@param avpkt input packet *@return number of bytes that were read from the input buffer */ -static int decode_packet(AVCodecContext *avctx, +int decode_packet(AVCodecContext *avctx, void *data, int *data_size, AVPacket* avpkt) { WMAProDecodeCtx *s = avctx->priv_data; @@ -1549,6 +1549,23 @@ *data_size = (int8_t *)s->samples - (int8_t *)data; s->packet_offset = get_bits_count(gb) & 7; +/* Convert the pcm samples to signed 16-bit integers. This is the format that + * the rockbox simulator works with. */ +#ifdef ROCKBOX + float* fptr = data; + int16_t* ptr = data; + int x; + for(x = 0; x < *data_size; x++) + { + fptr[x] *= ((float)INT16_MAX)/(32767.0 / 32768.0); + ptr[x] = av_clip_int16((int16_t)fptr[x]); + + } + + /* Now divide data_size by 2 */ + *data_size /= 2; +#endif + return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3; } Index: apps/codecs/libwmapro/wmaprodec.h =================================================================== --- apps/codecs/libwmapro/wmaprodec.h (revision 0) +++ apps/codecs/libwmapro/wmaprodec.h (revision 0) @@ -0,0 +1,6 @@ +#include "avcodec.h" + +av_cold int decode_end(AVCodecContext *avctx); +av_cold int decode_init(AVCodecContext *avctx); +int decode_packet(AVCodecContext *avctx, + void *data, int *data_size, AVPacket* avpkt); Index: apps/codecs/libwmapro/libwmapro.make =================================================================== --- apps/codecs/libwmapro/libwmapro.make (revision 0) +++ apps/codecs/libwmapro/libwmapro.make (revision 0) @@ -0,0 +1,18 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +# libwmapro +WMAPROLIB := $(CODECDIR)/libwmapro.a +WMAPROLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libwmapro/SOURCES) +WMAPROLIB_OBJ := $(call c2obj, $(WMAPROLIB_SRC)) +OTHER_SRC += $(WMAPROLIB_SRC) + +$(WMAPROLIB): $(WMAPROLIB_OBJ) + $(SILENT)$(shell rm -f $@) + $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null Property changes on: apps/codecs/libwmapro/libwmapro.make ___________________________________________________________________ Name: svn:keywords + Id Index: apps/codecs/libwmapro/dsputil.h =================================================================== --- apps/codecs/libwmapro/dsputil.h (revision 25992) +++ apps/codecs/libwmapro/dsputil.h (working copy) @@ -443,7 +443,7 @@ * @param v2 second input vector, difference output, 16-byte aligned * @param len length of vectors, multiple of 4 */ - void (*butterflies_float)(float *restrict v1, float *restrict v2, int len); + void (*butterflies_float)(float * v1, float * v2, int len); /* C version: convert floats from the range [384.0,386.0] to ints in [-32768,32767] * simd versions: convert floats from [-32768.0,32767.0] without rescaling and arrays are 16byte aligned */ Index: apps/metadata/asf.c =================================================================== --- apps/metadata/asf.c (revision 25992) +++ apps/metadata/asf.c (working copy) @@ -274,9 +274,14 @@ } fileprop = 1; - /* All we want is the play duration - uint64_t at offset 40 */ - lseek(fd, 40, SEEK_CUR); - + + /* Get the number of logical packets - uint16_t at offset 31 + * (Big endian byte order) */ + lseek(fd, 31, SEEK_CUR); + read_uint16be(fd, &wfx->numpackets); + + /* Now get the play duration - uint64_t at offset 40 */ + lseek(fd, 7, SEEK_CUR); read_uint64le(fd, &play_duration); id3->length = play_duration / 10000; @@ -346,8 +351,9 @@ lseek(fd,current.size - 24 - 72 - 6,SEEK_CUR); wfx->audiostream = flags&0x7f; } else if (wfx->codec_id == ASF_CODEC_ID_WMAPRO) { - read(fd, wfx->data, 10); - lseek(fd,current.size - 24 - 72 - 10,SEEK_CUR); + /* wma pro decoder needs the extra-data */ + read(fd, wfx->data, wfx->datalen); + lseek(fd,current.size - 24 - 72 - wfx->datalen,SEEK_CUR); wfx->audiostream = flags&0x7f; /* Correct codectype to redirect playback to the proper .codec */ id3->codectype = AFMT_WMAPRO;