| 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 | 51726 | static int check_pes(const uint8_t *p, const uint8_t *end) | |
| 38 | { | ||
| 39 | int pes1; | ||
| 40 | 107113 | int pes2 = (p[3] & 0xC0) == 0x80 && | |
| 41 |
4/4✓ Branch 0 taken 3661 times.
✓ Branch 1 taken 48065 times.
✓ Branch 2 taken 3074 times.
✓ Branch 3 taken 587 times.
|
54800 | (p[4] & 0xC0) != 0x40 && |
| 42 |
2/2✓ Branch 0 taken 1329 times.
✓ Branch 1 taken 1745 times.
|
3074 | ((p[4] & 0xC0) == 0x00 || |
| 43 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 1181 times.
|
1329 | (p[4] & 0xC0) >> 2 == (p[6] & 0xF0)); |
| 44 | |||
| 45 |
4/4✓ Branch 0 taken 54041 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 2384 times.
✓ Branch 3 taken 51657 times.
|
54110 | for (p += 3; p < end && *p == 0xFF; p++) ; |
| 46 |
2/2✓ Branch 0 taken 4786 times.
✓ Branch 1 taken 46940 times.
|
51726 | if ((*p & 0xC0) == 0x40) |
| 47 | 4786 | p += 2; | |
| 48 | |||
| 49 |
2/2✓ Branch 0 taken 1554 times.
✓ Branch 1 taken 50172 times.
|
51726 | if ((*p & 0xF0) == 0x20) |
| 50 | 1554 | pes1 = p[0] & p[2] & p[4] & 1; | |
| 51 |
2/2✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 48918 times.
|
50172 | else if ((*p & 0xF0) == 0x30) |
| 52 | 1254 | pes1 = p[0] & p[2] & p[4] & p[5] & p[7] & p[9] & 1; | |
| 53 | else | ||
| 54 | 48918 | pes1 = *p == 0x0F; | |
| 55 | |||
| 56 |
4/4✓ Branch 0 taken 51368 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 1893 times.
✓ Branch 3 taken 49475 times.
|
51726 | return pes1 || pes2; |
| 57 | } | ||
| 58 | |||
| 59 | 52046 | static int check_pack_header(const uint8_t *buf) | |
| 60 | { | ||
| 61 |
4/4✓ Branch 0 taken 44958 times.
✓ Branch 1 taken 7088 times.
✓ Branch 2 taken 2966 times.
✓ Branch 3 taken 41992 times.
|
52046 | return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20; |
| 62 | } | ||
| 63 | |||
| 64 | 7957 | static int mpegps_probe(const AVProbeData *p) | |
| 65 | { | ||
| 66 | 7957 | uint32_t code = -1; | |
| 67 | int i; | ||
| 68 | 7957 | int sys = 0, pspack = 0, priv1 = 0, vid = 0; | |
| 69 | 7957 | int audio = 0, invalid = 0, score = 0; | |
| 70 | 7957 | int endpes = 0; | |
| 71 | |||
| 72 |
2/2✓ Branch 0 taken 492336821 times.
✓ Branch 1 taken 7957 times.
|
492344778 | for (i = 0; i < p->buf_size; i++) { |
| 73 | 492336821 | code = (code << 8) + p->buf[i]; | |
| 74 |
2/2✓ Branch 0 taken 52046 times.
✓ Branch 1 taken 492284775 times.
|
492336821 | if ((code & 0xffffff00) == 0x100) { |
| 75 | 52046 | int len = p->buf[i + 1] << 8 | p->buf[i + 2]; | |
| 76 |
4/4✓ Branch 0 taken 51726 times.
✓ Branch 1 taken 320 times.
✓ Branch 3 taken 2251 times.
✓ Branch 4 taken 49475 times.
|
52046 | int pes = endpes <= i && check_pes(p->buf + i, p->buf + p->buf_size); |
| 77 | 52046 | int pack = check_pack_header(p->buf + i); | |
| 78 | |||
| 79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52046 times.
|
52046 | if (len > INT_MAX - i) |
| 80 | ✗ | break; | |
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 52000 times.
|
52046 | if (code == SYSTEM_HEADER_START_CODE) |
| 83 | 46 | sys++; | |
| 84 |
4/4✓ Branch 0 taken 81 times.
✓ Branch 1 taken 51919 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 5 times.
|
52000 | else if (code == PACK_START_CODE && pack) |
| 85 | 76 | pspack++; | |
| 86 |
4/4✓ Branch 0 taken 990 times.
✓ Branch 1 taken 50934 times.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 888 times.
|
51924 | else if ((code & 0xf0) == VIDEO_ID && pes) { |
| 87 | 102 | endpes = i + len; | |
| 88 | 102 | vid++; | |
| 89 | } | ||
| 90 | // skip pes payload to avoid start code emulation for private | ||
| 91 | // and audio streams | ||
| 92 |
4/4✓ Branch 0 taken 1427 times.
✓ Branch 1 taken 50395 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 1375 times.
|
51822 | else if ((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} |
| 93 |
4/4✓ Branch 0 taken 82 times.
✓ Branch 1 taken 51688 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 12 times.
|
51770 | else if (code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} |
| 94 |
3/4✓ Branch 0 taken 114 times.
✓ Branch 1 taken 51586 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
|
51700 | else if (code == 0x1fd && pes) vid++; //VC1 |
| 95 | |||
| 96 |
3/4✓ Branch 0 taken 888 times.
✓ Branch 1 taken 50812 times.
✓ Branch 2 taken 888 times.
✗ Branch 3 not taken.
|
51700 | else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++; |
| 97 |
3/4✓ Branch 0 taken 1375 times.
✓ Branch 1 taken 49437 times.
✓ Branch 2 taken 1375 times.
✗ Branch 3 not taken.
|
50812 | else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++; |
| 98 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 49425 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
49437 | else if (code == PRIVATE_STREAM_1 && !pes) invalid++; |
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7933 times.
|
7957 | if (vid + audio > invalid + 1) /* invalid VDR files nd short PES streams */ |
| 103 | 24 | 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 37 times.
✓ Branch 1 taken 7920 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 2 times.
|
7957 | if (sys > invalid && sys * 9 <= pspack * 10) |
| 109 |
3/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 1 times.
|
35 | return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 |
| 110 |
3/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 16 times.
|
70 | : AVPROBE_SCORE_EXTENSION / 2 + (audio + vid + pspack > 1); // 1 more than mp3 |
| 111 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7908 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 4 times.
|
7922 | 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 77 times.
✓ Branch 1 taken 7835 times.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 62 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
|
7912 | if ((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && |
| 115 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
15 | !pspack && p->buf_size > 2048 && vid + audio > invalid) /* PES stream */ |
| 116 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | return (audio > 12 || vid > 6 + 2 * invalid) ? AVPROBE_SCORE_EXTENSION + 1 |
| 117 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | : 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 | 7910 | 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 | 29 | static int mpegps_read_header(AVFormatContext *s) | |
| 135 | { | ||
| 136 | 29 | MpegDemuxContext *m = s->priv_data; | |
| 137 | 29 | char buffer[7] = { 0 }; | |
| 138 | 29 | int64_t last_pos = avio_tell(s->pb); | |
| 139 | |||
| 140 | 29 | m->header_state = 0xff; | |
| 141 | 29 | s->ctx_flags |= AVFMTCTX_NOHEADER; | |
| 142 | |||
| 143 | 29 | avio_get_str(s->pb, 6, buffer, sizeof(buffer)); | |
| 144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | if (!memcmp("IMKH", buffer, 4)) { |
| 145 | ✗ | m->imkh_cctv = 1; | |
| 146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | } else if (!memcmp("Sofdec", buffer, 6)) { |
| 147 | ✗ | m->sofdec = 1; | |
| 148 | } else | ||
| 149 | 29 | avio_seek(s->pb, last_pos, SEEK_SET); | |
| 150 | |||
| 151 | /* no need to do more */ | ||
| 152 | 29 | return 0; | |
| 153 | } | ||
| 154 | |||
| 155 | 7040 | 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 6118 times.
✓ Branch 1 taken 922 times.
|
7040 | buf[0] = c < 0 ? avio_r8(pb) : c; |
| 161 | 7040 | ret = avio_read(pb, buf + 1, 4); | |
| 162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7040 times.
|
7040 | if (ret < 4) |
| 163 | ✗ | return AV_NOPTS_VALUE; | |
| 164 | |||
| 165 | 7040 | return ff_parse_pes_pts(buf); | |
| 166 | } | ||
| 167 | |||
| 168 | 25090 | 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 | 25090 | state = *header_state; | |
| 175 | 25090 | n = *size_ptr; | |
| 176 |
1/2✓ Branch 0 taken 317561 times.
✗ Branch 1 not taken.
|
317561 | while (n > 0) { |
| 177 |
2/2✓ Branch 1 taken 132 times.
✓ Branch 2 taken 317429 times.
|
317561 | if (avio_feof(pb)) |
| 178 | 132 | break; | |
| 179 | 317429 | v = avio_r8(pb); | |
| 180 | 317429 | n--; | |
| 181 |
2/2✓ Branch 0 taken 24958 times.
✓ Branch 1 taken 292471 times.
|
317429 | if (state == 0x000001) { |
| 182 | 24958 | state = ((state << 8) | v) & 0xffffff; | |
| 183 | 24958 | val = state; | |
| 184 | 24958 | goto found; | |
| 185 | } | ||
| 186 | 292471 | state = ((state << 8) | v) & 0xffffff; | |
| 187 | } | ||
| 188 | 132 | val = -1; | |
| 189 | |||
| 190 | 25090 | found: | |
| 191 | 25090 | *header_state = state; | |
| 192 | 25090 | *size_ptr = n; | |
| 193 | 25090 | 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 | 13586 | static int mpegps_read_pes_header(AVFormatContext *s, | |
| 237 | int64_t *ppos, int *pstart_code, | ||
| 238 | int64_t *ppts, int64_t *pdts) | ||
| 239 | { | ||
| 240 | 13586 | 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 | 13586 | int64_t last_sync = avio_tell(s->pb); | |
| 245 | |||
| 246 | ✗ | error_redo: | |
| 247 | 13586 | avio_seek(s->pb, last_sync, SEEK_SET); | |
| 248 | 11504 | redo: | |
| 249 | /* next start code (should be immediately after) */ | ||
| 250 | 25090 | m->header_state = 0xff; | |
| 251 | 25090 | size = MAX_SYNC_SIZE; | |
| 252 | 25090 | startcode = find_next_start_code(s->pb, &size, &m->header_state); | |
| 253 | 25090 | last_sync = avio_tell(s->pb); | |
| 254 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 24958 times.
|
25090 | if (startcode < 0) { |
| 255 |
1/2✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
|
132 | if (avio_feof(s->pb)) |
| 256 | 132 | return AVERROR_EOF; | |
| 257 | // FIXME we should remember header_state | ||
| 258 | ✗ | return FFERROR_REDO; | |
| 259 | } | ||
| 260 | |||
| 261 |
2/2✓ Branch 0 taken 10458 times.
✓ Branch 1 taken 14500 times.
|
24958 | if (startcode == PACK_START_CODE) |
| 262 | 10458 | goto redo; | |
| 263 |
2/2✓ Branch 0 taken 195 times.
✓ Branch 1 taken 14305 times.
|
14500 | if (startcode == SYSTEM_HEADER_START_CODE) |
| 264 | 195 | goto redo; | |
| 265 |
2/2✓ Branch 0 taken 796 times.
✓ Branch 1 taken 13509 times.
|
14305 | 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 13465 times.
|
13509 | 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 13509 times.
|
13509 | 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 7590 times.
✓ Branch 1 taken 5919 times.
✓ Branch 2 taken 7227 times.
✓ Branch 3 taken 363 times.
✓ Branch 4 taken 7227 times.
✓ Branch 5 taken 5919 times.
✓ Branch 6 taken 55 times.
✗ Branch 7 not taken.
|
13564 | if (!((startcode >= 0x1c0 && startcode <= 0x1df) || |
| 354 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7227 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 5820 times.
|
13146 | (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 13067 times.
✓ Branch 1 taken 387 times.
|
13454 | if (ppos) { |
| 360 | 13067 | *ppos = avio_tell(s->pb) - 4; | |
| 361 | } | ||
| 362 | 13454 | len = avio_rb16(s->pb); | |
| 363 | 13454 | pts = | |
| 364 | 13454 | dts = AV_NOPTS_VALUE; | |
| 365 |
2/2✓ Branch 0 taken 13410 times.
✓ Branch 1 taken 44 times.
|
13454 | if (startcode != PRIVATE_STREAM_2) |
| 366 | { | ||
| 367 | /* stuffing */ | ||
| 368 | for (;;) { | ||
| 369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13416 times.
|
13416 | if (len < 1) |
| 370 | ✗ | goto error_redo; | |
| 371 | 13416 | c = avio_r8(s->pb); | |
| 372 | 13416 | len--; | |
| 373 | /* XXX: for MPEG-1, should test only bit 7 */ | ||
| 374 |
2/2✓ Branch 0 taken 13410 times.
✓ Branch 1 taken 6 times.
|
13416 | if (c != 0xff) |
| 375 | 13410 | break; | |
| 376 | } | ||
| 377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13410 times.
|
13410 | 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 12488 times.
|
13410 | 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 9940 times.
✓ Branch 1 taken 2548 times.
|
12488 | } else if ((c & 0xc0) == 0x80) { |
| 392 | /* mpeg 2 PES */ | ||
| 393 | 9940 | flags = avio_r8(s->pb); | |
| 394 | 9940 | header_len = avio_r8(s->pb); | |
| 395 | 9940 | len -= 2; | |
| 396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9940 times.
|
9940 | if (header_len > len) |
| 397 | ✗ | goto error_redo; | |
| 398 | 9940 | len -= header_len; | |
| 399 |
2/2✓ Branch 0 taken 5649 times.
✓ Branch 1 taken 4291 times.
|
9940 | if (flags & 0x80) { |
| 400 | 5649 | dts = pts = get_pts(s->pb, -1); | |
| 401 | 5649 | header_len -= 5; | |
| 402 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5618 times.
|
5649 | if (flags & 0x40) { |
| 403 | 31 | dts = get_pts(s->pb, -1); | |
| 404 | 31 | header_len -= 5; | |
| 405 | } | ||
| 406 | } | ||
| 407 |
3/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 9895 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
|
9940 | 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 45 times.
✓ Branch 1 taken 9895 times.
|
9940 | if (flags & 0x01) { /* PES extension */ |
| 412 | 45 | pes_ext = avio_r8(s->pb); | |
| 413 | 45 | header_len--; | |
| 414 | /* Skip PES private data, program packet sequence counter | ||
| 415 | * and P-STD buffer */ | ||
| 416 | 45 | skip = (pes_ext >> 4) & 0xb; | |
| 417 | 45 | skip += skip & 0x9; | |
| 418 |
2/4✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 45 times.
|
45 | 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 | 45 | avio_skip(s->pb, skip); | |
| 423 | 45 | header_len -= skip; | |
| 424 | |||
| 425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | 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 9940 times.
|
9940 | if (header_len < 0) |
| 437 | ✗ | goto error_redo; | |
| 438 | 9940 | 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 5820 times.
✓ Branch 1 taken 7634 times.
|
13454 | if (startcode == PRIVATE_STREAM_1) { |
| 444 | 5820 | int ret = ffio_ensure_seekback(s->pb, 2); | |
| 445 | |||
| 446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5820 times.
|
5820 | if (ret < 0) |
| 447 | ✗ | return ret; | |
| 448 | |||
| 449 | 5820 | startcode = avio_r8(s->pb); | |
| 450 | 5820 | m->raw_ac3 = 0; | |
| 451 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5820 times.
|
5820 | 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 | 5820 | len--; | |
| 461 | } | ||
| 462 | } | ||
| 463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13454 times.
|
13454 | if (len < 0) |
| 464 | ✗ | goto error_redo; | |
| 465 |
4/4✓ Branch 0 taken 6571 times.
✓ Branch 1 taken 6883 times.
✓ Branch 2 taken 6307 times.
✓ Branch 3 taken 264 times.
|
13454 | if (dts != AV_NOPTS_VALUE && ppos) { |
| 466 | int i; | ||
| 467 |
2/2✓ Branch 0 taken 7706 times.
✓ Branch 1 taken 6307 times.
|
14013 | for (i = 0; i < s->nb_streams; i++) { |
| 468 |
2/2✓ Branch 0 taken 6272 times.
✓ Branch 1 taken 1434 times.
|
7706 | if (startcode == s->streams[i]->id && |
| 469 |
1/2✓ Branch 0 taken 6272 times.
✗ Branch 1 not taken.
|
6272 | (s->pb->seekable & AVIO_SEEKABLE_NORMAL) /* index useless on streams anyway */) { |
| 470 | 6272 | ff_reduce_index(s, i); | |
| 471 | 6272 | av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, | |
| 472 | AVINDEX_KEYFRAME /* FIXME keyframe? */); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | 13454 | *pstart_code = startcode; | |
| 478 | 13454 | *ppts = pts; | |
| 479 | 13454 | *pdts = dts; | |
| 480 | 13454 | return len; | |
| 481 | } | ||
| 482 | |||
| 483 | 12261 | static int mpegps_read_packet(AVFormatContext *s, | |
| 484 | AVPacket *pkt) | ||
| 485 | { | ||
| 486 | 12261 | MpegDemuxContext *m = s->priv_data; | |
| 487 | AVStream *st; | ||
| 488 | FFStream *sti; | ||
| 489 | int len, startcode, i, es_type, ret; | ||
| 490 | 12261 | int pcm_dvd = 0; | |
| 491 | 12261 | int pcm_dvda = 0; | |
| 492 | 12261 | int request_probe= 0; | |
| 493 | 12261 | enum AVCodecID codec_id = AV_CODEC_ID_NONE; | |
| 494 | enum AVMediaType type; | ||
| 495 | int64_t pts, dts, dummy_pos; // dummy_pos is needed for the index building to work | ||
| 496 | |||
| 497 | 12742 | redo: | |
| 498 | 12742 | len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); | |
| 499 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 12661 times.
|
12742 | if (len < 0) |
| 500 | 81 | return len; | |
| 501 | |||
| 502 |
4/4✓ Branch 0 taken 12631 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5403 times.
✓ Branch 3 taken 7228 times.
|
12661 | if (startcode >= 0x80 && startcode <= 0xcf) { |
| 503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5403 times.
|
5403 | if (len < 4) |
| 504 | ✗ | goto skip; | |
| 505 | |||
| 506 |
1/2✓ Branch 0 taken 5403 times.
✗ Branch 1 not taken.
|
5403 | if (!m->raw_ac3) { |
| 507 |
3/4✓ Branch 0 taken 5397 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5397 times.
✗ Branch 3 not taken.
|
5403 | if (startcode >= 0xa0 && startcode <= 0xaf) { |
| 508 | uint8_t header[6]; | ||
| 509 | |||
| 510 | /* Classify the LPCM/MLP substream here; its header is | ||
| 511 | * skipped at "found" below, once the stream codec is known. */ | ||
| 512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5397 times.
|
5397 | if (len < 6) |
| 513 | ✗ | goto skip; | |
| 514 | 5397 | ret = ffio_ensure_seekback(s->pb, 6); | |
| 515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5397 times.
|
5397 | if (ret < 0) |
| 516 | ✗ | return ret; | |
| 517 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5397 times.
|
5397 | if (avio_read(s->pb, header, 6) != 6) |
| 518 | ✗ | return AVERROR_INVALIDDATA; | |
| 519 | 5397 | avio_seek(s->pb, -6, SEEK_CUR); | |
| 520 | /* DVD-Video LPCM has the dynamic range control byte here, while | ||
| 521 | * DVD-Audio LPCM and MLP do not. Only substream 0xa0 carries | ||
| 522 | * LPCM in DVD-Audio AOBs, MLP uses substream 0xa1. */ | ||
| 523 | 5397 | pcm_dvd = header[5] == 0x80; | |
| 524 |
3/4✓ Branch 0 taken 5397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 5325 times.
|
5397 | pcm_dvda = startcode == 0xa0 && !pcm_dvd; |
| 525 | } else { | ||
| 526 | /* audio: skip header */ | ||
| 527 | 6 | avio_skip(s->pb, 3); | |
| 528 | 6 | len -= 3; | |
| 529 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6 | if (startcode >= 0xb0 && startcode <= 0xbf) { |
| 530 | /* MLP/TrueHD audio has a 4-byte header */ | ||
| 531 | ✗ | avio_r8(s->pb); | |
| 532 | ✗ | len--; | |
| 533 | } | ||
| 534 | } | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | /* now find stream */ | ||
| 539 |
2/2✓ Branch 0 taken 16366 times.
✓ Branch 1 taken 40 times.
|
16406 | for (i = 0; i < s->nb_streams; i++) { |
| 540 | 16366 | st = s->streams[i]; | |
| 541 |
2/2✓ Branch 0 taken 12621 times.
✓ Branch 1 taken 3745 times.
|
16366 | if (st->id == startcode) |
| 542 | 12621 | goto found; | |
| 543 | } | ||
| 544 | |||
| 545 | 40 | es_type = m->psm_es_type[startcode & 0xff]; | |
| 546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (es_type == STREAM_TYPE_VIDEO_MPEG1) { |
| 547 | ✗ | codec_id = AV_CODEC_ID_MPEG2VIDEO; | |
| 548 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 549 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_VIDEO_MPEG2) { |
| 550 | ✗ | codec_id = AV_CODEC_ID_MPEG2VIDEO; | |
| 551 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 552 |
2/4✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_AUDIO_MPEG1 || |
| 553 | es_type == STREAM_TYPE_AUDIO_MPEG2) { | ||
| 554 | ✗ | codec_id = AV_CODEC_ID_MP3; | |
| 555 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 556 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_AUDIO_AAC) { |
| 557 | ✗ | codec_id = AV_CODEC_ID_AAC; | |
| 558 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_VIDEO_MPEG4) { |
| 560 | ✗ | codec_id = AV_CODEC_ID_MPEG4; | |
| 561 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 562 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_VIDEO_H264) { |
| 563 | ✗ | codec_id = AV_CODEC_ID_H264; | |
| 564 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_VIDEO_HEVC) { |
| 566 | ✗ | codec_id = AV_CODEC_ID_HEVC; | |
| 567 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_VIDEO_VVC) { |
| 569 | ✗ | codec_id = AV_CODEC_ID_VVC; | |
| 570 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 571 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == STREAM_TYPE_AUDIO_AC3) { |
| 572 | ✗ | codec_id = AV_CODEC_ID_AC3; | |
| 573 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 574 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | } else if (es_type == 0x90) { |
| 575 | ✗ | codec_id = AV_CODEC_ID_PCM_ALAW; | |
| 576 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 577 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
40 | } else if (m->imkh_cctv && es_type == 0x91) { |
| 578 | ✗ | codec_id = AV_CODEC_ID_PCM_MULAW; | |
| 579 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 580 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
40 | } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { |
| 581 | static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; | ||
| 582 | unsigned char buf[8]; | ||
| 583 | |||
| 584 | 13 | ret = ffio_read_size(s->pb, buf, 8); | |
| 585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (ret < 0) |
| 586 | ✗ | return ret; | |
| 587 | 13 | avio_seek(s->pb, -8, SEEK_CUR); | |
| 588 |
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)) |
| 589 | 2 | codec_id = AV_CODEC_ID_CAVS; | |
| 590 | else | ||
| 591 | 11 | request_probe= 1; | |
| 592 | 13 | type = AVMEDIA_TYPE_VIDEO; | |
| 593 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 24 times.
|
27 | } else if (startcode == PRIVATE_STREAM_2) { |
| 594 | 3 | type = AVMEDIA_TYPE_DATA; | |
| 595 | 3 | codec_id = AV_CODEC_ID_DVD_NAV; | |
| 596 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
24 | } else if (startcode >= 0x1c0 && startcode <= 0x1df) { |
| 597 | 7 | type = AVMEDIA_TYPE_AUDIO; | |
| 598 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (m->sofdec > 0) { |
| 599 | ✗ | codec_id = AV_CODEC_ID_ADPCM_ADX; | |
| 600 | // Auto-detect AC-3 | ||
| 601 | ✗ | request_probe = 50; | |
| 602 |
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) { |
| 603 | ✗ | codec_id = AV_CODEC_ID_PCM_ALAW; | |
| 604 | ✗ | request_probe = 50; | |
| 605 | } else { | ||
| 606 | 7 | codec_id = AV_CODEC_ID_MP2; | |
| 607 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (m->imkh_cctv) |
| 608 | ✗ | request_probe = 25; | |
| 609 | } | ||
| 610 |
4/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 14 times.
|
17 | } else if (startcode >= 0x80 && startcode <= 0x87) { |
| 611 | 1 | type = AVMEDIA_TYPE_AUDIO; | |
| 612 | 1 | codec_id = AV_CODEC_ID_AC3; | |
| 613 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
16 | } else if ((startcode >= 0x88 && startcode <= 0x8f) || |
| 614 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
16 | (startcode >= 0x98 && startcode <= 0x9f)) { |
| 615 | /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ | ||
| 616 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 617 | ✗ | codec_id = AV_CODEC_ID_DTS; | |
| 618 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
16 | } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
| 619 | 14 | type = AVMEDIA_TYPE_AUDIO; | |
| 620 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
|
14 | if (pcm_dvda) { |
| 621 | 1 | codec_id = AV_CODEC_ID_PCM_DVDA; | |
| 622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | } else if (!pcm_dvd) { |
| 623 | ✗ | codec_id = AV_CODEC_ID_MLP; | |
| 624 | } else { | ||
| 625 | 13 | codec_id = AV_CODEC_ID_PCM_DVD; | |
| 626 | } | ||
| 627 |
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) { |
| 628 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 629 | ✗ | codec_id = AV_CODEC_ID_TRUEHD; | |
| 630 |
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) { |
| 631 | /* Used for both AC-3 and E-AC-3 in EVOB files */ | ||
| 632 | ✗ | type = AVMEDIA_TYPE_AUDIO; | |
| 633 | ✗ | codec_id = AV_CODEC_ID_AC3; | |
| 634 |
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) { |
| 635 | 2 | type = AVMEDIA_TYPE_SUBTITLE; | |
| 636 | 2 | codec_id = AV_CODEC_ID_DVD_SUBTITLE; | |
| 637 | ✗ | } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { | |
| 638 | ✗ | type = AVMEDIA_TYPE_VIDEO; | |
| 639 | ✗ | codec_id = AV_CODEC_ID_VC1; | |
| 640 | ✗ | } else if (startcode == 0x69 || startcode == 0x49) { | |
| 641 | ✗ | type = AVMEDIA_TYPE_SUBTITLE; | |
| 642 | ✗ | codec_id = AV_CODEC_ID_IVTV_VBI; | |
| 643 | } else { | ||
| 644 | ✗ | skip: | |
| 645 | /* skip packet */ | ||
| 646 | 481 | avio_skip(s->pb, len); | |
| 647 | 481 | goto redo; | |
| 648 | } | ||
| 649 | /* no stream found: add a new stream */ | ||
| 650 | 40 | st = avformat_new_stream(s, NULL); | |
| 651 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (!st) |
| 652 | ✗ | goto skip; | |
| 653 | 40 | sti = ffstream(st); | |
| 654 | 40 | st->id = startcode; | |
| 655 | 40 | st->codecpar->codec_type = type; | |
| 656 | 40 | st->codecpar->codec_id = codec_id; | |
| 657 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | if ( st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW |
| 658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) { |
| 659 | ✗ | st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | |
| 660 | ✗ | st->codecpar->sample_rate = 8000; | |
| 661 | } | ||
| 662 | 40 | sti->request_probe = request_probe; | |
| 663 | 40 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
| 664 | |||
| 665 | 12661 | found: | |
| 666 |
2/2✓ Branch 0 taken 481 times.
✓ Branch 1 taken 12180 times.
|
12661 | if (st->discard >= AVDISCARD_ALL) |
| 667 | 481 | goto skip; | |
| 668 |
5/6✓ Branch 0 taken 12154 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 5397 times.
✓ Branch 3 taken 6757 times.
✓ Branch 4 taken 5397 times.
✗ Branch 5 not taken.
|
12180 | if (startcode >= 0xa0 && startcode <= 0xaf && !m->raw_ac3) { |
| 669 | 5397 | int header_len = 0; | |
| 670 | /* Skip the substream headers of codecs whose decoders do not expect | ||
| 671 | * them. AV_CODEC_ID_PCM_DVDA parses the header from the packet. */ | ||
| 672 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5397 times.
|
5397 | if (st->codecpar->codec_id == AV_CODEC_ID_MLP) { |
| 673 | /* 3-byte substream header + 6-byte MLP header */ | ||
| 674 | ✗ | header_len = 9; | |
| 675 |
2/2✓ Branch 0 taken 5325 times.
✓ Branch 1 taken 72 times.
|
5397 | } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) { |
| 676 | 5325 | header_len = 3; | |
| 677 | } | ||
| 678 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5397 times.
|
5397 | if (len <= header_len) |
| 679 | ✗ | goto skip; | |
| 680 | 5397 | avio_skip(s->pb, header_len); | |
| 681 | 5397 | len -= header_len; | |
| 682 |
3/4✓ Branch 0 taken 6757 times.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6757 times.
|
6783 | } else if (startcode >= 0xa0 && startcode <= 0xaf && |
| 683 | ✗ | st->codecpar->codec_id == AV_CODEC_ID_MLP) { | |
| 684 | ✗ | if (len < 6) | |
| 685 | ✗ | goto skip; | |
| 686 | ✗ | avio_skip(s->pb, 6); | |
| 687 | ✗ | len -= 6; | |
| 688 | } | ||
| 689 | 12180 | ret = av_get_packet(s->pb, pkt, len); | |
| 690 | |||
| 691 | 12180 | pkt->pts = pts; | |
| 692 | 12180 | pkt->dts = dts; | |
| 693 | 12180 | pkt->pos = dummy_pos; | |
| 694 | 12180 | pkt->stream_index = st->index; | |
| 695 | |||
| 696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12180 times.
|
12180 | if (s->debug & AV_FDEBUG_TS) |
| 697 | ✗ | av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", | |
| 698 | ✗ | pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, | |
| 699 | pkt->size); | ||
| 700 | |||
| 701 | 12180 | return (ret < 0) ? ret : 0; | |
| 702 | } | ||
| 703 | |||
| 704 | 91 | static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, | |
| 705 | int64_t *ppos, int64_t pos_limit) | ||
| 706 | { | ||
| 707 | int len, startcode; | ||
| 708 | int64_t pos, pts, dts; | ||
| 709 | |||
| 710 | 91 | pos = *ppos; | |
| 711 |
1/2✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
|
91 | if (avio_seek(s->pb, pos, SEEK_SET) < 0) |
| 712 | ✗ | return AV_NOPTS_VALUE; | |
| 713 | |||
| 714 | for (;;) { | ||
| 715 | 451 | len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); | |
| 716 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 406 times.
|
451 | if (len < 0) { |
| 717 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (s->debug & AV_FDEBUG_TS) |
| 718 | ✗ | av_log(s, AV_LOG_DEBUG, "none (ret=%d)\n", len); | |
| 719 | 45 | return AV_NOPTS_VALUE; | |
| 720 | } | ||
| 721 |
2/2✓ Branch 0 taken 323 times.
✓ Branch 1 taken 83 times.
|
406 | if (startcode == s->streams[stream_index]->id && |
| 722 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 277 times.
|
323 | dts != AV_NOPTS_VALUE) { |
| 723 | 46 | break; | |
| 724 | } | ||
| 725 | 360 | avio_skip(s->pb, len); | |
| 726 | } | ||
| 727 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (s->debug & AV_FDEBUG_TS) |
| 728 | ✗ | av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", | |
| 729 | pos, dts, dts / 90000.0); | ||
| 730 | 46 | *ppos = pos; | |
| 731 | 46 | return dts; | |
| 732 | } | ||
| 733 | |||
| 734 | const FFInputFormat ff_mpegps_demuxer = { | ||
| 735 | .p.name = "mpeg", | ||
| 736 | .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"), | ||
| 737 | .p.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||
| 738 | .priv_data_size = sizeof(MpegDemuxContext), | ||
| 739 | .read_probe = mpegps_probe, | ||
| 740 | .read_header = mpegps_read_header, | ||
| 741 | .read_packet = mpegps_read_packet, | ||
| 742 | .read_timestamp = mpegps_read_dts, | ||
| 743 | }; | ||
| 744 | |||
| 745 | #if CONFIG_VOBSUB_DEMUXER | ||
| 746 | |||
| 747 | #include "subtitles.h" | ||
| 748 | #include "libavutil/avassert.h" | ||
| 749 | #include "libavutil/bprint.h" | ||
| 750 | #include "libavutil/opt.h" | ||
| 751 | |||
| 752 | #define REF_STRING "# VobSub index file," | ||
| 753 | #define MAX_LINE_SIZE 2048 | ||
| 754 | |||
| 755 | typedef struct VobSubDemuxContext { | ||
| 756 | const AVClass *class; | ||
| 757 | AVFormatContext *sub_ctx; | ||
| 758 | FFDemuxSubtitlesQueue q[32]; | ||
| 759 | char *sub_name; | ||
| 760 | } VobSubDemuxContext; | ||
| 761 | |||
| 762 | 7957 | static int vobsub_probe(const AVProbeData *p) | |
| 763 | { | ||
| 764 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7955 times.
|
7957 | if (!strncmp(p->buf, REF_STRING, sizeof(REF_STRING) - 1)) |
| 765 | 2 | return AVPROBE_SCORE_MAX; | |
| 766 | 7955 | return 0; | |
| 767 | } | ||
| 768 | |||
| 769 | 3 | static int vobsub_read_close(AVFormatContext *s) | |
| 770 | { | ||
| 771 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 772 | int i; | ||
| 773 | |||
| 774 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) |
| 775 | 3 | ff_subtitles_queue_clean(&vobsub->q[i]); | |
| 776 | 3 | avformat_close_input(&vobsub->sub_ctx); | |
| 777 | 3 | return 0; | |
| 778 | } | ||
| 779 | |||
| 780 | 3 | static int vobsub_read_header(AVFormatContext *s) | |
| 781 | { | ||
| 782 | 3 | int i, ret = 0, header_parsed = 0, langidx = 0; | |
| 783 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 784 | const AVInputFormat *iformat; | ||
| 785 | size_t fname_len; | ||
| 786 | AVBPrint header; | ||
| 787 | 3 | int64_t delay = 0; | |
| 788 | 3 | AVStream *st = NULL; | |
| 789 | 3 | int stream_id = -1; | |
| 790 | 3 | char id[64] = {0}; | |
| 791 | 3 | char alt[MAX_LINE_SIZE] = {0}; | |
| 792 | |||
| 793 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!vobsub->sub_name) { |
| 794 | char *ext; | ||
| 795 | 3 | vobsub->sub_name = av_strdup(s->url); | |
| 796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_name) { |
| 797 | ✗ | return AVERROR(ENOMEM); | |
| 798 | } | ||
| 799 | |||
| 800 | 3 | fname_len = strlen(vobsub->sub_name); | |
| 801 | 3 | ext = vobsub->sub_name - 3 + fname_len; | |
| 802 |
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) != '.') { |
| 803 | ✗ | av_log(s, AV_LOG_ERROR, "The input index filename is too short " | |
| 804 | "to guess the associated .SUB file\n"); | ||
| 805 | ✗ | return AVERROR_INVALIDDATA; | |
| 806 | } | ||
| 807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); |
| 808 | 3 | av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); | |
| 809 | } | ||
| 810 | |||
| 811 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!(iformat = av_find_input_format("mpeg"))) { |
| 812 | ✗ | return AVERROR_DEMUXER_NOT_FOUND; | |
| 813 | } | ||
| 814 | |||
| 815 | 3 | vobsub->sub_ctx = avformat_alloc_context(); | |
| 816 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_ctx) { |
| 817 | ✗ | return AVERROR(ENOMEM); | |
| 818 | } | ||
| 819 | |||
| 820 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0) |
| 821 | ✗ | return ret; | |
| 822 | |||
| 823 | 3 | ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL); | |
| 824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
| 825 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to open %s as MPEG subtitles\n", vobsub->sub_name); | |
| 826 | ✗ | return ret; | |
| 827 | } | ||
| 828 | |||
| 829 | 3 | av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); | |
| 830 | |||
| 831 |
1/2✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
|
189 | while (!avio_feof(s->pb)) { |
| 832 | char line[MAX_LINE_SIZE]; | ||
| 833 | 189 | int len = ff_get_line(s->pb, line, sizeof(line)); | |
| 834 | |||
| 835 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 186 times.
|
189 | if (!len) |
| 836 | 3 | break; | |
| 837 | |||
| 838 | 186 | line[strcspn(line, "\r\n")] = 0; | |
| 839 | |||
| 840 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 183 times.
|
186 | if (!strncmp(line, "id:", 3)) { |
| 841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(line, "id: %63[^,], index: %u", id, &stream_id) != 2) { |
| 842 | ✗ | av_log(s, AV_LOG_WARNING, "Unable to parse index line '%s', " | |
| 843 | "assuming 'id: und, index: 0'\n", line); | ||
| 844 | ✗ | strcpy(id, "und"); | |
| 845 | ✗ | stream_id = 0; | |
| 846 | } | ||
| 847 | |||
| 848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (stream_id >= FF_ARRAY_ELEMS(vobsub->q)) { |
| 849 | ✗ | av_log(s, AV_LOG_ERROR, "Maximum number of subtitles streams reached\n"); | |
| 850 | ✗ | ret = AVERROR(EINVAL); | |
| 851 | ✗ | goto end; | |
| 852 | } | ||
| 853 | |||
| 854 | 3 | header_parsed = 1; | |
| 855 | 3 | alt[0] = '\0'; | |
| 856 | /* We do not create the stream immediately to avoid adding empty | ||
| 857 | * streams. See the following timestamp entry. */ | ||
| 858 | |||
| 859 | 3 | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); | |
| 860 | |||
| 861 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 42 times.
|
183 | } else if (!strncmp(line, "timestamp:", 10)) { |
| 862 | AVPacket *sub; | ||
| 863 | int hh, mm, ss, ms; | ||
| 864 | int64_t pos, timestamp; | ||
| 865 | 141 | const char *p = line + 10; | |
| 866 | |||
| 867 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (stream_id == -1) { |
| 868 | ✗ | av_log(s, AV_LOG_ERROR, "Timestamp declared before any stream\n"); | |
| 869 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 870 | ✗ | goto end; | |
| 871 | } | ||
| 872 | |||
| 873 |
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) { |
| 874 | 3 | st = NULL; | |
| 875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | for (i = 0; i < s->nb_streams; i++) { |
| 876 | ✗ | if (s->streams[i]->id == stream_id) { | |
| 877 | ✗ | st = s->streams[i]; | |
| 878 | ✗ | break; | |
| 879 | } | ||
| 880 | } | ||
| 881 | } | ||
| 882 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 138 times.
|
141 | if (!st) { |
| 883 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (s->nb_streams >= FF_ARRAY_ELEMS(vobsub->q)) { |
| 884 | ✗ | av_log(s, AV_LOG_ERROR, "Maximum number of subtitle streams reached\n"); | |
| 885 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 886 | ✗ | goto end; | |
| 887 | } | ||
| 888 | 3 | st = avformat_new_stream(s, NULL); | |
| 889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!st) { |
| 890 | ✗ | ret = AVERROR(ENOMEM); | |
| 891 | ✗ | goto end; | |
| 892 | } | ||
| 893 | 3 | st->id = stream_id; | |
| 894 | 3 | st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
| 895 | 3 | st->codecpar->codec_id = AV_CODEC_ID_DVD_SUBTITLE; | |
| 896 | 3 | avpriv_set_pts_info(st, 64, 1, 1000); | |
| 897 | 3 | av_dict_set(&st->metadata, "language", id, 0); | |
| 898 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (alt[0]) |
| 899 | ✗ | av_dict_set(&st->metadata, "title", alt, 0); | |
| 900 | } | ||
| 901 | |||
| 902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (sscanf(p, "%02d:%02d:%02d:%03d, filepos: %"SCNx64, |
| 903 | &hh, &mm, &ss, &ms, &pos) != 5) { | ||
| 904 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to parse timestamp line '%s', " | |
| 905 | "abort parsing\n", line); | ||
| 906 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 907 | ✗ | goto end; | |
| 908 | } | ||
| 909 | 141 | timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay; | |
| 910 | 141 | timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base); | |
| 911 | |||
| 912 | 141 | sub = ff_subtitles_queue_insert(&vobsub->q[st->index], "", 0, 0); | |
| 913 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (!sub) { |
| 914 | ✗ | ret = AVERROR(ENOMEM); | |
| 915 | ✗ | goto end; | |
| 916 | } | ||
| 917 | 141 | sub->pos = pos; | |
| 918 | 141 | sub->pts = timestamp; | |
| 919 | 141 | sub->stream_index = st->index; | |
| 920 | |||
| 921 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "alt:", 4)) { |
| 922 | ✗ | const char *p = line + 4; | |
| 923 | |||
| 924 | ✗ | while (*p == ' ') | |
| 925 | ✗ | p++; | |
| 926 | ✗ | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] name=%s\n", stream_id, p); | |
| 927 | ✗ | av_strlcpy(alt, p, sizeof(alt)); | |
| 928 | ✗ | header_parsed = 1; | |
| 929 | |||
| 930 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "delay:", 6)) { |
| 931 | ✗ | int sign = 1, hh = 0, mm = 0, ss = 0, ms = 0; | |
| 932 | ✗ | const char *p = line + 6; | |
| 933 | |||
| 934 | ✗ | while (*p == ' ') | |
| 935 | ✗ | p++; | |
| 936 | ✗ | if (*p == '-' || *p == '+') { | |
| 937 | ✗ | sign = *p == '-' ? -1 : 1; | |
| 938 | ✗ | p++; | |
| 939 | } | ||
| 940 | ✗ | sscanf(p, "%d:%d:%d:%d", &hh, &mm, &ss, &ms); | |
| 941 | ✗ | delay = ((hh*3600LL + mm*60LL + ss) * 1000LL + ms) * sign; | |
| 942 | |||
| 943 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 39 times.
|
42 | } else if (!strncmp(line, "langidx:", 8)) { |
| 944 | 3 | const char *p = line + 8; | |
| 945 | |||
| 946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(p, "%d", &langidx) != 1) |
| 947 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid langidx specified\n"); | |
| 948 | |||
| 949 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | } else if (!header_parsed) { |
| 950 |
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] != '#') |
| 951 | 9 | av_bprintf(&header, "%s\n", line); | |
| 952 | } | ||
| 953 | } | ||
| 954 | |||
| 955 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (langidx < s->nb_streams) |
| 956 | 3 | s->streams[langidx]->disposition |= AV_DISPOSITION_DEFAULT; | |
| 957 | |||
| 958 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
| 959 | 3 | vobsub->q[i].sort = SUB_SORT_POS_TS; | |
| 960 | 3 | vobsub->q[i].keep_duplicates = 1; | |
| 961 | 3 | ff_subtitles_queue_finalize(s, &vobsub->q[i]); | |
| 962 | } | ||
| 963 | |||
| 964 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!av_bprint_is_complete(&header)) { |
| 965 | ✗ | ret = AVERROR(ENOMEM); | |
| 966 | ✗ | goto end; | |
| 967 | } | ||
| 968 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
| 969 | 3 | AVCodecParameters *par = s->streams[i]->codecpar; | |
| 970 | 3 | ret = ff_alloc_extradata(par, header.len); | |
| 971 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
| 972 | ✗ | goto end; | |
| 973 | } | ||
| 974 | 3 | memcpy(par->extradata, header.str, header.len); | |
| 975 | } | ||
| 976 | 3 | end: | |
| 977 | 3 | av_bprint_finalize(&header, NULL); | |
| 978 | 3 | return ret; | |
| 979 | } | ||
| 980 | |||
| 981 | 141 | static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 982 | { | ||
| 983 | 141 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 984 | FFDemuxSubtitlesQueue *q; | ||
| 985 | 141 | AVIOContext *pb = vobsub->sub_ctx->pb; | |
| 986 | 141 | int ret, psize, total_read = 0, i; | |
| 987 | |||
| 988 | 141 | int64_t min_ts = INT64_MAX; | |
| 989 | 141 | int sid = 0; | |
| 990 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 141 times.
|
282 | for (i = 0; i < s->nb_streams; i++) { |
| 991 | 141 | FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i]; | |
| 992 | int64_t ts; | ||
| 993 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | av_assert0(tmpq->nb_subs); |
| 994 | |||
| 995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (tmpq->current_sub_idx >= tmpq->nb_subs) |
| 996 | ✗ | continue; | |
| 997 | |||
| 998 | 141 | ts = tmpq->subs[tmpq->current_sub_idx]->pts; | |
| 999 |
1/2✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
|
141 | if (ts < min_ts) { |
| 1000 | 141 | min_ts = ts; | |
| 1001 | 141 | sid = i; | |
| 1002 | } | ||
| 1003 | } | ||
| 1004 | 141 | q = &vobsub->q[sid]; | |
| 1005 | /* The returned packet will have size zero, | ||
| 1006 | * so that it can be directly used with av_grow_packet. */ | ||
| 1007 | 141 | ret = ff_subtitles_queue_read_packet(q, pkt); | |
| 1008 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (ret < 0) |
| 1009 | ✗ | return ret; | |
| 1010 | |||
| 1011 | /* compute maximum packet size using the next packet position. This is | ||
| 1012 | * useful when the len in the header is non-sense */ | ||
| 1013 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 3 times.
|
141 | if (q->current_sub_idx < q->nb_subs) { |
| 1014 | 138 | psize = q->subs[q->current_sub_idx]->pos - pkt->pos; | |
| 1015 | } else { | ||
| 1016 | 3 | int64_t fsize = avio_size(pb); | |
| 1017 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | psize = fsize < 0 ? 0xffff : fsize - pkt->pos; |
| 1018 | } | ||
| 1019 | |||
| 1020 | 141 | avio_seek(pb, pkt->pos, SEEK_SET); | |
| 1021 | |||
| 1022 | do { | ||
| 1023 | int n, to_read, startcode; | ||
| 1024 | int64_t pts, dts; | ||
| 1025 | 393 | int64_t old_pos = avio_tell(pb), new_pos; | |
| 1026 | int pkt_size; | ||
| 1027 | |||
| 1028 | 393 | ret = mpegps_read_pes_header(vobsub->sub_ctx, NULL, &startcode, &pts, &dts); | |
| 1029 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 387 times.
|
393 | if (ret < 0) { |
| 1030 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (pkt->size) // raise packet even if incomplete |
| 1031 | 129 | break; | |
| 1032 | 3 | return ret; | |
| 1033 | } | ||
| 1034 | 387 | to_read = ret & 0xffff; | |
| 1035 | 387 | new_pos = avio_tell(pb); | |
| 1036 | 387 | pkt_size = ret + (new_pos - old_pos); | |
| 1037 | |||
| 1038 | /* this prevents reads above the current packet */ | ||
| 1039 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 261 times.
|
387 | if (total_read + pkt_size > psize) |
| 1040 | 126 | break; | |
| 1041 | 261 | total_read += pkt_size; | |
| 1042 | |||
| 1043 | /* the current chunk doesn't match the stream index (unlikely) */ | ||
| 1044 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if ((startcode & 0x1f) != s->streams[pkt->stream_index]->id) |
| 1045 | ✗ | break; | |
| 1046 | |||
| 1047 | 261 | ret = av_grow_packet(pkt, to_read); | |
| 1048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (ret < 0) |
| 1049 | ✗ | return ret; | |
| 1050 | |||
| 1051 | 261 | n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read); | |
| 1052 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (n < to_read) |
| 1053 | ✗ | pkt->size -= to_read - n; | |
| 1054 |
2/2✓ Branch 0 taken 252 times.
✓ Branch 1 taken 9 times.
|
261 | } while (total_read < psize); |
| 1055 | |||
| 1056 | 138 | return 0; | |
| 1057 | } | ||
| 1058 | |||
| 1059 | 1 | static int vobsub_read_seek(AVFormatContext *s, int stream_index, | |
| 1060 | int64_t min_ts, int64_t ts, int64_t max_ts, int flags) | ||
| 1061 | { | ||
| 1062 | 1 | VobSubDemuxContext *vobsub = s->priv_data; | |
| 1063 | |||
| 1064 | /* Rescale requested timestamps based on the first stream (timebase is the | ||
| 1065 | * same for all subtitles stream within a .idx/.sub). Rescaling is done just | ||
| 1066 | * like in avformat_seek_file(). */ | ||
| 1067 |
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) { |
| 1068 | ✗ | int i, ret = 0; | |
| 1069 | ✗ | AVRational time_base = s->streams[0]->time_base; | |
| 1070 | ✗ | ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base); | |
| 1071 | ✗ | min_ts = av_rescale_rnd(min_ts, time_base.den, | |
| 1072 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
| 1073 | AV_ROUND_UP | AV_ROUND_PASS_MINMAX); | ||
| 1074 | ✗ | max_ts = av_rescale_rnd(max_ts, time_base.den, | |
| 1075 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
| 1076 | AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX); | ||
| 1077 | ✗ | for (i = 0; i < s->nb_streams; i++) { | |
| 1078 | ✗ | int r = ff_subtitles_queue_seek(&vobsub->q[i], s, stream_index, | |
| 1079 | min_ts, ts, max_ts, flags); | ||
| 1080 | ✗ | if (r < 0) | |
| 1081 | ✗ | ret = r; | |
| 1082 | } | ||
| 1083 | ✗ | return ret; | |
| 1084 | } | ||
| 1085 | |||
| 1086 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (stream_index == -1) // only 1 stream |
| 1087 | ✗ | stream_index = 0; | |
| 1088 | 1 | return ff_subtitles_queue_seek(&vobsub->q[stream_index], s, stream_index, | |
| 1089 | min_ts, ts, max_ts, flags); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static const AVOption options[] = { | ||
| 1093 | { "sub_name", "URI for .sub file", offsetof(VobSubDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 1094 | { NULL } | ||
| 1095 | }; | ||
| 1096 | |||
| 1097 | static const AVClass vobsub_demuxer_class = { | ||
| 1098 | .class_name = "vobsub", | ||
| 1099 | .item_name = av_default_item_name, | ||
| 1100 | .option = options, | ||
| 1101 | .version = LIBAVUTIL_VERSION_INT, | ||
| 1102 | }; | ||
| 1103 | |||
| 1104 | const FFInputFormat ff_vobsub_demuxer = { | ||
| 1105 | .p.name = "vobsub", | ||
| 1106 | .p.long_name = NULL_IF_CONFIG_SMALL("VobSub subtitle format"), | ||
| 1107 | .p.flags = AVFMT_SHOW_IDS, | ||
| 1108 | .p.extensions = "idx", | ||
| 1109 | .p.priv_class = &vobsub_demuxer_class, | ||
| 1110 | .priv_data_size = sizeof(VobSubDemuxContext), | ||
| 1111 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
| 1112 | .read_probe = vobsub_probe, | ||
| 1113 | .read_header = vobsub_read_header, | ||
| 1114 | .read_packet = vobsub_read_packet, | ||
| 1115 | .read_seek2 = vobsub_read_seek, | ||
| 1116 | .read_close = vobsub_read_close, | ||
| 1117 | }; | ||
| 1118 | #endif | ||
| 1119 |