PR #22723 opened by sohamukute
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22723
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22723.patch
Add API tests for three previously uncovered files (all at 0%):
- tests/api/api-cngdec-test.c: exercises cng_decode_frame via the uninited and
inited (blending) branches, 0th-order SID, silence, max noise level, flush, and
post-flush re-initialisation. Reaches 93.75% line coverage on cngdec.c.
- tests/api/api-cngenc-test.c: exercises cng_encode_frame via the energy > 0
path (qdbov computed from log10) and the energy == 0 silence path (qdbov =
127). Reaches 89.47% line coverage on cngenc.c.
- libavutil/tests/detection_bbox.c: exercises av_detection_bbox_alloc (zero
boxes, multiple boxes, NULL out_size) and av_detection_bbox_create_side_data.
Reaches 75% line coverage on detection_bbox.c. Remaining uncovered lines are
allocation failure paths.
Signed-off-by: Soham Kute [email protected]
>From 0e6452e119e1b692906680a5fae8e3c968dbcd1c Mon Sep 17 00:00:00 2001
From: Soham Kute <[email protected]>
Date: Sun, 5 Apr 2026 18:09:47 +0530
Subject: [PATCH 1/3] avcodec/tests: add CNG decoder API test
Exercise the main decode paths in cngdec.c without external samples.
The test sends hardcoded SID packets through avcodec_send_packet and
avcodec_receive_frame, covering the uninited and inited branches of
cng_decode_frame, the 0th-order and full-order coefficient paths, the
flush callback via avcodec_flush_buffers, and the re-initialisation
path after a flush.
---
tests/api/Makefile | 1 +
tests/api/api-cngdec-test.c | 126 ++++++++++++++++++++++++++++++++++++
tests/fate/api.mak | 5 ++
3 files changed, 132 insertions(+)
create mode 100644 tests/api/api-cngdec-test.c
diff --git a/tests/api/Makefile b/tests/api/Makefile
index 899aeb1f54..22c2527c45 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,3 +1,4 @@
+APITESTPROGS-$(CONFIG_COMFORTNOISE_DECODER) += api-cngdec
APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
diff --git a/tests/api/api-cngdec-test.c b/tests/api/api-cngdec-test.c
new file mode 100644
index 0000000000..54e94d3258
--- /dev/null
+++ b/tests/api/api-cngdec-test.c
@@ -0,0 +1,126 @@
+/*
+ * 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 <string.h>
+
+#include "libavcodec/avcodec.h"
+#include "libavutil/mem.h"
+
+static int send_sid(AVCodecContext *avctx, AVPacket *pkt, AVFrame *frame,
+ const uint8_t *payload, int payload_size)
+{
+ int ret = av_new_packet(pkt, payload_size);
+ if (ret < 0)
+ return ret;
+ memcpy(pkt->data, payload, payload_size);
+ ret = avcodec_send_packet(avctx, pkt);
+ av_packet_unref(pkt);
+ if (ret < 0)
+ return ret;
+ ret = avcodec_receive_frame(avctx, frame);
+ av_frame_unref(frame);
+ return ret;
+}
+
+int main(void)
+{
+ /* SID packet: noise level + 12 reflection coefficients (order == 12) */
+ static const uint8_t sid_full[13] = {
+ 20,
+ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50,
+ 0x60, 0x70, 0x08, 0x18, 0x28, 0x38,
+ };
+ /* SID packet: noise level only, no coefficients (0th order) */
+ static const uint8_t sid_level_only[1] = { 30 };
+ /* SID packet: silence */
+ static const uint8_t sid_silence[1] = { 0 };
+ /* SID packet: max noise level */
+ static const uint8_t sid_max[1] = { 127 };
+
+ const AVCodec *codec;
+ AVCodecContext *avctx = NULL;
+ AVPacket *pkt = NULL;
+ AVFrame *frame = NULL;
+ int ret;
+
+ codec = avcodec_find_decoder(AV_CODEC_ID_COMFORT_NOISE);
+ if (!codec) {
+ fprintf(stderr, "CNG decoder not found\n");
+ return 1;
+ }
+
+ avctx = avcodec_alloc_context3(codec);
+ if (!avctx)
+ return 1;
+
+ ret = avcodec_open2(avctx, codec, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "avcodec_open2 failed\n");
+ goto fail;
+ }
+
+ pkt = av_packet_alloc();
+ frame = av_frame_alloc();
+ if (!pkt || !frame) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ /* Full-order SID: exercises make_lpc_coefs and CELP synthesis.
+ * First call takes the uninited branch, copies target coefficients
+ * directly and sets the inited flag. */
+ ret = send_sid(avctx, pkt, frame, sid_full, sizeof(sid_full));
+ if (ret < 0) goto fail;
+
+ /* Second call takes the inited branch, blending energy and
+ * reflection coefficients toward the new target. */
+ ret = send_sid(avctx, pkt, frame, sid_full, sizeof(sid_full));
+ if (ret < 0) goto fail;
+
+ /* 0th-order SID: coefficient loop runs zero times, flat-spectrum path. */
+ ret = send_sid(avctx, pkt, frame, sid_level_only, sizeof(sid_level_only));
+ if (ret < 0) goto fail;
+
+ /* Silence level: target energy near zero. */
+ ret = send_sid(avctx, pkt, frame, sid_silence, sizeof(sid_silence));
+ if (ret < 0) goto fail;
+
+ /* Max noise level. */
+ ret = send_sid(avctx, pkt, frame, sid_max, sizeof(sid_max));
+ if (ret < 0) goto fail;
+
+ /* Flush resets the inited flag. */
+ avcodec_flush_buffers(avctx);
+
+ /* Packet after flush re-exercises the uninited branch. */
+ ret = send_sid(avctx, pkt, frame, sid_level_only, sizeof(sid_level_only));
+ if (ret < 0) goto fail;
+
+ av_packet_free(&pkt);
+ av_frame_free(&frame);
+ avcodec_free_context(&avctx);
+ return 0;
+
+fail:
+ fprintf(stderr, "error: %d\n", ret);
+ av_packet_free(&pkt);
+ av_frame_free(&frame);
+ avcodec_free_context(&avctx);
+ return 1;
+}
diff --git a/tests/fate/api.mak b/tests/fate/api.mak
index b760de5eb6..c20dfccf0e 100644
--- a/tests/fate/api.mak
+++ b/tests/fate/api.mak
@@ -1,3 +1,8 @@
+FATE_API_LIBAVCODEC-$(CONFIG_COMFORTNOISE_DECODER) += fate-api-cngdec
+fate-api-cngdec: $(APITESTSDIR)/api-cngdec-test$(EXESUF)
+fate-api-cngdec: CMD = run $(APITESTSDIR)/api-cngdec-test$(EXESUF)
+fate-api-cngdec: CMP = null
+
FATE_API_LIBAVCODEC-$(call ENCDEC, FLAC, FLAC) += fate-api-flac
fate-api-flac: $(APITESTSDIR)/api-flac-test$(EXESUF)
fate-api-flac: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF)
--
2.52.0
>From 13395be17bf286312cf870c34045647e10e1ba73 Mon Sep 17 00:00:00 2001
From: Soham Kute <[email protected]>
Date: Sun, 5 Apr 2026 18:37:50 +0530
Subject: [PATCH 2/3] avcodec/tests: add CNG encoder API test
Exercise both branches of cng_encode_frame: the energy > 0 path
which computes qdbov via log10, and the energy == 0 silence path
which sets qdbov = 127.
---
tests/api/Makefile | 1 +
tests/api/api-cngenc-test.c | 142 ++++++++++++++++++++++++++++++++++++
tests/fate/api.mak | 5 ++
3 files changed, 148 insertions(+)
create mode 100644 tests/api/api-cngenc-test.c
diff --git a/tests/api/Makefile b/tests/api/Makefile
index 22c2527c45..6978c980ac 100644
--- a/tests/api/Makefile
+++ b/tests/api/Makefile
@@ -1,4 +1,5 @@
APITESTPROGS-$(CONFIG_COMFORTNOISE_DECODER) += api-cngdec
+APITESTPROGS-$(CONFIG_COMFORTNOISE_ENCODER) += api-cngenc
APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac
APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264
APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice
diff --git a/tests/api/api-cngenc-test.c b/tests/api/api-cngenc-test.c
new file mode 100644
index 0000000000..e4a878da3d
--- /dev/null
+++ b/tests/api/api-cngenc-test.c
@@ -0,0 +1,142 @@
+/*
+ * 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/channel_layout.h"
+#include "libavutil/mem.h"
+#include "libavutil/samplefmt.h"
+
+static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, AVFrame *frame,
+ int16_t fill, int *got_packet)
+{
+ int ret;
+ int16_t *samples = (int16_t *)frame->data[0];
+
+ for (int i = 0; i < frame->nb_samples; i++)
+ samples[i] = fill;
+
+ ret = avcodec_send_frame(avctx, frame);
+ if (ret < 0)
+ return ret;
+ ret = avcodec_receive_packet(avctx, pkt);
+ if (ret == AVERROR(EAGAIN)) {
+ *got_packet = 0;
+ return 0;
+ }
+ if (ret < 0)
+ return ret;
+ *got_packet = 1;
+ return 0;
+}
+
+int main(void)
+{
+ const AVChannelLayout mono = AV_CHANNEL_LAYOUT_MONO;
+ const AVCodec *codec;
+ AVCodecContext *avctx = NULL;
+ AVPacket *pkt = NULL;
+ AVFrame *frame = NULL;
+ int ret, got_packet;
+
+ codec = avcodec_find_encoder(AV_CODEC_ID_COMFORT_NOISE);
+ if (!codec) {
+ fprintf(stderr, "CNG encoder not found\n");
+ return 1;
+ }
+
+ avctx = avcodec_alloc_context3(codec);
+ if (!avctx)
+ return 1;
+
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ avctx->sample_rate = 8000;
+ ret = av_channel_layout_copy(&avctx->ch_layout, &mono);
+ if (ret < 0)
+ goto fail;
+
+ ret = avcodec_open2(avctx, codec, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "avcodec_open2 failed\n");
+ goto fail;
+ }
+
+ pkt = av_packet_alloc();
+ frame = av_frame_alloc();
+ if (!pkt || !frame) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ frame->nb_samples = avctx->frame_size;
+ frame->format = avctx->sample_fmt;
+ ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout);
+ if (ret < 0)
+ goto fail;
+
+ ret = av_frame_get_buffer(frame, 0);
+ if (ret < 0)
+ goto fail;
+
+ /* Non-zero samples: exercises the energy > 0 branch (qdbov from log). */
+ ret = encode_frame(avctx, pkt, frame, 1000, &got_packet);
+ if (ret < 0) goto fail;
+ if (!got_packet) {
+ fprintf(stderr, "expected packet, got none\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ /* Output must be 1 (noise level) + order (10) = 11 bytes. */
+ if (pkt->size != 11) {
+ fprintf(stderr, "unexpected packet size %d\n", pkt->size);
+ ret = AVERROR_INVALIDDATA;
+ av_packet_unref(pkt);
+ goto fail;
+ }
+ av_packet_unref(pkt);
+
+ /* All-zero samples: exercises the energy == 0 branch (qdbov = 127). */
+ ret = encode_frame(avctx, pkt, frame, 0, &got_packet);
+ if (ret < 0) goto fail;
+ if (!got_packet) {
+ fprintf(stderr, "expected packet, got none\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ if (pkt->size != 11 || pkt->data[0] != 127) {
+ fprintf(stderr, "unexpected silence packet (size=%d qdbov=%d)\n",
+ pkt->size, pkt->size > 0 ? pkt->data[0] : -1);
+ ret = AVERROR_INVALIDDATA;
+ av_packet_unref(pkt);
+ goto fail;
+ }
+ av_packet_unref(pkt);
+
+ av_packet_free(&pkt);
+ av_frame_free(&frame);
+ avcodec_free_context(&avctx);
+ return 0;
+
+fail:
+ fprintf(stderr, "error: %d\n", ret);
+ av_packet_free(&pkt);
+ av_frame_free(&frame);
+ avcodec_free_context(&avctx);
+ return 1;
+}
diff --git a/tests/fate/api.mak b/tests/fate/api.mak
index c20dfccf0e..a0c5133354 100644
--- a/tests/fate/api.mak
+++ b/tests/fate/api.mak
@@ -3,6 +3,11 @@ fate-api-cngdec: $(APITESTSDIR)/api-cngdec-test$(EXESUF)
fate-api-cngdec: CMD = run $(APITESTSDIR)/api-cngdec-test$(EXESUF)
fate-api-cngdec: CMP = null
+FATE_API_LIBAVCODEC-$(CONFIG_COMFORTNOISE_ENCODER) += fate-api-cngenc
+fate-api-cngenc: $(APITESTSDIR)/api-cngenc-test$(EXESUF)
+fate-api-cngenc: CMD = run $(APITESTSDIR)/api-cngenc-test$(EXESUF)
+fate-api-cngenc: CMP = null
+
FATE_API_LIBAVCODEC-$(call ENCDEC, FLAC, FLAC) += fate-api-flac
fate-api-flac: $(APITESTSDIR)/api-flac-test$(EXESUF)
fate-api-flac: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF)
--
2.52.0
>From 3b3743d90a807125890498361bf38f909a269f21 Mon Sep 17 00:00:00 2001
From: Soham Kute <[email protected]>
Date: Sun, 5 Apr 2026 18:38:00 +0530
Subject: [PATCH 3/3] avutil/tests: add detection_bbox unit test
Cover av_detection_bbox_alloc (zero boxes, multiple boxes, NULL
out_size) and av_detection_bbox_create_side_data to bring
libavutil/detection_bbox.c from 0% coverage.
---
libavutil/Makefile | 1 +
libavutil/tests/detection_bbox.c | 74 ++++++++++++++++++++++++++++++++
tests/fate/libavutil.mak | 5 +++
3 files changed, 80 insertions(+)
create mode 100644 libavutil/tests/detection_bbox.c
diff --git a/libavutil/Makefile b/libavutil/Makefile
index c5241895ff..92cc40873c 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -270,6 +270,7 @@ TESTPROGS = adler32
\
cpu \
crc \
des \
+ detection_bbox \
dict \
display \
encryption_info \
diff --git a/libavutil/tests/detection_bbox.c b/libavutil/tests/detection_bbox.c
new file mode 100644
index 0000000000..19e508451a
--- /dev/null
+++ b/libavutil/tests/detection_bbox.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <stddef.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/detection_bbox.h"
+#include "libavutil/frame.h"
+#include "libavutil/mem.h"
+
+int main(void)
+{
+ AVDetectionBBoxHeader *header;
+ AVDetectionBBox *bbox;
+ AVFrame *frame;
+ size_t out_size;
+
+ /* Allocate with zero bounding boxes: header fields must be consistent. */
+ header = av_detection_bbox_alloc(0, &out_size);
+ av_assert0(header);
+ av_assert0(header->nb_bboxes == 0);
+ av_assert0(header->bbox_size == sizeof(AVDetectionBBox));
+ av_assert0(out_size > 0);
+ av_free(header);
+
+ /* Allocate with several bounding boxes. */
+ header = av_detection_bbox_alloc(3, &out_size);
+ av_assert0(header);
+ av_assert0(header->nb_bboxes == 3);
+ av_assert0(header->bbox_size == sizeof(AVDetectionBBox));
+ av_assert0(out_size >= header->bboxes_offset + 3 *
sizeof(AVDetectionBBox));
+
+ /* av_get_detection_bbox must return the expected element. */
+ bbox = av_get_detection_bbox(header, 0);
+ av_assert0(bbox == (AVDetectionBBox *)((uint8_t *)header +
header->bboxes_offset));
+ bbox = av_get_detection_bbox(header, 2);
+ av_assert0(bbox == (AVDetectionBBox *)((uint8_t *)header +
header->bboxes_offset +
+ 2 * sizeof(AVDetectionBBox)));
+ av_free(header);
+
+ /* out_size may be NULL. */
+ header = av_detection_bbox_alloc(1, NULL);
+ av_assert0(header);
+ av_assert0(header->nb_bboxes == 1);
+ av_free(header);
+
+ /* Attach bounding boxes as frame side data. */
+ frame = av_frame_alloc();
+ av_assert0(frame);
+
+ header = av_detection_bbox_create_side_data(frame, 2);
+ av_assert0(header);
+ av_assert0(header->nb_bboxes == 2);
+ av_assert0(av_frame_get_side_data(frame, AV_FRAME_DATA_DETECTION_BBOXES));
+
+ av_frame_free(&frame);
+
+ return 0;
+}
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 6bf03b2438..48b3106a4d 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -70,6 +70,11 @@ fate-des: libavutil/tests/des$(EXESUF)
fate-des: CMD = run libavutil/tests/des$(EXESUF)
fate-des: CMP = null
+FATE_LIBAVUTIL += fate-detection-bbox
+fate-detection-bbox: libavutil/tests/detection_bbox$(EXESUF)
+fate-detection-bbox: CMD = run libavutil/tests/detection_bbox$(EXESUF)
+fate-detection-bbox: CMP = null
+
FATE_LIBAVUTIL += fate-dict
fate-dict: libavutil/tests/dict$(EXESUF)
fate-dict: CMD = run libavutil/tests/dict$(EXESUF)
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]