1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 Dave Chapman
12 * ASF parsing code based on libasf by Juho Vähä-Herttua
13 * http://code.google.com/p/libasf/ libasf itself was based on the ASF
14 * parser in VLC - http://www.videolan.org/
16 * All files in this archive are subject to the GNU General Public License.
17 * See the file COPYING in the source tree root for full license agreement.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "libwma/asf.h"
26 #include "libwma/wmadec.h"
32 /* The output buffer containing the decoded samples (channels 0 and 1)
33 BLOCK_MAX_SIZE is 2048 (samples) and MAX_CHANNELS is 2.
36 static uint32_t decoded
[BLOCK_MAX_SIZE
* MAX_CHANNELS
];
38 /* NOTE: WMADecodeContext is 120152 bytes (on x86) */
39 static WMADecodeContext wmadec
;
42 ASF_ERROR_INTERNAL
= -1, /* incorrect input to API calls */
43 ASF_ERROR_OUTOFMEM
= -2, /* some malloc inside program failed */
44 ASF_ERROR_EOF
= -3, /* unexpected end of file */
45 ASF_ERROR_IO
= -4, /* error reading or writing to file */
46 ASF_ERROR_INVALID_LENGTH
= -5, /* length value conflict in input data */
47 ASF_ERROR_INVALID_VALUE
= -6, /* other value conflict in input data */
48 ASF_ERROR_INVALID_OBJECT
= -7, /* ASF object missing or in wrong place */
49 ASF_ERROR_OBJECT_SIZE
= -8, /* invalid ASF object size (too small) */
50 ASF_ERROR_SEEKABLE
= -9, /* file not seekable */
51 ASF_ERROR_SEEK
= -10 /* file is seekable but seeking failed */
54 /* Read an unaligned 32-bit little endian long from buffer. */
55 static unsigned long get_long_le(void* buf
)
57 unsigned char* p
= (unsigned char*) buf
;
59 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
62 /* Read an unaligned 16-bit little endian short from buffer. */
63 static unsigned short get_short_le(void* buf
)
65 unsigned char* p
= (unsigned char*) buf
;
67 return p
[0] | (p
[1] << 8);
70 #define GETLEN2b(bits) (((bits) == 0x03) ? 4 : bits)
72 #define GETVALUE2b(bits, data) \
73 (((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \
74 0 : *(data) : get_short_le(data) : get_long_le(data))
76 static int asf_read_packet(uint8_t** audiobuf
, int* audiobufsize
, int* packetlength
, asf_waveformatex_t
* wfx
)
78 uint8_t tmp8
, packet_flags
, packet_property
;
80 int ec_length
, opaque_data
, ec_length_type
;
85 uint32_t padding_length
;
88 uint16_t payload_count
;
89 int payload_length_type
;
90 uint32_t payload_hdrlen
;
93 uint32_t replicated_length
;
94 uint32_t media_object_number
;
95 uint32_t media_object_offset
;
96 uint32_t bytesread
= 0;
100 /*DEBUGF("Reading new packet at %d bytes ", (int)ci->curpos);*/
102 if (ci
->read_filebuf(&tmp8
, 1) == 0) {
103 return ASF_ERROR_EOF
;
107 /* TODO: We need a better way to detect endofstream */
109 DEBUGF("Read failed: packet did not sync\n");
115 ec_length
= tmp8
& 0x0f;
116 opaque_data
= (tmp8
>> 4) & 0x01;
117 ec_length_type
= (tmp8
>> 5) & 0x03;
119 if (ec_length_type
!= 0x00 || opaque_data
!= 0 || ec_length
!= 0x02) {
120 DEBUGF("incorrect error correction flags\n");
121 return ASF_ERROR_INVALID_VALUE
;
125 ci
->advance_buffer(ec_length
);
126 bytesread
+= ec_length
;
131 if (ci
->read_filebuf(&packet_flags
, 1) == 0) { return ASF_ERROR_EOF
; }
132 if (ci
->read_filebuf(&packet_property
, 1) == 0) { return ASF_ERROR_EOF
; }
135 datalen
= GETLEN2b((packet_flags
>> 1) & 0x03) +
136 GETLEN2b((packet_flags
>> 3) & 0x03) +
137 GETLEN2b((packet_flags
>> 5) & 0x03) + 6;
140 if (datalen
> sizeof(data
)) {
141 DEBUGF("Unexpectedly long datalen in data - %d\n",datalen
);
142 return ASF_ERROR_OUTOFMEM
;
146 if (ci
->read_filebuf(data
, datalen
) == 0) {
147 return ASF_ERROR_EOF
;
150 bytesread
+= datalen
;
153 length
= GETVALUE2b((packet_flags
>> 5) & 0x03, datap
);
154 datap
+= GETLEN2b((packet_flags
>> 5) & 0x03);
155 /* sequence value is not used */
156 GETVALUE2b((packet_flags
>> 1) & 0x03, datap
);
157 datap
+= GETLEN2b((packet_flags
>> 1) & 0x03);
158 padding_length
= GETVALUE2b((packet_flags
>> 3) & 0x03, datap
);
159 datap
+= GETLEN2b((packet_flags
>> 3) & 0x03);
160 send_time
= get_long_le(datap
);
162 duration
= get_short_le(datap
);
164 /*DEBUGF("and duration %d ms\n", duration);*/
166 /* this is really idiotic, packet length can (and often will) be
167 * undefined and we just have to use the header packet size as the size
169 if (!((packet_flags
>> 5) & 0x03)) {
170 length
= wfx
->packet_size
;
173 /* this is also really idiotic, if packet length is smaller than packet
174 * size, we need to manually add the additional bytes into padding length
176 if (length
< wfx
->packet_size
) {
177 padding_length
+= wfx
->packet_size
- length
;
178 length
= wfx
->packet_size
;
181 if (length
> wfx
->packet_size
) {
182 DEBUGF("packet with too big length value\n");
183 return ASF_ERROR_INVALID_LENGTH
;
186 /* check if we have multiple payloads */
187 if (packet_flags
& 0x01) {
188 if (ci
->read_filebuf(&tmp8
, 1) == 0) {
189 return ASF_ERROR_EOF
;
191 payload_count
= tmp8
& 0x3f;
192 payload_length_type
= (tmp8
>> 6) & 0x03;
196 payload_length_type
= 0x02; /* not used */
199 if (length
< bytesread
) {
200 DEBUGF("header exceeded packet size, invalid file - length=%d, bytesread=%d\n",(int)length
,(int)bytesread
);
201 /* FIXME: should this be checked earlier? */
202 return ASF_ERROR_INVALID_LENGTH
;
206 /* We now parse the individual payloads, and move all payloads
207 belonging to our audio stream to a contiguous block, starting at
208 the location of the first payload.
213 *packetlength
= length
- bytesread
;
215 buf
= ci
->request_buffer(&bufsize
, length
);
218 if (bufsize
!= length
) {
219 /* This should only happen with packets larger than 32KB (the
220 guard buffer size). All the streams I've seen have
221 relatively small packets less than about 8KB), but I don't
222 know what is expected.
224 DEBUGF("Could not read packet (requested %d bytes, received %d), curpos=%d, aborting\n",
225 (int)length
,(int)bufsize
,(int)ci
->curpos
);
229 for (i
=0; i
<payload_count
; i
++) {
230 stream_id
= datap
[0]&0x7f;
234 payload_hdrlen
= GETLEN2b(packet_property
& 0x03) +
235 GETLEN2b((packet_property
>> 2) & 0x03) +
236 GETLEN2b((packet_property
>> 4) & 0x03);
238 //DEBUGF("payload_hdrlen = %d\n",payload_hdrlen);
241 if (payload_hdrlen
> size
) {
242 return ASF_ERROR_INVALID_LENGTH
;
245 if (payload_hdrlen
> sizeof(data
)) {
246 DEBUGF("Unexpectedly long datalen in data - %d\n",datalen
);
247 return ASF_ERROR_OUTOFMEM
;
250 bytesread
+= payload_hdrlen
;
251 media_object_number
= GETVALUE2b((packet_property
>> 4) & 0x03, datap
);
252 datap
+= GETLEN2b((packet_property
>> 4) & 0x03);
253 media_object_offset
= GETVALUE2b((packet_property
>> 2) & 0x03, datap
);
254 datap
+= GETLEN2b((packet_property
>> 2) & 0x03);
255 replicated_length
= GETVALUE2b(packet_property
& 0x03, datap
);
256 datap
+= GETLEN2b(packet_property
& 0x03);
258 /* TODO: Validate replicated_length */
259 /* TODO: Is the content of this important for us? */
260 datap
+= replicated_length
;
261 bytesread
+= replicated_length
;
263 multiple
= packet_flags
& 0x01;
269 x
= GETLEN2b(payload_length_type
);
272 /* in multiple payloads datalen should be a word */
273 return ASF_ERROR_INVALID_VALUE
;
277 if (skip
+ tmp
> datalen
) {
278 /* not enough data */
279 return ASF_ERROR_INVALID_LENGTH
;
282 payload_datalen
= GETVALUE2b(payload_length_type
, datap
);
286 payload_datalen
= length
- bytesread
- padding_length
;
289 if (stream_id
== wfx
->audiostream
)
291 if (*audiobuf
== NULL
) {
292 /* The first payload can stay where it is */
294 *audiobufsize
= payload_datalen
;
296 /* The second and subsequent payloads in this packet
297 that belong to the audio stream need to be moved to be
298 contiguous with the first payload.
300 memmove(*audiobuf
+ *audiobufsize
, datap
, payload_datalen
);
301 *audiobufsize
+= payload_datalen
;
304 datap
+= payload_datalen
;
305 bytesread
+= payload_datalen
;
308 if (*audiobuf
!= NULL
)
315 static int get_timestamp(int *duration
)
317 uint8_t tmp8
, packet_flags
, packet_property
;
318 int ec_length
, opaque_data
, ec_length_type
;
323 uint32_t padding_length
;
326 uint32_t bytesread
= 0;
328 if (ci
->read_filebuf(&tmp8
, 1) == 0) {
329 DEBUGF("ASF ERROR (EOF?)\n");
330 return ASF_ERROR_EOF
;
334 /* TODO: We need a better way to detect endofstream */
336 DEBUGF("Get timestamp: Detected end of stream\n");
337 return ASF_ERROR_EOF
;
342 ec_length
= tmp8
& 0x0f;
343 opaque_data
= (tmp8
>> 4) & 0x01;
344 ec_length_type
= (tmp8
>> 5) & 0x03;
346 if (ec_length_type
!= 0x00 || opaque_data
!= 0 || ec_length
!= 0x02) {
347 DEBUGF("incorrect error correction flags\n");
348 return ASF_ERROR_INVALID_VALUE
;
352 ci
->advance_buffer(ec_length
);
353 bytesread
+= ec_length
;
358 if (ci
->read_filebuf(&packet_flags
, 1) == 0) {
359 DEBUGF("Detected end of stream 2\n");
360 return ASF_ERROR_EOF
;
363 if (ci
->read_filebuf(&packet_property
, 1) == 0) {
364 DEBUGF("Detected end of stream3\n");
365 return ASF_ERROR_EOF
;
369 datalen
= GETLEN2b((packet_flags
>> 1) & 0x03) +
370 GETLEN2b((packet_flags
>> 3) & 0x03) +
371 GETLEN2b((packet_flags
>> 5) & 0x03) + 6;
373 if (ci
->read_filebuf(data
, datalen
) == 0) {
374 DEBUGF("Detected end of stream4\n");
375 return ASF_ERROR_EOF
;
378 bytesread
+= datalen
;
381 length
= GETVALUE2b((packet_flags
>> 5) & 0x03, datap
);
382 datap
+= GETLEN2b((packet_flags
>> 5) & 0x03);
384 /* sequence value is not used */
385 GETVALUE2b((packet_flags
>> 1) & 0x03, datap
);
386 datap
+= GETLEN2b((packet_flags
>> 1) & 0x03);
387 padding_length
= GETVALUE2b((packet_flags
>> 3) & 0x03, datap
);
388 datap
+= GETLEN2b((packet_flags
>> 3) & 0x03);
389 send_time
= get_long_le(datap
);
391 *duration
= get_short_le(datap
);
393 /*the get_timestamp function advances us 12-13 bytes past the packet start,
394 need to undo this here so that we stay synced with the packet*/
395 ci
->seek_buffer(ci
->curpos
-bytesread
);
400 /*entry point for seeks*/
401 static int seek(int ms
, asf_waveformatex_t
* wfx
)
403 int time
, duration
, delta
, temp
, count
=0;
405 /*estimate packet number from bitrate*/
406 int initial_packet
= ci
->curpos
/wfx
->packet_size
;
407 int packet_num
= (((int64_t)ms
)*(wfx
->bitrate
>>3))/wfx
->packet_size
/1000;
408 int last_packet
= ci
->id3
->filesize
/ wfx
->packet_size
;
410 if (packet_num
> last_packet
) {
411 packet_num
= last_packet
;
414 /*calculate byte address of the start of that packet*/
415 int packet_offset
= packet_num
*wfx
->packet_size
;
417 /*seek to estimated packet*/
418 ci
->seek_buffer(ci
->id3
->first_frame_offset
+packet_offset
);
422 /*for very large files it can be difficult and unimportant to find the exact packet*/
425 /*check the time stamp of our packet*/
426 time
= get_timestamp(&duration
);
427 DEBUGF("seeked to %d ms with duration %d\n", time
, duration
);
430 /*unknown error, try to recover*/
431 DEBUGF("UKNOWN SEEK ERROR\n");
432 ci
->seek_buffer(ci
->id3
->first_frame_offset
+initial_packet
*wfx
->packet_size
);
433 /*seek failed so return time stamp of the initial packet*/
434 return get_timestamp(&duration
);
437 if ((time
+duration
>=ms
&& time
<=ms
) || count
> 10) {
438 DEBUGF("Found our packet! Now at %d packet\n", packet_num
);
443 /*estimate new packet number from bitrate and our current position*/
445 packet_num
= ((temp
/1000)*(wfx
->bitrate
>>3) - (wfx
->packet_size
>>1))/wfx
->packet_size
; //round down!
446 packet_offset
= packet_num
*wfx
->packet_size
;
447 ci
->seek_buffer(ci
->id3
->first_frame_offset
+packet_offset
);
454 /* this is the codec entry point */
455 enum codec_status
codec_main(void)
457 uint32_t elapsedtime
;
459 asf_waveformatex_t wfx
;
460 size_t resume_offset
;
468 /* Generic codec initialisation */
469 ci
->configure(CODEC_SET_FILEBUF_WATERMARK
, 1024*512);
471 ci
->configure(DSP_SET_SAMPLE_DEPTH
, 30);
475 /* Wait for the metadata to be read */
476 while (!*ci
->taginfo_ready
&& !ci
->stop_codec
)
481 /* Remember the resume position - when the codec is opened, the
482 playback engine will reset it. */
483 resume_offset
= ci
->id3
->offset
;
486 LOGF("WMA: Error initialising codec\n");
487 retval
= CODEC_ERROR
;
491 /* Copy the format metadata we've stored in the id3 TOC field. This
492 saves us from parsing it again here. */
493 memcpy(&wfx
, ci
->id3
->toc
, sizeof(wfx
));
495 if (wma_decode_init(&wmadec
,&wfx
) < 0) {
496 LOGF("WMA: Unsupported or corrupt file\n");
497 retval
= CODEC_ERROR
;
501 DEBUGF("**************** IN WMA.C ******************\n");
503 if (resume_offset
> ci
->id3
->first_frame_offset
)
505 /* Get start of current packet */
506 int packet_offset
= (resume_offset
- ci
->id3
->first_frame_offset
)
508 ci
->seek_buffer(resume_offset
- packet_offset
);
509 elapsedtime
= get_timestamp(&i
);
510 ci
->set_elapsed(elapsedtime
);
514 /* Now advance the file position to the first frame */
515 ci
->seek_buffer(ci
->id3
->first_frame_offset
);
520 ci
->configure(DSP_SWITCH_FREQUENCY
, wfx
.rate
);
521 ci
->configure(DSP_SET_STEREO_MODE
, wfx
.channels
== 1 ?
522 STEREO_MONO
: STEREO_INTERLEAVED
);
523 codec_set_replaygain(ci
->id3
);
525 /* The main decoding loop */
531 if (ci
->stop_codec
|| ci
->new_track
) {
535 /* Deal with any pending seek requests */
538 if (ci
->seek_time
== 1) {
540 goto restart_track
; /* Pretend you never saw this... */
543 elapsedtime
= seek(ci
->seek_time
, &wfx
);
544 if (elapsedtime
< 1){
548 /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/
549 ci
->set_elapsed(elapsedtime
);
551 /*flush the wma decoder state*/
552 wmadec
.last_superframe_len
= 0;
553 wmadec
.last_bitoffset
= 0;
558 res
= asf_read_packet(&audiobuf
, &audiobufsize
, &packetlength
, &wfx
);
561 /* We'll try to recover from a parse error a certain number of
562 * times. If we succeed, the error counter will be reset.
566 DEBUGF("read_packet error %d, errcount %d\n",wmares
, errcount
);
570 ci
->advance_buffer(packetlength
);
573 } else if (res
> 0) {
574 wma_decode_superframe_init(&wmadec
, audiobuf
, audiobufsize
);
576 for (i
=0; i
< wmadec
.nb_frames
; i
++)
578 wmares
= wma_decode_superframe_frame(&wmadec
,
580 audiobuf
, audiobufsize
);
585 /* Do the above, but for errors in decode. */
587 DEBUGF("WMA decode error %d, errcount %d\n",wmares
, errcount
);
591 ci
->advance_buffer(packetlength
);
594 } else if (wmares
> 0) {
595 ci
->pcmbuf_insert(decoded
, NULL
, wmares
);
596 elapsedtime
+= (wmares
*10)/(wfx
.rate
/100);
597 ci
->set_elapsed(elapsedtime
);
603 ci
->advance_buffer(packetlength
);
608 /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/
610 if (ci
->request_next_track())