forked from len0rd/rockbox
ASF parser improvements - it now correctly handles files containing multiple payloads. i.e. files where the audio packets are split into multiple payloads, and streams where audio/video payloads are mixed within the same packet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13840 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
830f4fcc8a
commit
47e969278b
1 changed files with 66 additions and 42 deletions
|
|
@ -67,9 +67,10 @@ static unsigned short get_short_le(void* buf)
|
|||
(((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \
|
||||
0 : *(data) : get_short_le(data) : get_long_le(data))
|
||||
|
||||
static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
||||
static int asf_read_packet(uint8_t** audiobuf, int* audiobufsize, int* packetlength, asf_waveformatex_t* wfx)
|
||||
{
|
||||
uint8_t tmp8, packet_flags, packet_property;
|
||||
int stream_id;
|
||||
int ec_length, opaque_data, ec_length_type;
|
||||
int datalen;
|
||||
uint8_t data[18];
|
||||
|
|
@ -87,16 +88,19 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
|||
uint32_t media_object_number;
|
||||
uint32_t media_object_offset;
|
||||
uint32_t bytesread = 0;
|
||||
uint8_t* buf;
|
||||
size_t bufsize;
|
||||
int i;
|
||||
|
||||
if (ci->read_filebuf(&tmp8, 1) == 0) {
|
||||
return ASF_ERROR_EOF;
|
||||
}
|
||||
bytesread++;
|
||||
|
||||
//DEBUGF("tmp8=0x%02x\n",tmp8);
|
||||
/* TODO: We need a better way to detect endofstream */
|
||||
if (tmp8 != 0x82) { return -1; }
|
||||
|
||||
//DEBUGF("tmp8=0x%02x\n",tmp8);
|
||||
|
||||
if (tmp8 & 0x80) {
|
||||
ec_length = tmp8 & 0x0f;
|
||||
|
|
@ -188,22 +192,33 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
|||
return ASF_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
if (ci->read_filebuf(&tmp8, 1) == 0) {
|
||||
return ASF_ERROR_EOF;
|
||||
|
||||
/* We now parse the individual payloads, and move all payloads
|
||||
belonging to our audio stream to a contiguous block, starting at
|
||||
the location of the first payload.
|
||||
*/
|
||||
|
||||
*audiobuf = NULL;
|
||||
*audiobufsize = 0;
|
||||
*packetlength = length - bytesread;
|
||||
|
||||
buf = ci->request_buffer(&bufsize, length);
|
||||
datap = buf;
|
||||
|
||||
if (bufsize != length) {
|
||||
/* This should only happen with packets larger than 32KB (the
|
||||
guard buffer size). All the streams I've seen have
|
||||
relatively small packets less than about 8KB), but I don't
|
||||
know what is expected.
|
||||
*/
|
||||
DEBUGF("Could not read packet (%d bytes), aborting\n",(int)length);
|
||||
return -1;
|
||||
}
|
||||
//DEBUGF("stream = %u\n",tmp8&0x7f);
|
||||
bytesread++;
|
||||
|
||||
if ((tmp8 & 0x7f) != wfx->audiostream) {
|
||||
/* Not interested in this packet, just skip it */
|
||||
ci->advance_buffer(length - bytesread);
|
||||
return 0;
|
||||
} else {
|
||||
/* We are now at the data */
|
||||
//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);
|
||||
|
||||
/* TODO: Loop through all payloads in this packet - or do we
|
||||
assume that audio streams only have one payload per packet? */
|
||||
for (i=0; i<payload_count; i++) {
|
||||
stream_id = datap[0]&0x7f;
|
||||
datap++;
|
||||
bytesread++;
|
||||
|
||||
payload_hdrlen = GETLEN2b(packet_property & 0x03) +
|
||||
GETLEN2b((packet_property >> 2) & 0x03) +
|
||||
|
|
@ -221,12 +236,7 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
|||
return ASF_ERROR_OUTOFMEM;
|
||||
}
|
||||
|
||||
if (ci->read_filebuf(data, payload_hdrlen) == 0) {
|
||||
return ASF_ERROR_EOF;
|
||||
}
|
||||
bytesread += payload_hdrlen;
|
||||
|
||||
datap = data;
|
||||
media_object_number = GETVALUE2b((packet_property >> 4) & 0x03, datap);
|
||||
datap += GETLEN2b((packet_property >> 4) & 0x03);
|
||||
media_object_offset = GETVALUE2b((packet_property >> 2) & 0x03, datap);
|
||||
|
|
@ -236,10 +246,9 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
|||
|
||||
/* TODO: Validate replicated_length */
|
||||
/* TODO: Is the content of this important for us? */
|
||||
ci->advance_buffer(replicated_length);
|
||||
datap += replicated_length;
|
||||
bytesread += replicated_length;
|
||||
|
||||
|
||||
multiple = packet_flags & 0x01;
|
||||
|
||||
if (multiple) {
|
||||
|
|
@ -258,20 +267,36 @@ static int asf_read_packet(int* padding, asf_waveformatex_t* wfx)
|
|||
return ASF_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
#endif
|
||||
if (ci->read_filebuf(&data, x) == 0) {
|
||||
return ASF_ERROR_EOF;
|
||||
}
|
||||
payload_datalen = GETVALUE2b(payload_length_type, datap);
|
||||
datap += x;
|
||||
bytesread += x;
|
||||
payload_datalen = GETVALUE2b(payload_length_type, data);
|
||||
} else {
|
||||
payload_datalen = length - bytesread;
|
||||
payload_datalen = length - bytesread - padding_length;
|
||||
}
|
||||
|
||||
//DEBUGF("WE HAVE DATA - %d bytes\n", payload_datalen);
|
||||
// lseek(fd, payload_datalen, SEEK_CUR);
|
||||
*padding = padding_length;
|
||||
return payload_datalen;
|
||||
if (stream_id == wfx->audiostream)
|
||||
{
|
||||
if (*audiobuf == NULL) {
|
||||
/* The first payload can stay where it is */
|
||||
*audiobuf = datap;
|
||||
*audiobufsize = payload_datalen;
|
||||
} else {
|
||||
/* The second and subsequent payloads in this packet
|
||||
that belong to the audio stream need to be moved to be
|
||||
contiguous with the first payload.
|
||||
*/
|
||||
memmove(*audiobuf + *audiobufsize, datap, payload_datalen);
|
||||
*audiobufsize += payload_datalen;
|
||||
}
|
||||
}
|
||||
datap += payload_datalen;
|
||||
bytesread += payload_datalen;
|
||||
}
|
||||
|
||||
if (*audiobuf != NULL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this is the codec entry point */
|
||||
|
|
@ -282,11 +307,12 @@ enum codec_status codec_main(void)
|
|||
int retval;
|
||||
asf_waveformatex_t wfx;
|
||||
uint32_t currentframe;
|
||||
unsigned char* inbuffer;
|
||||
size_t resume_offset;
|
||||
size_t n;
|
||||
int i;
|
||||
int wmares, res, padding;
|
||||
int wmares, res;
|
||||
uint8_t* audiobuf;
|
||||
int audiobufsize;
|
||||
int packetlength;
|
||||
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
|
||||
|
|
@ -348,18 +374,16 @@ enum codec_status codec_main(void)
|
|||
ci->seek_complete();
|
||||
}
|
||||
|
||||
res = asf_read_packet(&padding, &wfx);
|
||||
res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
|
||||
if (res > 0) {
|
||||
inbuffer = ci->request_buffer(&n, res - padding);
|
||||
|
||||
wma_decode_superframe_init(&wmadec,
|
||||
inbuffer,res - padding);
|
||||
audiobuf, audiobufsize);
|
||||
|
||||
for (i=0; i < wmadec.nb_frames; i++)
|
||||
{
|
||||
wmares = wma_decode_superframe_frame(&wmadec,
|
||||
decoded,
|
||||
inbuffer,res - padding);
|
||||
audiobuf, audiobufsize);
|
||||
|
||||
ci->yield ();
|
||||
|
||||
|
|
@ -375,9 +399,9 @@ enum codec_status codec_main(void)
|
|||
}
|
||||
ci->yield ();
|
||||
}
|
||||
|
||||
ci->advance_buffer(res);
|
||||
}
|
||||
|
||||
ci->advance_buffer(packetlength);
|
||||
}
|
||||
retval = CODEC_OK;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue