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