static int read_header(AVFormatContext *s)

{

    WtvContext *wtv = s->priv_data;

    int root_sector, root_size;

    uint8_t root[WTV_SECTOR_SIZE];

    AVIOContext *pb;

    int64_t timeline_pos;

    int64_t ret;



    wtv->epoch          =

    wtv->pts            =

    wtv->last_valid_pts = AV_NOPTS_VALUE;



    /* read root directory sector */

    avio_skip(s->pb, 0x30);

    root_size = avio_rl32(s->pb);

    if (root_size > sizeof(root)) {

        av_log(s, AV_LOG_ERROR, "root directory size exceeds sector size\n");

        return AVERROR_INVALIDDATA;

    }

    avio_skip(s->pb, 4);

    root_sector = avio_rl32(s->pb);



    ret = seek_by_sector(s->pb, root_sector, 0);

    if (ret < 0)

        return ret;

    root_size = avio_read(s->pb, root, root_size);

    if (root_size < 0)

        return AVERROR_INVALIDDATA;



    /* parse chunks up until first data chunk */

    wtv->pb = wtvfile_open(s, root, root_size, ff_timeline_le16);

    if (!wtv->pb) {

        av_log(s, AV_LOG_ERROR, "timeline data missing\n");

        return AVERROR_INVALIDDATA;

    }



    ret = parse_chunks(s, SEEK_TO_DATA, 0, 0);

    if (ret < 0)

        return ret;

    avio_seek(wtv->pb, -32, SEEK_CUR);



    timeline_pos = avio_tell(s->pb); // save before opening another file



    /* read metadata */

    pb = wtvfile_open(s, root, root_size, ff_table_0_entries_legacy_attrib_le16);

    if (pb) {

        parse_legacy_attrib(s, pb);

        wtvfile_close(pb);

    }



    s->ctx_flags |= AVFMTCTX_NOHEADER; // Needed for noStreams.wtv



    /* read seek index */

    if (s->nb_streams) {

        AVStream *st = s->streams[0];

        pb = wtvfile_open(s, root, root_size, ff_table_0_entries_time_le16);

        if (pb) {

            while(1) {

                uint64_t timestamp = avio_rl64(pb);

                uint64_t frame_nb  = avio_rl64(pb);

                if (avio_feof(pb))

                    break;

                ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,

                                   0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME);

            }

            wtvfile_close(pb);



            if (wtv->nb_index_entries) {

                pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);

                if (pb) {

                    AVIndexEntry *e = wtv->index_entries;

                    AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1;

                    uint64_t last_position = 0;

                    while (1) {

                        uint64_t frame_nb = avio_rl64(pb);

                        uint64_t position = avio_rl64(pb);

                        while (frame_nb > e->size && e <= e_end) {

                            e->pos = last_position;

                            e++;

                        }

                        if (avio_feof(pb))

                            break;

                        last_position = position;

                    }

                    e_end->pos = last_position;

                    wtvfile_close(pb);

                    st->duration = e_end->timestamp;

                }

            }

        }

    }



    avio_seek(s->pb, timeline_pos, SEEK_SET);

    return 0;

}

static int read_header(AVFormatContext *s)

{

    WtvContext *wtv = s->priv_data;

    int root_sector, root_size;

    uint8_t root[WTV_SECTOR_SIZE];

    AVIOContext *pb;

    int64_t timeline_pos;

    int64_t ret;



    wtv->epoch          =

    wtv->pts            =

    wtv->last_valid_pts = AV_NOPTS_VALUE;



    

    avio_skip(s->pb, 0x30);

    root_size = avio_rl32(s->pb);

    if (root_size > sizeof(root)) {

        av_log(s, AV_LOG_ERROR, "root directory size exceeds sector size\n");

        return AVERROR_INVALIDDATA;

    }

    avio_skip(s->pb, 4);

    root_sector = avio_rl32(s->pb);



    ret = seek_by_sector(s->pb, root_sector, 0);

    if (ret < 0)

        return ret;

    root_size = avio_read(s->pb, root, root_size);

    if (root_size < 0)

        return AVERROR_INVALIDDATA;



    

    wtv->pb = wtvfile_open(s, root, root_size, ff_timeline_le16);

    if (!wtv->pb) {

        av_log(s, AV_LOG_ERROR, "timeline data missing\n");

        return AVERROR_INVALIDDATA;

    }



    ret = parse_chunks(s, SEEK_TO_DATA, 0, 0);

    if (ret < 0)

        return ret;

    avio_seek(wtv->pb, -32, SEEK_CUR);



    timeline_pos = avio_tell(s->pb); 



    

    pb = wtvfile_open(s, root, root_size, ff_table_0_entries_legacy_attrib_le16);

    if (pb) {

        parse_legacy_attrib(s, pb);

        wtvfile_close(pb);

    }



    s->ctx_flags |= AVFMTCTX_NOHEADER; 



    

    if (s->nb_streams) {

        AVStream *st = s->streams[0];

        pb = wtvfile_open(s, root, root_size, ff_table_0_entries_time_le16);

        if (pb) {

            while(1) {

                uint64_t timestamp = avio_rl64(pb);

                uint64_t frame_nb  = avio_rl64(pb);

                if (avio_feof(pb))

                    break;

                ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,

                                   0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME);

            }

            wtvfile_close(pb);



            if (wtv->nb_index_entries) {

                pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);

                if (pb) {

                    AVIndexEntry *e = wtv->index_entries;

                    AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1;

                    uint64_t last_position = 0;

                    while (1) {

                        uint64_t frame_nb = avio_rl64(pb);

                        uint64_t position = avio_rl64(pb);

                        while (frame_nb > e->size && e <= e_end) {

                            e->pos = last_position;

                            e++;

                        }

                        if (avio_feof(pb))

                            break;

                        last_position = position;

                    }

                    e_end->pos = last_position;

                    wtvfile_close(pb);

                    st->duration = e_end->timestamp;

                }

            }

        }

    }



    avio_seek(s->pb, timeline_pos, SEEK_SET);

    return 0;

}

static int FUNC_0(AVFormatContext *VAR_0)

{

    WtvContext *wtv = VAR_0->priv_data;

    int VAR_1, VAR_2;

    uint8_t root[WTV_SECTOR_SIZE];

    AVIOContext *pb;

    int64_t timeline_pos;

    int64_t ret;



    wtv->epoch          =

    wtv->pts            =

    wtv->last_valid_pts = AV_NOPTS_VALUE;



    

    avio_skip(VAR_0->pb, 0x30);

    VAR_2 = avio_rl32(VAR_0->pb);

    if (VAR_2 > sizeof(root)) {

        av_log(VAR_0, AV_LOG_ERROR, "root directory size exceeds sector size\n");

        return AVERROR_INVALIDDATA;

    }

    avio_skip(VAR_0->pb, 4);

    VAR_1 = avio_rl32(VAR_0->pb);



    ret = seek_by_sector(VAR_0->pb, VAR_1, 0);

    if (ret < 0)

        return ret;

    VAR_2 = avio_read(VAR_0->pb, root, VAR_2);

    if (VAR_2 < 0)

        return AVERROR_INVALIDDATA;



    

    wtv->pb = wtvfile_open(VAR_0, root, VAR_2, ff_timeline_le16);

    if (!wtv->pb) {

        av_log(VAR_0, AV_LOG_ERROR, "timeline data missing\n");

        return AVERROR_INVALIDDATA;

    }



    ret = parse_chunks(VAR_0, SEEK_TO_DATA, 0, 0);

    if (ret < 0)

        return ret;

    avio_seek(wtv->pb, -32, SEEK_CUR);



    timeline_pos = avio_tell(VAR_0->pb); 



    

    pb = wtvfile_open(VAR_0, root, VAR_2, ff_table_0_entries_legacy_attrib_le16);

    if (pb) {

        parse_legacy_attrib(VAR_0, pb);

        wtvfile_close(pb);

    }



    VAR_0->ctx_flags |= AVFMTCTX_NOHEADER; 



    

    if (VAR_0->nb_streams) {

        AVStream *st = VAR_0->streams[0];

        pb = wtvfile_open(VAR_0, root, VAR_2, ff_table_0_entries_time_le16);

        if (pb) {

            while(1) {

                uint64_t timestamp = avio_rl64(pb);

                uint64_t frame_nb  = avio_rl64(pb);

                if (avio_feof(pb))

                    break;

                ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,

                                   0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME);

            }

            wtvfile_close(pb);



            if (wtv->nb_index_entries) {

                pb = wtvfile_open(VAR_0, root, VAR_2, ff_timeline_table_0_entries_Events_le16);

                if (pb) {

                    AVIndexEntry *e = wtv->index_entries;

                    AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1;

                    uint64_t last_position = 0;

                    while (1) {

                        uint64_t frame_nb = avio_rl64(pb);

                        uint64_t position = avio_rl64(pb);

                        while (frame_nb > e->size && e <= e_end) {

                            e->pos = last_position;

                            e++;

                        }

                        if (avio_feof(pb))

                            break;

                        last_position = position;

                    }

                    e_end->pos = last_position;

                    wtvfile_close(pb);

                    st->duration = e_end->timestamp;

                }

            }

        }

    }



    avio_seek(VAR_0->pb, timeline_pos, SEEK_SET);

    return 0;

}

static int FUNC_0(AVFormatContext *VAR_0)
{ WtvContext *wtv = VAR_0->priv_data; int VAR_1, VAR_2; uint8_t root[WTV_SECTOR_SIZE]; AVIOContext *pb; int64_t timeline_pos; int64_t ret; wtv->epoch          =
wtv->pts            =
wtv->last_valid_pts = AV_NOPTS_VALUE; avio_skip(VAR_0->pb, 0x30); VAR_2 = avio_rl32(VAR_0->pb); if (VAR_2 > sizeof(root)) { av_log(VAR_0, AV_LOG_ERROR, "root directory size exceeds sector size\n"); return AVERROR_INVALIDDATA; } avio_skip(VAR_0->pb, 4); VAR_1 = avio_rl32(VAR_0->pb); ret = seek_by_sector(VAR_0->pb, VAR_1, 0); if (ret < 0)
return ret; VAR_2 = avio_read(VAR_0->pb, root, VAR_2); if (VAR_2 < 0)
return AVERROR_INVALIDDATA; wtv->pb = wtvfile_open(VAR_0, root, VAR_2, ff_timeline_le16); if (!wtv->pb) { av_log(VAR_0, AV_LOG_ERROR, "timeline data missing\n"); return AVERROR_INVALIDDATA; } ret = parse_chunks(VAR_0, SEEK_TO_DATA, 0, 0); if (ret < 0)
return ret; avio_seek(wtv->pb, -32, SEEK_CUR); timeline_pos = avio_tell(VAR_0->pb); pb = wtvfile_open(VAR_0, root, VAR_2, ff_table_0_entries_legacy_attrib_le16); if (pb) { parse_legacy_attrib(VAR_0, pb); wtvfile_close(pb); } VAR_0->ctx_flags |= AVFMTCTX_NOHEADER; if (VAR_0->nb_streams) { AVStream *st = VAR_0->streams[0]; pb = wtvfile_open(VAR_0, root, VAR_2, ff_table_0_entries_time_le16); if (pb) { while(1) { uint64_t timestamp = avio_rl64(pb); uint64_t frame_nb  = avio_rl64(pb); if (avio_feof(pb))
break; ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size,
0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME); } wtvfile_close(pb); if (wtv->nb_index_entries) { pb = wtvfile_open(VAR_0, root, VAR_2, ff_timeline_table_0_entries_Events_le16); if (pb) { AVIndexEntry *e = wtv->index_entries; AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1; uint64_t last_position = 0; while (1) { uint64_t frame_nb = avio_rl64(pb); uint64_t position = avio_rl64(pb); while (frame_nb > e->size && e <= e_end) { e->pos = last_position; e++; } if (avio_feof(pb))
break; last_position = position; } e_end->pos = last_position; wtvfile_close(pb); st->duration = e_end->timestamp; } } } } avio_seek(VAR_0->pb, timeline_pos, SEEK_SET); return 0; }