Compare commits

..

20 commits

Author SHA1 Message Date
Manuel Lauss
0226b6fb2c avcodec/sanm: bl16: fix artifacts in larger videos
Some checks failed
/ lint (push) Has been cancelled
/ run_fate (linux-aarch64) (push) Has been cancelled
/ run_fate (linux-amd64) (push) Has been cancelled
/ compile_only (ghcr.io/btbn/ffmpeg-builds/win64-gpl:latest) (push) Has been cancelled
The DOS/Windows decoder precomputes a table of linear offsets of
all motion vectors given the current image width.
For larger widths (>=762), the pairs starting at indices 1 and 254
of motion_vectors[] will overflow the int16_t, changing the sign.

Playing back the 800x600 "jonesopn_8.snm" video of "Indiana Jones and
the Infernal Machine" reveals a lot of artifacts and a lot of
"Ignoring invalid motion vector (149, -41)->(136, 0), block size = 8"
messages, hinting at the wrong direction of the motion vectors.

Fix this by doing the calculation that the DOS/Windows players do,
let the value overflow and reextract the "new" mvec x/y components.
2025-08-18 09:11:09 +00:00
Valerii Zapodovnikov
8426622bb9 avformat/avio: clarify that AVSEEK_FORCE has no effect
avio_seek() never supported SEEK_END and returned AVERROR(EINVAL) when
specified, so the later check "(whence != SEEK_END || force)" was always true.

This also means that AVSEEK_FORCE had no effect since 7a6fe01f99, that is 15
years ago. Rather than changing behaviour, let's document instead that the flag
has no effect.

Also fixed other commit 41ed7ab45f which confused ORing / passing AVSEEK_FORCE
and AVSEEK_SIZE in the docs.

Signed-off-by: Valerii Zapodovnikov <val.zapod.vz@gmail.com>
2025-08-17 20:47:11 +00:00
Michael Niedermayer
134fbfd1dc
avcodec/sanm: Check w,h,left,top
The setup code fow w,h,left,top is complex, the code using it also falls in
at least 2 different classes, one using left/top the other not.

To ensure no out of array access happens we add this clear check.

Fixes: out of array access
Fixes: 439261995/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SANM_fuzzer-5383455572819968

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-17 15:39:33 +02:00
James Almer
a2cfaf1b91 avformat/mov: pass stream index to sanity_checks on HEIF images
Instead of item_id. Same behavior as with standard video tracks.

Signed-off-by: James Almer <jamrial@gmail.com>
2025-08-16 21:59:18 -03:00
James Almer
a28e01a6c1 avformat/mov: don't use an allocated array for sample_size with HEIF images
The array is only ever needed for streams where each sample entry may have a
different value. Given that for non animated HEIF there's a single value that
applies to the image, use the field defined for that.

Fixes: NULL pointer dereference
Fixes: 437528618/clusterfuzz-testcase-minimized-ffmpeg_dem_MOV_fuzzer-6537287645331456

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial@gmail.com>
2025-08-16 21:59:18 -03:00
Gyan Doshi
7df9271272 avfilter/whisper: correct option formatting 2025-08-17 00:58:03 +00:00
Zhao Zhili
1d06e8ddcd avfilter/af_whisper: fix broken output for multibyte character
text + 1 can break a multibyte character, e.g., Chinese in UTF-8.
There is no space at the beginning in this case.
2025-08-16 13:58:14 +00:00
Leo Izen
30e6956920
.forgejo/CODEOWNERS: add myself to JPEG XL and PNG
Add myself to JPEG XL and PNG decoders/encoders/parsers/etc. as a
suggested reviewer. I'm the maintainer of the JXL files and I know the
PNG code very well.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
2025-08-16 05:07:19 -04:00
Jack Lau
37507c6a78 avformat/whip: remove DTLSState enum
This patch aims to simplify the dtls handshake process
since dtls handshake use force block mode

We can just use the return code instead of DTLSState enum

Signed-off-by: Jack Lau <jacklau1222@qq.com>
2025-08-16 06:25:04 +00:00
Michael Niedermayer
50affd2b09 avcodec/rv60dec: clear pu_info
pu_info is read uninitialized on damaged input and at that point the following codepath is dependant
on the uninitialized data. In one of these pathes out of array accesses happen.
None of this is replicatable

Less uninitialized data also should result in more reproducable reports

Fixes: Use of uninitialized memory
Fixes: 418335931/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RV60_fuzzer-5103986067963904

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-16 00:24:52 +00:00
Kacper Michajłow
61d0050924 avformat/tls_openssl: simplify fingerprint generation
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-16 00:15:30 +00:00
Kacper Michajłow
4676f97928 avformat/tls_openssl: clean keys serialization
It was unnecessary convoluted, remove not needed memory allocations,
snprintf.

Also fixes posibility to call snprinft with NULL as %s input.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-16 00:15:30 +00:00
Kacper Michajłow
113c9c6cf3 configure: require at least OpenSSL 1.1.1 (LTS)
Commit f256487cd8 bumped requirement to
1.1.0 for OPENSSL_init_ssl.

Bump this again to 1.1.1, because it was an LTS version. Although it has
no mainline support anymore, it still has paid/premium support. 1.1.0 has
no support at all.

Motivated for use of BIO_read_ex() for next commits.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-16 00:15:30 +00:00
Kacper Michajłow
3a8b3dfeca avformat/tls_openssl: use ascii - (0x2D) instead of 0x2010 hyphen
Too much AI is bad for you...

Fixes: 167e343bbe
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-16 00:15:30 +00:00
Kacper Michajłow
1f4fed5cc3 w32pthreads: add support for setting thread name
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2025-08-15 19:54:01 +00:00
Kacper Michajłow
5ff2500514
avcodec/x86/Makefile: add missing x86/proresdsp.o for prores raw 2025-08-15 20:45:20 +02:00
wangbin
6e48050568 configure: fix -L flags for lld-link 2025-08-15 18:20:33 +00:00
Michael Niedermayer
2a22972db3
avcodec/utvideodec: Clear plane_start array
in pack mode the array is passed into decode_plane() without being initialized or used

Fixes: use of uninitialized memory
Fixes: 438780119/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_UTVIDEO_DEC_fuzzer-5464037027807232

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2025-08-15 18:00:11 +02:00
Oliver Chang
c9e93df4ee avcodec/prores_raw: Fix heap buffer overflow
When dimensions differ from context, those were updated using
ff_set_dimensions, however this overwrote the aligned coded_width and
coded_height that were set before, leading to a buffer overflow when
writing the frame data.

Fixes: OssFuzz 438771336
Fixes: Heap-buffer-overflow

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Reviewed-by: Marvin Scholz <epirat07@gmail.com>
2025-08-15 15:06:58 +00:00
David Rosca
ac5303a5b9 hw_base_encode: Support refs option to limit number of references
Set default value to 0 to keep the old behavior of using maximum number
of references.
2025-08-15 13:55:51 +00:00
33 changed files with 169 additions and 709 deletions

View file

@ -20,9 +20,10 @@ libavcodec/.*ffv1.* @lynne @michaelni
libavcodec/golomb.* @michaelni libavcodec/golomb.* @michaelni
libavcodec/.*h266.* @frankplow @NuoMi @jianhuaw libavcodec/.*h266.* @frankplow @NuoMi @jianhuaw
libavcodec/h26x/.* @frankplow @NuoMi @jianhuaw libavcodec/h26x/.* @frankplow @NuoMi @jianhuaw
libavcodec/.*jpegxl.* @lynne libavcodec/.*jpegxl.* @lynne @Traneptora
libavcodec/.*jxl.* @lynne libavcodec/.*jxl.* @lynne @Traneptora
libavcodec/.*opus.* @lynne libavcodec/.*opus.* @lynne
libavcodec/.*png.* @Traneptora
libavcodec/.*prores.* @lynne libavcodec/.*prores.* @lynne
libavcodec/rangecoder.* @michaelni libavcodec/rangecoder.* @michaelni
libavcodec/ratecontrol.* @michaelni libavcodec/ratecontrol.* @michaelni
@ -45,6 +46,8 @@ libavfilter/vsrc_mandelbrot.* @michaelni
# avformat # avformat
# ======= # =======
libavformat/iamf.* @jamrial libavformat/iamf.* @jamrial
libavformat/.*jpegxl.* @Traneptora
libavformat/.*jxl.* @Traneptora
# avutil # avutil
# ====== # ======

1
.gitignore vendored
View file

@ -46,4 +46,3 @@
/libavfilter/vulkan/*.c /libavfilter/vulkan/*.c
/.*/ /.*/
!/.forgejo/ !/.forgejo/
*.orig

View file

@ -8,6 +8,7 @@ version 8.0:
- Whisper filter - Whisper filter
- Drop support for OpenSSL < 1.1.0 - Drop support for OpenSSL < 1.1.0
- Enable TLS peer certificate verification by default (on next major version bump) - Enable TLS peer certificate verification by default (on next major version bump)
- Drop support for OpenSSL < 1.1.1
- yasm support dropped, users need to use nasm - yasm support dropped, users need to use nasm
- VVC VAAPI decoder - VVC VAAPI decoder
- RealVideo 6.0 decoder - RealVideo 6.0 decoder

View file

@ -44,6 +44,7 @@
#include "libavutil/internal.h" #include "libavutil/internal.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "libavutil/time.h" #include "libavutil/time.h"
#include "libavutil/wchar_filename.h"
typedef struct pthread_t { typedef struct pthread_t {
void *handle; void *handle;
@ -209,4 +210,38 @@ static inline int pthread_setcancelstate(int state, int *oldstate)
return 0; return 0;
} }
static inline int win32_thread_setname(const char *name)
{
#if !HAVE_UWP
typedef HRESULT (WINAPI *SetThreadDescriptionFn)(HANDLE, PCWSTR);
// Although SetThreadDescription lives in kernel32.dll, on Windows Server 2016,
// Windows 10 LTSB 2016 and Windows 10 version 1607, it was only available in
// kernelbase.dll. So, load it from there for maximum coverage.
HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
if (!kernelbase)
return AVERROR(ENOSYS);
SetThreadDescriptionFn pSetThreadDescription =
(SetThreadDescriptionFn)GetProcAddress(kernelbase, "SetThreadDescription");
if (!pSetThreadDescription)
return AVERROR(ENOSYS);
wchar_t *wname;
if (utf8towchar(name, &wname) < 0)
return AVERROR(ENOMEM);
HRESULT hr = pSetThreadDescription(GetCurrentThread(), wname);
av_free(wname);
return SUCCEEDED(hr) ? 0 : AVERROR(EINVAL);
#else
// UWP is not supported because we cannot use LoadLibrary/GetProcAddress to
// detect the availability of the SetThreadDescription API. There is a small
// gap in Windows builds 1507-1607 where it was not available. UWP allows
// querying the availability of APIs with QueryOptionalDelayLoadedAPI, but it
// requires /DELAYLOAD:kernel32.dll during linking, and we cannot enforce that.
return AVERROR(ENOSYS);
#endif
}
#endif /* COMPAT_W32PTHREADS_H */ #endif /* COMPAT_W32PTHREADS_H */

12
configure vendored
View file

@ -212,7 +212,6 @@ External library support:
--enable-jni enable JNI support [no] --enable-jni enable JNI support [no]
--enable-ladspa enable LADSPA audio filtering [no] --enable-ladspa enable LADSPA audio filtering [no]
--enable-lcms2 enable ICC profile support via LittleCMS 2 [no] --enable-lcms2 enable ICC profile support via LittleCMS 2 [no]
--enable-libaac-next enable AAC encoding using libaac-next [no]
--enable-libaom enable AV1 video encoding/decoding via libaom [no] --enable-libaom enable AV1 video encoding/decoding via libaom [no]
--enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no] --enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no]
--enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no] --enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no]
@ -1902,7 +1901,6 @@ EXTERNAL_LIBRARY_NONFREE_LIST="
EXTERNAL_LIBRARY_VERSION3_LIST=" EXTERNAL_LIBRARY_VERSION3_LIST="
gmp gmp
libaac_next
libaribb24 libaribb24
liblensfun liblensfun
libopencore_amrnb libopencore_amrnb
@ -3594,9 +3592,6 @@ hevc_videotoolbox_encoder_deps="pthreads"
hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder"
prores_videotoolbox_encoder_deps="pthreads" prores_videotoolbox_encoder_deps="pthreads"
prores_videotoolbox_encoder_select="videotoolbox_encoder" prores_videotoolbox_encoder_select="videotoolbox_encoder"
libaac_next_decoder_deps="libaac_next"
libaac_next_encoder_deps="libaac_next"
libaac_next_encoder_select="audio_frame_queue"
libaom_av1_decoder_deps="libaom" libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom" libaom_av1_encoder_deps="libaom"
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc" libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
@ -5179,7 +5174,7 @@ probe_cc(){
# but we can force it back to gnu mode and get the version from there. # but we can force it back to gnu mode and get the version from there.
_ident=$($_cc -flavor gnu --version 2>/dev/null) _ident=$($_cc -flavor gnu --version 2>/dev/null)
_ld_o='-out:$@' _ld_o='-out:$@'
_flags_filter=msvc_flags _flags_filter=msvc_flags_link
_ld_lib='%.lib' _ld_lib='%.lib'
_ld_path='-libpath:' _ld_path='-libpath:'
elif VSLANG=1033 $_cc -nologo- 2>&1 | grep -q ^Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then elif VSLANG=1033 $_cc -nologo- 2>&1 | grep -q ^Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then
@ -7021,7 +7016,6 @@ enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gn
enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; } enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; }
enabled ladspa && require_headers "ladspa.h dlfcn.h" enabled ladspa && require_headers "ladspa.h dlfcn.h"
enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext
enabled libaac_next && require_pkg_config libaac_next "libaac >= 1.0.0" libaac.h aac_encode_open
enabled libaom && require_pkg_config libaom "aom >= 2.0.0" aom/aom_codec.h aom_codec_version enabled libaom && require_pkg_config libaom "aom >= 2.0.0" aom/aom_codec.h aom_codec_version
enabled liboapv && require_pkg_config liboapv "oapv >= 0.2.0.0" "oapv/oapv.h" oapve_encode enabled liboapv && require_pkg_config liboapv "oapv >= 0.2.0.0" "oapv/oapv.h" oapve_encode
enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new || enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new ||
@ -7266,10 +7260,10 @@ enabled omx && require_headers OMX_Core.h && \
enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" openssl/ssl.h OPENSSL_init_ssl && enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0" openssl/ssl.h OPENSSL_init_ssl &&
{ enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } || { enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } ||
{ enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } || { enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } ||
check_pkg_config openssl "openssl >= 1.1.0" openssl/ssl.h OPENSSL_init_ssl || check_pkg_config openssl "openssl >= 1.1.1" openssl/ssl.h OPENSSL_init_ssl ||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto || check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto -lws2_32 -lgdi32 || check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto -lws2_32 -lgdi32 ||
die "ERROR: openssl (>= 1.1.0) not found"; } die "ERROR: openssl (>= 1.1.1) not found"; }
enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init
enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create && enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create &&
require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create && require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create &&

View file

@ -1144,8 +1144,6 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_LIBAAC_NEXT_ENCODER) += libaac_nextenc.o
OBJS-$(CONFIG_LIBAAC_NEXT_DECODER) += libaac_nextdec.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o

View file

@ -766,8 +766,6 @@ extern const FFCodec ff_pcm_mulaw_at_encoder;
extern const FFCodec ff_pcm_mulaw_at_decoder; extern const FFCodec ff_pcm_mulaw_at_decoder;
extern const FFCodec ff_qdmc_at_decoder; extern const FFCodec ff_qdmc_at_decoder;
extern const FFCodec ff_qdm2_at_decoder; extern const FFCodec ff_qdm2_at_decoder;
extern const FFCodec ff_libaac_next_encoder;
extern const FFCodec ff_libaac_next_decoder;
extern FFCodec ff_libaom_av1_encoder; extern FFCodec ff_libaom_av1_encoder;
/* preferred over libaribb24 */ /* preferred over libaribb24 */
extern const FFCodec ff_libaribcaption_decoder; extern const FFCodec ff_libaribcaption_decoder;

View file

@ -762,6 +762,7 @@ static const FFCodecDefault d3d12va_encode_hevc_defaults[] = {
{ "b_qoffset", "0" }, { "b_qoffset", "0" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -666,6 +666,11 @@ int ff_hw_base_init_gop_structure(FFHWBaseEncodeContext *ctx, AVCodecContext *av
ctx->ref_l0 = FFMIN(ref_l0, MAX_PICTURE_REFERENCES); ctx->ref_l0 = FFMIN(ref_l0, MAX_PICTURE_REFERENCES);
ctx->ref_l1 = FFMIN(ref_l1, MAX_PICTURE_REFERENCES); ctx->ref_l1 = FFMIN(ref_l1, MAX_PICTURE_REFERENCES);
if (avctx->refs > 0) {
ctx->ref_l0 = FFMIN(ctx->ref_l0, avctx->refs);
ctx->ref_l1 = FFMIN(ctx->ref_l1, avctx->refs);
}
if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) { if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) {
av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
ctx->gop_size = 1; ctx->gop_size = 1;

View file

@ -1,170 +0,0 @@
/*
* Libaac-next decoder (libxaac based)
* Copyright (c) 2025 Wrapper
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Interface to libaac-next decoder.
*/
#include "avcodec.h"
#include <libaac.h>
#include "libavcodec/codec_id.h"
#include "libavutil/channel_layout.h"
#include "libavutil/error.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "decode.h"
#include "libavutil/samplefmt.h"
#include "libavutil/mem.h"
typedef struct {
AVClass *class;
AACDecode *decoder;
int error_conceal;
int esbr;
unsigned char *decode_buffer;
} libaacDecodeCTX;
static const AVChannelLayout aac_ch_layouts[6] = {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND,
AV_CHANNEL_LAYOUT_4POINT0,
AV_CHANNEL_LAYOUT_5POINT0_BACK,
AV_CHANNEL_LAYOUT_5POINT1_BACK,
};
static const AVOption aac_dec_options[] = {
{ "conceal", "Error concealment", offsetof(libaacDecodeCTX, error_conceal), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
{ "esbr", "Enable the use of Enhanced SBR", offsetof(libaacDecodeCTX, esbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
{ NULL }
};
static const AVClass aac_dec_class = {
.class_name = "libaac",
.item_name = av_default_item_name,
.option = aac_dec_options,
.version = LIBAVUTIL_VERSION_INT,
};
static void aac_dec_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
AVCodecContext *ctx = (AVCodecContext *)handle;
av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
}
static av_cold int libaac_decode_init(AVCodecContext *avctx)
{
libaacDecodeCTX *s = avctx->priv_data;
AACDecodeSettings cfg = {0};
cfg.bitsPerSamples = 16;
cfg.errorConceal = s->error_conceal;
cfg.eSBR = s->esbr;
cfg.frameSize = 0;
cfg.asc = avctx->extradata;
cfg.ascSize = avctx->extradata_size;
cfg.errorHandleCtx = avctx;
cfg.errorHandler = aac_dec_error_handler;
s->decoder = aac_decode_open(cfg);
if (!s->decoder)
{
return AVERROR(EINVAL);
}
s->decode_buffer = av_mallocz(4096 * 8);
if (!s->decode_buffer)
{
return AVERROR(ENOMEM);
}
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
return 0;
}
static av_cold int libaac_decode_close(AVCodecContext *avctx)
{
libaacDecodeCTX *s = avctx->priv_data;
if (s->decoder)
aac_decode_close(s->decoder);
return 0;
}
static int libaac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
int *got_frame_ptr, AVPacket *avpkt)
{
libaacDecodeCTX *s = avctx->priv_data;
uint32_t decode_size, read_size;
int ret;
ret = aac_decode(s->decoder, avpkt->data, avpkt->size, s->decode_buffer, &decode_size, &read_size);
if (ret < 0)
return AVERROR_EXTERNAL;
avctx->sample_rate = s->decoder->sampleRate;
avctx->profile = s->decoder->aot - 1;
avctx->ch_layout = aac_ch_layouts[s->decoder->noChannels - 1];
avctx->frame_size = 1024;
if (decode_size <= 0)
return AVERROR_EOF;
frame->nb_samples = decode_size / av_get_bytes_per_sample(avctx->sample_fmt) / avctx->ch_layout.nb_channels;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
av_log(avctx, AV_LOG_TRACE, "aac decode size: %d, decode buf: %d\n", decode_size, avctx->ch_layout.nb_channels * frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt));
memcpy(frame->data[0], s->decode_buffer, decode_size);
*got_frame_ptr = 1;
return read_size;
}
static av_cold void libaac_decode_flush(AVCodecContext *avctx)
{
libaacDecodeCTX *s = avctx->priv_data;
if (!s->decoder)
return;
aac_decode_flush_buffer(s->decoder);
}
const FFCodec ff_libaac_next_decoder = {
.p.name = "libaac",
CODEC_LONG_NAME("custom libxaac-based AAC decoder"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(libaacDecodeCTX),
.init = libaac_decode_init,
FF_CODEC_DECODE_CB(libaac_decode_frame),
.close = libaac_decode_close,
.flush = libaac_decode_flush,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
.p.priv_class = &aac_dec_class,
.p.wrapper_name = "libaac",
};

View file

@ -1,305 +0,0 @@
/*
* Libaac-next encoder (libxaac based)
* Copyright (c) 2025 Wrapper
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Interface to libaac-next encoder.
*/
#include <libaac.h>
#include "libavutil/channel_layout.h"
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/mem.h"
#include "avcodec.h"
#include "defs.h"
#include "audio_frame_queue.h"
#include "codec_internal.h"
#include "encode.h"
#include "libavutil/samplefmt.h"
#include "profiles.h"
typedef struct
{
const AVClass *class;
AACContext *encoder;
int delay_sent;
int flush_delay;
int eld_v2;
int esbr;
int frame_length;
int iq;
int tns;
AudioFrameQueue afq;
} libaacEncodeCTX;
static const AVOption aac_enc_options[] = {
{ "eld_v2", "Enable ELDv2 (LD-MPS extension for ELD stereo signals)", offsetof(libaacEncodeCTX, eld_v2), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
{ "esbr", "Enable the use of Enhanced SBR", offsetof(libaacEncodeCTX, esbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
{ "frame_length", "The desired frame length", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1024, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
{ "iq", "Inverse quantization", offsetof(libaacEncodeCTX, frame_length), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
{ "tns", "Temporal Noise Shaping", offsetof(libaacEncodeCTX, tns), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
FF_AAC_PROFILE_OPTS
{ NULL }
};
static const AVClass aac_enc_class = {
.class_name = "libaac",
.item_name = av_default_item_name,
.option = aac_enc_options,
.version = LIBAVUTIL_VERSION_INT,
};
static void aac_enc_error_handler(uint32_t errorCode, const char *section, const char *errorMsg, bool isFatal, void *handle) {
AVCodecContext *ctx = (AVCodecContext *)handle;
av_log(ctx, AV_LOG_ERROR, "%s: %s (0x%08X)\n", section, errorMsg, errorCode);
}
static av_cold int libaac_encode_init(AVCodecContext *avctx)
{
libaacEncodeCTX *s = avctx->priv_data;
AACSettings cfg = {0};
/* number of channels */
if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 6)
{
av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->ch_layout.nb_channels);
return AVERROR(EINVAL);
}
cfg.sampleRate = avctx->sample_rate;
cfg.noChannels = avctx->ch_layout.nb_channels;
cfg.bitsPerSamples = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? 32 : 16;
cfg.bitrate = avctx->bit_rate;
cfg.adts = !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
cfg.cutoff = avctx->cutoff;
switch (avctx->profile) {
case AV_PROFILE_AAC_LOW:
case AV_PROFILE_UNKNOWN:
cfg.profile = AAC_LC;
break;
case AV_PROFILE_AAC_HE:
cfg.profile = AAC_HE;
break;
case AV_PROFILE_AAC_HE_V2:
cfg.profile = AAC_HEV2;
break;
case AV_PROFILE_AAC_LD:
cfg.profile = AAC_LD;
break;
case AV_PROFILE_AAC_ELD:
cfg.profile = AAC_ELD;
break;
default:
av_log(avctx, AV_LOG_ERROR, "unsupported profile, supported profiles are LC, HE, HEv2, LD and ELD\n");
return AVERROR(EINVAL);
}
cfg.tns = s->tns;
cfg.frameSize = s->frame_length;
cfg.eSBR = s->esbr;
cfg.iq = s->iq;
cfg.errorHandleCtx = avctx;
cfg.errorHandler = aac_enc_error_handler;
s->encoder = aac_encode_open(cfg);
if (!s->encoder)
{
return AVERROR(EINVAL);
}
avctx->frame_size = s->encoder->no_samples / avctx->ch_layout.nb_channels;
avctx->initial_padding = s->encoder->inputDelay;
s->flush_delay = s->encoder->inputDelay;
av_log(avctx, AV_LOG_TRACE, "frame size: %d, initial delay: %d\n", avctx->frame_size, avctx->initial_padding);
ff_af_queue_init(avctx, &s->afq);
/* Set decoder specific info */
avctx->extradata_size = 0;
if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
{
avctx->extradata = av_mallocz(s->encoder->ascSize + AV_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
{
return AVERROR(ENOMEM);
}
memcpy(avctx->extradata, s->encoder->asc, s->encoder->ascSize);
}
return 0;
}
static int libaac_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *frame, int *got_packet)
{
libaacEncodeCTX *s = avctx->priv_data;
int ret;
int discard_padding;
if ((ret = ff_alloc_packet(avctx, pkt, s->encoder->max_out_bytes)) < 0)
return ret;
if (!frame)
{
av_log(avctx, AV_LOG_TRACE, "flush_delay: %d\n", s->flush_delay);
if (s->flush_delay <= 0)
return 0;
/* Flushing */
if ((ret = aac_encode(s->encoder, NULL, 0, pkt->data, (unsigned int *)&pkt->size)) < 0)
{
return AVERROR(EINVAL);
}
s->flush_delay -= avctx->frame_size;
}
else
{
/* Encoding */
if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
return ret;
int encodeSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels * frame->nb_samples;
av_log(avctx, AV_LOG_TRACE, "encode size: %d\n", encodeSize);
if ((ret = aac_encode(s->encoder, frame->data[0], encodeSize, pkt->data, (unsigned int *)&pkt->size)) < 0)
{
return AVERROR(EINVAL);
}
}
ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration);
/* discard padding copied from fdkaac encoder */
discard_padding = avctx->frame_size - pkt->duration;
// Check if subtraction resulted in an overflow
if ((discard_padding < avctx->frame_size) != (pkt->duration > 0))
{
av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
return AVERROR(EINVAL);
}
if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0)
{
uint8_t *side_data =
av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
if (!s->delay_sent)
{
AV_WL32(side_data, avctx->initial_padding);
s->delay_sent = 1;
}
AV_WL32(side_data + 4, discard_padding);
}
pkt->flags |= AV_PKT_FLAG_KEY;
*got_packet = 1;
return 0;
}
static void libaac_encode_flush(AVCodecContext *avctx)
{
libaacEncodeCTX *s = avctx->priv_data;
uint8_t sink_null[32768];
int64_t pts, duration;
uint32_t out_bytes;
av_log(avctx, AV_LOG_TRACE, "encoder flush\n");
ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
aac_encode(s->encoder, NULL, 0, sink_null, &out_bytes);
}
static av_cold int libaac_encode_close(AVCodecContext *avctx)
{
libaacEncodeCTX *s = avctx->priv_data;
if (s->encoder)
aac_encode_close(s->encoder);
ff_af_queue_close(&s->afq);
return 0;
}
static const FFCodecDefault defaults[] = {
{"b", "128000"},
{NULL}};
static const AVProfile libaac_profiles[] = {
{ AV_PROFILE_AAC_LOW, "LC" },
{ AV_PROFILE_AAC_HE, "HE-AAC" },
{ AV_PROFILE_AAC_HE_V2, "HE-AACv2" },
{ AV_PROFILE_AAC_LD, "LD" },
{ AV_PROFILE_AAC_ELD, "ELD" },
{AV_PROFILE_UNKNOWN},
};
static const int aac_sample_rates[] = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 0
};
static const AVChannelLayout aac_ch_layouts[6] = {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND,
AV_CHANNEL_LAYOUT_4POINT0,
AV_CHANNEL_LAYOUT_5POINT0_BACK,
AV_CHANNEL_LAYOUT_5POINT1_BACK,
};
const FFCodec ff_libaac_next_encoder = {
.p.name = "libaac",
CODEC_LONG_NAME("custom libxaac-based AAC encoder"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_ENCODER_FLUSH,
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
.priv_data_size = sizeof(libaacEncodeCTX),
.init = libaac_encode_init,
FF_CODEC_ENCODE_CB(libaac_encode_frame),
.flush = libaac_encode_flush,
.close = libaac_encode_close,
CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16),
.p.priv_class = &aac_enc_class,
.defaults = defaults,
.p.profiles = libaac_profiles,
CODEC_SAMPLERATES_ARRAY(aac_sample_rates),
.p.wrapper_name = "libaac",
CODEC_CH_LAYOUTS_ARRAY(aac_ch_layouts),
};

View file

@ -367,9 +367,6 @@ static int decode_frame(AVCodecContext *avctx,
if ((w & 1) || (h & 1)) if ((w & 1) || (h & 1))
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
avctx->coded_width = FFALIGN(w, 16);
avctx->coded_height = FFALIGN(h, 16);
if (w != avctx->width || h != avctx->height) { if (w != avctx->width || h != avctx->height) {
av_log(avctx, AV_LOG_WARNING, "picture resolution change: %ix%i -> %ix%i\n", av_log(avctx, AV_LOG_WARNING, "picture resolution change: %ix%i -> %ix%i\n",
avctx->width, avctx->height, w, h); avctx->width, avctx->height, w, h);
@ -377,6 +374,9 @@ static int decode_frame(AVCodecContext *avctx,
return ret; return ret;
} }
avctx->coded_width = FFALIGN(w, 16);
avctx->coded_height = FFALIGN(h, 16);
enum AVPixelFormat pix_fmt = AV_PIX_FMT_BAYER_RGGB16; enum AVPixelFormat pix_fmt = AV_PIX_FMT_BAYER_RGGB16;
if (pix_fmt != s->pix_fmt) { if (pix_fmt != s->pix_fmt) {
s->pix_fmt = pix_fmt; s->pix_fmt = pix_fmt;

View file

@ -308,6 +308,8 @@ static int update_dimensions_clear_info(RV60Context *s, int width, int height)
if ((ret = av_reallocp_array(&s->blk_info, s->blk_stride * (s->cu_height << 4), sizeof(s->blk_info[0]))) < 0) if ((ret = av_reallocp_array(&s->blk_info, s->blk_stride * (s->cu_height << 4), sizeof(s->blk_info[0]))) < 0)
return ret; return ret;
memset(s->pu_info, 0, s->pu_stride * (s->cu_height << 3) * sizeof(s->pu_info[0]));
for (int j = 0; j < s->cu_height << 4; j++) for (int j = 0; j < s->cu_height << 4; j++)
for (int i = 0; i < s->cu_width << 4; i++) for (int i = 0; i < s->cu_width << 4; i++)
s->blk_info[j*s->blk_stride + i].mv.mvref = MVREF_NONE; s->blk_info[j*s->blk_stride + i].mv.mvref = MVREF_NONE;

View file

@ -1757,6 +1757,11 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb)
memset(ctx->fbuf, 0, ctx->frm0_size); memset(ctx->fbuf, 0, ctx->frm0_size);
} }
if (w + FFMAX(left, 0) > ctx->avctx->width || h + FFMAX(top, 0) > ctx->avctx->height) {
avpriv_request_sample(ctx->avctx, "overly large frame\n");
return AVERROR_PATCHWELCOME;
}
switch (codec) { switch (codec) {
case 1: case 1:
case 3: case 3:
@ -2069,6 +2074,20 @@ static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
mx = motion_vectors[opcode][0]; mx = motion_vectors[opcode][0];
my = motion_vectors[opcode][1]; my = motion_vectors[opcode][1];
/* The original implementation of this codec precomputes a table
* of int16_t all motion vectors for given image width.
* For larger widths, starting with 762 pixels, the calculation of
* mv table indices 1+ and 255- overflow the int16_t, inverting the
* sign of the offset. This is actively exploited in e.g. the
* "jonesopn_8.snm" video of "Indiana Jones and the Infernal Machine".
* Therefore let the overflow happen and extract x/y components from
* the new value.
*/
if (ctx->width > 761) {
index = (int16_t)(my * ctx->width + mx);
mx = index % ctx->width;
my = index / ctx->width;
}
if (good_mvec(ctx, cx, cy, mx, my, blk_size)) { if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
copy_block(ctx->frm0 + cx + ctx->pitch * cy, copy_block(ctx->frm0 + cx + ctx->pitch * cy,
ctx->frm2 + cx + mx + ctx->pitch * (cy + my), ctx->frm2 + cx + mx + ctx->pitch * (cy + my),

View file

@ -585,7 +585,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
int buf_size = avpkt->size; int buf_size = avpkt->size;
UtvideoContext *c = avctx->priv_data; UtvideoContext *c = avctx->priv_data;
int i, j; int i, j;
const uint8_t *plane_start[5]; const uint8_t *plane_start[5] = {NULL};
int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size; int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size;
int ret; int ret;
GetByteContext gb; GetByteContext gb;

View file

@ -1027,6 +1027,7 @@ static const FFCodecDefault vaapi_encode_av1_defaults[] = {
{ "g", "120" }, { "g", "120" },
{ "qmin", "1" }, { "qmin", "1" },
{ "qmax", "255" }, { "qmax", "255" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -1153,6 +1153,7 @@ static const FFCodecDefault vaapi_encode_h264_defaults[] = {
{ "b_qoffset", "0" }, { "b_qoffset", "0" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -1184,6 +1184,7 @@ static const FFCodecDefault vaapi_encode_h265_defaults[] = {
{ "b_qoffset", "0" }, { "b_qoffset", "0" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -235,6 +235,7 @@ static const FFCodecDefault vaapi_encode_vp8_defaults[] = {
{ "g", "120" }, { "g", "120" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -292,6 +292,7 @@ static const FFCodecDefault vaapi_encode_vp9_defaults[] = {
{ "g", "250" }, { "g", "250" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -1367,6 +1367,7 @@ static const FFCodecDefault vulkan_encode_av1_defaults[] = {
{ "g", "300" }, { "g", "300" },
{ "qmin", "1" }, { "qmin", "1" },
{ "qmax", "255" }, { "qmax", "255" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -1634,6 +1634,7 @@ static const FFCodecDefault vulkan_encode_h264_defaults[] = {
{ "b_qoffset", "0" }, { "b_qoffset", "0" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -1761,6 +1761,7 @@ static const FFCodecDefault vulkan_encode_h265_defaults[] = {
{ "b_qoffset", "0" }, { "b_qoffset", "0" },
{ "qmin", "-1" }, { "qmin", "-1" },
{ "qmax", "-1" }, { "qmax", "-1" },
{ "refs", "0" },
{ NULL }, { NULL },
}; };

View file

@ -170,6 +170,7 @@ X86ASM-OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o
X86ASM-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct.o X86ASM-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct.o
X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o
X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o
X86ASM-OBJS-$(CONFIG_PRORES_RAW_DECODER) += x86/proresdsp.o
X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o
X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp.o X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp.o
X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o

View file

@ -215,7 +215,9 @@ static void run_transcription(AVFilterContext *ctx, AVFrame *frame, int samples)
for (int i = 0; i < n_segments; ++i) { for (int i = 0; i < n_segments; ++i) {
const char *text = whisper_full_get_segment_text(wctx->ctx_wsp, i); const char *text = whisper_full_get_segment_text(wctx->ctx_wsp, i);
char *text_cleaned = av_strireplace(text + 1, "[BLANK_AUDIO]", ""); if (av_isspace(text[0]))
text++;
char *text_cleaned = av_strireplace(text, "[BLANK_AUDIO]", "");
if (av_strnlen(text_cleaned, 1) == 0) { if (av_strnlen(text_cleaned, 1) == 0) {
av_freep(&text_cleaned); av_freep(&text_cleaned);
@ -428,7 +430,8 @@ static int query_formats(const AVFilterContext *ctx,
#define HOURS 3600000000 #define HOURS 3600000000
static const AVOption whisper_options[] = { static const AVOption whisper_options[] = {
{ "model", "Path to the whisper.cpp model file", OFFSET(model_path), AV_OPT_TYPE_STRING,.flags = FLAGS }, { "language", "Language for transcription ('auto' for auto-detect)", OFFSET(language), AV_OPT_TYPE_STRING, {.str = "auto"}, .flags = FLAGS }, { "model", "Path to the whisper.cpp model file", OFFSET(model_path), AV_OPT_TYPE_STRING,.flags = FLAGS },
{ "language", "Language for transcription ('auto' for auto-detect)", OFFSET(language), AV_OPT_TYPE_STRING, {.str = "auto"}, .flags = FLAGS },
{ "queue", "Audio queue size", OFFSET(queue), AV_OPT_TYPE_DURATION, {.i64 = 3000000}, 20000, HOURS, .flags = FLAGS }, { "queue", "Audio queue size", OFFSET(queue), AV_OPT_TYPE_DURATION, {.i64 = 3000000}, 20000, HOURS, .flags = FLAGS },
{ "use_gpu", "Use GPU for processing", OFFSET(use_gpu), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, .flags = FLAGS }, { "use_gpu", "Use GPU for processing", OFFSET(use_gpu), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, .flags = FLAGS },
{ "gpu_device", "GPU device to use", OFFSET(gpu_device), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS }, { "gpu_device", "GPU device to use", OFFSET(gpu_device), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },

View file

@ -461,17 +461,17 @@ int avio_put_str16be(AVIOContext *s, const char *str);
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type); void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
/** /**
* ORing this as the "whence" parameter to a seek function causes it to * Passing this as the "whence" parameter to a seek function causes it to
* return the filesize without seeking anywhere. Supporting this is optional. * return the filesize without seeking anywhere. Supporting this is optional.
* If it is not supported then the seek function will return <0. * If it is not supported then the seek function will return <0.
*/ */
#define AVSEEK_SIZE 0x10000 #define AVSEEK_SIZE 0x10000
/** /**
* Passing this flag as the "whence" parameter to a seek function causes it to * OR'ing this flag into the "whence" parameter to a seek function causes it to
* seek by any means (like reopening and linear reading) or other normally unreasonable * seek by any means (like reopening and linear reading) or other normally unreasonable
* means that can be extremely slow. * means that can be extremely slow.
* This may be ignored by the seek code. * This is the default and therefore ignored by the seek code since 2010.
*/ */
#define AVSEEK_FORCE 0x20000 #define AVSEEK_FORCE 0x20000

View file

@ -238,10 +238,9 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
FFIOContext *const ctx = ffiocontext(s); FFIOContext *const ctx = ffiocontext(s);
int64_t offset1; int64_t offset1;
int64_t pos; int64_t pos;
int force = whence & AVSEEK_FORCE;
int buffer_size; int buffer_size;
int short_seek; int short_seek;
whence &= ~AVSEEK_FORCE; whence &= ~AVSEEK_FORCE; // force flag does nothing
if(!s) if(!s)
return AVERROR(EINVAL); return AVERROR(EINVAL);
@ -282,8 +281,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
} else if ((!(s->seekable & AVIO_SEEKABLE_NORMAL) || } else if ((!(s->seekable & AVIO_SEEKABLE_NORMAL) ||
offset1 <= buffer_size + short_seek) && offset1 <= buffer_size + short_seek) &&
!s->write_flag && offset1 >= 0 && !s->write_flag && offset1 >= 0 &&
(!s->direct || !s->seek) && (!s->direct || !s->seek)) {
(whence != SEEK_END || force)) {
while(s->pos < offset && !s->eof_reached) while(s->pos < offset && !s->eof_reached)
fill_buffer(s); fill_buffer(s);
if (s->eof_reached) if (s->eof_reached)
@ -300,7 +298,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
s->pos = pos; s->pos = pos;
s->eof_reached = 0; s->eof_reached = 0;
fill_buffer(s); fill_buffer(s);
return avio_seek(s, offset, SEEK_SET | force); return avio_seek(s, offset, SEEK_SET);
} else { } else {
int64_t res; int64_t res;
if (s->write_flag) { if (s->write_flag) {

View file

@ -5456,10 +5456,6 @@ static int heif_add_stream(MOVContext *c, HEIFItem *item)
if (!sc->chunk_offsets) if (!sc->chunk_offsets)
goto fail; goto fail;
sc->chunk_count = 1; sc->chunk_count = 1;
sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
if (!sc->sample_sizes)
goto fail;
sc->sample_count = 1;
sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data)); sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
if (!sc->stts_data) if (!sc->stts_data)
goto fail; goto fail;
@ -10471,11 +10467,13 @@ static int mov_parse_heif_items(AVFormatContext *s)
st->codecpar->width = item->width; st->codecpar->width = item->width;
st->codecpar->height = item->height; st->codecpar->height = item->height;
err = sanity_checks(s, sc, item->item_id); sc->sample_size = sc->stsz_sample_size = item->extent_length;
if (err || !sc->sample_count) sc->sample_count = 1;
err = sanity_checks(s, sc, st->index);
if (err)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
sc->sample_sizes[0] = item->extent_length;
sc->chunk_offsets[0] = item->extent_offset + offset; sc->chunk_offsets[0] = item->extent_offset + offset;
if (item->item_id == mov->primary_item_id) if (item->item_id == mov->primary_item_id)

View file

@ -34,17 +34,6 @@
*/ */
#define MAX_CERTIFICATE_SIZE 8192 #define MAX_CERTIFICATE_SIZE 8192
enum DTLSState {
DTLS_STATE_NONE,
/* Whether DTLS handshake is finished. */
DTLS_STATE_FINISHED,
/* Whether DTLS session is closed. */
DTLS_STATE_CLOSED,
/* Whether DTLS handshake is failed. */
DTLS_STATE_FAILED,
};
typedef struct TLSShared { typedef struct TLSShared {
char *ca_file; char *ca_file;
int verify; int verify;
@ -65,8 +54,6 @@ typedef struct TLSShared {
int is_dtls; int is_dtls;
int use_srtp; int use_srtp;
enum DTLSState state;
/* The certificate and private key content used for DTLS handshake */ /* The certificate and private key content used for DTLS handshake */
char* cert_buf; char* cert_buf;
char* key_buf; char* key_buf;
@ -112,8 +99,6 @@ int ff_tls_set_external_socket(URLContext *h, URLContext *sock);
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz); int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz);
int ff_dtls_state(URLContext *h);
int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint); int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint);
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint); int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint);

View file

@ -35,127 +35,82 @@
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
/** /**
* Returns a heapallocated nullterminated string containing * Convert an EVP_PKEY to a PEM string.
* the PEMencoded public key. Caller must free.
*/ */
static char *pkey_to_pem_string(EVP_PKEY *pkey) { static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz)
BIO *mem = NULL; {
BUF_MEM *bptr = NULL; BIO *mem = NULL;
char *pem_str = NULL; size_t read_bytes = 0;
if (!pkey || !out || !out_sz)
goto done;
// Create a memory BIO
if (!(mem = BIO_new(BIO_s_mem()))) if (!(mem = BIO_new(BIO_s_mem())))
goto err; goto done;
// Write public key in PEM form
if (!PEM_write_bio_PrivateKey(mem, pkey, NULL, NULL, 0, NULL, NULL)) if (!PEM_write_bio_PrivateKey(mem, pkey, NULL, NULL, 0, NULL, NULL))
goto err; goto done;
// Extract pointer/length if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
BIO_get_mem_ptr(mem, &bptr); goto done;
if (!bptr || !bptr->length)
goto err;
// Allocate string (+1 for NUL) done:
pem_str = av_malloc(bptr->length + 1);
if (!pem_str)
goto err;
// Copy data & NULterminate
memcpy(pem_str, bptr->data, bptr->length);
pem_str[bptr->length] = '\0';
cleanup:
BIO_free(mem); BIO_free(mem);
return pem_str; if (out && out_sz)
out[read_bytes] = '\0';
err: return read_bytes;
// error path: free and return NULL
free(pem_str);
pem_str = NULL;
goto cleanup;
} }
/** /**
* Serialize an X509 certificate to a av_mallocd PEM string. * Convert an X509 certificate to a PEM string.
* Caller must free the returned pointer.
*/ */
static char *cert_to_pem_string(X509 *cert) static int cert_to_pem_string(X509 *cert, char *out, size_t out_sz)
{ {
BIO *mem = BIO_new(BIO_s_mem()); BIO *mem = NULL;
BUF_MEM *bptr = NULL; size_t read_bytes = 0;
char *out = NULL;
if (!mem) goto err; if (!cert || !out || !out_sz)
goto done;
if (!(mem = BIO_new(BIO_s_mem())))
goto done;
/* Write the PEM certificate */
if (!PEM_write_bio_X509(mem, cert)) if (!PEM_write_bio_X509(mem, cert))
goto err; goto done;
BIO_get_mem_ptr(mem, &bptr); if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes))
if (!bptr || !bptr->length) goto err; goto done;
out = av_malloc(bptr->length + 1); done:
if (!out) goto err;
memcpy(out, bptr->data, bptr->length);
out[bptr->length] = '\0';
cleanup:
BIO_free(mem); BIO_free(mem);
return out; if (out && out_sz)
out[read_bytes] = '\0';
err: return read_bytes;
free(out);
out = NULL;
goto cleanup;
} }
/** /**
* Generate a SHA-256 fingerprint of an X.509 certificate. * Generate a SHA-256 fingerprint of an X.509 certificate.
*
* @param ctx AVFormatContext for logging (can be NULL)
* @param cert X509 certificate to fingerprint
* @return Newly allocated fingerprint string in "AA:BB:CC:…" format,
* or NULL on error (logs via av_log if ctx is not NULL).
* Caller must free() the returned string.
*/ */
static char *generate_fingerprint(X509 *cert) static int x509_fingerprint(X509 *cert, char **fingerprint)
{ {
unsigned char md[EVP_MAX_MD_SIZE]; unsigned char md[EVP_MAX_MD_SIZE];
int n = 0; int n = 0;
AVBPrint fingerprint; AVBPrint buf;
char *result = NULL;
int i;
/* To prevent a crash during cleanup, always initialize it. */
av_bprint_init(&fingerprint, 0, AV_BPRINT_SIZE_UNLIMITED);
if (X509_digest(cert, EVP_sha256(), md, &n) != 1) { if (X509_digest(cert, EVP_sha256(), md, &n) != 1) {
av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n", ERR_error_string(ERR_get_error(), NULL)); av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n",
goto end; ERR_error_string(ERR_get_error(), NULL));
return AVERROR(ENOMEM);
} }
for (i = 0; i < n; i++) { av_bprint_init(&buf, n*3, n*3);
av_bprintf(&fingerprint, "%02X", md[i]);
if (i + 1 < n)
av_bprintf(&fingerprint, ":");
}
if (!fingerprint.str || !strlen(fingerprint.str)) { for (int i = 0; i < n - 1; i++)
av_log(NULL, AV_LOG_ERROR, "TLS: Fingerprint is empty\n"); av_bprintf(&buf, "%02X:", md[i]);
goto end; av_bprintf(&buf, "%02X", md[n - 1]);
}
result = av_strdup(fingerprint.str); return av_bprint_finalize(&buf, fingerprint);
if (!result) {
av_log(NULL, AV_LOG_ERROR, "TLS: Out of memory generating fingerprint\n");
}
end:
av_bprint_finalize(&fingerprint, NULL);
return result;
} }
int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint) int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
@ -165,7 +120,6 @@ int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t ke
AVBPrint key_bp, cert_bp; AVBPrint key_bp, cert_bp;
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
X509 *cert = NULL; X509 *cert = NULL;
char *key_tem = NULL, *cert_tem = NULL;
/* To prevent a crash during cleanup, always initialize it. */ /* To prevent a crash during cleanup, always initialize it. */
av_bprint_init(&key_bp, 1, MAX_CERTIFICATE_SIZE); av_bprint_init(&key_bp, 1, MAX_CERTIFICATE_SIZE);
@ -211,29 +165,18 @@ int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t ke
goto end; goto end;
} }
key_tem = pkey_to_pem_string(pkey); pkey_to_pem_string(pkey, key_buf, key_sz);
cert_tem = cert_to_pem_string(cert); cert_to_pem_string(cert, cert_buf, cert_sz);
snprintf(key_buf, key_sz, "%s", key_tem); ret = x509_fingerprint(cert, fingerprint);
snprintf(cert_buf, cert_sz, "%s", cert_tem); if (ret < 0)
av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url);
/* Generate fingerprint. */
if (fingerprint) {
*fingerprint = generate_fingerprint(cert);
if (!*fingerprint) {
av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url);
ret = AVERROR(EIO);
goto end;
}
}
end: end:
BIO_free(key_b); BIO_free(key_b);
av_bprint_finalize(&key_bp, NULL); av_bprint_finalize(&key_bp, NULL);
BIO_free(cert_b); BIO_free(cert_b);
av_bprint_finalize(&cert_bp, NULL); av_bprint_finalize(&cert_bp, NULL);
av_free(key_tem);
av_free(cert_tem);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
X509_free(cert); X509_free(cert);
return ret; return ret;
@ -376,12 +319,9 @@ static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerpri
goto einval_end; goto einval_end;
} }
if (fingerprint) { ret = x509_fingerprint(*cert, fingerprint);
*fingerprint = generate_fingerprint(*cert); if (ret < 0)
if (!*fingerprint) { goto end;
goto enomem_end;
}
}
goto end; goto end;
enomem_end: enomem_end:
@ -403,7 +343,6 @@ int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cer
int ret = 0; int ret = 0;
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
X509 *cert = NULL; X509 *cert = NULL;
char *key_tem = NULL, *cert_tem = NULL;
ret = openssl_gen_private_key(&pkey); ret = openssl_gen_private_key(&pkey);
if (ret < 0) goto error; if (ret < 0) goto error;
@ -411,14 +350,9 @@ int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cer
ret = openssl_gen_certificate(pkey, &cert, fingerprint); ret = openssl_gen_certificate(pkey, &cert, fingerprint);
if (ret < 0) goto error; if (ret < 0) goto error;
key_tem = pkey_to_pem_string(pkey); pkey_to_pem_string(pkey, key_buf, key_sz);
cert_tem = cert_to_pem_string(cert); cert_to_pem_string(cert, cert_buf, cert_sz);
snprintf(key_buf, key_sz, "%s", key_tem);
snprintf(cert_buf, cert_sz, "%s", cert_tem);
av_free(key_tem);
av_free(cert_tem);
error: error:
X509_free(cert); X509_free(cert);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
@ -427,7 +361,7 @@ error:
/** /**
* Deserialize a PEMencoded private or public key from a NUL-terminated C string. * Deserialize a PEM-encoded private or public key from a NUL-terminated C string.
* *
* @param pem_str The PEM text, e.g. * @param pem_str The PEM text, e.g.
* "-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----\n" * "-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----\n"
@ -458,7 +392,7 @@ static EVP_PKEY *pkey_from_pem_string(const char *pem_str, int is_priv)
} }
/** /**
* Deserialize a PEMencoded certificate from a NUL-terminated C string. * Deserialize a PEM-encoded certificate from a NUL-terminated C string.
* *
* @param pem_str The PEM text, e.g. * @param pem_str The PEM text, e.g.
* "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----\n" * "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----\n"
@ -542,12 +476,6 @@ int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t ma
return 0; return 0;
} }
int ff_dtls_state(URLContext *h)
{
TLSContext *c = h->priv_data;
return c->tls_shared.state;
}
static int print_ssl_error(URLContext *h, int ret) static int print_ssl_error(URLContext *h, int ret)
{ {
TLSContext *c = h->priv_data; TLSContext *c = h->priv_data;
@ -722,7 +650,6 @@ static int dtls_handshake(URLContext *h)
goto end; goto end;
ret = 0; ret = 0;
c->tls_shared.state = DTLS_STATE_FINISHED;
end: end:
return ret; return ret;
} }

View file

@ -681,12 +681,6 @@ int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t ma
#endif #endif
} }
int ff_dtls_state(URLContext *h)
{
TLSContext *c = h->priv_data;
return c->tls_shared.state;
}
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
void *data, unsigned long size) void *data, unsigned long size)
{ {
@ -1111,7 +1105,6 @@ static int tls_handshake(URLContext *h)
#endif #endif
c->connected = 1; c->connected = 1;
s->state = DTLS_STATE_FINISHED;
fail: fail:
return ret; return ret;

View file

@ -198,9 +198,6 @@ typedef struct WHIPContext {
/* The state of the RTC connection. */ /* The state of the RTC connection. */
enum WHIPState state; enum WHIPState state;
/* The callback return value for DTLS. */
int dtls_ret;
int dtls_closed;
/* Parameters for the input audio and video codecs. */ /* Parameters for the input audio and video codecs. */
AVCodecParameters *audio_par; AVCodecParameters *audio_par;
@ -348,41 +345,6 @@ static av_cold int certificate_key_init(AVFormatContext *s)
return ret; return ret;
} }
/**
* When DTLS state change.
*/
static int dtls_context_on_state(AVFormatContext *s, const char* type, const char* desc)
{
int ret = 0;
WHIPContext *whip = s->priv_data;
int state = ff_dtls_state(whip->dtls_uc);
if (state == DTLS_STATE_CLOSED) {
whip->dtls_closed = 1;
av_log(whip, AV_LOG_VERBOSE, "DTLS session closed, type=%s, desc=%s, elapsed=%dms\n",
type ? type : "", desc ? desc : "", ELAPSED(whip->whip_starttime, av_gettime()));
goto error;
}
if (state == DTLS_STATE_FAILED) {
whip->state = WHIP_STATE_FAILED;
av_log(whip, AV_LOG_ERROR, "DTLS session failed, type=%s, desc=%s\n",
type ? type : "", desc ? desc : "");
whip->dtls_ret = AVERROR(EIO);
goto error;
}
if (state == DTLS_STATE_FINISHED && whip->state < WHIP_STATE_DTLS_FINISHED) {
whip->state = WHIP_STATE_DTLS_FINISHED;
whip->whip_dtls_time = av_gettime();
av_log(whip, AV_LOG_VERBOSE, "DTLS handshake is done, elapsed=%dms\n",
ELAPSED(whip->whip_starttime, av_gettime()));
return ret;
}
error:
return -1;
}
static av_cold int dtls_initialize(AVFormatContext *s) static av_cold int dtls_initialize(AVFormatContext *s)
{ {
WHIPContext *whip = s->priv_data; WHIPContext *whip = s->priv_data;
@ -1326,9 +1288,18 @@ next_packet:
/* If got any DTLS messages, handle it. */ /* If got any DTLS messages, handle it. */
if (is_dtls_packet(whip->buf, ret) && whip->state >= WHIP_STATE_ICE_CONNECTED || whip->state == WHIP_STATE_DTLS_CONNECTING) { if (is_dtls_packet(whip->buf, ret) && whip->state >= WHIP_STATE_ICE_CONNECTED || whip->state == WHIP_STATE_DTLS_CONNECTING) {
whip->state = WHIP_STATE_DTLS_CONNECTING; whip->state = WHIP_STATE_DTLS_CONNECTING;
if ((ret = ffurl_handshake(whip->dtls_uc)) < 0) ret = ffurl_handshake(whip->dtls_uc);
if (ret < 0) {
whip->state = WHIP_STATE_FAILED;
av_log(whip, AV_LOG_VERBOSE, "DTLS session failed\n");
goto end; goto end;
dtls_context_on_state(s, NULL, NULL); }
if (!ret) {
whip->state = WHIP_STATE_DTLS_FINISHED;
whip->whip_dtls_time = av_gettime();
av_log(whip, AV_LOG_VERBOSE, "DTLS handshake is done, elapsed=%dms\n",
ELAPSED(whip->whip_starttime, whip->whip_dtls_time));
}
goto next_packet; goto next_packet;
} }
} }
@ -1771,10 +1742,8 @@ static av_cold int whip_init(AVFormatContext *s)
goto end; goto end;
end: end:
if (ret < 0 && whip->state < WHIP_STATE_FAILED) if (ret < 0)
whip->state = WHIP_STATE_FAILED; whip->state = WHIP_STATE_FAILED;
if (ret >= 0 && whip->state >= WHIP_STATE_FAILED && whip->dtls_ret < 0)
ret = whip->dtls_ret;
return ret; return ret;
} }
@ -1822,12 +1791,8 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt)
} }
end: end:
if (ret < 0 && whip->state < WHIP_STATE_FAILED) if (ret < 0)
whip->state = WHIP_STATE_FAILED; whip->state = WHIP_STATE_FAILED;
if (ret >= 0 && whip->state >= WHIP_STATE_FAILED && whip->dtls_ret < 0)
ret = whip->dtls_ret;
if (ret >= 0 && whip->dtls_closed)
ret = AVERROR(EIO);
return ret; return ret;
} }

View file

@ -229,6 +229,8 @@ static inline int ff_thread_setname(const char *name)
#endif #endif
#elif HAVE_PTHREAD_SET_NAME_NP #elif HAVE_PTHREAD_SET_NAME_NP
pthread_set_name_np(pthread_self(), name); pthread_set_name_np(pthread_self(), name);
#elif HAVE_W32THREADS
ret = win32_thread_setname(name);
#else #else
ret = AVERROR(ENOSYS); ret = AVERROR(ENOSYS);
#endif #endif