FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/oggparsevorbis.c
Date: 2025-10-16 05:50:53
Exec Total Coverage
Lines: 274 331 82.8%
Functions: 11 11 100.0%
Branches: 146 212 68.9%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <stdlib.h>
26
27 #include "libavutil/avstring.h"
28 #include "libavutil/base64.h"
29 #include "libavutil/dict.h"
30 #include "libavutil/mem.h"
31
32 #include "libavcodec/bytestream.h"
33 #include "libavcodec/vorbis_parser.h"
34
35 #include "avformat.h"
36 #include "demux.h"
37 #include "flac_picture.h"
38 #include "internal.h"
39 #include "oggdec.h"
40 #include "vorbiscomment.h"
41 #include "replaygain.h"
42
43 234 static int ogm_chapter(AVFormatContext *as, const uint8_t *key, const uint8_t *val)
44 {
45 234 int i, cnum, h, m, s, ms, keylen = strlen(key);
46 234 AVChapter *chapter = NULL;
47
48
5/6
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 156 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
234 if (keylen < 9 || av_strncasecmp(key, "CHAPTER", 7) || sscanf(key+7, "%03d", &cnum) != 1)
49 210 return 0;
50
51
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 if (keylen <= 10) {
52
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
53 return 0;
54
55 12 avpriv_new_chapter(as, cnum, (AVRational) { 1, 1000 },
56 12 ms + 1000 * (s + 60 * (m + 60 * h)),
57 AV_NOPTS_VALUE, NULL);
58
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 } else if (!av_strcasecmp(key + keylen - 4, "NAME")) {
59
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (i = 0; i < as->nb_chapters; i++)
60
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 18 times.
30 if (as->chapters[i]->id == cnum) {
61 12 chapter = as->chapters[i];
62 12 break;
63 }
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!chapter)
65 return 0;
66
67 12 av_dict_set(&chapter->metadata, "title", val, 0);
68 } else
69 return 0;
70
71 24 return 1;
72 }
73
74 63 int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
75 const uint8_t *buf, int size)
76 {
77 63 int updates = ff_vorbis_comment(as, &st->metadata, buf, size, 1);
78
79
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 12 times.
63 if (updates > 0) {
80 51 st->event_flags |= AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
81 }
82
83 63 return updates;
84 }
85
86 /**
87 * This function temporarily modifies the (const qualified) input buffer
88 * and reverts its changes before return. The input buffer needs to have
89 * at least one byte of padding.
90 */
91 241 static int vorbis_parse_single_comment(AVFormatContext *as, AVDictionary **m,
92 const uint8_t *buf, uint32_t size,
93 int *updates, int parse_picture)
94 {
95 241 char *t = (char*)buf, *v = memchr(t, '=', size);
96 int tl, vl;
97 char backup;
98
99
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 238 times.
241 if (!v)
100 3 return 0;
101
102 238 tl = v - t;
103 238 vl = size - tl - 1;
104 238 v++;
105
106
2/4
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 238 times.
238 if (!tl || !vl)
107 return 0;
108
109 238 t[tl] = 0;
110
111 238 backup = v[vl];
112 238 v[vl] = 0;
113
114 /* The format in which the pictures are stored is the FLAC format.
115 * Xiph says: "The binary FLAC picture structure is base64 encoded
116 * and placed within a VorbisComment with the tag name
117 * 'METADATA_BLOCK_PICTURE'. This is the preferred and
118 * recommended way of embedding cover art within VorbisComments."
119 */
120
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 234 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
242 if (!av_strcasecmp(t, "METADATA_BLOCK_PICTURE") && parse_picture) {
121 4 int ret, len = AV_BASE64_DECODE_SIZE(vl);
122 4 uint8_t *pict = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE);
123
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!pict) {
125 av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n");
126 goto end;
127 }
128 4 ret = av_base64_decode(pict, v, len);
129
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ret > 0)
130 4 ret = ff_flac_parse_picture(as, &pict, ret, 0);
131 4 av_freep(&pict);
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0) {
133 av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n");
134 goto end;
135 }
136
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 210 times.
234 } else if (!ogm_chapter(as, t, v)) {
137 210 (*updates)++;
138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 210 times.
210 if (av_dict_get(*m, t, NULL, 0))
139 av_dict_set(m, t, ";", AV_DICT_APPEND);
140 210 av_dict_set(m, t, v, AV_DICT_APPEND);
141 }
142 24 end:
143 238 t[tl] = '=';
144 238 v[vl] = backup;
145
146 238 return 0;
147 }
148
149 102 int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
150 const uint8_t *buf, int size,
151 int parse_picture)
152 {
153 102 const uint8_t *p = buf;
154 102 const uint8_t *end = buf + size;
155 102 int updates = 0;
156 unsigned n;
157 int s, ret;
158
159 /* must have vendor_length and user_comment_list_length */
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (size < 8)
161 return AVERROR_INVALIDDATA;
162
163 102 s = bytestream_get_le32(&p);
164
165
2/4
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 102 times.
102 if (end - p - 4 < s || s < 0)
166 return AVERROR_INVALIDDATA;
167
168 102 p += s;
169
170 102 n = bytestream_get_le32(&p);
171
172
4/4
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 4 times.
343 while (end - p >= 4 && n > 0) {
173 241 s = bytestream_get_le32(&p);
174
175
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
241 if (end - p < s || s < 0)
176 break;
177
178 241 ret = vorbis_parse_single_comment(as, m, p, s, &updates, parse_picture);
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 if (ret < 0)
180 return ret;
181 241 p += s;
182 241 n--;
183 }
184
185
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 98 times.
102 if (p != end)
186 4 av_log(as, AV_LOG_INFO,
187 "%"PTRDIFF_SPECIFIER" bytes of comment header remain\n", end - p);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (n > 0)
189 av_log(as, AV_LOG_INFO,
190 "truncated comment header, %i comments not found\n", n);
191
192 102 ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
193
194 102 return updates;
195 }
196
197 /*
198 * Parse the vorbis header
199 *
200 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
201 * [vorbis_version] = read 32 bits as unsigned integer | Not used
202 * [audio_channels] = read 8 bit integer as unsigned | Used
203 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
204 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
205 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
206 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
207 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
208 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
209 * [framing_flag] = read one bit | Not Used
210 */
211
212 struct oggvorbis_private {
213 unsigned int len[3];
214 unsigned char *packet[3];
215 AVVorbisParseContext *vp;
216 int64_t final_pts;
217 int final_duration;
218 uint8_t *header;
219 int header_size;
220 uint8_t *comment;
221 int comment_size;
222 uint8_t *setup;
223 int setup_size;
224 };
225
226 28 static int fixup_vorbis_headers(AVFormatContext *as,
227 struct oggvorbis_private *priv,
228 uint8_t **buf)
229 {
230 int i, offset, len, err;
231 int buf_len;
232 unsigned char *ptr;
233
234 28 len = priv->len[0] + priv->len[1] + priv->len[2];
235 28 buf_len = len + len / 255 + 64;
236
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (*buf)
238 return AVERROR_INVALIDDATA;
239
240 28 ptr = *buf = av_realloc(NULL, buf_len);
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!ptr)
242 return AVERROR(ENOMEM);
243 28 memset(*buf, '\0', buf_len);
244
245 28 ptr[0] = 2;
246 28 offset = 1;
247 28 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
248 28 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
249
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 28 times.
112 for (i = 0; i < 3; i++) {
250 84 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
251 84 offset += priv->len[i];
252 84 av_freep(&priv->packet[i]);
253 }
254
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((err = av_reallocp(buf, offset + AV_INPUT_BUFFER_PADDING_SIZE)) < 0)
255 return err;
256 28 return offset;
257 }
258
259 28 static void vorbis_cleanup(AVFormatContext *s, int idx)
260 {
261 28 struct ogg *ogg = s->priv_data;
262 28 struct ogg_stream *os = ogg->streams + idx;
263 28 struct oggvorbis_private *priv = os->private;
264 int i;
265
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (os->private) {
266 28 av_vorbis_parse_free(&priv->vp);
267
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 28 times.
112 for (i = 0; i < 3; i++)
268 84 av_freep(&priv->packet[i]);
269
270 28 av_freep(&priv->header);
271 28 av_freep(&priv->comment);
272 28 av_freep(&priv->setup);
273 }
274 28 }
275
276 50 int ff_vorbis_update_metadata(AVFormatContext *s, AVStream *st,
277 const uint8_t *buf, int size)
278 {
279 50 struct ogg *ogg = s->priv_data;
280 50 struct ogg_stream *os = ogg->streams + st->index;
281 int ret;
282
283 /* New metadata packet; release old data. */
284 50 av_dict_free(&st->metadata);
285 50 ret = ff_vorbis_stream_comment(s, st, buf, size);
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (ret < 0)
287 return ret;
288
289 /* Update the metadata if possible. */
290 50 av_freep(&os->new_metadata);
291
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 10 times.
50 if (st->metadata) {
292 40 os->new_metadata = av_packet_pack_dictionary(st->metadata, &os->new_metadata_size);
293 /* Send an empty dictionary to indicate that metadata has been cleared. */
294 } else {
295 10 os->new_metadata = av_mallocz(1);
296 10 os->new_metadata_size = 0;
297 }
298
299 50 return ret;
300 }
301
302 29 static int vorbis_parse_header(AVFormatContext *s, AVStream *st,
303 const uint8_t *p, unsigned int psize)
304 {
305 unsigned blocksize, bs0, bs1;
306 int srate;
307 int channels;
308
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (psize != 30)
310 return AVERROR_INVALIDDATA;
311
312 29 p += 7; /* skip "\001vorbis" tag */
313
314
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (bytestream_get_le32(&p) != 0) /* vorbis_version */
315 return AVERROR_INVALIDDATA;
316
317 29 channels = bytestream_get_byte(&p);
318
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (st->codecpar->ch_layout.nb_channels &&
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 channels != st->codecpar->ch_layout.nb_channels) {
320 av_log(s, AV_LOG_ERROR, "Channel change is not supported\n");
321 return AVERROR_PATCHWELCOME;
322 }
323 29 st->codecpar->ch_layout.nb_channels = channels;
324 29 srate = bytestream_get_le32(&p);
325 29 p += 4; // skip maximum bitrate
326 29 st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate
327 29 p += 4; // skip minimum bitrate
328
329 29 blocksize = bytestream_get_byte(&p);
330 29 bs0 = blocksize & 15;
331 29 bs1 = blocksize >> 4;
332
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (bs0 > bs1)
334 return AVERROR_INVALIDDATA;
335
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 if (bs0 < 6 || bs1 > 13)
336 return AVERROR_INVALIDDATA;
337
338
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (bytestream_get_byte(&p) != 1) /* framing_flag */
339 return AVERROR_INVALIDDATA;
340
341 29 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
342 29 st->codecpar->codec_id = AV_CODEC_ID_VORBIS;
343
344
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (srate > 0) {
345
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (st->codecpar->sample_rate &&
346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 srate != st->codecpar->sample_rate) {
347 av_log(s, AV_LOG_ERROR, "Sample rate change is not supported\n");
348 return AVERROR_PATCHWELCOME;
349 }
350
351 29 st->codecpar->sample_rate = srate;
352 29 avpriv_set_pts_info(st, 64, 1, srate);
353 }
354
355 29 return 1;
356 }
357
358 30 static int vorbis_update_metadata(AVFormatContext *s, int idx)
359 {
360 30 struct ogg *ogg = s->priv_data;
361 30 struct ogg_stream *os = ogg->streams + idx;
362 30 AVStream *st = s->streams[idx];
363
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (os->psize <= 8)
365 return 0;
366
367 30 return ff_vorbis_update_metadata(s, st, os->buf + os->pstart + 7,
368 30 os->psize - 8);
369 }
370
371 113 static int vorbis_header(AVFormatContext *s, int idx)
372 {
373 113 struct ogg *ogg = s->priv_data;
374 113 AVStream *st = s->streams[idx];
375 113 struct ogg_stream *os = ogg->streams + idx;
376 struct oggvorbis_private *priv;
377 113 int pkt_type = os->buf[os->pstart];
378
379
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 85 times.
113 if (!os->private) {
380 28 os->private = av_mallocz(sizeof(struct oggvorbis_private));
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!os->private)
382 return AVERROR(ENOMEM);
383 }
384
385 113 priv = os->private;
386
387
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 84 times.
113 if (!(pkt_type & 1))
388
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 return priv->vp ? 0 : AVERROR_INVALIDDATA;
389
390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (pkt_type > 5) {
391 av_log(s, AV_LOG_VERBOSE, "Ignoring packet with unknown type %d\n", pkt_type);
392 return 1;
393 }
394
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (os->psize < 1)
396 return AVERROR_INVALIDDATA;
397
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (priv->packet[pkt_type >> 1])
399 return AVERROR_INVALIDDATA;
400
6/8
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 56 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 28 times.
84 if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
401 return priv->vp ? 0 : AVERROR_INVALIDDATA;
402
403 84 priv->len[pkt_type >> 1] = os->psize;
404 84 priv->packet[pkt_type >> 1] = av_memdup(os->buf + os->pstart, os->psize);
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (!priv->packet[pkt_type >> 1])
406 return AVERROR(ENOMEM);
407
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 56 times.
84 if (pkt_type == 1)
408 28 return vorbis_parse_header(s, st, os->buf + os->pstart, os->psize);
409
410
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
56 if (pkt_type == 3) {
411
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 if (vorbis_update_metadata(s, idx) >= 0 && priv->len[1] > 10) {
412 unsigned new_len;
413
414 28 int ret = ff_replaygain_export(st, st->metadata);
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
416 return ret;
417
418 // drop all metadata we parsed and which is not required by libvorbis
419 28 new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
420
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 8 times.
28 if (new_len >= 16 && new_len < os->psize) {
421 20 AV_WL32(priv->packet[1] + new_len - 5, 0);
422 20 priv->packet[1][new_len - 1] = 1;
423 20 priv->len[1] = new_len;
424 }
425 }
426 } else {
427 int ret;
428
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (priv->vp)
430 return AVERROR_INVALIDDATA;
431
432 28 ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata);
433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0) {
434 st->codecpar->extradata_size = 0;
435 return ret;
436 }
437 28 st->codecpar->extradata_size = ret;
438
439 28 priv->vp = av_vorbis_parse_init(st->codecpar->extradata, st->codecpar->extradata_size);
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!priv->vp) {
441 av_freep(&st->codecpar->extradata);
442 st->codecpar->extradata_size = 0;
443 return AVERROR_UNKNOWN;
444 }
445 }
446
447 56 return 1;
448 }
449
450 11113 static int vorbis_packet(AVFormatContext *s, int idx)
451 {
452 11113 struct ogg *ogg = s->priv_data;
453 11113 struct ogg_stream *os = ogg->streams + idx;
454 11113 struct oggvorbis_private *priv = os->private;
455 11113 int duration, flags = 0;
456 11113 int skip_packet = 0;
457 int ret, new_extradata_size;
458 PutByteContext pb;
459
460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11113 times.
11113 if (!priv->vp)
461 return AVERROR_INVALIDDATA;
462
463 /* first packet handling
464 * here we parse the duration of each packet in the first page and compare
465 * the total duration to the page granule to find the encoder delay and
466 * set the first timestamp */
467
8/8
✓ Branch 0 taken 11053 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 10575 times.
✓ Branch 3 taken 478 times.
✓ Branch 4 taken 10502 times.
✓ Branch 5 taken 133 times.
✓ Branch 6 taken 10333 times.
✓ Branch 7 taken 169 times.
11113 if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS) && (int64_t)os->granule>=0) {
468 int seg, d;
469 10333 uint8_t *last_pkt = os->buf + os->pstart;
470 10333 uint8_t *next_pkt = last_pkt;
471
472 10333 av_vorbis_parse_reset(priv->vp);
473 10333 duration = 0;
474 10333 seg = os->segp;
475 10333 d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags);
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10333 times.
10333 if (d < 0) {
477 os->pflags |= AV_PKT_FLAG_CORRUPT;
478 return 0;
479
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10332 times.
10333 } else if (flags & VORBIS_FLAG_COMMENT) {
480 1 vorbis_update_metadata(s, idx);
481 1 flags = 0;
482 }
483 10333 duration += d;
484 10333 last_pkt = next_pkt = next_pkt + os->psize;
485
2/2
✓ Branch 0 taken 192737 times.
✓ Branch 1 taken 10333 times.
203070 for (; seg < os->nsegs; seg++) {
486
2/2
✓ Branch 0 taken 143343 times.
✓ Branch 1 taken 49394 times.
192737 if (os->segments[seg] < 255) {
487 143343 int d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags);
488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143343 times.
143343 if (d < 0) {
489 duration = os->granule;
490 break;
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143343 times.
143343 } else if (flags & VORBIS_FLAG_COMMENT) {
492 vorbis_update_metadata(s, idx);
493 flags = 0;
494 }
495 143343 duration += d;
496 143343 last_pkt = next_pkt + os->segments[seg];
497 }
498 192737 next_pkt += os->segments[seg];
499 }
500 10333 os->lastpts =
501 10333 os->lastdts = os->granule - duration;
502
503
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
10333 if (!os->granule && duration) //hack to deal with broken files (Ticket3710)
504 os->lastpts = os->lastdts = AV_NOPTS_VALUE;
505
506
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 10306 times.
10333 if (s->streams[idx]->start_time == AV_NOPTS_VALUE) {
507 27 s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
508
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (s->streams[idx]->duration != AV_NOPTS_VALUE)
509 27 s->streams[idx]->duration -= s->streams[idx]->start_time;
510 }
511 10333 priv->final_pts = AV_NOPTS_VALUE;
512 10333 av_vorbis_parse_reset(priv->vp);
513 }
514
515 /* parse packet duration */
516
1/2
✓ Branch 0 taken 11113 times.
✗ Branch 1 not taken.
11113 if (os->psize > 0) {
517 11113 duration = av_vorbis_parse_frame_flags(priv->vp, os->buf + os->pstart, 1, &flags);
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11113 times.
11113 if (duration < 0) {
519 os->pflags |= AV_PKT_FLAG_CORRUPT;
520 return 0;
521 }
522
523
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11112 times.
11113 if (flags & VORBIS_FLAG_HEADER) {
524 1 ret = vorbis_parse_header(s, s->streams[idx], os->buf + os->pstart, os->psize);
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
526 return ret;
527
528 1 ret = av_reallocp(&priv->header, os->psize);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
530 return ret;
531
532 1 memcpy(priv->header, os->buf + os->pstart, os->psize);
533 1 priv->header_size = os->psize;
534
535 1 skip_packet = 1;
536 }
537
538
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11112 times.
11113 if (flags & VORBIS_FLAG_COMMENT) {
539 1 ret = vorbis_update_metadata(s, idx);
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
541 return ret;
542
543 1 ret = av_reallocp(&priv->comment, os->psize);
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
545 return ret;
546
547 1 memcpy(priv->comment, os->buf + os->pstart, os->psize);
548 1 priv->comment_size = os->psize;
549
550 1 flags = 0;
551 1 skip_packet = 1;
552 }
553
554
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11112 times.
11113 if (flags & VORBIS_FLAG_SETUP) {
555 1 ret = av_reallocp(&priv->setup, os->psize);
556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
557 return ret;
558
559 1 memcpy(priv->setup, os->buf + os->pstart, os->psize);
560 1 priv->setup_size = os->psize;
561
562 1 skip_packet = 1;
563 }
564
565 11113 os->pduration = duration;
566 }
567
568 /* final packet handling
569 * here we save the pts of the first packet in the final page, sum up all
570 * packet durations in the final page except for the last one, and compare
571 * to the page granule to find the duration of the final packet */
572
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 10975 times.
11113 if (os->flags & OGG_FLAG_EOS) {
573
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 130 times.
138 if (os->lastpts != AV_NOPTS_VALUE) {
574 8 priv->final_pts = os->lastpts;
575 8 priv->final_duration = 0;
576 }
577
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 131 times.
138 if (os->segp == os->nsegs) {
578 7 int64_t skip = priv->final_pts + priv->final_duration + os->pduration - os->granule;
579
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (skip > 0)
580 7 os->end_trimming = skip;
581 7 os->pduration = os->granule - priv->final_pts - priv->final_duration;
582 }
583 138 priv->final_duration += os->pduration;
584 }
585
586
6/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11110 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
11113 if (priv->header && priv->comment && priv->setup) {
587 1 new_extradata_size = priv->header_size + priv->comment_size + priv->setup_size + 6;
588
589 1 ret = av_reallocp(&os->new_extradata, new_extradata_size);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
591 return ret;
592
593 1 os->new_extradata_size = new_extradata_size;
594 1 bytestream2_init_writer(&pb, os->new_extradata, new_extradata_size);
595 1 bytestream2_put_be16(&pb, priv->header_size);
596 1 bytestream2_put_buffer(&pb, priv->header, priv->header_size);
597 1 bytestream2_put_be16(&pb, priv->comment_size);
598 1 bytestream2_put_buffer(&pb, priv->comment, priv->comment_size);
599 1 bytestream2_put_be16(&pb, priv->setup_size);
600 1 bytestream2_put_buffer(&pb, priv->setup, priv->setup_size);
601
602 1 av_freep(&priv->header);
603 1 priv->header_size = 0;
604 1 av_freep(&priv->comment);
605 1 priv->comment_size = 0;
606 1 av_freep(&priv->setup);
607 1 priv->setup_size = 0;
608 }
609
610 11113 return skip_packet;
611 }
612
613 const struct ogg_codec ff_vorbis_codec = {
614 .magic = "\001vorbis",
615 .magicsize = 7,
616 .header = vorbis_header,
617 .packet = vorbis_packet,
618 .cleanup = vorbis_cleanup,
619 .nb_header = 3,
620 };
621