Wrote apps/codecs/wmapro.c and modified libwmapro to make the codec work in the sim. Neither libwmapro nor wmapro.c have been added to the main build yet, codecs.make should be edited to compile both with rockbox.

current status of the decoder :
- Plays and seeks in the sim
- Still in floating point

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27006 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Mohamed Tarek 2010-06-21 10:48:34 +00:00
parent 9297a02d49
commit 816fca820c
16 changed files with 246 additions and 42 deletions

View file

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

View file

@ -296,7 +296,7 @@ int init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
av_log(NULL,AV_LOG_DEBUG,"build table nb_codes=%d\n", nb_codes);
#endif
assert(symbols_size <= 2 || !symbols);
//assert(symbols_size <= 2 || !symbols);
j = 0;
#define COPY(condition)\
for (i = 0; i < nb_codes; i++) {\

View file

@ -443,7 +443,7 @@ typedef struct DSPContext {
* @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 */

View file

@ -102,11 +102,11 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
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

View file

@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
//#include <assert.h>
#include "libavutil/bswap.h"
#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"

View file

@ -33,7 +33,7 @@
#include <limits.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
//#include <assert.h>
//#include "config.h"
#include "attributes.h"
//#include "timer.h"
@ -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

View file

@ -54,10 +54,10 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
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);
}

View file

@ -23,7 +23,7 @@
* miscellaneous math routines and tables
*/
#include <assert.h>
//#include <assert.h>
#include <stdint.h>
#include <limits.h>
#include "mathematics.h"
@ -76,9 +76,9 @@ int64_t av_gcd(int64_t a, int64_t b){
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));

View file

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

View file

@ -20,7 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
//#include <assert.h>
// do not use libavutil/mathematics.h since this is compiled both
// for the host and the target and config.h is only valid for the target
#include <math.h>
@ -53,7 +53,7 @@ av_cold void ff_sine_window_init(float *window, int n) {
}
av_cold void ff_init_ff_sine_windows(int index) {
assert(index >= 0 && index < FF_ARRAY_ELEMS(ff_sine_windows));
//assert(index >= 0 && index < FF_ARRAY_ELEMS(ff_sine_windows));
#if !CONFIG_HARDCODED_TABLES
ff_sine_window_init(ff_sine_windows[index], 1 << index);
#endif

View file

@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
//#include <assert.h>
#include "libavutil/bswap.h"
#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"
@ -153,7 +153,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value)
int bit_left;
// printf("put_bits=%d %x\n", n, value);
assert(n <= 31 && value < (1U << n));
//assert(n <= 31 && value < (1U << n));
bit_buf = s->bit_buf;
bit_left = s->bit_left;
@ -264,7 +264,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value)
static inline void put_sbits(PutBitContext *pb, int n, int32_t value)
{
assert(n >= 0 && n <= 31);
//assert(n >= 0 && n <= 31);
put_bits(pb, n, value & ((1<<n)-1));
}
@ -304,12 +304,12 @@ static inline uint8_t* put_bits_ptr(PutBitContext *s)
*/
static inline void skip_put_bytes(PutBitContext *s, int n)
{
assert((put_bits_count(s)&7)==0);
//assert((put_bits_count(s)&7)==0);
#ifdef ALT_BITSTREAM_WRITER
FIXME may need some cleaning of the buffer
s->index += n<<3;
#else
assert(s->bit_left==32);
//assert(s->bit_left==32);
s->buf_ptr += n;
#endif
}

View file

@ -23,8 +23,8 @@
#include "wma.h"
//#include "wmadata.h"
#undef NDEBUG
#include <assert.h>
//#undef NDEBUG
//#include <assert.h>
#if 0
/* XXX: use same run/length optimization as mpeg decoders */
//FIXME maybe split decode / encode or pass flag

View file

@ -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 @@ typedef struct WMAProDecodeCtx {
*/
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 @@ static void av_cold dump_context(WMAProDecodeCtx *s)
*@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 @@ static av_cold int decode_end(AVCodecContext *avctx)
*@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;
@ -454,7 +454,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
sin64[i] = sin(i*M_PI / 64.0);
#if 0
if (avctx->debug & FF_DEBUG_BITSTREAM)
dump_context(s);
#endif
avctx->channel_layout = channel_mask;
@ -1379,7 +1378,7 @@ static int decode_frame(WMAProDecodeCtx *s)
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 +1464,7 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len,
*@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 +1548,20 @@ static int decode_packet(AVCodecContext *avctx,
*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;
int32_t* ptr = data;
int x;
for(x = 0; x < *data_size; x++)
{
fptr[x] *= ((float)(INT32_MAX));
ptr[x] = (int32_t)fptr[x];
}
#endif
return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
}

View file

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

View file

@ -20,14 +20,166 @@
****************************************************************************/
#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 int32_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, 32);
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;
restart_track:
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;
}
/* Deal with any pending seek requests */
if (ci->seek_time){
if (ci->seek_time == 1) {
ci->seek_complete();
goto restart_track; /* Pretend you never saw this... */
}
elapsedtime = asf_seek(ci->seek_time, &wfx);
if (elapsedtime < 1){
ci->seek_complete();
goto next_track;
}
ci->set_elapsed(elapsedtime);
ci->seek_complete();
}
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 /= (sizeof(int32_t) * wfx.channels);
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;
}

View file

@ -274,9 +274,14 @@ static int asf_parse_header(int fd, struct mp3entry* id3,
}
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 @@ static int asf_parse_header(int fd, struct mp3entry* id3,
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;