| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * MPEG-1/2 demuxer | ||
| 3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard | ||
| 4 | * | ||
| 5 | * This file is part of FFmpeg. | ||
| 6 | * | ||
| 7 | * FFmpeg is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with FFmpeg; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "config_components.h" | ||
| 23 | |||
| 24 | #include "libavutil/channel_layout.h" | ||
| 25 | #include "libavutil/mem.h" | ||
| 26 | #include "avformat.h" | ||
| 27 | #include "avio_internal.h" | ||
| 28 | #include "demux.h" | ||
| 29 | #include "internal.h" | ||
| 30 | #include "mpeg.h" | ||
| 31 | |||
| 32 | /*********************************************/ | ||
| 33 | /* demux code */ | ||
| 34 | |||
| 35 | #define MAX_SYNC_SIZE 100000 | ||
| 36 | |||
| 37 | 49162 | static int check_pes(const uint8_t *p, const uint8_t *end) | |
| 38 | { | ||
| 39 | int pes1; | ||
| 40 | 101736 | int pes2 = (p[3] & 0xC0) == 0x80 && | |
| 41 |
4/4✓ Branch 0 taken 3412 times.
✓ Branch 1 taken 45750 times.
✓ Branch 2 taken 2843 times.
✓ Branch 3 taken 569 times.
|
52005 | (p[4] & 0xC0) != 0x40 && |
| 42 |
2/2✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 1623 times.
|
2843 | ((p[4] & 0xC0) == 0x00 || |
| 43 |
2/2✓ Branch 0 taken 125 times.
✓ Branch 1 taken 1095 times.
|
1220 | (p[4] & 0xC0) >> 2 == (p[6] & 0xF0)); |
| 44 | |||
| 45 |
4/4✓ Branch 0 taken 51343 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 2249 times.
✓ Branch 3 taken 49094 times.
|
51411 | for (p += 3; p < end && *p == 0xFF; p++) ; |
| 46 |
2/2✓ Branch 0 taken 4572 times.
✓ Branch 1 taken 44590 times.
|
49162 | if ((*p & 0xC0) == 0x40) |
| 47 | 4572 | p += 2; | |
| 48 | |||
| 49 |
2/2✓ Branch 0 taken 1502 times.
✓ Branch 1 taken 47660 times.
|
49162 | if ((*p & 0xF0) == 0x20) |
| 50 | 1502 | pes1 = p[0] & p[2] & p[4] & 1; | |
| 51 |
2/2✓ Branch 0 taken 1223 times.
✓ Branch 1 taken 46437 times.
|
47660 | else if ((*p & 0xF0) == 0x30) |
| 52 | 1223 | pes1 = p[0] & p[2] & p[4] & p[5] & p[7] & p[9] & 1; | |
| 53 | else | ||
| 54 | 46437 | pes1 = *p == 0x0F; | |
| 55 | |||
| 56 |
4/4✓ Branch 0 taken 48831 times.
✓ Branch 1 taken 331 times.
✓ Branch 2 taken 1748 times.
✓ Branch 3 taken 47083 times.
|
49162 | return pes1 || pes2; |
| 57 | } | ||
| 58 | |||
| 59 | 49481 | static int check_pack_header(const uint8_t *buf) | |
| 60 | { | ||
| 61 |
4/4✓ Branch 0 taken 42515 times.
✓ Branch 1 taken 6966 times.
✓ Branch 2 taken 2762 times.
✓ Branch 3 taken 39753 times.
|
49481 | return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20; |
| 62 | } | ||
| 63 | |||
| 64 | 7279 | static int mpegps_probe(const AVProbeData *p) | |
| 65 | { | ||
| 66 | 7279 | uint32_t code = -1; | |
| 67 | int i; | ||
| 68 | 7279 | int sys = 0, pspack = 0, priv1 = 0, vid = 0; | |
| 69 | 7279 | int audio = 0, invalid = 0, score = 0; | |
| 70 | 7279 | int endpes = 0; | |
| 71 | |||
| 72 |
2/2✓ Branch 0 taken 391278788 times.
✓ Branch 1 taken 7279 times.
|
391286067 | for (i = 0; i < p->buf_size; i++) { |
| 73 | 391278788 | code = (code << 8) + p->buf[i]; | |
| 74 |
2/2✓ Branch 0 taken 49481 times.
✓ Branch 1 taken 391229307 times.
|
391278788 | if ((code & 0xffffff00) == 0x100) { |
| 75 | 49481 | int len = p->buf[i + 1] << 8 | p->buf[i + 2]; | |
| 76 |
4/4✓ Branch 0 taken 49162 times.
✓ Branch 1 taken 319 times.
✓ Branch 3 taken 2079 times.
✓ Branch 4 taken 47083 times.
|
49481 | int pes = endpes <= i && check_pes(p->buf + i, p->buf + p->buf_size); |
| 77 | 49481 | int pack = check_pack_header(p->buf + i); | |
| 78 | |||
| 79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49481 times.
|
49481 | if (len > INT_MAX - i) |
| 80 | ✗ | break; | |
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 49438 times.
|
49481 | if (code == SYSTEM_HEADER_START_CODE) |
| 83 | 43 | sys++; | |
| 84 |
4/4✓ Branch 0 taken 78 times.
✓ Branch 1 taken 49360 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 5 times.
|
49438 | else if (code == PACK_START_CODE && pack) |
| 85 | 73 | pspack++; | |
| 86 |
4/4✓ Branch 0 taken 925 times.
✓ Branch 1 taken 48440 times.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 842 times.
|
49365 | else if ((code & 0xf0) == VIDEO_ID && pes) { |
| 87 | 83 | endpes = i + len; | |
| 88 | 83 | vid++; | |
| 89 | } | ||
| 90 | // skip pes payload to avoid start code emulation for private | ||
| 91 | // and audio streams | ||
| 92 |
4/4✓ Branch 0 taken 1190 times.
✓ Branch 1 taken 48092 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1152 times.
|
49282 | else if ((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} |
| 93 |
4/4✓ Branch 0 taken 66 times.
✓ Branch 1 taken 49178 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 11 times.
|
49244 | else if (code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} |
| 94 |
3/4✓ Branch 0 taken 114 times.
✓ Branch 1 taken 49075 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
|
49189 | else if (code == 0x1fd && pes) vid++; //VC1 |
| 95 | |||
| 96 |
3/4✓ Branch 0 taken 842 times.
✓ Branch 1 taken 48347 times.
✓ Branch 2 taken 842 times.
✗ Branch 3 not taken.
|
49189 | else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++; |
| 97 |
3/4✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 47195 times.
✓ Branch 2 taken 1152 times.
✗ Branch 3 not taken.
|
48347 | else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++; |
| 98 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 47184 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
47195 | else if (code == PRIVATE_STREAM_1 && !pes) invalid++; |
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7258 times.
|
7279 | if (vid + audio > invalid + 1) /* invalid VDR files nd short PES streams */ |
| 103 | 21 | score = AVPROBE_SCORE_EXTENSION / 2; | |
| 104 | |||
| 105 | // av_log(NULL, AV_LOG_ERROR, "vid:%d aud:%d sys:%d pspack:%d invalid:%d size:%d \n", | ||
| 106 | // vid, audio, sys, pspack, invalid, p->buf_size); | ||
| 107 | |||
| 108 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 7245 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1 times.
|
7279 | if (sys > invalid && sys * 9 <= pspack * 10) |
| 109 |
3/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 1 times.
|
33 | return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 |
| 110 |
3/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 15 times.
|
66 | : AVPROBE_SCORE_EXTENSION / 2 + (audio + vid + pspack > 1); // 1 more than mp3 |
| 111 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7232 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 4 times.
|
7246 | if (pspack > invalid && (priv1 + vid + audio) * 10 >= pspack * 9) |
| 112 | return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 | ||
| 113 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg |
| 114 |
7/10✓ Branch 0 taken 52 times.
✓ Branch 1 taken 7184 times.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
|
7236 | if ((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && |
| 115 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
12 | !pspack && p->buf_size > 2048 && vid + audio > invalid) /* PES stream */ |
| 116 | ✗ | return (audio > 12 || vid > 6 + 2 * invalid) ? AVPROBE_SCORE_EXTENSION + 2 | |
| 117 | ✗ | : AVPROBE_SCORE_EXTENSION / 2; | |
| 118 | |||
| 119 | // 02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 | ||
| 120 | // mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6 | ||
| 121 | // Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618 | ||
| 122 | 7236 | return score; | |
| 123 | } | ||
| 124 | |||
| 125 | typedef struct MpegDemuxContext { | ||
| 126 | int32_t header_state; | ||
| 127 | unsigned char psm_es_type[256]; | ||
| 128 | int sofdec; | ||
| 129 | int dvd; | ||
| 130 | int imkh_cctv; | ||
| 131 | int raw_ac3; | ||
| 132 | } MpegDemuxContext; | ||
| 133 | |||
| 134 | 28 | static int mpegps_read_header(AVFormatContext *s) | |
| 135 | { | ||
| 136 | 28 | MpegDemuxContext *m = s->priv_data; | |
| 137 | 28 | char buffer[7] = { 0 }; | |
| 138 | 28 | int64_t last_pos = avio_tell(s->pb); | |
| 139 | |||
| 140 | 28 | m->header_state = 0xff; | |
| 141 | 28 | s->ctx_flags |= AVFMTCTX_NOHEADER; | |
| 142 | |||
| 143 | 28 | avio_get_str(s->pb, 6, buffer, sizeof(buffer)); | |
| 144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (!memcmp("IMKH", buffer, 4)) { |
| 145 | ✗ | m->imkh_cctv = 1; | |
| 146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | } else if (!memcmp("Sofdec", buffer, 6)) { |
| 147 | ✗ | m->sofdec = 1; | |
| 148 | } else | ||
| 149 | 28 | avio_seek(s->pb, last_pos, SEEK_SET); | |
| 150 | |||
| 151 | /* no need to do more */ | ||
| 152 | 28 | return 0; | |
| 153 | } | ||
| 154 | |||
| 155 | 6952 | static int64_t get_pts(AVIOContext *pb, int c) | |
| 156 | { | ||
| 157 | uint8_t buf[5]; | ||
| 158 | int ret; | ||
| 159 | |||
| 160 |
2/2✓ Branch 0 taken 6030 times.
✓ Branch 1 taken 922 times.
|
6952 | buf[0] = c < 0 ? avio_r8(pb) : c; |
| 161 | 6952 | ret = avio_read(pb, buf + 1, 4); | |
| 162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6952 times.
|
6952 | if (ret < 4) |
| 163 | ✗ | return AV_NOPTS_VALUE; | |
| 164 | |||
| 165 | 6952 | return ff_parse_pes_pts(buf); | |
| 166 | } | ||
| 167 | |||
| 168 | 24661 | static int find_next_start_code(AVIOContext *pb, int *size_ptr, | |
| 169 | int32_t *header_state) | ||
| 170 | { | ||
| 171 | unsigned int state, v; | ||
| 172 | int val, n; | ||
| 173 | |||
| 174 | 24661 | state = *header_state; | |
| 175 | 24661 | n = *size_ptr; | |
| 176 |
1/2✓ Branch 0 taken 313700 times.
✗ Branch 1 not taken.
|
313700 | while (n > 0) { |
| 177 |
2/2✓ Branch 1 taken 129 times.
✓ Branch 2 taken 313571 times.
|
313700 | if (avio_feof(pb)) |
| 178 | 129 | break; | |
| 179 | 313571 | v = avio_r8(pb); | |
| 180 | 313571 | n--; | |
| 181 |
2/2✓ Branch 0 taken 24532 times.
✓ Branch 1 taken 289039 times.
|
313571 | if (state == 0x000001) { |
| 182 | 24532 | state = ((state << 8) | v) & 0xffffff; | |
| 183 | 24532 | val = state; | |
| 184 | 24532 | goto found; | |
| 185 | } | ||
| 186 | 289039 | state = ((state << 8) | v) & 0xffffff; | |
| 187 | } | ||
| 188 | 129 | val = -1; | |
| 189 | |||
| 190 | 24661 | found: | |
| 191 | 24661 | *header_state = state; | |
| 192 | 24661 | *size_ptr = n; | |
| 193 | 24661 | return val; | |
| 194 | } | ||
| 195 | |||
| 196 | /** | ||
| 197 | * Extract stream types from a program stream map | ||
| 198 | * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35 | ||
| 199 | * | ||
| 200 | * @return number of bytes occupied by PSM in the bitstream | ||
| 201 | */ | ||
| 202 | ✗ | static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb) | |
| 203 | { | ||
| 204 | int psm_length, ps_info_length, es_map_length; | ||
| 205 | |||
| 206 | ✗ | psm_length = avio_rb16(pb); | |
| 207 | ✗ | avio_r8(pb); | |
| 208 | ✗ | avio_r8(pb); | |
| 209 | ✗ | ps_info_length = avio_rb16(pb); | |
| 210 | |||
| 211 | /* skip program_stream_info */ | ||
| 212 | ✗ | avio_skip(pb, ps_info_length); | |
| 213 | ✗ | /*es_map_length = */avio_rb16(pb); | |
| 214 | /* Ignore es_map_length, trust psm_length */ | ||
| 215 | ✗ | es_map_length = psm_length - ps_info_length - 10; | |
| 216 | |||
| 217 | /* at least one es available? */ | ||
| 218 | ✗ | while (es_map_length >= 4) { | |
| 219 | ✗ | unsigned char type = avio_r8(pb); | |
| 220 | ✗ | unsigned char es_id = avio_r8(pb); | |
| 221 | ✗ | uint16_t es_info_length = avio_rb16(pb); | |
| 222 | |||
| 223 | /* remember mapping from stream id to stream type */ | ||
| 224 | ✗ | m->psm_es_type[es_id] = type; | |
| 225 | /* skip program_stream_info */ | ||
| 226 | ✗ | avio_skip(pb, es_info_length); | |
| 227 | ✗ | es_map_length -= 4 + es_info_length; | |
| 228 | } | ||
| 229 | ✗ | avio_rb32(pb); /* crc32 */ | |
| 230 | ✗ | return 2 + psm_length; | |
| 231 | } | ||
| 232 | |||
| 233 | /* read the next PES header. Return its position in ppos | ||
| 234 | * (if not NULL), and its start code, pts and dts. | ||
| 235 | */ | ||
| 236 | 13371 | static int mpegps_read_pes_header(AVFormatContext *s, | |
| 237 | int64_t *ppos, int *pstart_code, | ||
| 238 | int64_t *ppts, int64_t *pdts) | ||
| 239 | { | ||
| 240 | 13371 | MpegDemuxContext *m = s->priv_data; | |
| 241 | int len, size, startcode, c, flags, header_len; | ||
| 242 | int pes_ext, ext2_len, id_ext, skip; | ||
| 243 | int64_t pts, dts; | ||
| 244 | 13371 | int64_t last_sync = avio_tell(s->pb); | |
| 245 | |||
| 246 | ✗ | error_redo: | |
| 247 | 13371 | avio_seek(s->pb, last_sync, SEEK_SET); | |
| 248 | 11290 | redo: | |
| 249 | /* next start code (should be immediately after) */ | ||
| 250 | 24661 | m->header_state = 0xff; | |
| 251 | 24661 | size = MAX_SYNC_SIZE; | |
| 252 | 24661 | startcode = find_next_start_code(s->pb, &size, &m->header_state); | |
| 253 | 24661 | last_sync = avio_tell(s->pb); | |
| 254 |
2/2✓ Branch 0 taken 129 times.
✓ Branch 1 taken 24532 times.
|
24661 | if (startcode < 0) { |
| 255 |
1/2✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
|
129 | if (avio_feof(s->pb)) |
| 256 | 129 | return AVERROR_EOF; | |
| 257 | // FIXME we should remember header_state | ||
| 258 | ✗ | return FFERROR_REDO; | |
| 259 | } | ||
| 260 | |||
| 261 |
2/2✓ Branch 0 taken 10246 times.
✓ Branch 1 taken 14286 times.
|
24532 | if (startcode == PACK_START_CODE) |
| 262 | 10246 | goto redo; | |
| 263 |
2/2✓ Branch 0 taken 193 times.
✓ Branch 1 taken 14093 times.
|
14286 | if (startcode == SYSTEM_HEADER_START_CODE) |
| 264 | 193 | goto redo; | |
| 265 |
2/2✓ Branch 0 taken 796 times.
✓ Branch 1 taken 13297 times.
|
14093 | if (startcode == PADDING_STREAM) { |
| 266 | 796 | avio_skip(s->pb, avio_rb16(s->pb)); | |
| 267 | 796 | goto redo; | |
| 268 | } | ||
| 269 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 13253 times.
|
13297 | if (startcode == PRIVATE_STREAM_2) { |
| 270 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 41 times.
|
44 | if (!m->sofdec) { |
| 271 | /* Need to detect whether this from a DVD or a 'Sofdec' stream */ | ||
| 272 | 3 | int len = avio_rb16(s->pb); | |
| 273 | 3 | int bytesread = 0; | |
| 274 | 3 | uint8_t *ps2buf = av_malloc(len); | |
| 275 | |||
| 276 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (ps2buf) { |
| 277 | 3 | bytesread = avio_read(s->pb, ps2buf, len); | |
| 278 | |||
| 279 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (bytesread != len) { |
| 280 | ✗ | avio_skip(s->pb, len - bytesread); | |
| 281 | } else { | ||
| 282 | 3 | uint8_t *p = 0; | |
| 283 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (len >= 6) |
| 284 | 3 | p = memchr(ps2buf, 'S', len - 5); | |
| 285 | |||
| 286 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (p) |
| 287 | ✗ | m->sofdec = !memcmp(p+1, "ofdec", 5); | |
| 288 | |||
| 289 | 3 | m->sofdec -= !m->sofdec; | |
| 290 | |||
| 291 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (m->sofdec < 0) { |
| 292 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (len == 980 && ps2buf[0] == 0) { |
| 293 | /* PCI structure? */ | ||
| 294 | 3 | uint32_t startpts = AV_RB32(ps2buf + 0x0d); | |
| 295 | 3 | uint32_t endpts = AV_RB32(ps2buf + 0x11); | |
| 296 | 3 | uint8_t hours = ((ps2buf[0x19] >> 4) * 10) + (ps2buf[0x19] & 0x0f); | |
| 297 | 3 | uint8_t mins = ((ps2buf[0x1a] >> 4) * 10) + (ps2buf[0x1a] & 0x0f); | |
| 298 | 3 | uint8_t secs = ((ps2buf[0x1b] >> 4) * 10) + (ps2buf[0x1b] & 0x0f); | |
| 299 | |||
| 300 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | m->dvd = (hours <= 23 && |
| 301 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | mins <= 59 && |
| 302 | 3 | secs <= 59 && | |
| 303 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | (ps2buf[0x19] & 0x0f) < 10 && |
| 304 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | (ps2buf[0x1a] & 0x0f) < 10 && |
| 305 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | (ps2buf[0x1b] & 0x0f) < 10 && |
| 306 | endpts >= startpts); | ||
| 307 | ✗ | } else if (len == 1018 && ps2buf[0] == 1) { | |
| 308 | /* DSI structure? */ | ||
| 309 | ✗ | uint8_t hours = ((ps2buf[0x1d] >> 4) * 10) + (ps2buf[0x1d] & 0x0f); | |
| 310 | ✗ | uint8_t mins = ((ps2buf[0x1e] >> 4) * 10) + (ps2buf[0x1e] & 0x0f); | |
| 311 | ✗ | uint8_t secs = ((ps2buf[0x1f] >> 4) * 10) + (ps2buf[0x1f] & 0x0f); | |
| 312 | |||
| 313 | ✗ | m->dvd = (hours <= 23 && | |
| 314 | ✗ | mins <= 59 && | |
| 315 | ✗ | secs <= 59 && | |
| 316 | ✗ | (ps2buf[0x1d] & 0x0f) < 10 && | |
| 317 | ✗ | (ps2buf[0x1e] & 0x0f) < 10 && | |
| 318 | ✗ | (ps2buf[0x1f] & 0x0f) < 10); | |
| 319 | } | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | 3 | av_free(ps2buf); | |
| 324 | |||
| 325 | /* If this isn't a DVD packet or no memory | ||
| 326 | * could be allocated, just ignore it. | ||
| 327 | * If we did, move back to the start of the | ||
| 328 | * packet (plus 'length' field) */ | ||
| 329 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | if (!m->dvd || avio_skip(s->pb, -(len + 2)) < 0) { |
| 330 | /* Skip back failed. | ||
| 331 | * This packet will be lost but that can't be helped | ||
| 332 | * if we can't skip back | ||
| 333 | */ | ||
| 334 | ✗ | goto redo; | |
| 335 | } | ||
| 336 | } else { | ||
| 337 | /* No memory */ | ||
| 338 | ✗ | avio_skip(s->pb, len); | |
| 339 | ✗ | goto redo; | |
| 340 | } | ||
| 341 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | } else if (!m->dvd) { |
| 342 | ✗ | int len = avio_rb16(s->pb); | |
| 343 | ✗ | avio_skip(s->pb, len); | |
| 344 | ✗ | goto redo; | |
| 345 | } | ||
| 346 | } | ||
| 347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13297 times.
|
13297 | if (startcode == PROGRAM_STREAM_MAP) { |
| 348 | ✗ | mpegps_psm_parse(m, s->pb); | |
| 349 | ✗ | goto redo; | |
| 350 | } | ||
| 351 | |||
| 352 | /* find matching stream */ | ||
| 353 |
7/8✓ Branch 0 taken 7456 times.
✓ Branch 1 taken 5841 times.
✓ Branch 2 taken 7103 times.
✓ Branch 3 taken 353 times.
✓ Branch 4 taken 7103 times.
✓ Branch 5 taken 5841 times.
✓ Branch 6 taken 55 times.
✗ Branch 7 not taken.
|
13352 | if (!((startcode >= 0x1c0 && startcode <= 0x1df) || |
| 354 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7103 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 5742 times.
|
12944 | (startcode >= 0x1e0 && startcode <= 0x1ef) || |
| 355 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 44 times.
|
99 | (startcode == 0x1bd) || |
| 356 | (startcode == PRIVATE_STREAM_2) || | ||
| 357 | (startcode == 0x1fd))) | ||
| 358 | 55 | goto redo; | |
| 359 |
2/2✓ Branch 0 taken 12855 times.
✓ Branch 1 taken 387 times.
|
13242 | if (ppos) { |
| 360 | 12855 | *ppos = avio_tell(s->pb) - 4; | |
| 361 | } | ||
| 362 | 13242 | len = avio_rb16(s->pb); | |
| 363 | 13242 | pts = | |
| 364 | 13242 | dts = AV_NOPTS_VALUE; | |
| 365 |
2/2✓ Branch 0 taken 13198 times.
✓ Branch 1 taken 44 times.
|
13242 | if (startcode != PRIVATE_STREAM_2) |
| 366 | { | ||
| 367 | /* stuffing */ | ||
| 368 | for (;;) { | ||
| 369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13204 times.
|
13204 | if (len < 1) |
| 370 | ✗ | goto error_redo; | |
| 371 | 13204 | c = avio_r8(s->pb); | |
| 372 | 13204 | len--; | |
| 373 | /* XXX: for MPEG-1, should test only bit 7 */ | ||
| 374 |
2/2✓ Branch 0 taken 13198 times.
✓ Branch 1 taken 6 times.
|
13204 | if (c != 0xff) |
| 375 | 13198 | break; | |
| 376 | } | ||
| 377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13198 times.
|
13198 | if ((c & 0xc0) == 0x40) { |
| 378 | /* buffer scale & size */ | ||
| 379 | ✗ | avio_r8(s->pb); | |
| 380 | ✗ | c = avio_r8(s->pb); | |
| 381 | ✗ | len -= 2; | |
| 382 | } | ||
| 383 |
2/2✓ Branch 0 taken 922 times.
✓ Branch 1 taken 12276 times.
|
13198 | if ((c & 0xe0) == 0x20) { |
| 384 | 922 | dts = | |
| 385 | 922 | pts = get_pts(s->pb, c); | |
| 386 | 922 | len -= 4; | |
| 387 |
2/2✓ Branch 0 taken 438 times.
✓ Branch 1 taken 484 times.
|
922 | if (c & 0x10) { |
| 388 | 438 | dts = get_pts(s->pb, -1); | |
| 389 | 438 | len -= 5; | |
| 390 | } | ||
| 391 |
2/2✓ Branch 0 taken 9728 times.
✓ Branch 1 taken 2548 times.
|
12276 | } else if ((c & 0xc0) == 0x80) { |
| 392 | /* mpeg 2 PES */ | ||
| 393 | 9728 | flags = avio_r8(s->pb); | |
| 394 | 9728 | header_len = avio_r8(s->pb); | |
| 395 | 9728 | len -= 2; | |
| 396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9728 times.
|
9728 | if (header_len > len) |
| 397 | ✗ | goto error_redo; | |
| 398 | 9728 | len -= header_len; | |
| 399 |
2/2✓ Branch 0 taken 5561 times.
✓ Branch 1 taken 4167 times.
|
9728 | if (flags & 0x80) { |
| 400 | 5561 | dts = pts = get_pts(s->pb, -1); | |
| 401 | 5561 | header_len -= 5; | |
| 402 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5530 times.
|
5561 | if (flags & 0x40) { |
| 403 | 31 | dts = get_pts(s->pb, -1); | |
| 404 | 31 | header_len -= 5; | |
| 405 | } | ||
| 406 | } | ||
| 407 |
3/4✓ Branch 0 taken 42 times.
✓ Branch 1 taken 9686 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
|
9728 | if (flags & 0x3f && header_len == 0) { |
| 408 | ✗ | flags &= 0xC0; | |
| 409 | ✗ | av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n"); | |
| 410 | } | ||
| 411 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 9686 times.
|
9728 | if (flags & 0x01) { /* PES extension */ |
| 412 | 42 | pes_ext = avio_r8(s->pb); | |
| 413 | 42 | header_len--; | |
| 414 | /* Skip PES private data, program packet sequence counter | ||
| 415 | * and P-STD buffer */ | ||
| 416 | 42 | skip = (pes_ext >> 4) & 0xb; | |
| 417 | 42 | skip += skip & 0x9; | |
| 418 |
2/4✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
|
42 | if (pes_ext & 0x40 || skip > header_len) { |
| 419 | ✗ | av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext); | |
| 420 | ✗ | pes_ext = skip = 0; | |
| 421 | } | ||
| 422 | 42 | avio_skip(s->pb, skip); | |
| 423 | 42 | header_len -= skip; | |
| 424 | |||
| 425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | if (pes_ext & 0x01) { /* PES extension 2 */ |
| 426 | ✗ | ext2_len = avio_r8(s->pb); | |
| 427 | ✗ | header_len--; | |
| 428 | ✗ | if ((ext2_len & 0x7f) > 0) { | |
| 429 | ✗ | id_ext = avio_r8(s->pb); | |
| 430 | ✗ | if ((id_ext & 0x80) == 0) | |
| 431 | ✗ | startcode = ((startcode & 0xff) << 8) | id_ext; | |
| 432 | ✗ | header_len--; | |
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9728 times.
|
9728 | if (header_len < 0) |
| 437 | ✗ | goto error_redo; | |
| 438 | 9728 | avio_skip(s->pb, header_len); | |
| 439 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2548 times.
|
2548 | } else if (c != 0xf) |
| 440 | ✗ | goto redo; | |
| 441 | } | ||
| 442 | |||
| 443 |
2/2✓ Branch 0 taken 5742 times.
✓ Branch 1 taken 7500 times.
|
13242 | if (startcode == PRIVATE_STREAM_1) { |
| 444 | 5742 | int ret = ffio_ensure_seekback(s->pb, 2); | |
| 445 | |||
| 446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5742 times.
|
5742 | if (ret < 0) |
| 447 | ✗ | return ret; | |
| 448 | |||
| 449 | 5742 | startcode = avio_r8(s->pb); | |
| 450 | 5742 | m->raw_ac3 = 0; | |
| 451 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5742 times.
|
5742 | if (startcode == 0x0b) { |
| 452 | ✗ | if (avio_r8(s->pb) == 0x77) { | |
| 453 | ✗ | startcode = 0x80; | |
| 454 | ✗ | m->raw_ac3 = 1; | |
| 455 | ✗ | avio_skip(s->pb, -2); | |
| 456 | } else { | ||
| 457 | ✗ | avio_skip(s->pb, -1); | |
| 458 | } | ||
| 459 | } else { | ||
| 460 | 5742 | len--; | |
| 461 | } | ||
| 462 | } | ||
| 463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13242 times.
|
13242 | if (len < 0) |
| 464 | ✗ | goto error_redo; | |
| 465 |
4/4✓ Branch 0 taken 6483 times.
✓ Branch 1 taken 6759 times.
✓ Branch 2 taken 6219 times.
✓ Branch 3 taken 264 times.
|
13242 | if (dts != AV_NOPTS_VALUE && ppos) { |
| 466 | int i; | ||
| 467 |
2/2✓ Branch 0 taken 7599 times.
✓ Branch 1 taken 6219 times.
|
13818 | for (i = 0; i < s->nb_streams; i++) { |
| 468 |
2/2✓ Branch 0 taken 6185 times.
✓ Branch 1 taken 1414 times.
|
7599 | if (startcode == s->streams[i]->id && |
| 469 |
1/2✓ Branch 0 taken 6185 times.
✗ Branch 1 not taken.
|
6185 | (s->pb->seekable & AVIO_SEEKABLE_NORMAL) /* index useless on streams anyway */) { |
| 470 | 6185 | ff_reduce_index(s, i); | |
| 471 | 6185 | av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, | |
| 472 | AVINDEX_KEYFRAME /* FIXME keyframe? */); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | 13242 | *pstart_code = startcode; | |
| 478 | 13242 | *ppts = pts; | |
| 479 | 13242 | *pdts = dts; | |
| 480 | 13242 | return len; | |
| 481 | } | ||
| 482 | |||
| 483 | 12046 | static int mpegps_read_packet(AVFormatContext *s, | |
| 484 | AVPacket *pkt) | ||
| 485 | { | ||
| 486 | 12046 | MpegDemuxContext *m = s->priv_data; | |
| 487 | AVStream *st; | ||
| 488 | FFStream *sti; | ||
| 489 | int len, startcode, i, es_type, ret; | ||
| 490 | 12046 | int pcm_dvd = 0; | |
| 491 | 12046 | int request_probe= 0; | |
| 492 | 12046 | enum AVCodecID codec_id = AV_CODEC_ID_NONE; | |
| 493 | enum AVMediaType type; | ||
| 494 | int64_t pts, dts, dummy_pos; // dummy_pos is needed for the index building to work | ||
| 495 | |||
| 496 | 12527 | redo: | |
| 497 | 12527 | len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); | |
| 498 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 12449 times.
|
12527 | if (len < 0) |
| 499 | 78 | return len; | |
| 500 | |||
| 501 |
4/4✓ Branch 0 taken 12419 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5325 times.
✓ Branch 3 taken 7094 times.
|
12449 | if (startcode >= 0x80 && startcode <= 0xcf) { |
| 502 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5325 times.
|
5325 | if (len < 4) |
| 503 | ✗ | goto skip; | |
| 504 | |||
| 505 |
1/2✓ Branch 0 taken 5325 times.
✗ Branch 1 not taken.
|
5325 | if (!m->raw_ac3) { |
| 506 | /* audio: skip header */ | ||
| 507 | 5325 | avio_skip(s->pb, 3); | |
| 508 | 5325 | len -= 3; | |
| 509 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5325 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5325 | if (startcode >= 0xb0 && startcode <= 0xbf) { |
| 510 | /* MLP/TrueHD audio has a 4-byte header */ | ||
| 511 | ✗ | avio_r8(s->pb); | |
| 512 | ✗ | len--; | |
| 513 |
3/4✓ Branch 0 taken 5319 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5319 times.
✗ Branch 3 not taken.
|
5325 | } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
| 514 | 5319 | ret = ffio_ensure_seekback(s->pb, 3); | |
| 515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5319 times.
|
5319 | if (ret < 0) |
| 516 | ✗ | return ret; | |
| 517 | 5319 | pcm_dvd = (avio_rb24(s->pb) & 0xFF) == 0x80; | |
| 518 | 5319 | avio_skip(s->pb, -3); | |
| 519 | } | ||
| 520 | } | ||
| 521 | } | ||
| 522 | |||
| 523 | /* now find stream */ | ||
| 524 |
2/2✓ Branch 0 taken 16011 times.
✓ Branch 1 taken 39 times.
|
16050 | for (i = 0; i < s->nb_streams; i++) { |
| 525 | 16011 | st = s->streams[i]; | |
| 526 |
2/2✓ Branch 0 taken 12410 times.
✓ Branch 1 taken 3601 times.
|
16011 | if (st->id == startcode) |
| 527 | 12410 | goto found; | |
| 528 | } | ||
| 529 | |||
| 530 | 39 | es_type = m->psm_es_type[startcode & 0xff]; | |
| 531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if (es_type == STREAM_TYPE_VIDEO_MPEG1) { |
| 532 | ✗ | codec_id = AV_CODEC_ID_MPEG2VIDEO; | |
| 533 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 534 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_VIDEO_MPEG2) { |
| 535 | ✗ | codec_id = AV_CODEC_ID_MPEG2VIDEO; | |
| 536 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 537 |
2/4✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_AUDIO_MPEG1 || |
| 538 | es_type == STREAM_TYPE_AUDIO_MPEG2) { | ||
| 539 | ✗ | codec_id = AV_CODEC_ID_MP3; | |
| 540 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_AUDIO_AAC) { |
| 542 | ✗ | codec_id = AV_CODEC_ID_AAC; | |
| 543 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_VIDEO_MPEG4) { |
| 545 | ✗ | codec_id = AV_CODEC_ID_MPEG4; | |
| 546 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_VIDEO_H264) { |
| 548 | ✗ | codec_id = AV_CODEC_ID_H264; | |
| 549 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_VIDEO_HEVC) { |
| 551 | ✗ | codec_id = AV_CODEC_ID_HEVC; | |
| 552 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_VIDEO_VVC) { |
| 554 | ✗ | codec_id = AV_CODEC_ID_VVC; | |
| 555 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 556 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == STREAM_TYPE_AUDIO_AC3) { |
| 557 | ✗ | codec_id = AV_CODEC_ID_AC3; | |
| 558 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | } else if (es_type == 0x90) { |
| 560 | ✗ | codec_id = AV_CODEC_ID_PCM_ALAW; | |
| 561 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 562 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
39 | } else if (m->imkh_cctv && es_type == 0x91) { |
| 563 | ✗ | codec_id = AV_CODEC_ID_PCM_MULAW; | |
| 564 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 565 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
39 | } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { |
| 566 | static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; | ||
| 567 | unsigned char buf[8]; | ||
| 568 | |||
| 569 | 13 | ret = ffio_read_size(s->pb, buf, 8); | |
| 570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (ret < 0) |
| 571 | ✗ | return ret; | |
| 572 | 13 | avio_seek(s->pb, -8, SEEK_CUR); | |
| 573 |
3/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
13 | if (!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) |
| 574 | 2 | codec_id = AV_CODEC_ID_CAVS; | |
| 575 | else | ||
| 576 | 11 | request_probe= 1; | |
| 577 | 13 | type = AVMEDIA_TYPE_VIDEO; | |
| 578 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 23 times.
|
26 | } else if (startcode == PRIVATE_STREAM_2) { |
| 579 | 3 | type = AVMEDIA_TYPE_DATA; | |
| 580 | 3 | codec_id = AV_CODEC_ID_DVD_NAV; | |
| 581 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
23 | } else if (startcode >= 0x1c0 && startcode <= 0x1df) { |
| 582 | 7 | type = AVMEDIA_TYPE_AUDIO; | |
| 583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (m->sofdec > 0) { |
| 584 | ✗ | codec_id = AV_CODEC_ID_ADPCM_ADX; | |
| 585 | // Auto-detect AC-3 | ||
| 586 | ✗ | request_probe = 50; | |
| 587 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
7 | } else if (m->imkh_cctv && startcode == 0x1c0 && len > 80) { |
| 588 | ✗ | codec_id = AV_CODEC_ID_PCM_ALAW; | |
| 589 | ✗ | request_probe = 50; | |
| 590 | } else { | ||
| 591 | 7 | codec_id = AV_CODEC_ID_MP2; | |
| 592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (m->imkh_cctv) |
| 593 | ✗ | request_probe = 25; | |
| 594 | } | ||
| 595 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
|
16 | } else if (startcode >= 0x80 && startcode <= 0x87) { |
| 596 | 1 | type = AVMEDIA_TYPE_AUDIO; | |
| 597 | 1 | codec_id = AV_CODEC_ID_AC3; | |
| 598 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
15 | } else if ((startcode >= 0x88 && startcode <= 0x8f) || |
| 599 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
15 | (startcode >= 0x98 && startcode <= 0x9f)) { |
| 600 | /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ | ||
| 601 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 602 | ✗ | codec_id = AV_CODEC_ID_DTS; | |
| 603 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
15 | } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
| 604 | 13 | type = AVMEDIA_TYPE_AUDIO; | |
| 605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!pcm_dvd) { |
| 606 | ✗ | codec_id = AV_CODEC_ID_MLP; | |
| 607 | } else { | ||
| 608 | 13 | codec_id = AV_CODEC_ID_PCM_DVD; | |
| 609 | } | ||
| 610 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2 | } else if (startcode >= 0xb0 && startcode <= 0xbf) { |
| 611 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 612 | ✗ | codec_id = AV_CODEC_ID_TRUEHD; | |
| 613 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2 | } else if (startcode >= 0xc0 && startcode <= 0xcf) { |
| 614 | /* Used for both AC-3 and E-AC-3 in EVOB files */ | ||
| 615 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 616 | ✗ | codec_id = AV_CODEC_ID_AC3; | |
| 617 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | } else if (startcode >= 0x20 && startcode <= 0x3f) { |
| 618 | 2 | type = AVMEDIA_TYPE_SUBTITLE; | |
| 619 | 2 | codec_id = AV_CODEC_ID_DVD_SUBTITLE; | |
| 620 | ✗ | } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { | |
| 621 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 622 | ✗ | codec_id = AV_CODEC_ID_VC1; | |
| 623 | ✗ | } else if (startcode == 0x69 || startcode == 0x49) { | |
| 624 | ✗ | type = AVMEDIA_TYPE_SUBTITLE; | |
| 625 | ✗ | codec_id = AV_CODEC_ID_IVTV_VBI; | |
| 626 | } else { | ||
| 627 | ✗ | skip: | |
| 628 | /* skip packet */ | ||
| 629 | 481 | avio_skip(s->pb, len); | |
| 630 | 481 | goto redo; | |
| 631 | } | ||
| 632 | /* no stream found: add a new stream */ | ||
| 633 | 39 | st = avformat_new_stream(s, NULL); | |
| 634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if (!st) |
| 635 | ✗ | goto skip; | |
| 636 | 39 | sti = ffstream(st); | |
| 637 | 39 | st->id = startcode; | |
| 638 | 39 | st->codecpar->codec_type = type; | |
| 639 | 39 | st->codecpar->codec_id = codec_id; | |
| 640 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | if ( st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW |
| 641 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) { |
| 642 | ✗ | st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | |
| 643 | ✗ | st->codecpar->sample_rate = 8000; | |
| 644 | } | ||
| 645 | 39 | sti->request_probe = request_probe; | |
| 646 | 39 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
| 647 | |||
| 648 | 12449 | found: | |
| 649 |
2/2✓ Branch 0 taken 481 times.
✓ Branch 1 taken 11968 times.
|
12449 | if (st->discard >= AVDISCARD_ALL) |
| 650 | 481 | goto skip; | |
| 651 |
4/4✓ Branch 0 taken 11942 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 5319 times.
✓ Branch 3 taken 6623 times.
|
11968 | if (startcode >= 0xa0 && startcode <= 0xaf) { |
| 652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5319 times.
|
5319 | if (st->codecpar->codec_id == AV_CODEC_ID_MLP) { |
| 653 | ✗ | if (len < 6) | |
| 654 | ✗ | goto skip; | |
| 655 | ✗ | avio_skip(s->pb, 6); | |
| 656 | ✗ | len -=6; | |
| 657 | } | ||
| 658 | } | ||
| 659 | 11968 | ret = av_get_packet(s->pb, pkt, len); | |
| 660 | |||
| 661 | 11968 | pkt->pts = pts; | |
| 662 | 11968 | pkt->dts = dts; | |
| 663 | 11968 | pkt->pos = dummy_pos; | |
| 664 | 11968 | pkt->stream_index = st->index; | |
| 665 | |||
| 666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11968 times.
|
11968 | if (s->debug & FF_FDEBUG_TS) |
| 667 | ✗ | av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", | |
| 668 | ✗ | pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, | |
| 669 | pkt->size); | ||
| 670 | |||
| 671 | 11968 | return (ret < 0) ? ret : 0; | |
| 672 | } | ||
| 673 | |||
| 674 | 91 | static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, | |
| 675 | int64_t *ppos, int64_t pos_limit) | ||
| 676 | { | ||
| 677 | int len, startcode; | ||
| 678 | int64_t pos, pts, dts; | ||
| 679 | |||
| 680 | 91 | pos = *ppos; | |
| 681 |
1/2✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
|
91 | if (avio_seek(s->pb, pos, SEEK_SET) < 0) |
| 682 | ✗ | return AV_NOPTS_VALUE; | |
| 683 | |||
| 684 | for (;;) { | ||
| 685 | 451 | len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); | |
| 686 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 406 times.
|
451 | if (len < 0) { |
| 687 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (s->debug & FF_FDEBUG_TS) |
| 688 | ✗ | av_log(s, AV_LOG_DEBUG, "none (ret=%d)\n", len); | |
| 689 | 45 | return AV_NOPTS_VALUE; | |
| 690 | } | ||
| 691 |
2/2✓ Branch 0 taken 323 times.
✓ Branch 1 taken 83 times.
|
406 | if (startcode == s->streams[stream_index]->id && |
| 692 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 277 times.
|
323 | dts != AV_NOPTS_VALUE) { |
| 693 | 46 | break; | |
| 694 | } | ||
| 695 | 360 | avio_skip(s->pb, len); | |
| 696 | } | ||
| 697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (s->debug & FF_FDEBUG_TS) |
| 698 | ✗ | av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", | |
| 699 | pos, dts, dts / 90000.0); | ||
| 700 | 46 | *ppos = pos; | |
| 701 | 46 | return dts; | |
| 702 | } | ||
| 703 | |||
| 704 | const FFInputFormat ff_mpegps_demuxer = { | ||
| 705 | .p.name = "mpeg", | ||
| 706 | .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"), | ||
| 707 | .p.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||
| 708 | .priv_data_size = sizeof(MpegDemuxContext), | ||
| 709 | .read_probe = mpegps_probe, | ||
| 710 | .read_header = mpegps_read_header, | ||
| 711 | .read_packet = mpegps_read_packet, | ||
| 712 | .read_timestamp = mpegps_read_dts, | ||
| 713 | }; | ||
| 714 | |||
| 715 | #if CONFIG_VOBSUB_DEMUXER | ||
| 716 | |||
| 717 | #include "subtitles.h" | ||
| 718 | #include "libavutil/avassert.h" | ||
| 719 | #include "libavutil/bprint.h" | ||
| 720 | #include "libavutil/opt.h" | ||
| 721 | |||
| 722 | #define REF_STRING "# VobSub index file," | ||
| 723 | #define MAX_LINE_SIZE 2048 | ||
| 724 | |||
| 725 | typedef struct VobSubDemuxContext { | ||
| 726 | const AVClass *class; | ||
| 727 | AVFormatContext *sub_ctx; | ||
| 728 | FFDemuxSubtitlesQueue q[32]; | ||
| 729 | char *sub_name; | ||
| 730 | } VobSubDemuxContext; | ||
| 731 | |||
| 732 | 7279 | static int vobsub_probe(const AVProbeData *p) | |
| 733 | { | ||
| 734 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7277 times.
|
7279 | if (!strncmp(p->buf, REF_STRING, sizeof(REF_STRING) - 1)) |
| 735 | 2 | return AVPROBE_SCORE_MAX; | |
| 736 | 7277 | return 0; | |
| 737 | } | ||
| 738 | |||
| 739 | 3 | static int vobsub_read_close(AVFormatContext *s) | |
| 740 | { | ||
| 741 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 742 | int i; | ||
| 743 | |||
| 744 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) |
| 745 | 3 | ff_subtitles_queue_clean(&vobsub->q[i]); | |
| 746 | 3 | avformat_close_input(&vobsub->sub_ctx); | |
| 747 | 3 | return 0; | |
| 748 | } | ||
| 749 | |||
| 750 | 3 | static int vobsub_read_header(AVFormatContext *s) | |
| 751 | { | ||
| 752 | 3 | int i, ret = 0, header_parsed = 0, langidx = 0; | |
| 753 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 754 | const AVInputFormat *iformat; | ||
| 755 | size_t fname_len; | ||
| 756 | AVBPrint header; | ||
| 757 | 3 | int64_t delay = 0; | |
| 758 | 3 | AVStream *st = NULL; | |
| 759 | 3 | int stream_id = -1; | |
| 760 | 3 | char id[64] = {0}; | |
| 761 | 3 | char alt[MAX_LINE_SIZE] = {0}; | |
| 762 | |||
| 763 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!vobsub->sub_name) { |
| 764 | char *ext; | ||
| 765 | 3 | vobsub->sub_name = av_strdup(s->url); | |
| 766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_name) { |
| 767 | ✗ | return AVERROR(ENOMEM); | |
| 768 | } | ||
| 769 | |||
| 770 | 3 | fname_len = strlen(vobsub->sub_name); | |
| 771 | 3 | ext = vobsub->sub_name - 3 + fname_len; | |
| 772 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (fname_len < 4 || *(ext - 1) != '.') { |
| 773 | ✗ | av_log(s, AV_LOG_ERROR, "The input index filename is too short " | |
| 774 | "to guess the associated .SUB file\n"); | ||
| 775 | ✗ | return AVERROR_INVALIDDATA; | |
| 776 | } | ||
| 777 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); |
| 778 | 3 | av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); | |
| 779 | } | ||
| 780 | |||
| 781 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!(iformat = av_find_input_format("mpeg"))) { |
| 782 | ✗ | return AVERROR_DEMUXER_NOT_FOUND; | |
| 783 | } | ||
| 784 | |||
| 785 | 3 | vobsub->sub_ctx = avformat_alloc_context(); | |
| 786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_ctx) { |
| 787 | ✗ | return AVERROR(ENOMEM); | |
| 788 | } | ||
| 789 | |||
| 790 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0) |
| 791 | ✗ | return ret; | |
| 792 | |||
| 793 | 3 | ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL); | |
| 794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
| 795 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to open %s as MPEG subtitles\n", vobsub->sub_name); | |
| 796 | ✗ | return ret; | |
| 797 | } | ||
| 798 | |||
| 799 | 3 | av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); | |
| 800 | |||
| 801 |
1/2✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
|
189 | while (!avio_feof(s->pb)) { |
| 802 | char line[MAX_LINE_SIZE]; | ||
| 803 | 189 | int len = ff_get_line(s->pb, line, sizeof(line)); | |
| 804 | |||
| 805 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 186 times.
|
189 | if (!len) |
| 806 | 3 | break; | |
| 807 | |||
| 808 | 186 | line[strcspn(line, "\r\n")] = 0; | |
| 809 | |||
| 810 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 183 times.
|
186 | if (!strncmp(line, "id:", 3)) { |
| 811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(line, "id: %63[^,], index: %u", id, &stream_id) != 2) { |
| 812 | ✗ | av_log(s, AV_LOG_WARNING, "Unable to parse index line '%s', " | |
| 813 | "assuming 'id: und, index: 0'\n", line); | ||
| 814 | ✗ | strcpy(id, "und"); | |
| 815 | ✗ | stream_id = 0; | |
| 816 | } | ||
| 817 | |||
| 818 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (stream_id >= FF_ARRAY_ELEMS(vobsub->q)) { |
| 819 | ✗ | av_log(s, AV_LOG_ERROR, "Maximum number of subtitles streams reached\n"); | |
| 820 | ✗ | ret = AVERROR(EINVAL); | |
| 821 | ✗ | goto end; | |
| 822 | } | ||
| 823 | |||
| 824 | 3 | header_parsed = 1; | |
| 825 | 3 | alt[0] = '\0'; | |
| 826 | /* We do not create the stream immediately to avoid adding empty | ||
| 827 | * streams. See the following timestamp entry. */ | ||
| 828 | |||
| 829 | 3 | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); | |
| 830 | |||
| 831 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 42 times.
|
183 | } else if (!strncmp(line, "timestamp:", 10)) { |
| 832 | AVPacket *sub; | ||
| 833 | int hh, mm, ss, ms; | ||
| 834 | int64_t pos, timestamp; | ||
| 835 | 141 | const char *p = line + 10; | |
| 836 | |||
| 837 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (stream_id == -1) { |
| 838 | ✗ | av_log(s, AV_LOG_ERROR, "Timestamp declared before any stream\n"); | |
| 839 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 840 | ✗ | goto end; | |
| 841 | } | ||
| 842 | |||
| 843 |
3/4✓ Branch 0 taken 138 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
|
141 | if (!st || st->id != stream_id) { |
| 844 | 3 | st = avformat_new_stream(s, NULL); | |
| 845 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!st) { |
| 846 | ✗ | ret = AVERROR(ENOMEM); | |
| 847 | ✗ | goto end; | |
| 848 | } | ||
| 849 | 3 | st->id = stream_id; | |
| 850 | 3 | st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
| 851 | 3 | st->codecpar->codec_id = AV_CODEC_ID_DVD_SUBTITLE; | |
| 852 | 3 | avpriv_set_pts_info(st, 64, 1, 1000); | |
| 853 | 3 | av_dict_set(&st->metadata, "language", id, 0); | |
| 854 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (alt[0]) |
| 855 | ✗ | av_dict_set(&st->metadata, "title", alt, 0); | |
| 856 | } | ||
| 857 | |||
| 858 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (sscanf(p, "%02d:%02d:%02d:%03d, filepos: %"SCNx64, |
| 859 | &hh, &mm, &ss, &ms, &pos) != 5) { | ||
| 860 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to parse timestamp line '%s', " | |
| 861 | "abort parsing\n", line); | ||
| 862 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 863 | ✗ | goto end; | |
| 864 | } | ||
| 865 | 141 | timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay; | |
| 866 | 141 | timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base); | |
| 867 | |||
| 868 | 141 | sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 0, 0); | |
| 869 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (!sub) { |
| 870 | ✗ | ret = AVERROR(ENOMEM); | |
| 871 | ✗ | goto end; | |
| 872 | } | ||
| 873 | 141 | sub->pos = pos; | |
| 874 | 141 | sub->pts = timestamp; | |
| 875 | 141 | sub->stream_index = s->nb_streams - 1; | |
| 876 | |||
| 877 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "alt:", 4)) { |
| 878 | ✗ | const char *p = line + 4; | |
| 879 | |||
| 880 | ✗ | while (*p == ' ') | |
| 881 | ✗ | p++; | |
| 882 | ✗ | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] name=%s\n", stream_id, p); | |
| 883 | ✗ | av_strlcpy(alt, p, sizeof(alt)); | |
| 884 | ✗ | header_parsed = 1; | |
| 885 | |||
| 886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "delay:", 6)) { |
| 887 | ✗ | int sign = 1, hh = 0, mm = 0, ss = 0, ms = 0; | |
| 888 | ✗ | const char *p = line + 6; | |
| 889 | |||
| 890 | ✗ | while (*p == ' ') | |
| 891 | ✗ | p++; | |
| 892 | ✗ | if (*p == '-' || *p == '+') { | |
| 893 | ✗ | sign = *p == '-' ? -1 : 1; | |
| 894 | ✗ | p++; | |
| 895 | } | ||
| 896 | ✗ | sscanf(p, "%d:%d:%d:%d", &hh, &mm, &ss, &ms); | |
| 897 | ✗ | delay = ((hh*3600LL + mm*60LL + ss) * 1000LL + ms) * sign; | |
| 898 | |||
| 899 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 39 times.
|
42 | } else if (!strncmp(line, "langidx:", 8)) { |
| 900 | 3 | const char *p = line + 8; | |
| 901 | |||
| 902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(p, "%d", &langidx) != 1) |
| 903 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid langidx specified\n"); | |
| 904 | |||
| 905 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | } else if (!header_parsed) { |
| 906 |
4/4✓ Branch 0 taken 33 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 24 times.
|
39 | if (line[0] && line[0] != '#') |
| 907 | 9 | av_bprintf(&header, "%s\n", line); | |
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (langidx < s->nb_streams) |
| 912 | 3 | s->streams[langidx]->disposition |= AV_DISPOSITION_DEFAULT; | |
| 913 | |||
| 914 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
| 915 | 3 | vobsub->q[i].sort = SUB_SORT_POS_TS; | |
| 916 | 3 | vobsub->q[i].keep_duplicates = 1; | |
| 917 | 3 | ff_subtitles_queue_finalize(s, &vobsub->q[i]); | |
| 918 | } | ||
| 919 | |||
| 920 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!av_bprint_is_complete(&header)) { |
| 921 | ✗ | ret = AVERROR(ENOMEM); | |
| 922 | ✗ | goto end; | |
| 923 | } | ||
| 924 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
| 925 | 3 | AVCodecParameters *par = s->streams[i]->codecpar; | |
| 926 | 3 | ret = ff_alloc_extradata(par, header.len); | |
| 927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
| 928 | ✗ | goto end; | |
| 929 | } | ||
| 930 | 3 | memcpy(par->extradata, header.str, header.len); | |
| 931 | } | ||
| 932 | 3 | end: | |
| 933 | 3 | av_bprint_finalize(&header, NULL); | |
| 934 | 3 | return ret; | |
| 935 | } | ||
| 936 | |||
| 937 | 141 | static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 938 | { | ||
| 939 | 141 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 940 | FFDemuxSubtitlesQueue *q; | ||
| 941 | 141 | AVIOContext *pb = vobsub->sub_ctx->pb; | |
| 942 | 141 | int ret, psize, total_read = 0, i; | |
| 943 | |||
| 944 | 141 | int64_t min_ts = INT64_MAX; | |
| 945 | 141 | int sid = 0; | |
| 946 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 141 times.
|
282 | for (i = 0; i < s->nb_streams; i++) { |
| 947 | 141 | FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i]; | |
| 948 | int64_t ts; | ||
| 949 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | av_assert0(tmpq->nb_subs); |
| 950 | |||
| 951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (tmpq->current_sub_idx >= tmpq->nb_subs) |
| 952 | ✗ | continue; | |
| 953 | |||
| 954 | 141 | ts = tmpq->subs[tmpq->current_sub_idx]->pts; | |
| 955 |
1/2✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
|
141 | if (ts < min_ts) { |
| 956 | 141 | min_ts = ts; | |
| 957 | 141 | sid = i; | |
| 958 | } | ||
| 959 | } | ||
| 960 | 141 | q = &vobsub->q[sid]; | |
| 961 | /* The returned packet will have size zero, | ||
| 962 | * so that it can be directly used with av_grow_packet. */ | ||
| 963 | 141 | ret = ff_subtitles_queue_read_packet(q, pkt); | |
| 964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (ret < 0) |
| 965 | ✗ | return ret; | |
| 966 | |||
| 967 | /* compute maximum packet size using the next packet position. This is | ||
| 968 | * useful when the len in the header is non-sense */ | ||
| 969 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 3 times.
|
141 | if (q->current_sub_idx < q->nb_subs) { |
| 970 | 138 | psize = q->subs[q->current_sub_idx]->pos - pkt->pos; | |
| 971 | } else { | ||
| 972 | 3 | int64_t fsize = avio_size(pb); | |
| 973 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | psize = fsize < 0 ? 0xffff : fsize - pkt->pos; |
| 974 | } | ||
| 975 | |||
| 976 | 141 | avio_seek(pb, pkt->pos, SEEK_SET); | |
| 977 | |||
| 978 | do { | ||
| 979 | int n, to_read, startcode; | ||
| 980 | int64_t pts, dts; | ||
| 981 | 393 | int64_t old_pos = avio_tell(pb), new_pos; | |
| 982 | int pkt_size; | ||
| 983 | |||
| 984 | 393 | ret = mpegps_read_pes_header(vobsub->sub_ctx, NULL, &startcode, &pts, &dts); | |
| 985 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 387 times.
|
393 | if (ret < 0) { |
| 986 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (pkt->size) // raise packet even if incomplete |
| 987 | 129 | break; | |
| 988 | 3 | return ret; | |
| 989 | } | ||
| 990 | 387 | to_read = ret & 0xffff; | |
| 991 | 387 | new_pos = avio_tell(pb); | |
| 992 | 387 | pkt_size = ret + (new_pos - old_pos); | |
| 993 | |||
| 994 | /* this prevents reads above the current packet */ | ||
| 995 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 261 times.
|
387 | if (total_read + pkt_size > psize) |
| 996 | 126 | break; | |
| 997 | 261 | total_read += pkt_size; | |
| 998 | |||
| 999 | /* the current chunk doesn't match the stream index (unlikely) */ | ||
| 1000 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if ((startcode & 0x1f) != s->streams[pkt->stream_index]->id) |
| 1001 | ✗ | break; | |
| 1002 | |||
| 1003 | 261 | ret = av_grow_packet(pkt, to_read); | |
| 1004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (ret < 0) |
| 1005 | ✗ | return ret; | |
| 1006 | |||
| 1007 | 261 | n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read); | |
| 1008 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (n < to_read) |
| 1009 | ✗ | pkt->size -= to_read - n; | |
| 1010 |
2/2✓ Branch 0 taken 252 times.
✓ Branch 1 taken 9 times.
|
261 | } while (total_read < psize); |
| 1011 | |||
| 1012 | 138 | return 0; | |
| 1013 | } | ||
| 1014 | |||
| 1015 | 1 | static int vobsub_read_seek(AVFormatContext *s, int stream_index, | |
| 1016 | int64_t min_ts, int64_t ts, int64_t max_ts, int flags) | ||
| 1017 | { | ||
| 1018 | 1 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 1019 | |||
| 1020 | /* Rescale requested timestamps based on the first stream (timebase is the | ||
| 1021 | * same for all subtitles stream within a .idx/.sub). Rescaling is done just | ||
| 1022 | * like in avformat_seek_file(). */ | ||
| 1023 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if (stream_index == -1 && s->nb_streams != 1) { |
| 1024 | ✗ | int i, ret = 0; | |
| 1025 | ✗ | AVRational time_base = s->streams[0]->time_base; | |
| 1026 | ✗ | ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base); | |
| 1027 | ✗ | min_ts = av_rescale_rnd(min_ts, time_base.den, | |
| 1028 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
| 1029 | AV_ROUND_UP | AV_ROUND_PASS_MINMAX); | ||
| 1030 | ✗ | max_ts = av_rescale_rnd(max_ts, time_base.den, | |
| 1031 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
| 1032 | AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX); | ||
| 1033 | ✗ | for (i = 0; i < s->nb_streams; i++) { | |
| 1034 | ✗ | int r = ff_subtitles_queue_seek(&vobsub->q[i], s, stream_index, | |
| 1035 | min_ts, ts, max_ts, flags); | ||
| 1036 | ✗ | if (r < 0) | |
| 1037 | ✗ | ret = r; | |
| 1038 | } | ||
| 1039 | ✗ | return ret; | |
| 1040 | } | ||
| 1041 | |||
| 1042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (stream_index == -1) // only 1 stream |
| 1043 | ✗ | stream_index = 0; | |
| 1044 | 1 | return ff_subtitles_queue_seek(&vobsub->q[stream_index], s, stream_index, | |
| 1045 | min_ts, ts, max_ts, flags); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static const AVOption options[] = { | ||
| 1049 | { "sub_name", "URI for .sub file", offsetof(VobSubDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 1050 | { NULL } | ||
| 1051 | }; | ||
| 1052 | |||
| 1053 | static const AVClass vobsub_demuxer_class = { | ||
| 1054 | .class_name = "vobsub", | ||
| 1055 | .item_name = av_default_item_name, | ||
| 1056 | .option = options, | ||
| 1057 | .version = LIBAVUTIL_VERSION_INT, | ||
| 1058 | }; | ||
| 1059 | |||
| 1060 | const FFInputFormat ff_vobsub_demuxer = { | ||
| 1061 | .p.name = "vobsub", | ||
| 1062 | .p.long_name = NULL_IF_CONFIG_SMALL("VobSub subtitle format"), | ||
| 1063 | .p.flags = AVFMT_SHOW_IDS, | ||
| 1064 | .p.extensions = "idx", | ||
| 1065 | .p.priv_class = &vobsub_demuxer_class, | ||
| 1066 | .priv_data_size = sizeof(VobSubDemuxContext), | ||
| 1067 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
| 1068 | .read_probe = vobsub_probe, | ||
| 1069 | .read_header = vobsub_read_header, | ||
| 1070 | .read_packet = vobsub_read_packet, | ||
| 1071 | .read_seek2 = vobsub_read_seek, | ||
| 1072 | .read_close = vobsub_read_close, | ||
| 1073 | }; | ||
| 1074 | #endif | ||
| 1075 |