summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/wma.c108
1 files changed, 66 insertions, 42 deletions
diff --git a/apps/codecs/wma.c b/apps/codecs/wma.c
index ab4a808f92..71b1720408 100644
--- a/apps/codecs/wma.c
+++ b/apps/codecs/wma.c
@@ -67,9 +67,10 @@ static unsigned short get_short_le(void* buf)
67 (((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \ 67 (((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \
68 0 : *(data) : get_short_le(data) : get_long_le(data)) 68 0 : *(data) : get_short_le(data) : get_long_le(data))
69 69
70static int asf_read_packet(int* padding, asf_waveformatex_t* wfx) 70static int asf_read_packet(uint8_t** audiobuf, int* audiobufsize, int* packetlength, asf_waveformatex_t* wfx)
71{ 71{
72 uint8_t tmp8, packet_flags, packet_property; 72 uint8_t tmp8, packet_flags, packet_property;
73 int stream_id;
73 int ec_length, opaque_data, ec_length_type; 74 int ec_length, opaque_data, ec_length_type;
74 int datalen; 75 int datalen;
75 uint8_t data[18]; 76 uint8_t data[18];
@@ -87,16 +88,19 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
87 uint32_t media_object_number; 88 uint32_t media_object_number;
88 uint32_t media_object_offset; 89 uint32_t media_object_offset;
89 uint32_t bytesread = 0; 90 uint32_t bytesread = 0;
91 uint8_t* buf;
92 size_t bufsize;
93 int i;
90 94
91 if (ci->read_filebuf(&tmp8, 1) == 0) { 95 if (ci->read_filebuf(&tmp8, 1) == 0) {
92 return ASF_ERROR_EOF; 96 return ASF_ERROR_EOF;
93 } 97 }
94 bytesread++; 98 bytesread++;
95 99
100 //DEBUGF("tmp8=0x%02x\n",tmp8);
96 /* TODO: We need a better way to detect endofstream */ 101 /* TODO: We need a better way to detect endofstream */
97 if (tmp8 != 0x82) { return -1; } 102 if (tmp8 != 0x82) { return -1; }
98 103
99 //DEBUGF("tmp8=0x%02x\n",tmp8);
100 104
101 if (tmp8 & 0x80) { 105 if (tmp8 & 0x80) {
102 ec_length = tmp8 & 0x0f; 106 ec_length = tmp8 & 0x0f;
@@ -188,22 +192,33 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
188 return ASF_ERROR_INVALID_LENGTH; 192 return ASF_ERROR_INVALID_LENGTH;
189 } 193 }
190 194
191 if (ci->read_filebuf(&tmp8, 1) == 0) {
192 return ASF_ERROR_EOF;
193 }
194 //DEBUGF("stream = %u\n",tmp8&0x7f);
195 bytesread++;
196 195
197 if ((tmp8 & 0x7f) != wfx->audiostream) { 196 /* We now parse the individual payloads, and move all payloads
198 /* Not interested in this packet, just skip it */ 197 belonging to our audio stream to a contiguous block, starting at
199 ci->advance_buffer(length - bytesread); 198 the location of the first payload.
200 return 0; 199 */
201 } else { 200
202 /* We are now at the data */ 201 *audiobuf = NULL;
203 //DEBUGF("Read packet - length=%u, padding_length=%u, send_time=%u, duration=%u, payload_count=%d, bytesread=%d\n",length,padding_length,(int)send_time,duration,payload_count,bytesread); 202 *audiobufsize = 0;
203 *packetlength = length - bytesread;
204
205 buf = ci->request_buffer(&bufsize, length);
206 datap = buf;
204 207
205 /* TODO: Loop through all payloads in this packet - or do we 208 if (bufsize != length) {
206 assume that audio streams only have one payload per packet? */ 209 /* This should only happen with packets larger than 32KB (the
210 guard buffer size). All the streams I've seen have
211 relatively small packets less than about 8KB), but I don't
212 know what is expected.
213 */
214 DEBUGF("Could not read packet (%d bytes), aborting\n",(int)length);
215 return -1;
216 }
217
218 for (i=0; i<payload_count; i++) {
219 stream_id = datap[0]&0x7f;
220 datap++;
221 bytesread++;
207 222
208 payload_hdrlen = GETLEN2b(packet_property & 0x03) + 223 payload_hdrlen = GETLEN2b(packet_property & 0x03) +
209 GETLEN2b((packet_property >> 2) & 0x03) + 224 GETLEN2b((packet_property >> 2) & 0x03) +
@@ -221,12 +236,7 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
221 return ASF_ERROR_OUTOFMEM; 236 return ASF_ERROR_OUTOFMEM;
222 } 237 }
223 238
224 if (ci->read_filebuf(data, payload_hdrlen) == 0) {
225 return ASF_ERROR_EOF;
226 }
227 bytesread += payload_hdrlen; 239 bytesread += payload_hdrlen;
228
229 datap = data;
230 media_object_number = GETVALUE2b((packet_property >> 4) & 0x03, datap); 240 media_object_number = GETVALUE2b((packet_property >> 4) & 0x03, datap);
231 datap += GETLEN2b((packet_property >> 4) & 0x03); 241 datap += GETLEN2b((packet_property >> 4) & 0x03);
232 media_object_offset = GETVALUE2b((packet_property >> 2) & 0x03, datap); 242 media_object_offset = GETVALUE2b((packet_property >> 2) & 0x03, datap);
@@ -236,10 +246,9 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
236 246
237 /* TODO: Validate replicated_length */ 247 /* TODO: Validate replicated_length */
238 /* TODO: Is the content of this important for us? */ 248 /* TODO: Is the content of this important for us? */
239 ci->advance_buffer(replicated_length); 249 datap += replicated_length;
240 bytesread += replicated_length; 250 bytesread += replicated_length;
241 251
242
243 multiple = packet_flags & 0x01; 252 multiple = packet_flags & 0x01;
244 253
245 if (multiple) { 254 if (multiple) {
@@ -258,20 +267,36 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
258 return ASF_ERROR_INVALID_LENGTH; 267 return ASF_ERROR_INVALID_LENGTH;
259 } 268 }
260#endif 269#endif
261 if (ci->read_filebuf(&data, x) == 0) { 270 payload_datalen = GETVALUE2b(payload_length_type, datap);
262 return ASF_ERROR_EOF; 271 datap += x;
263 }
264 bytesread += x; 272 bytesread += x;
265 payload_datalen = GETVALUE2b(payload_length_type, data);
266 } else { 273 } else {
267 payload_datalen = length - bytesread; 274 payload_datalen = length - bytesread - padding_length;
268 } 275 }
269 276
270 //DEBUGF("WE HAVE DATA - %d bytes\n", payload_datalen); 277 if (stream_id == wfx->audiostream)
271// lseek(fd, payload_datalen, SEEK_CUR); 278 {
272 *padding = padding_length; 279 if (*audiobuf == NULL) {
273 return payload_datalen; 280 /* The first payload can stay where it is */
281 *audiobuf = datap;
282 *audiobufsize = payload_datalen;
283 } else {
284 /* The second and subsequent payloads in this packet
285 that belong to the audio stream need to be moved to be
286 contiguous with the first payload.
287 */
288 memmove(*audiobuf + *audiobufsize, datap, payload_datalen);
289 *audiobufsize += payload_datalen;
290 }
291 }
292 datap += payload_datalen;
293 bytesread += payload_datalen;
274 } 294 }
295
296 if (*audiobuf != NULL)
297 return 1;
298 else
299 return 0;
275} 300}
276 301
277/* this is the codec entry point */ 302/* this is the codec entry point */
@@ -282,11 +307,12 @@ enum codec_status codec_main(void)
282 int retval; 307 int retval;
283 asf_waveformatex_t wfx; 308 asf_waveformatex_t wfx;
284 uint32_t currentframe; 309 uint32_t currentframe;
285 unsigned char* inbuffer;
286 size_t resume_offset; 310 size_t resume_offset;
287 size_t n;
288 int i; 311 int i;
289 int wmares, res, padding; 312 int wmares, res;
313 uint8_t* audiobuf;
314 int audiobufsize;
315 int packetlength;
290 316
291 /* Generic codec initialisation */ 317 /* Generic codec initialisation */
292 ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); 318 ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
@@ -348,18 +374,16 @@ enum codec_status codec_main(void)
348 ci->seek_complete(); 374 ci->seek_complete();
349 } 375 }
350 376
351 res = asf_read_packet(&padding, &wfx); 377 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
352 if (res > 0) { 378 if (res > 0) {
353 inbuffer = ci->request_buffer(&n, res - padding);
354
355 wma_decode_superframe_init(&wmadec, 379 wma_decode_superframe_init(&wmadec,
356 inbuffer,res - padding); 380 audiobuf, audiobufsize);
357 381
358 for (i=0; i < wmadec.nb_frames; i++) 382 for (i=0; i < wmadec.nb_frames; i++)
359 { 383 {
360 wmares = wma_decode_superframe_frame(&wmadec, 384 wmares = wma_decode_superframe_frame(&wmadec,
361 decoded, 385 decoded,
362 inbuffer,res - padding); 386 audiobuf, audiobufsize);
363 387
364 ci->yield (); 388 ci->yield ();
365 389
@@ -375,9 +399,9 @@ enum codec_status codec_main(void)
375 } 399 }
376 ci->yield (); 400 ci->yield ();
377 } 401 }
378
379 ci->advance_buffer(res);
380 } 402 }
403
404 ci->advance_buffer(packetlength);
381 } 405 }
382 retval = CODEC_OK; 406 retval = CODEC_OK;
383 407