diff --git a/.forgejo/CODEOWNERS b/.forgejo/CODEOWNERS index a4ea6dd50f..0d310fb71f 100644 --- a/.forgejo/CODEOWNERS +++ b/.forgejo/CODEOWNERS @@ -20,9 +20,10 @@ libavcodec/.*ffv1.* @lynne @michaelni libavcodec/golomb.* @michaelni libavcodec/.*h266.* @frankplow @NuoMi @jianhuaw libavcodec/h26x/.* @frankplow @NuoMi @jianhuaw -libavcodec/.*jpegxl.* @lynne -libavcodec/.*jxl.* @lynne +libavcodec/.*jpegxl.* @lynne @Traneptora +libavcodec/.*jxl.* @lynne @Traneptora libavcodec/.*opus.* @lynne +libavcodec/.*png.* @Traneptora libavcodec/.*prores.* @lynne libavcodec/rangecoder.* @michaelni libavcodec/ratecontrol.* @michaelni @@ -45,6 +46,8 @@ libavfilter/vsrc_mandelbrot.* @michaelni # avformat # ======= libavformat/iamf.* @jamrial +libavformat/.*jpegxl.* @Traneptora +libavformat/.*jxl.* @Traneptora # avutil # ====== diff --git a/.gitignore b/.gitignore index a54527cf89..4aa49c52c7 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,3 @@ /libavfilter/vulkan/*.c /.*/ !/.forgejo/ -*.orig \ No newline at end of file diff --git a/Changelog b/Changelog index 0b0e6ecbf4..98b259f17f 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,7 @@ version 8.0: - Whisper filter - Drop support for OpenSSL < 1.1.0 - 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 - VVC VAAPI decoder - RealVideo 6.0 decoder diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index fd6428e29f..6f2734b470 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -44,6 +44,7 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/time.h" +#include "libavutil/wchar_filename.h" typedef struct pthread_t { void *handle; @@ -209,4 +210,38 @@ static inline int pthread_setcancelstate(int state, int *oldstate) 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 */ diff --git a/configure b/configure index eaa52b63ad..e1809a3e58 100755 --- a/configure +++ b/configure @@ -212,7 +212,6 @@ External library support: --enable-jni enable JNI support [no] --enable-ladspa enable LADSPA audio filtering [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-libaribb24 enable ARIB text and caption decoding via libaribb24 [no] --enable-libaribcaption enable ARIB text and caption decoding via libaribcaption [no] @@ -1902,7 +1901,6 @@ EXTERNAL_LIBRARY_NONFREE_LIST=" EXTERNAL_LIBRARY_VERSION3_LIST=" gmp - libaac_next libaribb24 liblensfun libopencore_amrnb @@ -3594,9 +3592,6 @@ hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" prores_videotoolbox_encoder_deps="pthreads" 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_encoder_deps="libaom" 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. _ident=$($_cc -flavor gnu --version 2>/dev/null) _ld_o='-out:$@' - _flags_filter=msvc_flags + _flags_filter=msvc_flags_link _ld_lib='%.lib' _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 @@ -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 ladspa && require_headers "ladspa.h dlfcn.h" 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 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 || @@ -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 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"; } || - 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 -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 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 && diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 740a008131..fb22541f8d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1144,8 +1144,6 @@ OBJS-$(CONFIG_ALAC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_ILBC_AT_ENCODER) += audiotoolboxenc.o OBJS-$(CONFIG_PCM_ALAW_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_ENCODER) += libaomenc.o libaom.o OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8fcd1a806c..f5ec2e01e8 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -766,8 +766,6 @@ extern const FFCodec ff_pcm_mulaw_at_encoder; extern const FFCodec ff_pcm_mulaw_at_decoder; extern const FFCodec ff_qdmc_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; /* preferred over libaribb24 */ extern const FFCodec ff_libaribcaption_decoder; diff --git a/libavcodec/d3d12va_encode_hevc.c b/libavcodec/d3d12va_encode_hevc.c index ce5d1bf110..0aa1a1d3a4 100644 --- a/libavcodec/d3d12va_encode_hevc.c +++ b/libavcodec/d3d12va_encode_hevc.c @@ -762,6 +762,7 @@ static const FFCodecDefault d3d12va_encode_hevc_defaults[] = { { "b_qoffset", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 33a30c8d10..927aeb4bad 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -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_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) { av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); ctx->gop_size = 1; diff --git a/libavcodec/libaac_nextdec.c b/libavcodec/libaac_nextdec.c deleted file mode 100644 index 7450c14322..0000000000 --- a/libavcodec/libaac_nextdec.c +++ /dev/null @@ -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 -#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", -}; diff --git a/libavcodec/libaac_nextenc.c b/libavcodec/libaac_nextenc.c deleted file mode 100755 index 8bc7fccb0f..0000000000 --- a/libavcodec/libaac_nextenc.c +++ /dev/null @@ -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 - -#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), -}; diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c index 748e176815..b2aa97ddda 100644 --- a/libavcodec/prores_raw.c +++ b/libavcodec/prores_raw.c @@ -367,9 +367,6 @@ static int decode_frame(AVCodecContext *avctx, if ((w & 1) || (h & 1)) return AVERROR_INVALIDDATA; - avctx->coded_width = FFALIGN(w, 16); - avctx->coded_height = FFALIGN(h, 16); - if (w != avctx->width || h != avctx->height) { av_log(avctx, AV_LOG_WARNING, "picture resolution change: %ix%i -> %ix%i\n", avctx->width, avctx->height, w, h); @@ -377,6 +374,9 @@ static int decode_frame(AVCodecContext *avctx, return ret; } + avctx->coded_width = FFALIGN(w, 16); + avctx->coded_height = FFALIGN(h, 16); + enum AVPixelFormat pix_fmt = AV_PIX_FMT_BAYER_RGGB16; if (pix_fmt != s->pix_fmt) { s->pix_fmt = pix_fmt; diff --git a/libavcodec/rv60dec.c b/libavcodec/rv60dec.c index 4a3d9067db..208fbc68f7 100644 --- a/libavcodec/rv60dec.c +++ b/libavcodec/rv60dec.c @@ -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) 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 i = 0; i < s->cu_width << 4; i++) s->blk_info[j*s->blk_stride + i].mv.mvref = MVREF_NONE; diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index a066a864eb..e4308af647 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1757,6 +1757,11 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) 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) { case 1: case 3: @@ -2069,6 +2074,20 @@ static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size) mx = motion_vectors[opcode][0]; 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)) { copy_block(ctx->frm0 + cx + ctx->pitch * cy, ctx->frm2 + cx + mx + ctx->pitch * (cy + my), diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index 934945c1be..bc02ac44d5 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -585,7 +585,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int buf_size = avpkt->size; UtvideoContext *c = avctx->priv_data; 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 ret; GetByteContext gb; diff --git a/libavcodec/vaapi_encode_av1.c b/libavcodec/vaapi_encode_av1.c index 3d8f29d599..9d837f5c6b 100644 --- a/libavcodec/vaapi_encode_av1.c +++ b/libavcodec/vaapi_encode_av1.c @@ -1027,6 +1027,7 @@ static const FFCodecDefault vaapi_encode_av1_defaults[] = { { "g", "120" }, { "qmin", "1" }, { "qmax", "255" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 0cd5b0ac50..27f6551719 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -1153,6 +1153,7 @@ static const FFCodecDefault vaapi_encode_h264_defaults[] = { { "b_qoffset", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 1539bfbf79..baf0d77c8a 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -1184,6 +1184,7 @@ static const FFCodecDefault vaapi_encode_h265_defaults[] = { { "b_qoffset", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c index 125d760b9b..69a56a17af 100644 --- a/libavcodec/vaapi_encode_vp8.c +++ b/libavcodec/vaapi_encode_vp8.c @@ -235,6 +235,7 @@ static const FFCodecDefault vaapi_encode_vp8_defaults[] = { { "g", "120" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index e88967a053..ca8de541d9 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -292,6 +292,7 @@ static const FFCodecDefault vaapi_encode_vp9_defaults[] = { { "g", "250" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vulkan_encode_av1.c b/libavcodec/vulkan_encode_av1.c index 840092cf6d..08ffbfa393 100644 --- a/libavcodec/vulkan_encode_av1.c +++ b/libavcodec/vulkan_encode_av1.c @@ -1367,6 +1367,7 @@ static const FFCodecDefault vulkan_encode_av1_defaults[] = { { "g", "300" }, { "qmin", "1" }, { "qmax", "255" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vulkan_encode_h264.c b/libavcodec/vulkan_encode_h264.c index 8bbb4639e6..942e911fb7 100644 --- a/libavcodec/vulkan_encode_h264.c +++ b/libavcodec/vulkan_encode_h264.c @@ -1634,6 +1634,7 @@ static const FFCodecDefault vulkan_encode_h264_defaults[] = { { "b_qoffset", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/vulkan_encode_h265.c b/libavcodec/vulkan_encode_h265.c index f0ec852557..c30b7e8f93 100644 --- a/libavcodec/vulkan_encode_h265.c +++ b/libavcodec/vulkan_encode_h265.c @@ -1761,6 +1761,7 @@ static const FFCodecDefault vulkan_encode_h265_defaults[] = { { "b_qoffset", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, + { "refs", "0" }, { NULL }, }; diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index ebf458453e..ebd2bdb310 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -170,6 +170,7 @@ X86ASM-OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o X86ASM-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct.o X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.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_SBC_ENCODER) += x86/sbcdsp.o X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o diff --git a/libavfilter/af_whisper.c b/libavfilter/af_whisper.c index 186b624504..385180b4ed 100644 --- a/libavfilter/af_whisper.c +++ b/libavfilter/af_whisper.c @@ -215,7 +215,9 @@ static void run_transcription(AVFilterContext *ctx, AVFrame *frame, int samples) for (int i = 0; i < n_segments; ++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) { av_freep(&text_cleaned); @@ -428,7 +430,8 @@ static int query_formats(const AVFilterContext *ctx, #define HOURS 3600000000 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 }, { "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 }, diff --git a/libavformat/avio.h b/libavformat/avio.h index ebf611187d..fbcb7dbfc3 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -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); /** - * 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. * If it is not supported then the seek function will return <0. */ #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 * 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 diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 34743556ae..2e65f50006 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -238,10 +238,9 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) FFIOContext *const ctx = ffiocontext(s); int64_t offset1; int64_t pos; - int force = whence & AVSEEK_FORCE; int buffer_size; int short_seek; - whence &= ~AVSEEK_FORCE; + whence &= ~AVSEEK_FORCE; // force flag does nothing if(!s) 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) || offset1 <= buffer_size + short_seek) && !s->write_flag && offset1 >= 0 && - (!s->direct || !s->seek) && - (whence != SEEK_END || force)) { + (!s->direct || !s->seek)) { while(s->pos < offset && !s->eof_reached) fill_buffer(s); if (s->eof_reached) @@ -300,7 +298,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) s->pos = pos; s->eof_reached = 0; fill_buffer(s); - return avio_seek(s, offset, SEEK_SET | force); + return avio_seek(s, offset, SEEK_SET); } else { int64_t res; if (s->write_flag) { diff --git a/libavformat/mov.c b/libavformat/mov.c index 86037c6712..e9a582e5aa 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5456,10 +5456,6 @@ static int heif_add_stream(MOVContext *c, HEIFItem *item) if (!sc->chunk_offsets) goto fail; 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)); if (!sc->stts_data) goto fail; @@ -10471,11 +10467,13 @@ static int mov_parse_heif_items(AVFormatContext *s) st->codecpar->width = item->width; st->codecpar->height = item->height; - err = sanity_checks(s, sc, item->item_id); - if (err || !sc->sample_count) + sc->sample_size = sc->stsz_sample_size = item->extent_length; + sc->sample_count = 1; + + err = sanity_checks(s, sc, st->index); + if (err) return AVERROR_INVALIDDATA; - sc->sample_sizes[0] = item->extent_length; sc->chunk_offsets[0] = item->extent_offset + offset; if (item->item_id == mov->primary_item_id) diff --git a/libavformat/tls.h b/libavformat/tls.h index 4d4999aa7c..2afa248f4c 100644 --- a/libavformat/tls.h +++ b/libavformat/tls.h @@ -34,17 +34,6 @@ */ #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 { char *ca_file; int verify; @@ -65,8 +54,6 @@ typedef struct TLSShared { int is_dtls; int use_srtp; - enum DTLSState state; - /* The certificate and private key content used for DTLS handshake */ char* cert_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_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_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint); diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index bab2e711c6..db7147e491 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -35,127 +35,82 @@ #include /** - * Returns a heap‐allocated null‐terminated string containing - * the PEM‐encoded public key. Caller must free. + * Convert an EVP_PKEY to a PEM string. */ -static char *pkey_to_pem_string(EVP_PKEY *pkey) { - BIO *mem = NULL; - BUF_MEM *bptr = NULL; - char *pem_str = NULL; +static int pkey_to_pem_string(EVP_PKEY *pkey, char *out, size_t out_sz) +{ + BIO *mem = NULL; + size_t read_bytes = 0; + + if (!pkey || !out || !out_sz) + goto done; - // Create a memory BIO 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)) - goto err; + goto done; - // Extract pointer/length - BIO_get_mem_ptr(mem, &bptr); - if (!bptr || !bptr->length) - goto err; + if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes)) + goto done; - // Allocate string (+1 for NUL) - pem_str = av_malloc(bptr->length + 1); - if (!pem_str) - goto err; - - // Copy data & NUL‐terminate - memcpy(pem_str, bptr->data, bptr->length); - pem_str[bptr->length] = '\0'; - -cleanup: +done: BIO_free(mem); - return pem_str; - -err: - // error path: free and return NULL - free(pem_str); - pem_str = NULL; - goto cleanup; + if (out && out_sz) + out[read_bytes] = '\0'; + return read_bytes; } /** - * Serialize an X509 certificate to a av_malloc’d PEM string. - * Caller must free the returned pointer. + * Convert an X509 certificate to a PEM string. */ -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()); - BUF_MEM *bptr = NULL; - char *out = NULL; + BIO *mem = NULL; + size_t read_bytes = 0; - 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)) - goto err; + goto done; - BIO_get_mem_ptr(mem, &bptr); - if (!bptr || !bptr->length) goto err; + if (!BIO_read_ex(mem, out, out_sz - 1, &read_bytes)) + goto done; - out = av_malloc(bptr->length + 1); - if (!out) goto err; - - memcpy(out, bptr->data, bptr->length); - out[bptr->length] = '\0'; - -cleanup: +done: BIO_free(mem); - return out; - -err: - free(out); - out = NULL; - goto cleanup; + if (out && out_sz) + out[read_bytes] = '\0'; + return read_bytes; } /** * 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]; int n = 0; - AVBPrint fingerprint; - char *result = NULL; - int i; - - /* To prevent a crash during cleanup, always initialize it. */ - av_bprint_init(&fingerprint, 0, AV_BPRINT_SIZE_UNLIMITED); + AVBPrint buf; 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)); - goto end; + av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint, %s\n", + ERR_error_string(ERR_get_error(), NULL)); + return AVERROR(ENOMEM); } - for (i = 0; i < n; i++) { - av_bprintf(&fingerprint, "%02X", md[i]); - if (i + 1 < n) - av_bprintf(&fingerprint, ":"); - } + av_bprint_init(&buf, n*3, n*3); - if (!fingerprint.str || !strlen(fingerprint.str)) { - av_log(NULL, AV_LOG_ERROR, "TLS: Fingerprint is empty\n"); - goto end; - } + for (int i = 0; i < n - 1; i++) + av_bprintf(&buf, "%02X:", md[i]); + av_bprintf(&buf, "%02X", md[n - 1]); - result = av_strdup(fingerprint.str); - if (!result) { - av_log(NULL, AV_LOG_ERROR, "TLS: Out of memory generating fingerprint\n"); - } - -end: - av_bprint_finalize(&fingerprint, NULL); - return result; + return av_bprint_finalize(&buf, 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; EVP_PKEY *pkey = NULL; X509 *cert = NULL; - char *key_tem = NULL, *cert_tem = NULL; /* To prevent a crash during cleanup, always initialize it. */ 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; } - key_tem = pkey_to_pem_string(pkey); - cert_tem = cert_to_pem_string(cert); + pkey_to_pem_string(pkey, key_buf, key_sz); + 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); - - /* 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; - } - } + ret = x509_fingerprint(cert, fingerprint); + if (ret < 0) + av_log(NULL, AV_LOG_ERROR, "TLS: Failed to generate fingerprint from %s\n", cert_url); end: BIO_free(key_b); av_bprint_finalize(&key_bp, NULL); BIO_free(cert_b); av_bprint_finalize(&cert_bp, NULL); - av_free(key_tem); - av_free(cert_tem); EVP_PKEY_free(pkey); X509_free(cert); return ret; @@ -376,12 +319,9 @@ static int openssl_gen_certificate(EVP_PKEY *pkey, X509 **cert, char **fingerpri goto einval_end; } - if (fingerprint) { - *fingerprint = generate_fingerprint(*cert); - if (!*fingerprint) { - goto enomem_end; - } - } + ret = x509_fingerprint(*cert, fingerprint); + if (ret < 0) + goto end; goto 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; EVP_PKEY *pkey = NULL; X509 *cert = NULL; - char *key_tem = NULL, *cert_tem = NULL; ret = openssl_gen_private_key(&pkey); 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); if (ret < 0) goto error; - key_tem = pkey_to_pem_string(pkey); - cert_tem = cert_to_pem_string(cert); + pkey_to_pem_string(pkey, key_buf, key_sz); + 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: X509_free(cert); EVP_PKEY_free(pkey); @@ -427,7 +361,7 @@ error: /** - * Deserialize a PEM‐encoded 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. * "-----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 PEM‐encoded 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. * "-----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; } -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) { TLSContext *c = h->priv_data; @@ -722,7 +650,6 @@ static int dtls_handshake(URLContext *h) goto end; ret = 0; - c->tls_shared.state = DTLS_STATE_FINISHED; end: return ret; } diff --git a/libavformat/tls_schannel.c b/libavformat/tls_schannel.c index b60e3100be..b854f484fa 100644 --- a/libavformat/tls_schannel.c +++ b/libavformat/tls_schannel.c @@ -681,12 +681,6 @@ int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t ma #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, void *data, unsigned long size) { @@ -1111,7 +1105,6 @@ static int tls_handshake(URLContext *h) #endif c->connected = 1; - s->state = DTLS_STATE_FINISHED; fail: return ret; diff --git a/libavformat/whip.c b/libavformat/whip.c index 65fd3b39b2..e2fa774c6f 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -198,9 +198,6 @@ typedef struct WHIPContext { /* The state of the RTC connection. */ enum WHIPState state; - /* The callback return value for DTLS. */ - int dtls_ret; - int dtls_closed; /* Parameters for the input audio and video codecs. */ AVCodecParameters *audio_par; @@ -348,41 +345,6 @@ static av_cold int certificate_key_init(AVFormatContext *s) 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) { WHIPContext *whip = s->priv_data; @@ -1326,9 +1288,18 @@ next_packet: /* 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) { 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; - 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; } } @@ -1771,10 +1742,8 @@ static av_cold int whip_init(AVFormatContext *s) goto end; end: - if (ret < 0 && whip->state < WHIP_STATE_FAILED) + if (ret < 0) whip->state = WHIP_STATE_FAILED; - if (ret >= 0 && whip->state >= WHIP_STATE_FAILED && whip->dtls_ret < 0) - ret = whip->dtls_ret; return ret; } @@ -1822,12 +1791,8 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt) } end: - if (ret < 0 && whip->state < WHIP_STATE_FAILED) + if (ret < 0) 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; } diff --git a/libavutil/thread.h b/libavutil/thread.h index 2c00c7cc35..184e2d8c5f 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -229,6 +229,8 @@ static inline int ff_thread_setname(const char *name) #endif #elif HAVE_PTHREAD_SET_NAME_NP pthread_set_name_np(pthread_self(), name); +#elif HAVE_W32THREADS + ret = win32_thread_setname(name); #else ret = AVERROR(ENOSYS); #endif