diff options
author | Michael Giacomelli <giac2000@hotmail.com> | 2014-11-28 22:25:23 +0100 |
---|---|---|
committer | Michael Giacomelli <giac2000@hotmail.com> | 2014-11-28 22:30:05 +0100 |
commit | aa2c55e1057c0c220a1eb37c99d2c251bfe850ab (patch) | |
tree | 0e69f0d611b2d343a9545719fda5913ef69747a4 /lib/rbcodec/metadata | |
parent | 0cd9e4e6bc9e485bb527ccd5bdfe7ce74445949d (diff) | |
download | rockbox-aa2c55e1057c0c220a1eb37c99d2c251bfe850ab.tar.gz rockbox-aa2c55e1057c0c220a1eb37c99d2c251bfe850ab.zip |
Fix FS#13009.
This file revealed several problems with our ASF parser:
1) The packet count in the ASF was actually a 64 bit value,
leading to overflow in very long files.
2) Seeking blindly trusted the bitrate listed in the ASF header
rather than computing it from the packet size and number of packets.
Fix these problems and fix a few minor issues.
Change-Id: Ie0f68734e6423e837757528ddb155f3bdcc979f3
Diffstat (limited to 'lib/rbcodec/metadata')
-rw-r--r-- | lib/rbcodec/metadata/asf.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/lib/rbcodec/metadata/asf.c b/lib/rbcodec/metadata/asf.c index 469a5739d2..50e021b6a4 100644 --- a/lib/rbcodec/metadata/asf.c +++ b/lib/rbcodec/metadata/asf.c | |||
@@ -275,16 +275,16 @@ static int asf_parse_header(int fd, struct mp3entry* id3, | |||
275 | 275 | ||
276 | fileprop = 1; | 276 | fileprop = 1; |
277 | 277 | ||
278 | /* Get the number of logical packets - uint16_t at offset 31 | 278 | /* Get the number of logical packets - uint64_t at offset 32 |
279 | * (Big endian byte order) */ | 279 | * (little endian byte order) */ |
280 | lseek(fd, 31, SEEK_CUR); | 280 | lseek(fd, 32, SEEK_CUR); |
281 | read_uint16be(fd, &wfx->numpackets); | 281 | read_uint64le(fd, &wfx->numpackets); |
282 | //DEBUGF("read packets: %llx %lld\n", wfx->numpackets, wfx->numpackets); | ||
282 | 283 | ||
283 | /* Now get the play duration - uint64_t at offset 40 */ | 284 | /* Now get the play duration - uint64_t at offset 40 */ |
284 | lseek(fd, 7, SEEK_CUR); | 285 | //lseek(fd, 4, SEEK_CUR); |
285 | read_uint64le(fd, &play_duration); | 286 | read_uint64le(fd, &play_duration); |
286 | id3->length = play_duration / 10000; | 287 | id3->length = play_duration / 10000; |
287 | |||
288 | //DEBUGF("****** length = %lums\n", id3->length); | 288 | //DEBUGF("****** length = %lums\n", id3->length); |
289 | 289 | ||
290 | /* Read the packet size - uint32_t at offset 68 */ | 290 | /* Read the packet size - uint32_t at offset 68 */ |
@@ -338,8 +338,22 @@ static int asf_parse_header(int fd, struct mp3entry* id3, | |||
338 | read_uint16le(fd, &wfx->bitspersample); | 338 | read_uint16le(fd, &wfx->bitspersample); |
339 | read_uint16le(fd, &wfx->datalen); | 339 | read_uint16le(fd, &wfx->datalen); |
340 | 340 | ||
341 | /* Round bitrate to the nearest kbit */ | 341 | /*sanity check the included bitrate by comparing to file size and length*/ |
342 | id3->bitrate = (wfx->bitrate + 500) / 1000; | 342 | unsigned int estimated_bitrate = (wfx->packet_size*wfx->numpackets)/id3->length*8000; |
343 | |||
344 | /*in theory we could just use the estimated bitrate always, | ||
345 | but its safer to underestimate*/ | ||
346 | if( wfx->bitrate > estimated_bitrate) | ||
347 | { | ||
348 | /* Round bitrate to the nearest kbit */ | ||
349 | id3->bitrate = (estimated_bitrate + 500) / 1000; | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | /* Round bitrate to the nearest kbit */ | ||
354 | id3->bitrate = (wfx->bitrate + 500) / 1000; | ||
355 | } | ||
356 | /*DEBUGF("bitrate: %d estimated: %d\n", wfx->bitrate, estimated_bitrate);*/ | ||
343 | id3->frequency = wfx->rate; | 357 | id3->frequency = wfx->rate; |
344 | 358 | ||
345 | if (wfx->codec_id == ASF_CODEC_ID_WMAV1) { | 359 | if (wfx->codec_id == ASF_CODEC_ID_WMAV1) { |