|
|
|
@ -46,6 +46,8 @@ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS) |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
AVIOContext *pb_filesystem; /**< file system (AVFormatContext->pb) */ |
|
|
|
|
|
|
|
|
@ -58,6 +60,11 @@ typedef struct { |
|
|
|
|
int64_t length; |
|
|
|
|
} 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 |
|
|
|
|
*/ |
|
|
|
@ -88,7 +95,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) |
|
|
|
|
int i = wf->position >> wf->sector_bits; |
|
|
|
|
if (i >= wf->nb_sectors || |
|
|
|
|
(wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && |
|
|
|
|
avio_seek(pb, (int64_t)wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { |
|
|
|
|
seek_by_sector(pb, wf->sectors[i], 0) < 0)) { |
|
|
|
|
wf->error = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -113,8 +120,8 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence) |
|
|
|
|
offset = wf->length; |
|
|
|
|
|
|
|
|
|
wf->error = offset < 0 || offset >= wf->length || |
|
|
|
|
avio_seek(pb, ((int64_t)wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) |
|
|
|
|
+ (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0; |
|
|
|
|
seek_by_sector(pb, wf->sectors[offset >> wf->sector_bits], |
|
|
|
|
offset & ((1 << wf->sector_bits) - 1)) < 0; |
|
|
|
|
wf->position = offset; |
|
|
|
|
return offset; |
|
|
|
|
} |
|
|
|
@ -149,7 +156,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int |
|
|
|
|
WtvFile *wf; |
|
|
|
|
uint8_t *buffer; |
|
|
|
|
|
|
|
|
|
if (avio_seek(s->pb, (int64_t)first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0) |
|
|
|
|
if (seek_by_sector(s->pb, first_sector, 0) < 0) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
wf = av_mallocz(sizeof(WtvFile)); |
|
|
|
@ -176,14 +183,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 i; |
|
|
|
|
|
|
|
|
|
wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS); |
|
|
|
|
wf->sectors = av_malloc(SHIFT_SECTOR_BITS(nb_sectors1)); |
|
|
|
|
if (!wf->sectors) { |
|
|
|
|
av_free(wf); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
wf->nb_sectors = 0; |
|
|
|
|
for (i = 0; i < nb_sectors1; i++) { |
|
|
|
|
if (avio_seek(s->pb, (int64_t)sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) |
|
|
|
|
if (seek_by_sector(s->pb, sectors1[i], 0) < 0) |
|
|
|
|
break; |
|
|
|
|
wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); |
|
|
|
|
} |
|
|
|
@ -213,7 +220,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int |
|
|
|
|
|
|
|
|
|
/* seek to initial sector */ |
|
|
|
|
wf->position = 0; |
|
|
|
|
if (avio_seek(s->pb, (int64_t)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); |
|
|
|
|
return NULL; |
|
|
|
@ -941,7 +948,7 @@ static int read_header(AVFormatContext *s) |
|
|
|
|
avio_skip(s->pb, 4); |
|
|
|
|
root_sector = avio_rl32(s->pb); |
|
|
|
|
|
|
|
|
|
avio_seek(s->pb, (int64_t)root_sector << WTV_SECTOR_BITS, SEEK_SET); |
|
|
|
|
seek_by_sector(s->pb, root_sector, 0); |
|
|
|
|
root_size = avio_read(s->pb, root, root_size); |
|
|
|
|
if (root_size < 0) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|