PR #24744 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24744 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24744.patch
Fixes #23945. Subtitle decoders use the dedicated `decode_sub` callback and return `AVSubtitle`, while the send/receive API is defined for audio and video `AVFrame` output. Calling `avcodec_send_packet()` on an opened subtitle decoder currently enters the frame decoding path, invokes the callback union through its incompatible `decode` member, and reaches an unconditional assertion. Reject media types other than audio and video at the public packet-submission boundary. Also clarify the API documentation and add a FATE API regression test using the PGS subtitle decoder. Before the change, the regression test aborts in `decode_simple_internal()` with exit status 134. After the change, `avcodec_send_packet()` returns `AVERROR(EINVAL)`. Tested with: - `make fate-api-send-packet-media-type` - `make fate-api` - `make fate` under a minimal PGS-decoder configuration >From a5643a08348a60e01d857e20262cb0e0f707314d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sun, 27 Sep 2026 20:51:31 +0000 Subject: [PATCH] avcodec/decode: reject non-audio/video send_packet calls The send/receive API outputs AVFrames and does not support subtitle decoders. Reject unsupported media types before entering the frame decoding path, where a subtitle decoder would otherwise be invoked through the wrong callback union member and reach an assertion. Add an API regression test and clarify the public API documentation. Assisted-by: Fairy --- libavcodec/avcodec.h | 5 +- libavcodec/decode.c | 4 ++ tests/api/Makefile | 1 + tests/api/api-send-packet-media-type-test.c | 52 +++++++++++++++++++++ tests/fate/api.mak | 4 ++ tests/ref/fate/api-send-packet-media-type | 1 + 6 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 tests/api/api-send-packet-media-type-test.c create mode 100644 tests/ref/fate/api-send-packet-media-type diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1b3eaa799c..a6a86e5dad 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2354,7 +2354,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt); /** - * Supply raw packet data as input to a decoder. + * Supply raw packet data as input to an audio or video decoder. * * Internally, this call will copy relevant AVCodecContext fields, which can * influence decoding per-packet, and apply them when the packet is actually @@ -2395,7 +2395,8 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, * @retval AVERROR_EOF the decoder has been flushed, and no new packets can be * sent to it (also returned if more than 1 flush * packet is sent) - * @retval AVERROR(EINVAL) codec not opened, it is an encoder, or requires flush + * @retval AVERROR(EINVAL) codec not opened, it is an encoder, its media type is + * neither audio nor video, or it requires flush * @retval AVERROR(ENOMEM) failed to add packet to internal queue, or similar * @retval "another negative error code" legitimate decoding errors */ diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 94dfc06a84..797606f6d0 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -740,6 +740,10 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL); + if (avctx->codec_type != AVMEDIA_TYPE_VIDEO && + avctx->codec_type != AVMEDIA_TYPE_AUDIO) + return AVERROR(EINVAL); + if (dc->draining_started) return AVERROR_EOF; diff --git a/tests/api/Makefile b/tests/api/Makefile index f2738d4cba..0950fe99ed 100644 --- a/tests/api/Makefile +++ b/tests/api/Makefile @@ -4,6 +4,7 @@ APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice APITESTPROGS-$(CONFIG_MOV_MUXER) += api-movenc APITESTPROGS-$(CONFIG_MOVTEXT_ENCODER) += api-movtext +APITESTPROGS-$(CONFIG_PGSSUB_DECODER) += api-send-packet-media-type APITESTPROGS-yes += api-seek api-dump-stream-meta APITESTPROGS-$(call DEMDEC, H263, H263) += api-band APITESTPROGS-$(HAVE_THREADS) += api-threadmessage diff --git a/tests/api/api-send-packet-media-type-test.c b/tests/api/api-send-packet-media-type-test.c new file mode 100644 index 0000000000..53ba92e7e7 --- /dev/null +++ b/tests/api/api-send-packet-media-type-test.c @@ -0,0 +1,52 @@ +/* + * 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 + */ + +#include <stdio.h> + +#include "libavcodec/avcodec.h" +#include "libavutil/error.h" + +int main(void) +{ + const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_HDMV_PGS_SUBTITLE); + AVCodecContext *ctx = NULL; + AVPacket *pkt = NULL; + int ret = 1; + + if (!codec) + goto end; + + ctx = avcodec_alloc_context3(codec); + pkt = av_packet_alloc(); + if (!ctx || !pkt) + goto end; + + if (avcodec_open2(ctx, codec, NULL) < 0 || + av_new_packet(pkt, 1) < 0) + goto end; + pkt->data[0] = 0; + + ret = avcodec_send_packet(ctx, pkt); + printf("send_packet: %s\n", av_err2str(ret)); + ret = ret < 0 ? 0 : 1; + +end: + av_packet_free(&pkt); + avcodec_free_context(&ctx); + return ret; +} diff --git a/tests/fate/api.mak b/tests/fate/api.mak index a10edfe4da..1657d35032 100644 --- a/tests/fate/api.mak +++ b/tests/fate/api.mak @@ -11,6 +11,10 @@ FATE_API_LIBAVCODEC-$(CONFIG_MOVTEXT_ENCODER) += fate-api-movtext fate-api-movtext: $(APITESTSDIR)/api-movtext-test$(EXESUF) fate-api-movtext: CMD = run $(APITESTSDIR)/api-movtext-test$(EXESUF) +FATE_API_LIBAVCODEC-$(CONFIG_PGSSUB_DECODER) += fate-api-send-packet-media-type +fate-api-send-packet-media-type: $(APITESTSDIR)/api-send-packet-media-type-test$(EXESUF) +fate-api-send-packet-media-type: CMD = run $(APITESTSDIR)/api-send-packet-media-type-test$(EXESUF) + FATE_API_LIBAVCODEC-$(call ALLYES, H261_ENCODER H261_PARSER) += fate-api-enc-parser fate-api-enc-parser-cif fate-api-enc-parser: $(APITESTSDIR)/api-enc-parser-test$(EXESUF) fate-api-enc-parser: CMD = run $(APITESTSDIR)/api-enc-parser-test$(EXESUF) h261 176 144 diff --git a/tests/ref/fate/api-send-packet-media-type b/tests/ref/fate/api-send-packet-media-type new file mode 100644 index 0000000000..f5f20447d0 --- /dev/null +++ b/tests/ref/fate/api-send-packet-media-type @@ -0,0 +1 @@ +send_packet: Invalid argument -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
