mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-13 21:28:01 +02:00
wtv: Seek by sector properly
Use an helper function to seek by sector to avoid possible mistakes due shifting by WTV_SECTOR_BITS a 32bit integer. Contrary to common intuition, a 32 bit integer left shifted by a 64 bit integer does not promote the 32 bit integer to 64 bit before shifting.
This commit is contained in:
parent
a27f1116cd
commit
2b72f8ac32
@ -48,10 +48,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WTV_SECTOR_BITS INT64_C(12)
|
#define WTV_SECTOR_BITS 12
|
||||||
#define WTV_SECTOR_SIZE (1 << WTV_SECTOR_BITS)
|
#define WTV_SECTOR_SIZE (1 << WTV_SECTOR_BITS)
|
||||||
#define WTV_BIGSECTOR_BITS 18
|
#define WTV_BIGSECTOR_BITS 18
|
||||||
|
|
||||||
|
#define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
AVIOContext *pb_filesystem; /** file system (AVFormatContext->pb) */
|
AVIOContext *pb_filesystem; /** file system (AVFormatContext->pb) */
|
||||||
|
|
||||||
@ -64,6 +66,11 @@ typedef struct {
|
|||||||
int64_t length;
|
int64_t length;
|
||||||
} WtvFile;
|
} WtvFile;
|
||||||
|
|
||||||
|
static int64_t seek_by_sector(AVIOContext *pb, int64_t sector, int64_t offset)
|
||||||
|
{
|
||||||
|
return avio_seek(pb, SHIFT_SECTOR_BITS(sector) + offset, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bytes read, 0 on end of file, or <0 on error
|
* @return bytes read, 0 on end of file, or <0 on error
|
||||||
*/
|
*/
|
||||||
@ -94,7 +101,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size)
|
|||||||
int i = wf->position >> wf->sector_bits;
|
int i = wf->position >> wf->sector_bits;
|
||||||
if (i >= wf->nb_sectors ||
|
if (i >= wf->nb_sectors ||
|
||||||
(wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) &&
|
(wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) &&
|
||||||
avio_seek(pb, wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) {
|
seek_by_sector(pb, wf->sectors[i], 0) < 0)) {
|
||||||
wf->error = 1;
|
wf->error = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -119,8 +126,8 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence)
|
|||||||
offset = wf->length;
|
offset = wf->length;
|
||||||
|
|
||||||
wf->error = offset < 0 || offset >= wf->length ||
|
wf->error = offset < 0 || offset >= wf->length ||
|
||||||
avio_seek(pb, (wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS)
|
seek_by_sector(pb, wf->sectors[offset >> wf->sector_bits],
|
||||||
+ (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0;
|
offset & ((1 << wf->sector_bits) - 1)) < 0;
|
||||||
wf->position = offset;
|
wf->position = offset;
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
@ -155,7 +162,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int
|
|||||||
WtvFile *wf;
|
WtvFile *wf;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
|
|
||||||
if (avio_seek(s->pb, first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0)
|
if (seek_by_sector(s->pb, first_sector, 0) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wf = av_mallocz(sizeof(WtvFile));
|
wf = av_mallocz(sizeof(WtvFile));
|
||||||
@ -184,14 +191,14 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int
|
|||||||
int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4);
|
int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS);
|
wf->sectors = av_malloc(SHIFT_SECTOR_BITS(nb_sectors1));
|
||||||
if (!wf->sectors) {
|
if (!wf->sectors) {
|
||||||
av_free(wf);
|
av_free(wf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wf->nb_sectors = 0;
|
wf->nb_sectors = 0;
|
||||||
for (i = 0; i < nb_sectors1; i++) {
|
for (i = 0; i < nb_sectors1; i++) {
|
||||||
if (avio_seek(s->pb, sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)
|
if (seek_by_sector(s->pb, sectors1[i], 0) < 0)
|
||||||
break;
|
break;
|
||||||
wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4);
|
wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4);
|
||||||
}
|
}
|
||||||
@ -218,7 +225,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int
|
|||||||
|
|
||||||
/* seek to initial sector */
|
/* seek to initial sector */
|
||||||
wf->position = 0;
|
wf->position = 0;
|
||||||
if (avio_seek(s->pb, wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) {
|
if (seek_by_sector(s->pb, wf->sectors[0], 0) < 0) {
|
||||||
av_free(wf->sectors);
|
av_free(wf->sectors);
|
||||||
av_free(wf);
|
av_free(wf);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -963,7 +970,7 @@ static int read_header(AVFormatContext *s)
|
|||||||
avio_skip(s->pb, 4);
|
avio_skip(s->pb, 4);
|
||||||
root_sector = avio_rl32(s->pb);
|
root_sector = avio_rl32(s->pb);
|
||||||
|
|
||||||
avio_seek(s->pb, root_sector << WTV_SECTOR_BITS, SEEK_SET);
|
seek_by_sector(s->pb, root_sector, 0);
|
||||||
root_size = avio_read(s->pb, root, root_size);
|
root_size = avio_read(s->pb, root, root_size);
|
||||||
if (root_size < 0)
|
if (root_size < 0)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
Loading…
Reference in New Issue
Block a user