| 957 | } |
| 958 | |
| 959 | static int read_header(AVFormatContext *s) |
| 960 | { |
| 961 | WtvContext *wtv = s->priv_data; |
| 962 | unsigned root_sector; |
| 963 | int root_size; |
| 964 | uint8_t root[WTV_SECTOR_SIZE]; |
| 965 | AVIOContext *pb; |
| 966 | int64_t timeline_pos; |
| 967 | int64_t ret; |
| 968 | |
| 969 | wtv->epoch = |
| 970 | wtv->pts = |
| 971 | wtv->last_valid_pts = AV_NOPTS_VALUE; |
| 972 | |
| 973 | /* read root directory sector */ |
| 974 | avio_skip(s->pb, 0x30); |
| 975 | root_size = avio_rl32(s->pb); |
| 976 | if (root_size > sizeof(root)) { |
| 977 | av_log(s, AV_LOG_ERROR, "root directory size exceeds sector size\n"); |
| 978 | return AVERROR_INVALIDDATA; |
| 979 | } |
| 980 | avio_skip(s->pb, 4); |
| 981 | root_sector = avio_rl32(s->pb); |
| 982 | |
| 983 | ret = seek_by_sector(s->pb, root_sector, 0); |
| 984 | if (ret < 0) |
| 985 | return ret; |
| 986 | root_size = avio_read(s->pb, root, root_size); |
| 987 | if (root_size < 0) |
| 988 | return AVERROR_INVALIDDATA; |
| 989 | |
| 990 | /* parse chunks up until first data chunk */ |
| 991 | wtv->pb = wtvfile_open(s, root, root_size, ff_timeline_le16); |
| 992 | if (!wtv->pb) { |
| 993 | av_log(s, AV_LOG_ERROR, "timeline data missing\n"); |
| 994 | return AVERROR_INVALIDDATA; |
| 995 | } |
| 996 | |
| 997 | ret = parse_chunks(s, SEEK_TO_DATA, 0, 0); |
| 998 | if (ret < 0) { |
| 999 | wtvfile_close(wtv->pb); |
| 1000 | return ret; |
| 1001 | } |
| 1002 | avio_seek(wtv->pb, -32, SEEK_CUR); |
| 1003 | |
| 1004 | timeline_pos = avio_tell(s->pb); // save before opening another file |
| 1005 | |
| 1006 | /* read metadata */ |
| 1007 | pb = wtvfile_open(s, root, root_size, ff_table_0_entries_legacy_attrib_le16); |
| 1008 | if (pb) { |
| 1009 | parse_legacy_attrib(s, pb); |
| 1010 | wtvfile_close(pb); |
| 1011 | } |
| 1012 | |
| 1013 | s->ctx_flags |= AVFMTCTX_NOHEADER; // Needed for noStreams.wtv |
| 1014 | |
| 1015 | /* read seek index */ |
| 1016 | if (s->nb_streams) { |
nothing calls this directly
no test coverage detected