diff options
Diffstat (limited to 'apps/codecs/wma.c')
-rw-r--r-- | apps/codecs/wma.c | 108 |
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 | ||
70 | static int asf_read_packet(int* padding, asf_waveformatex_t* wfx) | 70 | static 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 | ||