diff options
author | Sean Bartell <wingedtachikoma@gmail.com> | 2011-06-25 21:32:25 -0400 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2012-04-25 22:13:20 +0200 |
commit | f40bfc9267b13b54e6379dfe7539447662879d24 (patch) | |
tree | 9b20069d5e62809ff434061ad730096836f916f2 /lib/rbcodec/codecs/wmavoice.c | |
parent | a0009907de7a0107d49040d8a180f140e2eff299 (diff) | |
download | rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.tar.gz rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.zip |
Add codecs to librbcodec.
Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97
Reviewed-on: http://gerrit.rockbox.org/137
Reviewed-by: Nils Wallménius <nils@rockbox.org>
Tested-by: Nils Wallménius <nils@rockbox.org>
Diffstat (limited to 'lib/rbcodec/codecs/wmavoice.c')
-rw-r--r-- | lib/rbcodec/codecs/wmavoice.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/wmavoice.c b/lib/rbcodec/codecs/wmavoice.c new file mode 100644 index 0000000000..9cf5a49f1a --- /dev/null +++ b/lib/rbcodec/codecs/wmavoice.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Mohamed Tarek | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "codeclib.h" | ||
23 | #include "libasf/asf.h" | ||
24 | #include "libwmavoice/wmavoice.h" | ||
25 | |||
26 | CODEC_HEADER | ||
27 | |||
28 | static AVCodecContext avctx; | ||
29 | static AVPacket avpkt; | ||
30 | |||
31 | #define MAX_FRAMES 3 /*maximum number of frames per superframe*/ | ||
32 | #define MAX_FRAMESIZE 160 /* maximum number of samples per frame */ | ||
33 | #define BUFSIZE MAX_FRAMES*MAX_FRAMESIZE | ||
34 | static int32_t decoded[BUFSIZE] IBSS_ATTR; | ||
35 | |||
36 | |||
37 | /* This function initialises AVCodecContext with the data needed for the wmapro | ||
38 | * decoder to work. The required data is taken from asf_waveformatex_t because that's | ||
39 | * what the rockbox asf metadata parser fill/work with. In the future, when the | ||
40 | * codec is being optimised for on-target playback this function should not be needed. */ | ||
41 | static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx) | ||
42 | { | ||
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)); | ||
47 | |||
48 | avctx->block_align = wfx->blockalign; | ||
49 | avctx->sample_rate = wfx->rate; | ||
50 | avctx->channels = wfx->channels; | ||
51 | |||
52 | } | ||
53 | |||
54 | /* this is the codec entry point */ | ||
55 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
56 | { | ||
57 | if (reason == CODEC_LOAD) { | ||
58 | /* Generic codec initialisation */ | ||
59 | ci->configure(DSP_SET_SAMPLE_DEPTH, 31); | ||
60 | } | ||
61 | |||
62 | return CODEC_OK; | ||
63 | } | ||
64 | |||
65 | /* this is called for each file to process */ | ||
66 | enum codec_status codec_run(void) | ||
67 | { | ||
68 | uint32_t elapsedtime; | ||
69 | asf_waveformatex_t wfx; /* Holds the stream properties */ | ||
70 | size_t resume_offset; | ||
71 | int res; /* Return values from asf_read_packet() and decode_packet() */ | ||
72 | uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */ | ||
73 | int audiobufsize; /* Payload size */ | ||
74 | int packetlength = 0; /* Logical packet size (minus the header size) */ | ||
75 | int outlen = 0; /* Number of bytes written to the output buffer */ | ||
76 | int pktcnt = 0; /* Count of the packets played */ | ||
77 | intptr_t param; | ||
78 | |||
79 | /* Remember the resume position */ | ||
80 | resume_offset = ci->id3->offset; | ||
81 | restart_track: | ||
82 | if (codec_init()) { | ||
83 | LOGF("(WMA Voice) Error: Error initialising codec\n"); | ||
84 | return CODEC_ERROR; | ||
85 | } | ||
86 | |||
87 | /* Copy the format metadata we've stored in the id3 TOC field. This | ||
88 | saves us from parsing it again here. */ | ||
89 | memcpy(&wfx, ci->id3->toc, sizeof(wfx)); | ||
90 | memset(&avctx, 0, sizeof(AVCodecContext)); | ||
91 | memset(&avpkt, 0, sizeof(AVPacket)); | ||
92 | |||
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); | ||
97 | |||
98 | ci->seek_buffer(0); | ||
99 | |||
100 | /* Initialise the AVCodecContext */ | ||
101 | init_codec_ctx(&avctx, &wfx); | ||
102 | |||
103 | if (wmavoice_decode_init(&avctx) < 0) { | ||
104 | LOGF("(WMA Voice) Error: Unsupported or corrupt file\n"); | ||
105 | return CODEC_ERROR; | ||
106 | } | ||
107 | |||
108 | /* Now advance the file position to the first frame */ | ||
109 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
110 | |||
111 | elapsedtime = 0; | ||
112 | ci->set_elapsed(0); | ||
113 | |||
114 | resume_offset = 0; | ||
115 | |||
116 | /* The main decoding loop */ | ||
117 | |||
118 | while (pktcnt < wfx.numpackets) | ||
119 | { | ||
120 | enum codec_command_action action = ci->get_command(¶m); | ||
121 | |||
122 | if (action == CODEC_ACTION_HALT) | ||
123 | break; | ||
124 | |||
125 | /* Deal with any pending seek requests */ | ||
126 | if (action == CODEC_ACTION_SEEK_TIME) { | ||
127 | ci->set_elapsed(param); | ||
128 | |||
129 | if (param == 0) { | ||
130 | ci->set_elapsed(0); | ||
131 | ci->seek_complete(); | ||
132 | goto restart_track; /* Pretend you never saw this... */ | ||
133 | } | ||
134 | |||
135 | elapsedtime = asf_seek(param, &wfx); | ||
136 | if (elapsedtime < 1){ | ||
137 | ci->set_elapsed(0); | ||
138 | ci->seek_complete(); | ||
139 | goto next_track; | ||
140 | } | ||
141 | |||
142 | ci->set_elapsed(elapsedtime); | ||
143 | ci->seek_complete(); | ||
144 | } | ||
145 | |||
146 | new_packet: | ||
147 | res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); | ||
148 | |||
149 | if (res < 0) { | ||
150 | LOGF("(WMA Voice) read_packet error %d\n",res); | ||
151 | return CODEC_ERROR; | ||
152 | } else { | ||
153 | avpkt.data = audiobuf; | ||
154 | avpkt.size = audiobufsize; | ||
155 | pktcnt++; | ||
156 | |||
157 | while(avpkt.size > 0) | ||
158 | { | ||
159 | /* wmavoice_decode_packet checks for the output buffer size to | ||
160 | avoid overflows */ | ||
161 | outlen = BUFSIZE*sizeof(int32_t); | ||
162 | |||
163 | res = wmavoice_decode_packet(&avctx, decoded, &outlen, &avpkt); | ||
164 | if(res < 0) { | ||
165 | LOGF("(WMA Voice) Error: decode_packet returned %d", res); | ||
166 | if(res == ERROR_WMAPRO_IN_WMAVOICE){ | ||
167 | /* Just skip this packet */ | ||
168 | ci->advance_buffer(packetlength); | ||
169 | goto new_packet; | ||
170 | } | ||
171 | else { | ||
172 | return CODEC_ERROR; | ||
173 | } | ||
174 | } | ||
175 | avpkt.data += res; | ||
176 | avpkt.size -= res; | ||
177 | if(outlen) { | ||
178 | ci->yield (); | ||
179 | outlen /= sizeof(int32_t); | ||
180 | ci->pcmbuf_insert(decoded, NULL, outlen); | ||
181 | elapsedtime += outlen*10/(wfx.rate/100); | ||
182 | ci->set_elapsed(elapsedtime); | ||
183 | ci->yield (); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | } | ||
188 | |||
189 | /* Advance to the next logical packet */ | ||
190 | ci->advance_buffer(packetlength); | ||
191 | } | ||
192 | |||
193 | return CODEC_OK; | ||
194 | } | ||
195 | |||