FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/oggparsetheora.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 88 106 83.0%
Functions: 3 3 100.0%
Branches: 41 64 64.1%

Line Branch Exec Source
1 /**
2 * Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi
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 #include "libavutil/mem.h"
27 #include "libavcodec/get_bits.h"
28 #include "avformat.h"
29 #include "internal.h"
30 #include "oggdec.h"
31
32 typedef struct TheoraParams {
33 int gpshift;
34 int gpmask;
35 unsigned version;
36 } TheoraParams;
37
38 12 static int theora_header(AVFormatContext *s, int idx)
39 {
40 12 struct ogg *ogg = s->priv_data;
41 12 struct ogg_stream *os = ogg->streams + idx;
42 12 AVStream *st = s->streams[idx];
43 12 TheoraParams *thp = os->private;
44 12 int cds = st->codecpar->extradata_size + os->psize + 2;
45 int err;
46 uint8_t *cdp;
47
48
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (!(os->buf[os->pstart] & 0x80))
49 3 return 0;
50
51
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (!thp) {
52 3 thp = av_mallocz(sizeof(*thp));
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!thp)
54 return AVERROR(ENOMEM);
55 3 os->private = thp;
56 }
57
58
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
9 switch (os->buf[os->pstart]) {
59 3 case 0x80: {
60 GetBitContext gb;
61 AVRational timebase;
62
63 3 init_get_bits(&gb, os->buf + os->pstart, os->psize * 8);
64
65 /* 0x80"theora" */
66 3 skip_bits_long(&gb, 7 * 8);
67
68 3 thp->version = get_bits(&gb, 24);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (thp->version < 0x030100) {
70 av_log(s, AV_LOG_ERROR,
71 "Too old or unsupported Theora (%x)\n", thp->version);
72 return AVERROR(ENOSYS);
73 }
74
75 3 st->codecpar->width = get_bits(&gb, 16) << 4;
76 3 st->codecpar->height = get_bits(&gb, 16) << 4;
77
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (thp->version >= 0x030400)
79 skip_bits(&gb, 100);
80
81
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (thp->version >= 0x030200) {
82 3 int width = get_bits(&gb, 24);
83 3 int height = get_bits(&gb, 24);
84
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (width <= st->codecpar->width && width > st->codecpar->width - 16 &&
85
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 height <= st->codecpar->height && height > st->codecpar->height - 16) {
86 1 st->codecpar->width = width;
87 1 st->codecpar->height = height;
88 }
89
90 3 skip_bits(&gb, 16);
91 }
92
93 3 timebase.den = get_bits_long(&gb, 32);
94 3 timebase.num = get_bits_long(&gb, 32);
95
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!(timebase.num > 0 && timebase.den > 0)) {
96 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
97 timebase.num = 1;
98 timebase.den = 25;
99 }
100 3 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
101
102 3 st->sample_aspect_ratio.num = get_bits(&gb, 24);
103 3 st->sample_aspect_ratio.den = get_bits(&gb, 24);
104
105
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (thp->version >= 0x030200)
106 3 skip_bits_long(&gb, 38);
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (thp->version >= 0x304000)
108 skip_bits(&gb, 2);
109
110 3 thp->gpshift = get_bits(&gb, 5);
111 3 thp->gpmask = (1U << thp->gpshift) - 1;
112
113 3 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
114 3 st->codecpar->codec_id = AV_CODEC_ID_THEORA;
115 3 ffstream(st)->need_parsing = AVSTREAM_PARSE_HEADERS;
116 }
117 3 break;
118 3 case 0x81:
119 3 ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 7, os->psize - 7);
120 6 case 0x82:
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!thp->version)
122 return AVERROR_INVALIDDATA;
123 6 break;
124 default:
125 av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
126 return AVERROR_INVALIDDATA;
127 }
128
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if ((err = av_reallocp(&st->codecpar->extradata,
130 9 cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
131 st->codecpar->extradata_size = 0;
132 return err;
133 }
134 9 memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
135
136 9 cdp = st->codecpar->extradata + st->codecpar->extradata_size;
137 9 *cdp++ = os->psize >> 8;
138 9 *cdp++ = os->psize & 0xff;
139 9 memcpy(cdp, os->buf + os->pstart, os->psize);
140 9 st->codecpar->extradata_size = cds;
141
142 9 return 1;
143 }
144
145 10 static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
146 int64_t *dts)
147 {
148 10 struct ogg *ogg = ctx->priv_data;
149 10 struct ogg_stream *os = ogg->streams + idx;
150 10 TheoraParams *thp = os->private;
151 uint64_t iframe, pframe;
152
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!thp)
154 return AV_NOPTS_VALUE;
155
156 10 iframe = gp >> thp->gpshift;
157 10 pframe = gp & thp->gpmask;
158
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (thp->version < 0x030201)
160 iframe++;
161
162
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (!pframe)
163 4 os->pflags |= AV_PKT_FLAG_KEY;
164
165
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (dts)
166 5 *dts = iframe + pframe;
167
168 10 return iframe + pframe;
169 }
170
171 31 static int theora_packet(AVFormatContext *s, int idx)
172 {
173 31 struct ogg *ogg = s->priv_data;
174 31 struct ogg_stream *os = ogg->streams + idx;
175 int duration;
176
177 /* first packet handling
178 here we parse the duration of each packet in the first page and compare
179 the total duration to the page granule to find the encoder delay and
180 set the first timestamp */
181
182
6/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 28 times.
31 if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
183 int seg;
184 int64_t pts;
185
186 2 duration = 1;
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (seg = os->segp; seg < os->nsegs; seg++) {
188 if (os->segments[seg] < 255)
189 duration ++;
190 }
191
192 2 pts = theora_gptopts(s, idx, os->granule, NULL);
193
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pts != AV_NOPTS_VALUE)
194 2 pts = av_sat_sub64(pts, duration);
195 2 os->lastpts = os->lastdts = pts;
196
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 if(s->streams[idx]->start_time == AV_NOPTS_VALUE && os->lastpts != AV_NOPTS_VALUE) {
197 1 s->streams[idx]->start_time = os->lastpts;
198
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s->streams[idx]->duration > 0)
199 1 s->streams[idx]->duration = av_sat_sub64(s->streams[idx]->duration, s->streams[idx]->start_time);
200 }
201 }
202
203 /* parse packet duration */
204
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (os->psize > 0) {
205 31 os->pduration = 1;
206 }
207
208 31 return 0;
209 }
210
211 const struct ogg_codec ff_theora_codec = {
212 .magic = "\200theora",
213 .magicsize = 7,
214 .header = theora_header,
215 .packet = theora_packet,
216 .gptopts = theora_gptopts,
217 .nb_header = 3,
218 };
219