Bug Summary

File:root/firefox-clang/media/ffvpx/libavcodec/libvorbisenc.c
Warning:line 209, column 10
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'

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-10-17-231001-351276-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#include "vorbis_parser_internal.h"
36
37
38/* Number of samples the user should send in each call.
39 * This value is used because it is the LCD of all possible frame sizes, so
40 * an output packet will always start at the same point as one of the input
41 * packets.
42 */
43#define LIBVORBIS_FRAME_SIZE64 64
44
45#define BUFFER_SIZE(1024 * 64) (1024 * 64)
46
47typedef struct LibvorbisEncContext {
48 AVClass *av_class; /**< class for AVOptions */
49 vorbis_info vi; /**< vorbis_info used during init */
50 vorbis_dsp_state vd; /**< DSP state used for analysis */
51 vorbis_block vb; /**< vorbis_block used for analysis */
52 AVFifo *pkt_fifo; /**< output packet buffer */
53 int eof; /**< end-of-file flag */
54 int dsp_initialized; /**< vd has been initialized */
55 vorbis_comment vc; /**< VorbisComment info */
56 double iblock; /**< impulse block bias option */
57 AVVorbisParseContext vp; /**< parse context to get durations */
58 AudioFrameQueue afq; /**< frame queue for timestamps */
59} LibvorbisEncContext;
60
61static const AVOption options[] = {
62 { "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) },
63 { NULL((void*)0) }
64};
65
66static const FFCodecDefault defaults[] = {
67 { "b", "0" },
68 { NULL((void*)0) },
69};
70
71static const AVClass vorbis_class = {
72 .class_name = "libvorbis",
73 .item_name = av_default_item_name,
74 .option = options,
75 .version = LIBAVUTIL_VERSION_INT((61)<<16 | (1)<<8 | (101)),
76};
77
78static const uint8_t vorbis_encoding_channel_layout_offsets[8][8] = {
79 { 0 },
80 { 0, 1 },
81 { 0, 2, 1 },
82 { 0, 1, 2, 3 },
83 { 0, 2, 1, 3, 4 },
84 { 0, 2, 1, 4, 5, 3 },
85 { 0, 2, 1, 5, 6, 4, 3 },
86 { 0, 2, 1, 6, 7, 4, 5, 3 },
87};
88
89static int vorbis_error_to_averror(int ov_err)
90{
91 switch (ov_err) {
92 case OV_EFAULT-129: return AVERROR_BUG(-(int)(('B') | (('U') << 8) | (('G') << 16) | ((
unsigned)('!') << 24)))
;
93 case OV_EINVAL-131: return AVERROR(EINVAL)(-(22));
94 case OV_EIMPL-130: return AVERROR(EINVAL)(-(22));
95 default: return AVERROR_UNKNOWN(-(int)(('U') | (('N') << 8) | (('K') << 16) | ((
unsigned)('N') << 24)))
;
96 }
97}
98
99static av_cold__attribute__((cold)) int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx)
100{
101 LibvorbisEncContext *s = avctx->priv_data;
102 int channels = avctx->ch_layout.nb_channels;
103 double cfreq;
104 int ret;
105
106 if (avctx->flags & AV_CODEC_FLAG_QSCALE(1 << 1) || !avctx->bit_rate) {
107 /* variable bitrate
108 * NOTE: we use the oggenc range of -1 to 10 for global_quality for
109 * user convenience, but libvorbis uses -0.1 to 1.0.
110 */
111 float q = avctx->global_quality / (float)FF_QP2LAMBDA118;
112 /* default to 3 if the user did not set quality or bitrate */
113 if (!(avctx->flags & AV_CODEC_FLAG_QSCALE(1 << 1)))
114 q = 3.0;
115 if ((ret = vorbis_encode_setup_vbr(vi, channels,
116 avctx->sample_rate,
117 q / 10.0)))
118 goto error;
119 } else {
120 int minrate = avctx->rc_min_rate > 0 ? avctx->rc_min_rate : -1;
121 int maxrate = avctx->rc_max_rate > 0 ? avctx->rc_max_rate : -1;
122
123 /* average bitrate */
124 if ((ret = vorbis_encode_setup_managed(vi, channels,
125 avctx->sample_rate, maxrate,
126 avctx->bit_rate, minrate)))
127 goto error;
128
129 /* variable bitrate by estimate, disable slow rate management */
130 if (minrate == -1 && maxrate == -1)
131 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET0x15, NULL((void*)0))))
132 goto error; /* should not happen */
133 }
134
135 /* cutoff frequency */
136 if (avctx->cutoff > 0) {
137 cfreq = avctx->cutoff / 1000.0;
138 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET0x21, &cfreq)))
139 goto error; /* should not happen */
140 }
141
142 /* impulse block bias */
143 if (s->iblock) {
144 if ((ret = vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET0x31, &s->iblock)))
145 goto error;
146 }
147
148 if ((channels == 3 &&
149 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) }
)) ||
150 (channels == 4 &&
151 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) }
) &&
152 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) }
)) ||
153 (channels == 5 &&
154 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) }
) &&
155 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) }
)) ||
156 (channels == 6 &&
157 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) }
) &&
158 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) }
)) ||
159 (channels == 7 &&
160 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) }
)) ||
161 (channels == 8 &&
162 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) }
))) {
163 if (avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
164 char name[32];
165 av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name));
166 av_log(avctx, AV_LOG_ERROR16, "%s not supported by Vorbis: "
167 "output stream will have incorrect "
168 "channel layout.\n", name);
169 } else {
170 av_log(avctx, AV_LOG_WARNING24, "No channel layout specified. The encoder "
171 "will use Vorbis channel layout for "
172 "%d channels.\n", channels);
173 }
174 }
175
176 if ((ret = vorbis_encode_setup_init(vi)))
177 goto error;
178
179 return 0;
180error:
181 return vorbis_error_to_averror(ret);
182}
183
184static av_cold__attribute__((cold)) int libvorbis_get_priming_samples(vorbis_info *vi, AVCodecContext *avctx)
185{
186 LibvorbisEncContext *s = avctx->priv_data;
187 vorbis_dsp_state vd;
188 vorbis_block vb;
189 ogg_packet op;
190 int ret;
191
192 if ((ret = vorbis_analysis_init(&vd, vi))) {
193 av_log(avctx, AV_LOG_ERROR16, "analysis init failed\n");
194 return vorbis_error_to_averror(ret);
195 }
196 if ((ret = vorbis_block_init(&vd, &vb))) {
197 av_log(avctx, AV_LOG_ERROR16, "dsp init failed\n");
198 vorbis_dsp_clear(&vd);
199 return vorbis_error_to_averror(ret);
200 }
201
202 if ((ret = vorbis_analysis_wrote(&vd, 0)) < 0) {
203 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote() during init\n");
204 ret = vorbis_error_to_averror(ret);
205 goto error;
206 }
207
208 /* retrieve available packets from libvorbis */
209 if ((ret = vorbis_analysis_blockout(&vd, &vb)) == 1) {
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'
210 if ((ret = vorbis_analysis(&vb, NULL((void*)0))) < 0) {
211 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_blockout() during init\n");
212 ret = vorbis_error_to_averror(ret);
213 goto error;
214 }
215 if ((ret = vorbis_bitrate_addblock(&vb)) < 0) {
216 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_bitrate_addblock() during init\n");
217 ret = vorbis_error_to_averror(ret);
218 goto error;
219 }
220
221 /* add any available packets to the output packet buffer */
222 ret = vorbis_bitrate_flushpacket(&vd, &op);
223 if (ret < 0) {
224 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_bitrate_flushpacket() during init\n");
225 ret = vorbis_error_to_averror(ret);
226 goto error;
227 }
228 avctx->initial_padding = av_vorbis_parse_frame(&s->vp, op.packet, op.bytes);
229 }
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 return 0;
261}
262
263static av_cold__attribute__((cold)) int libvorbis_encode_init(AVCodecContext *avctx)
264{
265 LibvorbisEncContext *s = avctx->priv_data;
266 ogg_packet header, header_comm, header_code;
267 uint8_t *p;
268 unsigned int offset;
269 int ret;
270
271 vorbis_info_init(&s->vi);
272 if ((ret = libvorbis_setup(&s->vi, avctx))) {
273 av_log(avctx, AV_LOG_ERROR16, "encoder setup failed\n");
274 goto error;
275 }
276 if ((ret = vorbis_analysis_init(&s->vd, &s->vi))) {
277 av_log(avctx, AV_LOG_ERROR16, "analysis init failed\n");
278 ret = vorbis_error_to_averror(ret);
279 goto error;
280 }
281 s->dsp_initialized = 1;
282 if ((ret = vorbis_block_init(&s->vd, &s->vb))) {
283 av_log(avctx, AV_LOG_ERROR16, "dsp init failed\n");
284 ret = vorbis_error_to_averror(ret);
285 goto error;
286 }
287
288 vorbis_comment_init(&s->vc);
289 if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT(1 << 23)))
290 vorbis_comment_add_tag(&s->vc, "encoder", LIBAVCODEC_IDENT"Lavc" "63.1.101");
291
292 ret = vorbis_analysis_headerout(&s->vd, &s->vc, &header, &header_comm,
293 &header_code);
294 vorbis_comment_clear(&s->vc);
295 if (ret) {
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) {
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)
;
320
321 ret = ff_vorbis_parse_init(&s->vp, avctx->extradata, avctx->extradata_size);
322 if (ret < 0) {
323 av_log(avctx, AV_LOG_ERROR16, "invalid extradata\n");
324 goto error;
325 }
326
327 if ((ret = libvorbis_get_priming_samples(&s->vi, avctx)))
328 goto error;
329
330 avctx->frame_size = LIBVORBIS_FRAME_SIZE64;
331 ff_af_queue_init(avctx, &s->afq);
332
333 s->pkt_fifo = av_fifo_alloc2(BUFFER_SIZE(1024 * 64), 1, 0);
334 if (!s->pkt_fifo) {
335 ret = AVERROR(ENOMEM)(-(12));
336 goto error;
337 }
338
339 return 0;
340error:
341 libvorbis_encode_close(avctx);
342 return ret;
343}
344
345static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
346 const AVFrame *frame, int *got_packet_ptr)
347{
348 LibvorbisEncContext *s = avctx->priv_data;
349 ogg_packet op;
350 int ret, duration;
351
352 /* send samples to libvorbis */
353 if (frame) {
354 const int samples = frame->nb_samples;
355 float **buffer;
356 int c, channels = s->vi.channels;
357
358 buffer = vorbis_analysis_buffer(&s->vd, samples);
359 for (c = 0; c < channels; c++) {
360 int co = (channels > 8) ? c :
361 vorbis_encoding_channel_layout_offsets[channels - 1][c];
362 memcpy(buffer[c], frame->extended_data[co],
363 samples * sizeof(*buffer[c]));
364 }
365 if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) {
366 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote()\n");
367 return vorbis_error_to_averror(ret);
368 }
369 if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
370 return ret;
371 } else {
372 if (!s->eof && s->afq.frame_alloc)
373 if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) {
374 av_log(avctx, AV_LOG_ERROR16, "error in vorbis_analysis_wrote()\n");
375 return vorbis_error_to_averror(ret);
376 }
377 s->eof = 1;
378 }
379
380 /* retrieve available packets from libvorbis */
381 while ((ret = vorbis_analysis_blockout(&s->vd, &s->vb)) == 1) {
382 if ((ret = vorbis_analysis(&s->vb, NULL((void*)0))) < 0)
383 break;
384 if ((ret = vorbis_bitrate_addblock(&s->vb)) < 0)
385 break;
386
387 /* add any available packets to the output packet buffer */
388 while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) {
389 if (av_fifo_can_write(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) {
390 av_log(avctx, AV_LOG_ERROR16, "packet buffer is too small\n");
391 return AVERROR_BUG(-(int)(('B') | (('U') << 8) | (('G') << 16) | ((
unsigned)('!') << 24)))
;
392 }
393 av_fifo_write(s->pkt_fifo, &op, sizeof(ogg_packet));
394 av_fifo_write(s->pkt_fifo, op.packet, op.bytes);
395 }
396 if (ret < 0) {
397 av_log(avctx, AV_LOG_ERROR16, "error getting available packets\n");
398 break;
399 }
400 }
401 if (ret < 0) {
402 av_log(avctx, AV_LOG_ERROR16, "error getting available packets\n");
403 return vorbis_error_to_averror(ret);
404 }
405
406 /* Read an available packet if possible */
407 if (av_fifo_read(s->pkt_fifo, &op, sizeof(ogg_packet)) < 0)
408 return 0;
409
410 if ((ret = ff_get_encode_buffer(avctx, avpkt, op.bytes, 0)) < 0)
411 return ret;
412 av_fifo_read(s->pkt_fifo, avpkt->data, op.bytes);
413
414 avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos);
415
416 duration = av_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size);
417 if (duration > 0) {
418 int discard_padding;
419
420 ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration);
421
422 discard_padding = duration - ff_samples_from_time_base(avctx, avpkt->duration);
423 if (discard_padding > 0) {
424 uint8_t *side_data = av_packet_new_side_data(avpkt,
425 AV_PKT_DATA_SKIP_SAMPLES,
426 10);
427 if (!side_data)
428 return AVERROR(ENOMEM)(-(12));
429 AV_WL32(side_data + 4, discard_padding)((((union unaligned_32 *) (side_data + 4))->l) = (discard_padding
))
;
430 }
431 }
432
433 *got_packet_ptr = 1;
434 return 0;
435}
436
437const FFCodec ff_libvorbis_encoder = {
438 .p.name = "libvorbis",
439 CODEC_LONG_NAME("libvorbis").p.long_name = "libvorbis",
440 .p.type = AVMEDIA_TYPE_AUDIO,
441 .p.id = AV_CODEC_ID_VORBIS,
442 .p.capabilities = AV_CODEC_CAP_DR1(1 << 1) | AV_CODEC_CAP_DELAY(1 << 5) |
443 AV_CODEC_CAP_SMALL_LAST_FRAME(1 << 6),
444 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE(1 << 0),
445 .priv_data_size = sizeof(LibvorbisEncContext),
446 .init = libvorbis_encode_init,
447 FF_CODEC_ENCODE_CB(libvorbis_encode_frame).is_decoder = 0, .cb_type = FF_CODEC_CB_TYPE_ENCODE, .cb.encode
= (libvorbis_encode_frame)
,
448 .close = libvorbis_encode_close,
449 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP).sample_fmts = ((((const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP
, AV_SAMPLE_FMT_NONE })))
,
450 .p.priv_class = &vorbis_class,
451 .defaults = defaults,
452 .p.wrapper_name = "libvorbis",
453};