Bug Summary

File:root/firefox-clang/media/ffvpx/libavcodec/libvorbisenc.c
Warning:line 229, column 30
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name libvorbisenc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -include libavutil_visibility.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_AV_CONFIG_H -D ASSERT_LEVEL=2 -I /root/firefox-clang/media/ffvpx/libavcodec -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -I /root/firefox-clang/modules/fdlibm/inexact-math-override -I /root/firefox-clang/third_party/khronos/vulkan-headers/include -I /root/firefox-clang/media/mozva -I /root/firefox-clang/media/libopus/include -I /root/firefox-clang/media/libvorbis -I /root/firefox-clang/media/libvpx -I /root/firefox-clang/media/ffvpx -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-pointer-sign -Wno-sign-compare -Wno-switch -Wno-type-limits -Wno-unused-function -Wno-deprecated-declarations -Wno-absolute-value -Wno-incompatible-pointer-types -Wno-string-conversion -Wno-visibility -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/media/ffvpx/libavcodec/libvorbisenc.c
1/*
2 * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <vorbis/vorbisenc.h>
22
23#include "libavutil/avassert.h"
24#include "libavutil/channel_layout.h"
25#include "libavutil/fifo.h"
26#include "libavutil/intreadwrite.h"
27#include "libavutil/mem.h"
28#include "libavutil/opt.h"
29#include "avcodec.h"
30#include "audio_frame_queue.h"
31#include "codec_internal.h"
32#include "encode.h"
33#include "version.h"
34#include "vorbis_parser.h"
35
36
37/* Number of samples the user should send in each call.
38 * This value is used because it is the LCD of all possible frame sizes, so
39 * an output packet will always start at the same point as one of the input
40 * packets.
41 */
42#define LIBVORBIS_FRAME_SIZE64 64
43
44#define BUFFER_SIZE(1024 * 64) (1024 * 64)
45
46typedef struct LibvorbisEncContext {
47 AVClass *av_class; /**< class for AVOptions */
48 vorbis_info vi; /**< vorbis_info used during init */
49 vorbis_dsp_state vd; /**< DSP state used for analysis */
50 vorbis_block vb; /**< vorbis_block used for analysis */
51 AVFifo *pkt_fifo; /**< output packet buffer */
52 int eof; /**< end-of-file flag */
53 int dsp_initialized; /**< vd has been initialized */
54 vorbis_comment vc; /**< VorbisComment info */
55 double iblock; /**< impulse block bias option */
56 AVVorbisParseContext *vp; /**< parse context to get durations */
57 AudioFrameQueue afq; /**< frame queue for timestamps */
58} LibvorbisEncContext;
59
60static const AVOption options[] = {
61 { "iblock", "Sets the impulse block bias", offsetof(LibvorbisEncContext, iblock)__builtin_offsetof(LibvorbisEncContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM(1 << 3) | AV_OPT_FLAG_ENCODING_PARAM(1 << 0) },
62 { NULL((void*)0) }
63};
64
65static const FFCodecDefault defaults[] = {
66 { "b", "0" },
67 { NULL((void*)0) },
68};
69
70static const AVClass vorbis_class = {
71 .class_name = "libvorbis",
72 .item_name = av_default_item_name,
73 .option = options,
74 .version = LIBAVUTIL_VERSION_INT((60)<<16 | (29)<<8 | (100)),
75};
76
77static const uint8_t vorbis_encoding_channel_layout_offsets[8][8] = {
78 { 0 },
79 { 0, 1 },
80 { 0, 2, 1 },
81 { 0, 1, 2, 3 },
82 { 0, 2, 1, 3, 4 },
83 { 0, 2, 1, 4, 5, 3 },
84 { 0, 2, 1, 5, 6, 4, 3 },
85 { 0, 2, 1, 6, 7, 4, 5, 3 },
86};
87
88static int vorbis_error_to_averror(int ov_err)
89{
90 switch (ov_err) {
91 case OV_EFAULT-129: return AVERROR_BUG(-(int)(('B') | (('U') << 8) | (('G') << 16) | ((
unsigned)('!') << 24)))
;
92 case OV_EINVAL-131: return AVERROR(EINVAL)(-(22));
93 case OV_EIMPL-130: return AVERROR(EINVAL)(-(22));
94 default: return AVERROR_UNKNOWN(-(int)(('U') | (('N') << 8) | (('K') << 16) | ((
unsigned)('N') << 24)))
;
95 }
96}
97
98static av_cold__attribute__((cold)) int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx)
99{
100 LibvorbisEncContext *s = avctx->priv_data;
101 int channels = avctx->ch_layout.nb_channels;
102 double cfreq;
103 int ret;
104
105 if (avctx->flags & AV_CODEC_FLAG_QSCALE(1 << 1) || !avctx->bit_rate) {
106 /* variable bitrate
107 * NOTE: we use the oggenc range of -1 to 10 for global_quality for
108 * user convenience, but libvorbis uses -0.1 to 1.0.
109 */
110 float q = avctx->global_quality / (float)FF_QP2LAMBDA118;
111 /* default to 3 if the user did not set quality or bitrate */
112 if (!(avctx->flags & AV_CODEC_FLAG_QSCALE(1 << 1)))
113 q = 3.0;
114 if ((ret = vorbis_encode_setup_vbr(vi, channels,
115 avctx->sample_rate,
116 q / 10.0)))
117 goto error;
118 } else {
119 int minrate = avctx->rc_min_rate > 0 ? avctx->rc_min_rate : -1;
120 int maxrate = avctx->rc_max_rate > 0 ? avctx->rc_max_rate : -1;
121
122 /* average bitrate */
123 if ((ret = vorbis_encode_setup_managed(vi, channels,
124 avctx->sample_rate, maxrate,
125 avctx->bit_rate, minrate)))
126 goto error;
127
128 /* variable bitrate by estimate, disable slow rate management */
129 if (minrate == -1 && maxrate == -1)
130 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET0x15, NULL((void*)0))))
131 goto error; /* should not happen */
132 }
133
134 /* cutoff frequency */
135 if (avctx->cutoff > 0) {
136 cfreq = avctx->cutoff / 1000.0;
137 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET0x21, &cfreq)))
138 goto error; /* should not happen */
139 }
140
141 /* impulse block bias */
142 if (s->iblock) {
143 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET0x31, &s->iblock)))
144 goto error;
145 }
146
147 if ((channels == 3 &&
148 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND{ AV_CHANNEL_ORDER_NATIVE, (3), { (((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
)) }, ((void*)0) }
)) ||
149 (channels == 4 &&
150 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2{ AV_CHANNEL_ORDER_NATIVE, (4), { (((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_SIDE_LEFT
)|(1ULL << AV_CHAN_SIDE_RIGHT )) }, ((void*)0) }
) &&
151 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD{ AV_CHANNEL_ORDER_NATIVE, (4), { (((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_BACK_LEFT
)|(1ULL << AV_CHAN_BACK_RIGHT )) }, ((void*)0) }
)) ||
152 (channels == 5 &&
153 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0{ AV_CHANNEL_ORDER_NATIVE, (5), { ((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_SIDE_LEFT )|(1ULL << AV_CHAN_SIDE_RIGHT
)) }, ((void*)0) }
) &&
154 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK{ AV_CHANNEL_ORDER_NATIVE, (5), { ((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_BACK_LEFT )|(1ULL << AV_CHAN_BACK_RIGHT
)) }, ((void*)0) }
)) ||
155 (channels == 6 &&
156 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1{ AV_CHANNEL_ORDER_NATIVE, (6), { (((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_SIDE_LEFT )|(1ULL << AV_CHAN_SIDE_RIGHT
))|(1ULL << AV_CHAN_LOW_FREQUENCY )) }, ((void*)0) }
) &&
157 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK{ AV_CHANNEL_ORDER_NATIVE, (6), { (((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_BACK_LEFT )|(1ULL << AV_CHAN_BACK_RIGHT
))|(1ULL << AV_CHAN_LOW_FREQUENCY )) }, ((void*)0) }
)) ||
158 (channels == 7 &&
159 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1{ AV_CHANNEL_ORDER_NATIVE, (7), { ((((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_SIDE_LEFT )|(1ULL << AV_CHAN_SIDE_RIGHT
))|(1ULL << AV_CHAN_LOW_FREQUENCY ))|(1ULL << AV_CHAN_BACK_CENTER
)) }, ((void*)0) }
)) ||
160 (channels == 8 &&
161 av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1{ AV_CHANNEL_ORDER_NATIVE, (8), { ((((((1ULL << AV_CHAN_FRONT_LEFT
)|(1ULL << AV_CHAN_FRONT_RIGHT ))|(1ULL << AV_CHAN_FRONT_CENTER
))|(1ULL << AV_CHAN_SIDE_LEFT )|(1ULL << AV_CHAN_SIDE_RIGHT
))|(1ULL << AV_CHAN_LOW_FREQUENCY ))|(1ULL << AV_CHAN_BACK_LEFT
)|(1ULL << AV_CHAN_BACK_RIGHT )) }, ((void*)0) }
))) {
162 if (avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
163 char name[32];
164 av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name));
165 av_log(avctx, AV_LOG_ERROR16, "%s not supported by Vorbis: "
166 "output stream will have incorrect "
167 "channel layout.\n", name);
168 } else {
169 av_log(avctx, AV_LOG_WARNING24, "No channel layout specified. The encoder "
170 "will use Vorbis channel layout for "
171 "%d channels.\n", channels);
172 }
173 }
174
175 if ((ret = vorbis_encode_setup_init(vi)))
176 goto error;
177
178 return 0;
179error:
180 return vorbis_error_to_averror(ret);
181}
182
183static av_cold__attribute__((cold)) int libvorbis_get_priming_samples(vorbis_info *vi, AVCodecContext *avctx)
184{
185 LibvorbisEncContext *s = avctx->priv_data;
186 vorbis_dsp_state vd;
187 vorbis_block vb;
188 ogg_packet op;
189 int ret;
190
191 if ((ret = vorbis_analysis_init(&vd, vi))) {
19
Assuming 'ret' is 0
20
Taking false branch
192 av_log(avctx, AV_LOG_ERROR16, "analysis init failed\n");
193 return vorbis_error_to_averror(ret);
194 }
195 if ((ret = vorbis_block_init(&vd, &vb))) {
21
Assuming 'ret' is 0
22
Taking false branch
196 av_log(avctx, AV_LOG_ERROR16, "dsp init failed\n");
197 vorbis_dsp_clear(&vd);
198 return vorbis_error_to_averror(ret);
199 }
200
201 if ((ret = vorbis_analysis_wrote(&vd, 0)) < 0) {
23
Assuming the condition is false
24
Taking false branch
202 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote() during init\n");
203 ret = vorbis_error_to_averror(ret);
204 goto error;
205 }
206
207 /* retrieve available packets from libvorbis */
208 if ((ret = vorbis_analysis_blockout(&vd, &vb)) == 1) {
25
Assuming the condition is false
26
Taking false branch
209 if ((ret = vorbis_analysis(&vb, NULL((void*)0))) < 0) {
210 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_blockout() during init\n");
211 ret = vorbis_error_to_averror(ret);
212 goto error;
213 }
214 if ((ret = vorbis_bitrate_addblock(&vb)) < 0) {
215 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_bitrate_addblock() during init\n");
216 ret = vorbis_error_to_averror(ret);
217 goto error;
218 }
219
220 /* add any available packets to the output packet buffer */
221 ret = vorbis_bitrate_flushpacket(&vd, &op);
222 if (ret < 0) {
223 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_bitrate_flushpacket() during init\n");
224 ret = vorbis_error_to_averror(ret);
225 goto error;
226 }
227 }
228
229 avctx->initial_padding = av_vorbis_parse_frame(s->vp, op.packet, op.bytes);
27
2nd function call argument is an uninitialized value
230
231 ret = 0;
232error:
233 vorbis_block_clear(&vb);
234 vorbis_dsp_clear(&vd);
235
236 return ret;
237}
238
239/* How many bytes are needed for a buffer of length 'l' */
240static int xiph_len(int l)
241{
242 return 1 + l / 255 + l;
243}
244
245static av_cold__attribute__((cold)) int libvorbis_encode_close(AVCodecContext *avctx)
246{
247 LibvorbisEncContext *s = avctx->priv_data;
248
249 /* notify vorbisenc this is EOF */
250 if (s->dsp_initialized)
251 vorbis_analysis_wrote(&s->vd, 0);
252
253 vorbis_block_clear(&s->vb);
254 vorbis_dsp_clear(&s->vd);
255 vorbis_info_clear(&s->vi);
256
257 av_fifo_freep2(&s->pkt_fifo);
258 ff_af_queue_close(&s->afq);
259
260 av_vorbis_parse_free(&s->vp);
261
262 return 0;
263}
264
265static av_cold__attribute__((cold)) int libvorbis_encode_init(AVCodecContext *avctx)
266{
267 LibvorbisEncContext *s = avctx->priv_data;
268 ogg_packet header, header_comm, header_code;
269 uint8_t *p;
270 unsigned int offset;
271 int ret;
272
273 vorbis_info_init(&s->vi);
274 if ((ret = libvorbis_setup(&s->vi, avctx))) {
1
Assuming 'ret' is 0
2
Taking false branch
275 av_log(avctx, AV_LOG_ERROR16, "encoder setup failed\n");
276 goto error;
277 }
278 if ((ret = vorbis_analysis_init(&s->vd, &s->vi))) {
3
Assuming 'ret' is 0
4
Taking false branch
279 av_log(avctx, AV_LOG_ERROR16, "analysis init failed\n");
280 ret = vorbis_error_to_averror(ret);
281 goto error;
282 }
283 s->dsp_initialized = 1;
284 if ((ret = vorbis_block_init(&s->vd, &s->vb))) {
5
Assuming 'ret' is 0
6
Taking false branch
285 av_log(avctx, AV_LOG_ERROR16, "dsp init failed\n");
286 ret = vorbis_error_to_averror(ret);
287 goto error;
288 }
289
290 vorbis_comment_init(&s->vc);
291 if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT(1 << 23)))
7
Assuming the condition is false
8
Taking false branch
292 vorbis_comment_add_tag(&s->vc, "encoder", LIBAVCODEC_IDENT"Lavc" "62.29.101");
293
294 if ((ret = vorbis_analysis_headerout(&s->vd, &s->vc, &header, &header_comm,
9
Assuming 'ret' is 0
10
Taking false branch
295 &header_code))) {
296 ret = vorbis_error_to_averror(ret);
297 goto error;
298 }
299
300 avctx->extradata_size = 1 + xiph_len(header.bytes) +
301 xiph_len(header_comm.bytes) +
302 header_code.bytes;
303 p = avctx->extradata = av_malloc(avctx->extradata_size +
304 AV_INPUT_BUFFER_PADDING_SIZE64);
305 if (!p) {
11
Assuming 'p' is non-null
12
Taking false branch
306 ret = AVERROR(ENOMEM)(-(12));
307 goto error;
308 }
309 p[0] = 2;
310 offset = 1;
311 offset += av_xiphlacing(&p[offset], header.bytes);
312 offset += av_xiphlacing(&p[offset], header_comm.bytes);
313 memcpy(&p[offset], header.packet, header.bytes);
314 offset += header.bytes;
315 memcpy(&p[offset], header_comm.packet, header_comm.bytes);
316 offset += header_comm.bytes;
317 memcpy(&p[offset], header_code.packet, header_code.bytes);
318 offset += header_code.bytes;
319 av_assert0(offset == avctx->extradata_size)do { if (!(offset == avctx->extradata_size)) { av_log(((void
*)0), 0, "Assertion %s failed at %s:%d\n", "offset == avctx->extradata_size"
, "/root/firefox-clang/media/ffvpx/libavcodec/libvorbisenc.c"
, 319); abort(); } } while (0)
;
13
Assuming 'offset' is equal to field 'extradata_size'
14
Taking false branch
15
Loop condition is false. Exiting loop
320
321 s->vp = av_vorbis_parse_init(avctx->extradata, avctx->extradata_size);
322 if (!s->vp) {
16
Assuming field 'vp' is non-null
17
Taking false branch
323 av_log(avctx, AV_LOG_ERROR16, "invalid extradata\n");
324 return ret;
325 }
326
327 vorbis_comment_clear(&s->vc);
328
329 if ((ret = libvorbis_get_priming_samples(&s->vi, avctx)))
18
Calling 'libvorbis_get_priming_samples'
330 return ret;
331
332 avctx->frame_size = LIBVORBIS_FRAME_SIZE64;
333 ff_af_queue_init(avctx, &s->afq);
334
335 s->pkt_fifo = av_fifo_alloc2(BUFFER_SIZE(1024 * 64), 1, 0);
336 if (!s->pkt_fifo) {
337 ret = AVERROR(ENOMEM)(-(12));
338 goto error;
339 }
340
341 return 0;
342error:
343 libvorbis_encode_close(avctx);
344 return ret;
345}
346
347static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
348 const AVFrame *frame, int *got_packet_ptr)
349{
350 LibvorbisEncContext *s = avctx->priv_data;
351 ogg_packet op;
352 int ret, duration;
353
354 /* send samples to libvorbis */
355 if (frame) {
356 const int samples = frame->nb_samples;
357 float **buffer;
358 int c, channels = s->vi.channels;
359
360 buffer = vorbis_analysis_buffer(&s->vd, samples);
361 for (c = 0; c < channels; c++) {
362 int co = (channels > 8) ? c :
363 vorbis_encoding_channel_layout_offsets[channels - 1][c];
364 memcpy(buffer[c], frame->extended_data[co],
365 samples * sizeof(*buffer[c]));
366 }
367 if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) {
368 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote()\n");
369 return vorbis_error_to_averror(ret);
370 }
371 if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
372 return ret;
373 } else {
374 if (!s->eof && s->afq.frame_alloc)
375 if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) {
376 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote()\n");
377 return vorbis_error_to_averror(ret);
378 }
379 s->eof = 1;
380 }
381
382 /* retrieve available packets from libvorbis */
383 while ((ret = vorbis_analysis_blockout(&s->vd, &s->vb)) == 1) {
384 if ((ret = vorbis_analysis(&s->vb, NULL((void*)0))) < 0)
385 break;
386 if ((ret = vorbis_bitrate_addblock(&s->vb)) < 0)
387 break;
388
389 /* add any available packets to the output packet buffer */
390 while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) {
391 if (av_fifo_can_write(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) {
392 av_log(avctx, AV_LOG_ERROR16, "packet buffer is too small\n");
393 return AVERROR_BUG(-(int)(('B') | (('U') << 8) | (('G') << 16) | ((
unsigned)('!') << 24)))
;
394 }
395 av_fifo_write(s->pkt_fifo, &op, sizeof(ogg_packet));
396 av_fifo_write(s->pkt_fifo, op.packet, op.bytes);
397 }
398 if (ret < 0) {
399 av_log(avctx, AV_LOG_ERROR16, "error getting available packets\n");
400 break;
401 }
402 }
403 if (ret < 0) {
404 av_log(avctx, AV_LOG_ERROR16, "error getting available packets\n");
405 return vorbis_error_to_averror(ret);
406 }
407
408 /* Read an available packet if possible */
409 if (av_fifo_read(s->pkt_fifo, &op, sizeof(ogg_packet)) < 0)
410 return 0;
411
412 if ((ret = ff_get_encode_buffer(avctx, avpkt, op.bytes, 0)) < 0)
413 return ret;
414 av_fifo_read(s->pkt_fifo, avpkt->data, op.bytes);
415
416 avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos);
417
418 duration = av_vorbis_parse_frame(s->vp, avpkt->data, avpkt->size);
419 if (duration > 0) {
420 int discard_padding;
421
422 ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration);
423
424 discard_padding = duration - ff_samples_from_time_base(avctx, avpkt->duration);
425 if (discard_padding > 0) {
426 uint8_t *side_data = av_packet_new_side_data(avpkt,
427 AV_PKT_DATA_SKIP_SAMPLES,
428 10);
429 if (!side_data)
430 return AVERROR(ENOMEM)(-(12));
431 AV_WL32(side_data + 4, discard_padding)((((union unaligned_32 *) (side_data + 4))->l) = (discard_padding
))
;
432 }
433 }
434
435 *got_packet_ptr = 1;
436 return 0;
437}
438
439const FFCodec ff_libvorbis_encoder = {
440 .p.name = "libvorbis",
441 CODEC_LONG_NAME("libvorbis").p.long_name = "libvorbis",
442 .p.type = AVMEDIA_TYPE_AUDIO,
443 .p.id = AV_CODEC_ID_VORBIS,
444 .p.capabilities = AV_CODEC_CAP_DR1(1 << 1) | AV_CODEC_CAP_DELAY(1 << 5) |
445 AV_CODEC_CAP_SMALL_LAST_FRAME(1 << 6),
446 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE(1 << 0),
447 .priv_data_size = sizeof(LibvorbisEncContext),
448 .init = libvorbis_encode_init,
449 FF_CODEC_ENCODE_CB(libvorbis_encode_frame).is_decoder = 0, .cb_type = FF_CODEC_CB_TYPE_ENCODE, .cb.encode
= (libvorbis_encode_frame)
,
450 .close = libvorbis_encode_close,
451 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP)GCC diagnostic push GCC diagnostic ignored "-Wdeprecated-declarations"
.p.sample_fmts = ((((const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP
, AV_SAMPLE_FMT_NONE }))) GCC diagnostic pop
,
452 .p.priv_class = &vorbis_class,
453 .defaults = defaults,
454 .p.wrapper_name = "libvorbis",
455};