synaptics: add a small delay in syn_get_data() for PB Vibe. Touchpad doesn't work...
[kugel-rb.git] / apps / codecs / wmapro.c
blob9e035559178d02c0271cf77b55ae4c2ebd662d34
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Mohamed Tarek
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "codeclib.h"
23 #include "libasf/asf.h"
24 #include "libwmapro/wmaprodec.h"
26 CODEC_HEADER
28 #define MAXSAMPLES (1L << 12) /* Max number of samples in a wma pro subframe */
29 #define MAXCHANNELS 8
30 #define BUFSIZE MAXCHANNELS * MAXSAMPLES
31 static int32_t decoded[BUFSIZE] IBSS_ATTR;
33 AVCodecContext avctx;
34 AVPacket avpkt;
36 /* This function initialises AVCodecContext with the data needed for the wmapro
37 * decoder to work. The required data is taken from asf_waveformatex_t because that's
38 * what the rockbox asf metadata parser fill/work with. In the future, when the
39 * codec is being optimised for on-target playback this function should not be needed,
40 * as we will be working directly with WMAProDecodeCtx (declared in wmaprodec.c) */
41 static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx)
43 /* Copy the extra-data */
44 avctx->extradata_size = wfx->datalen;
45 avctx->extradata = (uint8_t *)malloc(wfx->datalen*sizeof(uint8_t));
46 memcpy(avctx->extradata, wfx->data, wfx->datalen*sizeof(uint8_t));
48 avctx->block_align = wfx->blockalign;
49 avctx->sample_rate = wfx->rate;
50 avctx->channels = wfx->channels;
54 /* this is the codec entry point */
55 enum codec_status codec_main(void)
57 uint32_t elapsedtime;
58 int retval;
59 asf_waveformatex_t wfx; /* Holds the stream properties */
60 size_t resume_offset;
61 int res; /* Return values from asf_read_packet() and decode_packet() */
62 uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */
63 int audiobufsize; /* Payload size */
64 int packetlength = 0; /* Logical packet size (minus the header size) */
65 int outlen = 0; /* Number of bytes written to the output buffer */
66 int pktcnt = 0; /* Count of the packets played */
68 /* Generic codec initialisation */
69 ci->configure(DSP_SET_SAMPLE_DEPTH, 32);
72 next_track:
74 /* Wait for the metadata to be read */
75 while (!*ci->taginfo_ready && !ci->stop_codec)
76 ci->sleep(1);
78 retval = CODEC_OK;
80 /* Remember the resume position */
81 resume_offset = ci->id3->offset;
82 restart_track:
83 if (codec_init()) {
84 LOGF("(WMA PRO) Error: Error initialising codec\n");
85 retval = CODEC_ERROR;
86 goto done;
89 /* Copy the format metadata we've stored in the id3 TOC field. This
90 saves us from parsing it again here. */
91 memcpy(&wfx, ci->id3->toc, sizeof(wfx));
93 ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
94 ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
95 STEREO_MONO : STEREO_INTERLEAVED);
96 codec_set_replaygain(ci->id3);
98 /* Initialise the AVCodecContext */
99 init_codec_ctx(&avctx, &wfx);
101 if (decode_init(&avctx) < 0) {
102 LOGF("(WMA PRO) Error: Unsupported or corrupt file\n");
103 retval = CODEC_ERROR;
104 goto done;
107 /* Now advance the file position to the first frame */
108 ci->seek_buffer(ci->id3->first_frame_offset);
110 elapsedtime = 0;
111 resume_offset = 0;
113 /* The main decoding loop */
115 while (pktcnt < wfx.numpackets)
117 ci->yield();
118 if (ci->stop_codec || ci->new_track) {
119 goto done;
122 /* Deal with any pending seek requests */
123 if (ci->seek_time){
125 if (ci->seek_time == 1) {
126 ci->seek_complete();
127 goto restart_track; /* Pretend you never saw this... */
130 elapsedtime = asf_seek(ci->seek_time, &wfx);
131 if (elapsedtime < 1){
132 ci->seek_complete();
133 goto next_track;
136 ci->set_elapsed(elapsedtime);
137 ci->seek_complete();
140 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
142 if (res < 0) {
143 LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res);
144 goto done;
145 } else {
146 avpkt.data = audiobuf;
147 avpkt.size = audiobufsize;
148 pktcnt++;
150 /* We now loop on the packet, decoding and outputting the subframes
151 * one-by-one. For more information about how wma pro structures its
152 * audio frames, see libwmapro/wmaprodec.c */
153 while(avpkt.size > 0)
155 outlen = BUFSIZE; /* decode_packet needs to know the size of the output buffer */
156 res = decode_packet(&avctx, decoded, &outlen, &avpkt);
157 avpkt.data += res;
158 avpkt.size -= res;
159 avctx.frame_number++;
160 if(outlen) {
161 ci->yield ();
162 /* outlen now holds the size of the data in bytes - we want the
163 * number of samples. */
164 outlen /= (sizeof(int32_t) * wfx.channels);
165 ci->pcmbuf_insert(decoded, NULL, outlen);
166 elapsedtime += outlen*10/(wfx.rate/100);
167 ci->set_elapsed(elapsedtime);
168 ci->yield ();
174 /* Advance to the next logical packet */
175 ci->advance_buffer(packetlength);
177 retval = CODEC_OK;
179 done:
180 if (ci->request_next_track())
181 goto next_track;
183 return retval;