diff --git a/lib/rbcodec/codecs/libasf/asf.c b/lib/rbcodec/codecs/libasf/asf.c index 4e3235a422..5f6456a2cb 100644 --- a/lib/rbcodec/codecs/libasf/asf.c +++ b/lib/rbcodec/codecs/libasf/asf.c @@ -386,11 +386,17 @@ int asf_get_timestamp(int *duration) int asf_seek(int ms, asf_waveformatex_t* wfx) { int time, duration, delta, temp, count=0; + int bitrate = ci->id3->bitrate*1000/8; /*estimate packet number from bitrate*/ int initial_packet = ci->curpos/wfx->packet_size; - int packet_num = (((int64_t)ms)*(wfx->bitrate>>3))/wfx->packet_size/1000; - int last_packet = ci->id3->filesize / wfx->packet_size; + int packet_num = (((int64_t)ms)*(bitrate))/wfx->packet_size/1000; + /*subtract header size in case theres a lot of metadata*/ + int last_packet = (ci->id3->filesize-ci->id3->first_frame_offset) / wfx->packet_size; + + /* + DEBUGF("bitrate: %d\n", bitrate); + DEBUGF("attempting seek to: %d ms, initialp: %d, lastp: %d, estimating packet: %d, packet size: %d\n", ms, initial_packet, last_packet, packet_num, wfx->packet_size);*/ if (packet_num > last_packet) { packet_num = last_packet; @@ -409,7 +415,7 @@ int asf_seek(int ms, asf_waveformatex_t* wfx) /*check the time stamp of our packet*/ time = asf_get_timestamp(&duration); - /*DEBUGF("seeked to %d ms with duration %d\n", time, duration);*/ + /*DEBUGF("seeked to %d ms (%d) with duration %d\n", time,packet_num, duration);*/ if (time < 0) { /*unknown error, try to recover*/ @@ -427,7 +433,7 @@ int asf_seek(int ms, asf_waveformatex_t* wfx) delta = ms-time; /*estimate new packet number from bitrate and our current position*/ temp += delta; - packet_num = ((temp/1000)*(wfx->bitrate>>3) - (wfx->packet_size>>1))/wfx->packet_size; //round down! + packet_num = ((temp/1000)*(bitrate) - (wfx->packet_size<<1))/wfx->packet_size; //round down! packet_offset = packet_num*wfx->packet_size; ci->seek_buffer(ci->id3->first_frame_offset+packet_offset); } diff --git a/lib/rbcodec/codecs/libasf/asf.h b/lib/rbcodec/codecs/libasf/asf.h index a7d384cf3d..2398a44eab 100644 --- a/lib/rbcodec/codecs/libasf/asf.h +++ b/lib/rbcodec/codecs/libasf/asf.h @@ -33,7 +33,7 @@ struct asf_waveformatex_s { uint16_t blockalign; uint16_t bitspersample; uint16_t datalen; - uint16_t numpackets; + uint64_t numpackets; uint8_t data[46]; }; typedef struct asf_waveformatex_s asf_waveformatex_t; 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, fileprop = 1; - /* Get the number of logical packets - uint16_t at offset 31 - * (Big endian byte order) */ - lseek(fd, 31, SEEK_CUR); - read_uint16be(fd, &wfx->numpackets); + /* Get the number of logical packets - uint64_t at offset 32 + * (little endian byte order) */ + lseek(fd, 32, SEEK_CUR); + read_uint64le(fd, &wfx->numpackets); + //DEBUGF("read packets: %llx %lld\n", wfx->numpackets, wfx->numpackets); /* Now get the play duration - uint64_t at offset 40 */ - lseek(fd, 7, SEEK_CUR); + //lseek(fd, 4, SEEK_CUR); read_uint64le(fd, &play_duration); id3->length = play_duration / 10000; - //DEBUGF("****** length = %lums\n", id3->length); /* Read the packet size - uint32_t at offset 68 */ @@ -338,8 +338,22 @@ static int asf_parse_header(int fd, struct mp3entry* id3, read_uint16le(fd, &wfx->bitspersample); read_uint16le(fd, &wfx->datalen); - /* Round bitrate to the nearest kbit */ - id3->bitrate = (wfx->bitrate + 500) / 1000; + /*sanity check the included bitrate by comparing to file size and length*/ + unsigned int estimated_bitrate = (wfx->packet_size*wfx->numpackets)/id3->length*8000; + + /*in theory we could just use the estimated bitrate always, + but its safer to underestimate*/ + if( wfx->bitrate > estimated_bitrate) + { + /* Round bitrate to the nearest kbit */ + id3->bitrate = (estimated_bitrate + 500) / 1000; + } + else + { + /* Round bitrate to the nearest kbit */ + id3->bitrate = (wfx->bitrate + 500) / 1000; + } + /*DEBUGF("bitrate: %d estimated: %d\n", wfx->bitrate, estimated_bitrate);*/ id3->frequency = wfx->rate; if (wfx->codec_id == ASF_CODEC_ID_WMAV1) {