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 | 48548 | static int check_pes(const uint8_t *p, const uint8_t *end) | |
38 | { | ||
39 | int pes1; | ||
40 | 100508 | int pes2 = (p[3] & 0xC0) == 0x80 && | |
41 |
4/4✓ Branch 0 taken 3412 times.
✓ Branch 1 taken 45136 times.
✓ Branch 2 taken 2843 times.
✓ Branch 3 taken 569 times.
|
51391 | (p[4] & 0xC0) != 0x40 && |
42 |
2/2✓ Branch 0 taken 1224 times.
✓ Branch 1 taken 1619 times.
|
2843 | ((p[4] & 0xC0) == 0x00 || |
43 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 1102 times.
|
1224 | (p[4] & 0xC0) >> 2 == (p[6] & 0xF0)); |
44 | |||
45 |
4/4✓ Branch 0 taken 50724 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 2244 times.
✓ Branch 3 taken 48480 times.
|
50792 | for (p += 3; p < end && *p == 0xFF; p++) ; |
46 |
2/2✓ Branch 0 taken 4475 times.
✓ Branch 1 taken 44073 times.
|
48548 | if ((*p & 0xC0) == 0x40) |
47 | 4475 | p += 2; | |
48 | |||
49 |
2/2✓ Branch 0 taken 1479 times.
✓ Branch 1 taken 47069 times.
|
48548 | if ((*p & 0xF0) == 0x20) |
50 | 1479 | pes1 = p[0] & p[2] & p[4] & 1; | |
51 |
2/2✓ Branch 0 taken 1184 times.
✓ Branch 1 taken 45885 times.
|
47069 | else if ((*p & 0xF0) == 0x30) |
52 | 1184 | pes1 = p[0] & p[2] & p[4] & p[5] & p[7] & p[9] & 1; | |
53 | else | ||
54 | 45885 | pes1 = *p == 0x0F; | |
55 | |||
56 |
4/4✓ Branch 0 taken 48218 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 1741 times.
✓ Branch 3 taken 46477 times.
|
48548 | return pes1 || pes2; |
57 | } | ||
58 | |||
59 | 48867 | static int check_pack_header(const uint8_t *buf) | |
60 | { | ||
61 |
4/4✓ Branch 0 taken 41943 times.
✓ Branch 1 taken 6924 times.
✓ Branch 2 taken 2742 times.
✓ Branch 3 taken 39201 times.
|
48867 | return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20; |
62 | } | ||
63 | |||
64 | 7186 | static int mpegps_probe(const AVProbeData *p) | |
65 | { | ||
66 | 7186 | uint32_t code = -1; | |
67 | int i; | ||
68 | 7186 | int sys = 0, pspack = 0, priv1 = 0, vid = 0; | |
69 | 7186 | int audio = 0, invalid = 0, score = 0; | |
70 | 7186 | int endpes = 0; | |
71 | |||
72 |
2/2✓ Branch 0 taken 375197406 times.
✓ Branch 1 taken 7186 times.
|
375204592 | for (i = 0; i < p->buf_size; i++) { |
73 | 375197406 | code = (code << 8) + p->buf[i]; | |
74 |
2/2✓ Branch 0 taken 48867 times.
✓ Branch 1 taken 375148539 times.
|
375197406 | if ((code & 0xffffff00) == 0x100) { |
75 | 48867 | int len = p->buf[i + 1] << 8 | p->buf[i + 2]; | |
76 |
4/4✓ Branch 0 taken 48548 times.
✓ Branch 1 taken 319 times.
✓ Branch 3 taken 2071 times.
✓ Branch 4 taken 46477 times.
|
48867 | int pes = endpes <= i && check_pes(p->buf + i, p->buf + p->buf_size); |
77 | 48867 | int pack = check_pack_header(p->buf + i); | |
78 | |||
79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48867 times.
|
48867 | if (len > INT_MAX - i) |
80 | ✗ | break; | |
81 | |||
82 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 48824 times.
|
48867 | if (code == SYSTEM_HEADER_START_CODE) |
83 | 43 | sys++; | |
84 |
4/4✓ Branch 0 taken 78 times.
✓ Branch 1 taken 48746 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 5 times.
|
48824 | else if (code == PACK_START_CODE && pack) |
85 | 73 | pspack++; | |
86 |
4/4✓ Branch 0 taken 915 times.
✓ Branch 1 taken 47836 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 833 times.
|
48751 | else if ((code & 0xf0) == VIDEO_ID && pes) { |
87 | 82 | endpes = i + len; | |
88 | 82 | vid++; | |
89 | } | ||
90 | // skip pes payload to avoid start code emulation for private | ||
91 | // and audio streams | ||
92 |
4/4✓ Branch 0 taken 1199 times.
✓ Branch 1 taken 47470 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1161 times.
|
48669 | else if ((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} |
93 |
4/4✓ Branch 0 taken 66 times.
✓ Branch 1 taken 48565 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 11 times.
|
48631 | else if (code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} |
94 |
3/4✓ Branch 0 taken 113 times.
✓ Branch 1 taken 48463 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 113 times.
|
48576 | else if (code == 0x1fd && pes) vid++; //VC1 |
95 | |||
96 |
3/4✓ Branch 0 taken 833 times.
✓ Branch 1 taken 47743 times.
✓ Branch 2 taken 833 times.
✗ Branch 3 not taken.
|
48576 | else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++; |
97 |
3/4✓ Branch 0 taken 1161 times.
✓ Branch 1 taken 46582 times.
✓ Branch 2 taken 1161 times.
✗ Branch 3 not taken.
|
47743 | else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++; |
98 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 46571 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
46582 | else if (code == PRIVATE_STREAM_1 && !pes) invalid++; |
99 | } | ||
100 | } | ||
101 | |||
102 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7165 times.
|
7186 | 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 7152 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1 times.
|
7186 | 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 7139 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 4 times.
|
7153 | 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 51 times.
✓ Branch 1 taken 7092 times.
✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 39 times.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
|
7143 | 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 | 7143 | 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 | 6976 | 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 6054 times.
✓ Branch 1 taken 922 times.
|
6976 | buf[0] = c < 0 ? avio_r8(pb) : c; |
161 | 6976 | ret = avio_read(pb, buf + 1, 4); | |
162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6976 times.
|
6976 | if (ret < 4) |
163 | ✗ | return AV_NOPTS_VALUE; | |
164 | |||
165 | 6976 | return ff_parse_pes_pts(buf); | |
166 | } | ||
167 | |||
168 | 24705 | 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 | 24705 | state = *header_state; | |
175 | 24705 | n = *size_ptr; | |
176 |
1/2✓ Branch 0 taken 314096 times.
✗ Branch 1 not taken.
|
314096 | while (n > 0) { |
177 |
2/2✓ Branch 1 taken 129 times.
✓ Branch 2 taken 313967 times.
|
314096 | if (avio_feof(pb)) |
178 | 129 | break; | |
179 | 313967 | v = avio_r8(pb); | |
180 | 313967 | n--; | |
181 |
2/2✓ Branch 0 taken 24576 times.
✓ Branch 1 taken 289391 times.
|
313967 | if (state == 0x000001) { |
182 | 24576 | state = ((state << 8) | v) & 0xffffff; | |
183 | 24576 | val = state; | |
184 | 24576 | goto found; | |
185 | } | ||
186 | 289391 | state = ((state << 8) | v) & 0xffffff; | |
187 | } | ||
188 | 129 | val = -1; | |
189 | |||
190 | 24705 | found: | |
191 | 24705 | *header_state = state; | |
192 | 24705 | *size_ptr = n; | |
193 | 24705 | 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 | 13393 | static int mpegps_read_pes_header(AVFormatContext *s, | |
237 | int64_t *ppos, int *pstart_code, | ||
238 | int64_t *ppts, int64_t *pdts) | ||
239 | { | ||
240 | 13393 | 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 | 13393 | int64_t last_sync = avio_tell(s->pb); | |
245 | |||
246 | ✗ | error_redo: | |
247 | 13393 | avio_seek(s->pb, last_sync, SEEK_SET); | |
248 | 11312 | redo: | |
249 | /* next start code (should be immediately after) */ | ||
250 | 24705 | m->header_state = 0xff; | |
251 | 24705 | size = MAX_SYNC_SIZE; | |
252 | 24705 | startcode = find_next_start_code(s->pb, &size, &m->header_state); | |
253 | 24705 | last_sync = avio_tell(s->pb); | |
254 |
2/2✓ Branch 0 taken 129 times.
✓ Branch 1 taken 24576 times.
|
24705 | 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 10268 times.
✓ Branch 1 taken 14308 times.
|
24576 | if (startcode == PACK_START_CODE) |
262 | 10268 | goto redo; | |
263 |
2/2✓ Branch 0 taken 193 times.
✓ Branch 1 taken 14115 times.
|
14308 | if (startcode == SYSTEM_HEADER_START_CODE) |
264 | 193 | goto redo; | |
265 |
2/2✓ Branch 0 taken 796 times.
✓ Branch 1 taken 13319 times.
|
14115 | 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 13275 times.
|
13319 | 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 13319 times.
|
13319 | 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 7454 times.
✓ Branch 1 taken 5865 times.
✓ Branch 2 taken 7101 times.
✓ Branch 3 taken 353 times.
✓ Branch 4 taken 7101 times.
✓ Branch 5 taken 5865 times.
✓ Branch 6 taken 55 times.
✗ Branch 7 not taken.
|
13374 | if (!((startcode >= 0x1c0 && startcode <= 0x1df) || |
354 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7101 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 5766 times.
|
12966 | (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 12877 times.
✓ Branch 1 taken 387 times.
|
13264 | if (ppos) { |
360 | 12877 | *ppos = avio_tell(s->pb) - 4; | |
361 | } | ||
362 | 13264 | len = avio_rb16(s->pb); | |
363 | 13264 | pts = | |
364 | 13264 | dts = AV_NOPTS_VALUE; | |
365 |
2/2✓ Branch 0 taken 13220 times.
✓ Branch 1 taken 44 times.
|
13264 | if (startcode != PRIVATE_STREAM_2) |
366 | { | ||
367 | /* stuffing */ | ||
368 | for (;;) { | ||
369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13226 times.
|
13226 | if (len < 1) |
370 | ✗ | goto error_redo; | |
371 | 13226 | c = avio_r8(s->pb); | |
372 | 13226 | len--; | |
373 | /* XXX: for MPEG-1, should test only bit 7 */ | ||
374 |
2/2✓ Branch 0 taken 13220 times.
✓ Branch 1 taken 6 times.
|
13226 | if (c != 0xff) |
375 | 13220 | break; | |
376 | } | ||
377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13220 times.
|
13220 | 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 12298 times.
|
13220 | 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 9750 times.
✓ Branch 1 taken 2548 times.
|
12298 | } else if ((c & 0xc0) == 0x80) { |
392 | /* mpeg 2 PES */ | ||
393 | 9750 | flags = avio_r8(s->pb); | |
394 | 9750 | header_len = avio_r8(s->pb); | |
395 | 9750 | len -= 2; | |
396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9750 times.
|
9750 | if (header_len > len) |
397 | ✗ | goto error_redo; | |
398 | 9750 | len -= header_len; | |
399 |
2/2✓ Branch 0 taken 5585 times.
✓ Branch 1 taken 4165 times.
|
9750 | if (flags & 0x80) { |
400 | 5585 | dts = pts = get_pts(s->pb, -1); | |
401 | 5585 | header_len -= 5; | |
402 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5554 times.
|
5585 | 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 9708 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
|
9750 | 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 9708 times.
|
9750 | 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 9750 times.
|
9750 | if (header_len < 0) |
437 | ✗ | goto error_redo; | |
438 | 9750 | 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 5766 times.
✓ Branch 1 taken 7498 times.
|
13264 | if (startcode == PRIVATE_STREAM_1) { |
444 | 5766 | int ret = ffio_ensure_seekback(s->pb, 2); | |
445 | |||
446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5766 times.
|
5766 | if (ret < 0) |
447 | ✗ | return ret; | |
448 | |||
449 | 5766 | startcode = avio_r8(s->pb); | |
450 | 5766 | m->raw_ac3 = 0; | |
451 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5766 times.
|
5766 | 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 | 5766 | len--; | |
461 | } | ||
462 | } | ||
463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13264 times.
|
13264 | if (len < 0) |
464 | ✗ | goto error_redo; | |
465 |
4/4✓ Branch 0 taken 6507 times.
✓ Branch 1 taken 6757 times.
✓ Branch 2 taken 6243 times.
✓ Branch 3 taken 264 times.
|
13264 | if (dts != AV_NOPTS_VALUE && ppos) { |
466 | int i; | ||
467 |
2/2✓ Branch 0 taken 7623 times.
✓ Branch 1 taken 6243 times.
|
13866 | for (i = 0; i < s->nb_streams; i++) { |
468 |
2/2✓ Branch 0 taken 6209 times.
✓ Branch 1 taken 1414 times.
|
7623 | if (startcode == s->streams[i]->id && |
469 |
1/2✓ Branch 0 taken 6209 times.
✗ Branch 1 not taken.
|
6209 | (s->pb->seekable & AVIO_SEEKABLE_NORMAL) /* index useless on streams anyway */) { |
470 | 6209 | ff_reduce_index(s, i); | |
471 | 6209 | av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, | |
472 | AVINDEX_KEYFRAME /* FIXME keyframe? */); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | 13264 | *pstart_code = startcode; | |
478 | 13264 | *ppts = pts; | |
479 | 13264 | *pdts = dts; | |
480 | 13264 | return len; | |
481 | } | ||
482 | |||
483 | 12068 | static int mpegps_read_packet(AVFormatContext *s, | |
484 | AVPacket *pkt) | ||
485 | { | ||
486 | 12068 | MpegDemuxContext *m = s->priv_data; | |
487 | AVStream *st; | ||
488 | FFStream *sti; | ||
489 | int len, startcode, i, es_type, ret; | ||
490 | 12068 | int pcm_dvd = 0; | |
491 | 12068 | int request_probe= 0; | |
492 | 12068 | 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 | 12549 | redo: | |
497 | 12549 | len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); | |
498 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 12471 times.
|
12549 | if (len < 0) |
499 | 78 | return len; | |
500 | |||
501 |
4/4✓ Branch 0 taken 12441 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5349 times.
✓ Branch 3 taken 7092 times.
|
12471 | if (startcode >= 0x80 && startcode <= 0xcf) { |
502 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5349 times.
|
5349 | if (len < 4) |
503 | ✗ | goto skip; | |
504 | |||
505 |
1/2✓ Branch 0 taken 5349 times.
✗ Branch 1 not taken.
|
5349 | if (!m->raw_ac3) { |
506 | /* audio: skip header */ | ||
507 | 5349 | avio_skip(s->pb, 3); | |
508 | 5349 | len -= 3; | |
509 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5349 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5349 | 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 5343 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5343 times.
✗ Branch 3 not taken.
|
5349 | } else if (startcode >= 0xa0 && startcode <= 0xaf) { |
514 | 5343 | ret = ffio_ensure_seekback(s->pb, 3); | |
515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5343 times.
|
5343 | if (ret < 0) |
516 | ✗ | return ret; | |
517 | 5343 | pcm_dvd = (avio_rb24(s->pb) & 0xFF) == 0x80; | |
518 | 5343 | avio_skip(s->pb, -3); | |
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /* now find stream */ | ||
524 |
2/2✓ Branch 0 taken 16031 times.
✓ Branch 1 taken 39 times.
|
16070 | for (i = 0; i < s->nb_streams; i++) { |
525 | 16031 | st = s->streams[i]; | |
526 |
2/2✓ Branch 0 taken 12432 times.
✓ Branch 1 taken 3599 times.
|
16031 | if (st->id == startcode) |
527 | 12432 | 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 = avio_read(s->pb, buf, 8); | |
570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (ret != 8) |
571 | ✗ | return AVERROR_INVALIDDATA; | |
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 { | ||
624 | ✗ | skip: | |
625 | /* skip packet */ | ||
626 | 481 | avio_skip(s->pb, len); | |
627 | 481 | goto redo; | |
628 | } | ||
629 | /* no stream found: add a new stream */ | ||
630 | 39 | st = avformat_new_stream(s, NULL); | |
631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if (!st) |
632 | ✗ | goto skip; | |
633 | 39 | sti = ffstream(st); | |
634 | 39 | st->id = startcode; | |
635 | 39 | st->codecpar->codec_type = type; | |
636 | 39 | st->codecpar->codec_id = codec_id; | |
637 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | if ( st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW |
638 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) { |
639 | ✗ | st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | |
640 | ✗ | st->codecpar->sample_rate = 8000; | |
641 | } | ||
642 | 39 | sti->request_probe = request_probe; | |
643 | 39 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
644 | |||
645 | 12471 | found: | |
646 |
2/2✓ Branch 0 taken 481 times.
✓ Branch 1 taken 11990 times.
|
12471 | if (st->discard >= AVDISCARD_ALL) |
647 | 481 | goto skip; | |
648 |
4/4✓ Branch 0 taken 11964 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 5343 times.
✓ Branch 3 taken 6621 times.
|
11990 | if (startcode >= 0xa0 && startcode <= 0xaf) { |
649 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5343 times.
|
5343 | if (st->codecpar->codec_id == AV_CODEC_ID_MLP) { |
650 | ✗ | if (len < 6) | |
651 | ✗ | goto skip; | |
652 | ✗ | avio_skip(s->pb, 6); | |
653 | ✗ | len -=6; | |
654 | } | ||
655 | } | ||
656 | 11990 | ret = av_get_packet(s->pb, pkt, len); | |
657 | |||
658 | 11990 | pkt->pts = pts; | |
659 | 11990 | pkt->dts = dts; | |
660 | 11990 | pkt->pos = dummy_pos; | |
661 | 11990 | pkt->stream_index = st->index; | |
662 | |||
663 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11990 times.
|
11990 | if (s->debug & FF_FDEBUG_TS) |
664 | ✗ | av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", | |
665 | ✗ | pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, | |
666 | pkt->size); | ||
667 | |||
668 | 11990 | return (ret < 0) ? ret : 0; | |
669 | } | ||
670 | |||
671 | 91 | static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, | |
672 | int64_t *ppos, int64_t pos_limit) | ||
673 | { | ||
674 | int len, startcode; | ||
675 | int64_t pos, pts, dts; | ||
676 | |||
677 | 91 | pos = *ppos; | |
678 |
1/2✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
|
91 | if (avio_seek(s->pb, pos, SEEK_SET) < 0) |
679 | ✗ | return AV_NOPTS_VALUE; | |
680 | |||
681 | for (;;) { | ||
682 | 451 | len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); | |
683 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 406 times.
|
451 | if (len < 0) { |
684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (s->debug & FF_FDEBUG_TS) |
685 | ✗ | av_log(s, AV_LOG_DEBUG, "none (ret=%d)\n", len); | |
686 | 45 | return AV_NOPTS_VALUE; | |
687 | } | ||
688 |
2/2✓ Branch 0 taken 323 times.
✓ Branch 1 taken 83 times.
|
406 | if (startcode == s->streams[stream_index]->id && |
689 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 277 times.
|
323 | dts != AV_NOPTS_VALUE) { |
690 | 46 | break; | |
691 | } | ||
692 | 360 | avio_skip(s->pb, len); | |
693 | } | ||
694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (s->debug & FF_FDEBUG_TS) |
695 | ✗ | av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", | |
696 | pos, dts, dts / 90000.0); | ||
697 | 46 | *ppos = pos; | |
698 | 46 | return dts; | |
699 | } | ||
700 | |||
701 | const FFInputFormat ff_mpegps_demuxer = { | ||
702 | .p.name = "mpeg", | ||
703 | .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"), | ||
704 | .p.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||
705 | .priv_data_size = sizeof(MpegDemuxContext), | ||
706 | .read_probe = mpegps_probe, | ||
707 | .read_header = mpegps_read_header, | ||
708 | .read_packet = mpegps_read_packet, | ||
709 | .read_timestamp = mpegps_read_dts, | ||
710 | }; | ||
711 | |||
712 | #if CONFIG_VOBSUB_DEMUXER | ||
713 | |||
714 | #include "subtitles.h" | ||
715 | #include "libavutil/avassert.h" | ||
716 | #include "libavutil/bprint.h" | ||
717 | #include "libavutil/opt.h" | ||
718 | |||
719 | #define REF_STRING "# VobSub index file," | ||
720 | #define MAX_LINE_SIZE 2048 | ||
721 | |||
722 | typedef struct VobSubDemuxContext { | ||
723 | const AVClass *class; | ||
724 | AVFormatContext *sub_ctx; | ||
725 | FFDemuxSubtitlesQueue q[32]; | ||
726 | char *sub_name; | ||
727 | } VobSubDemuxContext; | ||
728 | |||
729 | 7186 | static int vobsub_probe(const AVProbeData *p) | |
730 | { | ||
731 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7184 times.
|
7186 | if (!strncmp(p->buf, REF_STRING, sizeof(REF_STRING) - 1)) |
732 | 2 | return AVPROBE_SCORE_MAX; | |
733 | 7184 | return 0; | |
734 | } | ||
735 | |||
736 | 3 | static int vobsub_read_close(AVFormatContext *s) | |
737 | { | ||
738 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
739 | int i; | ||
740 | |||
741 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) |
742 | 3 | ff_subtitles_queue_clean(&vobsub->q[i]); | |
743 | 3 | avformat_close_input(&vobsub->sub_ctx); | |
744 | 3 | return 0; | |
745 | } | ||
746 | |||
747 | 3 | static int vobsub_read_header(AVFormatContext *s) | |
748 | { | ||
749 | 3 | int i, ret = 0, header_parsed = 0, langidx = 0; | |
750 | 3 | VobSubDemuxContext *vobsub = s->priv_data; | |
751 | const AVInputFormat *iformat; | ||
752 | size_t fname_len; | ||
753 | AVBPrint header; | ||
754 | 3 | int64_t delay = 0; | |
755 | 3 | AVStream *st = NULL; | |
756 | 3 | int stream_id = -1; | |
757 | 3 | char id[64] = {0}; | |
758 | 3 | char alt[MAX_LINE_SIZE] = {0}; | |
759 | |||
760 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!vobsub->sub_name) { |
761 | char *ext; | ||
762 | 3 | vobsub->sub_name = av_strdup(s->url); | |
763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_name) { |
764 | ✗ | return AVERROR(ENOMEM); | |
765 | } | ||
766 | |||
767 | 3 | fname_len = strlen(vobsub->sub_name); | |
768 | 3 | ext = vobsub->sub_name - 3 + fname_len; | |
769 |
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) != '.') { |
770 | ✗ | av_log(s, AV_LOG_ERROR, "The input index filename is too short " | |
771 | "to guess the associated .SUB file\n"); | ||
772 | ✗ | return AVERROR_INVALIDDATA; | |
773 | } | ||
774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); |
775 | 3 | av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); | |
776 | } | ||
777 | |||
778 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!(iformat = av_find_input_format("mpeg"))) { |
779 | ✗ | return AVERROR_DEMUXER_NOT_FOUND; | |
780 | } | ||
781 | |||
782 | 3 | vobsub->sub_ctx = avformat_alloc_context(); | |
783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!vobsub->sub_ctx) { |
784 | ✗ | return AVERROR(ENOMEM); | |
785 | } | ||
786 | |||
787 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0) |
788 | ✗ | return ret; | |
789 | |||
790 | 3 | ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL); | |
791 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
792 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to open %s as MPEG subtitles\n", vobsub->sub_name); | |
793 | ✗ | return ret; | |
794 | } | ||
795 | |||
796 | 3 | av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); | |
797 | |||
798 |
1/2✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
|
189 | while (!avio_feof(s->pb)) { |
799 | char line[MAX_LINE_SIZE]; | ||
800 | 189 | int len = ff_get_line(s->pb, line, sizeof(line)); | |
801 | |||
802 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 186 times.
|
189 | if (!len) |
803 | 3 | break; | |
804 | |||
805 | 186 | line[strcspn(line, "\r\n")] = 0; | |
806 | |||
807 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 183 times.
|
186 | if (!strncmp(line, "id:", 3)) { |
808 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(line, "id: %63[^,], index: %u", id, &stream_id) != 2) { |
809 | ✗ | av_log(s, AV_LOG_WARNING, "Unable to parse index line '%s', " | |
810 | "assuming 'id: und, index: 0'\n", line); | ||
811 | ✗ | strcpy(id, "und"); | |
812 | ✗ | stream_id = 0; | |
813 | } | ||
814 | |||
815 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (stream_id >= FF_ARRAY_ELEMS(vobsub->q)) { |
816 | ✗ | av_log(s, AV_LOG_ERROR, "Maximum number of subtitles streams reached\n"); | |
817 | ✗ | ret = AVERROR(EINVAL); | |
818 | ✗ | goto end; | |
819 | } | ||
820 | |||
821 | 3 | header_parsed = 1; | |
822 | 3 | alt[0] = '\0'; | |
823 | /* We do not create the stream immediately to avoid adding empty | ||
824 | * streams. See the following timestamp entry. */ | ||
825 | |||
826 | 3 | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); | |
827 | |||
828 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 42 times.
|
183 | } else if (!strncmp(line, "timestamp:", 10)) { |
829 | AVPacket *sub; | ||
830 | int hh, mm, ss, ms; | ||
831 | int64_t pos, timestamp; | ||
832 | 141 | const char *p = line + 10; | |
833 | |||
834 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (stream_id == -1) { |
835 | ✗ | av_log(s, AV_LOG_ERROR, "Timestamp declared before any stream\n"); | |
836 | ✗ | ret = AVERROR_INVALIDDATA; | |
837 | ✗ | goto end; | |
838 | } | ||
839 | |||
840 |
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) { |
841 | 3 | st = avformat_new_stream(s, NULL); | |
842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!st) { |
843 | ✗ | ret = AVERROR(ENOMEM); | |
844 | ✗ | goto end; | |
845 | } | ||
846 | 3 | st->id = stream_id; | |
847 | 3 | st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
848 | 3 | st->codecpar->codec_id = AV_CODEC_ID_DVD_SUBTITLE; | |
849 | 3 | avpriv_set_pts_info(st, 64, 1, 1000); | |
850 | 3 | av_dict_set(&st->metadata, "language", id, 0); | |
851 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (alt[0]) |
852 | ✗ | av_dict_set(&st->metadata, "title", alt, 0); | |
853 | } | ||
854 | |||
855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (sscanf(p, "%02d:%02d:%02d:%03d, filepos: %"SCNx64, |
856 | &hh, &mm, &ss, &ms, &pos) != 5) { | ||
857 | ✗ | av_log(s, AV_LOG_ERROR, "Unable to parse timestamp line '%s', " | |
858 | "abort parsing\n", line); | ||
859 | ✗ | ret = AVERROR_INVALIDDATA; | |
860 | ✗ | goto end; | |
861 | } | ||
862 | 141 | timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay; | |
863 | 141 | timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base); | |
864 | |||
865 | 141 | sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 0, 0); | |
866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (!sub) { |
867 | ✗ | ret = AVERROR(ENOMEM); | |
868 | ✗ | goto end; | |
869 | } | ||
870 | 141 | sub->pos = pos; | |
871 | 141 | sub->pts = timestamp; | |
872 | 141 | sub->stream_index = s->nb_streams - 1; | |
873 | |||
874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "alt:", 4)) { |
875 | ✗ | const char *p = line + 4; | |
876 | |||
877 | ✗ | while (*p == ' ') | |
878 | ✗ | p++; | |
879 | ✗ | av_log(s, AV_LOG_DEBUG, "IDX stream[%d] name=%s\n", stream_id, p); | |
880 | ✗ | av_strlcpy(alt, p, sizeof(alt)); | |
881 | ✗ | header_parsed = 1; | |
882 | |||
883 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | } else if (!strncmp(line, "delay:", 6)) { |
884 | ✗ | int sign = 1, hh = 0, mm = 0, ss = 0, ms = 0; | |
885 | ✗ | const char *p = line + 6; | |
886 | |||
887 | ✗ | while (*p == ' ') | |
888 | ✗ | p++; | |
889 | ✗ | if (*p == '-' || *p == '+') { | |
890 | ✗ | sign = *p == '-' ? -1 : 1; | |
891 | ✗ | p++; | |
892 | } | ||
893 | ✗ | sscanf(p, "%d:%d:%d:%d", &hh, &mm, &ss, &ms); | |
894 | ✗ | delay = ((hh*3600LL + mm*60LL + ss) * 1000LL + ms) * sign; | |
895 | |||
896 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 39 times.
|
42 | } else if (!strncmp(line, "langidx:", 8)) { |
897 | 3 | const char *p = line + 8; | |
898 | |||
899 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (sscanf(p, "%d", &langidx) != 1) |
900 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid langidx specified\n"); | |
901 | |||
902 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | } else if (!header_parsed) { |
903 |
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] != '#') |
904 | 9 | av_bprintf(&header, "%s\n", line); | |
905 | } | ||
906 | } | ||
907 | |||
908 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (langidx < s->nb_streams) |
909 | 3 | s->streams[langidx]->disposition |= AV_DISPOSITION_DEFAULT; | |
910 | |||
911 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
912 | 3 | vobsub->q[i].sort = SUB_SORT_POS_TS; | |
913 | 3 | vobsub->q[i].keep_duplicates = 1; | |
914 | 3 | ff_subtitles_queue_finalize(s, &vobsub->q[i]); | |
915 | } | ||
916 | |||
917 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (!av_bprint_is_complete(&header)) { |
918 | ✗ | ret = AVERROR(ENOMEM); | |
919 | ✗ | goto end; | |
920 | } | ||
921 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (i = 0; i < s->nb_streams; i++) { |
922 | 3 | AVCodecParameters *par = s->streams[i]->codecpar; | |
923 | 3 | ret = ff_alloc_extradata(par, header.len); | |
924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
925 | ✗ | goto end; | |
926 | } | ||
927 | 3 | memcpy(par->extradata, header.str, header.len); | |
928 | } | ||
929 | 3 | end: | |
930 | 3 | av_bprint_finalize(&header, NULL); | |
931 | 3 | return ret; | |
932 | } | ||
933 | |||
934 | 141 | static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) | |
935 | { | ||
936 | 141 | VobSubDemuxContext *vobsub = s->priv_data; | |
937 | FFDemuxSubtitlesQueue *q; | ||
938 | 141 | AVIOContext *pb = vobsub->sub_ctx->pb; | |
939 | 141 | int ret, psize, total_read = 0, i; | |
940 | |||
941 | 141 | int64_t min_ts = INT64_MAX; | |
942 | 141 | int sid = 0; | |
943 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 141 times.
|
282 | for (i = 0; i < s->nb_streams; i++) { |
944 | 141 | FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i]; | |
945 | int64_t ts; | ||
946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | av_assert0(tmpq->nb_subs); |
947 | |||
948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (tmpq->current_sub_idx >= tmpq->nb_subs) |
949 | ✗ | continue; | |
950 | |||
951 | 141 | ts = tmpq->subs[tmpq->current_sub_idx]->pts; | |
952 |
1/2✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
|
141 | if (ts < min_ts) { |
953 | 141 | min_ts = ts; | |
954 | 141 | sid = i; | |
955 | } | ||
956 | } | ||
957 | 141 | q = &vobsub->q[sid]; | |
958 | /* The returned packet will have size zero, | ||
959 | * so that it can be directly used with av_grow_packet. */ | ||
960 | 141 | ret = ff_subtitles_queue_read_packet(q, pkt); | |
961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
|
141 | if (ret < 0) |
962 | ✗ | return ret; | |
963 | |||
964 | /* compute maximum packet size using the next packet position. This is | ||
965 | * useful when the len in the header is non-sense */ | ||
966 |
2/2✓ Branch 0 taken 138 times.
✓ Branch 1 taken 3 times.
|
141 | if (q->current_sub_idx < q->nb_subs) { |
967 | 138 | psize = q->subs[q->current_sub_idx]->pos - pkt->pos; | |
968 | } else { | ||
969 | 3 | int64_t fsize = avio_size(pb); | |
970 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | psize = fsize < 0 ? 0xffff : fsize - pkt->pos; |
971 | } | ||
972 | |||
973 | 141 | avio_seek(pb, pkt->pos, SEEK_SET); | |
974 | |||
975 | do { | ||
976 | int n, to_read, startcode; | ||
977 | int64_t pts, dts; | ||
978 | 393 | int64_t old_pos = avio_tell(pb), new_pos; | |
979 | int pkt_size; | ||
980 | |||
981 | 393 | ret = mpegps_read_pes_header(vobsub->sub_ctx, NULL, &startcode, &pts, &dts); | |
982 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 387 times.
|
393 | if (ret < 0) { |
983 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (pkt->size) // raise packet even if incomplete |
984 | 129 | break; | |
985 | 3 | return ret; | |
986 | } | ||
987 | 387 | to_read = ret & 0xffff; | |
988 | 387 | new_pos = avio_tell(pb); | |
989 | 387 | pkt_size = ret + (new_pos - old_pos); | |
990 | |||
991 | /* this prevents reads above the current packet */ | ||
992 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 261 times.
|
387 | if (total_read + pkt_size > psize) |
993 | 126 | break; | |
994 | 261 | total_read += pkt_size; | |
995 | |||
996 | /* the current chunk doesn't match the stream index (unlikely) */ | ||
997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if ((startcode & 0x1f) != s->streams[pkt->stream_index]->id) |
998 | ✗ | break; | |
999 | |||
1000 | 261 | ret = av_grow_packet(pkt, to_read); | |
1001 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (ret < 0) |
1002 | ✗ | return ret; | |
1003 | |||
1004 | 261 | n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read); | |
1005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
|
261 | if (n < to_read) |
1006 | ✗ | pkt->size -= to_read - n; | |
1007 |
2/2✓ Branch 0 taken 252 times.
✓ Branch 1 taken 9 times.
|
261 | } while (total_read < psize); |
1008 | |||
1009 | 138 | return 0; | |
1010 | } | ||
1011 | |||
1012 | 1 | static int vobsub_read_seek(AVFormatContext *s, int stream_index, | |
1013 | int64_t min_ts, int64_t ts, int64_t max_ts, int flags) | ||
1014 | { | ||
1015 | 1 | VobSubDemuxContext *vobsub = s->priv_data; | |
1016 | |||
1017 | /* Rescale requested timestamps based on the first stream (timebase is the | ||
1018 | * same for all subtitles stream within a .idx/.sub). Rescaling is done just | ||
1019 | * like in avformat_seek_file(). */ | ||
1020 |
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) { |
1021 | ✗ | int i, ret = 0; | |
1022 | ✗ | AVRational time_base = s->streams[0]->time_base; | |
1023 | ✗ | ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base); | |
1024 | ✗ | min_ts = av_rescale_rnd(min_ts, time_base.den, | |
1025 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
1026 | AV_ROUND_UP | AV_ROUND_PASS_MINMAX); | ||
1027 | ✗ | max_ts = av_rescale_rnd(max_ts, time_base.den, | |
1028 | ✗ | time_base.num * (int64_t)AV_TIME_BASE, | |
1029 | AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX); | ||
1030 | ✗ | for (i = 0; i < s->nb_streams; i++) { | |
1031 | ✗ | int r = ff_subtitles_queue_seek(&vobsub->q[i], s, stream_index, | |
1032 | min_ts, ts, max_ts, flags); | ||
1033 | ✗ | if (r < 0) | |
1034 | ✗ | ret = r; | |
1035 | } | ||
1036 | ✗ | return ret; | |
1037 | } | ||
1038 | |||
1039 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (stream_index == -1) // only 1 stream |
1040 | ✗ | stream_index = 0; | |
1041 | 1 | return ff_subtitles_queue_seek(&vobsub->q[stream_index], s, stream_index, | |
1042 | min_ts, ts, max_ts, flags); | ||
1043 | } | ||
1044 | |||
1045 | static const AVOption options[] = { | ||
1046 | { "sub_name", "URI for .sub file", offsetof(VobSubDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | ||
1047 | { NULL } | ||
1048 | }; | ||
1049 | |||
1050 | static const AVClass vobsub_demuxer_class = { | ||
1051 | .class_name = "vobsub", | ||
1052 | .item_name = av_default_item_name, | ||
1053 | .option = options, | ||
1054 | .version = LIBAVUTIL_VERSION_INT, | ||
1055 | }; | ||
1056 | |||
1057 | const FFInputFormat ff_vobsub_demuxer = { | ||
1058 | .p.name = "vobsub", | ||
1059 | .p.long_name = NULL_IF_CONFIG_SMALL("VobSub subtitle format"), | ||
1060 | .p.flags = AVFMT_SHOW_IDS, | ||
1061 | .p.extensions = "idx", | ||
1062 | .p.priv_class = &vobsub_demuxer_class, | ||
1063 | .priv_data_size = sizeof(VobSubDemuxContext), | ||
1064 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
1065 | .read_probe = vobsub_probe, | ||
1066 | .read_header = vobsub_read_header, | ||
1067 | .read_packet = vobsub_read_packet, | ||
1068 | .read_seek2 = vobsub_read_seek, | ||
1069 | .read_close = vobsub_read_close, | ||
1070 | }; | ||
1071 | #endif | ||
1072 |