Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: sohamukute via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: sohamukute <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PR] fate: add tests for h261_parser and yuv4mpegenc, extend file test (PR #22237)
Date: Sat, 21 Feb 2026 05:31:50 -0000
Message-ID: <177165191131.25.15704043415661500015@29965ddac10e> (raw)

PR #22237 opened by sohamukute
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22237
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22237.patch

libavutil/tests/file.c: add error path coverage for av_file_map()
with nonexistent files and non-zero log_offset.

libavcodec/tests/h261_parser.c: test the h261 parser with a flush
call, garbage input, mid-buffer PSC, split input across two calls,
and both QCIF and CIF source formats.

libavformat/tests/yuv4mpegenc.c: test the yuv4mpegpipe muxer with
various pixel formats (yuv420p/422p/444p/411p/gray8/yuvj*), square
and non-square SAR, unknown SAR, interlaced and progressive field
order, limited and full color range, and an unsupported pixel format
that must be rejected.

Coverage results (measured with gcov on Linux x86_64):

libavutil/file.c:
  Lines:    8.8%  -> 64.7%  (remaining uncovered: Windows-only code paths)
  Branches: 8.3%  -> 100%

libavcodec/h261_parser.c:
  Lines:    21.9% -> 96.9%
  Branches: 5.0%  -> 100%

libavformat/yuv4mpegenc.c:
  Lines:    32.2% -> 47.9%
  Branches: 30.0% -> 77.1%

Note: yuv4mpegenc line coverage is limited by non-standard pixel
formats requiring -strict -1 and the wrapped avframe write path.
Branch coverage improved from 30% to 77%. Tested on Linux x86_64.

Signed-off-by: Soham Kute <officialsohamkute@gmail.com>


From fd605c7b0f8c8cbb1a107f94b218c60cd6aee3a9 Mon Sep 17 00:00:00 2001
From: Soham Kute <officialsohamkute@gmail.com>
Date: Sat, 21 Feb 2026 10:50:12 +0530
Subject: [PATCH] fate: add coverage tests for file, h261_parser and
 yuv4mpegenc

Extend and add self-tests to improve branch and line coverage:

- libavutil/tests/file.c: extend existing test to cover av_file_map()
  error paths (nonexistent file, non-zero log_offset branch).
  Lines: 8.8% -> 64.7%, Branches: 8.3% -> 100%

- libavcodec/tests/h261_parser.c: new test covering flush call (size=0),
  garbage input with no PSC, PSC at mid-buffer, split PSC across two
  calls, and QCIF/CIF source format detection branches.
  Lines: 21.9% -> 96.9%, Branches: 5.0% -> 100%

- libavformat/tests/yuv4mpegenc.c: new test covering pixel format
  variants (YUV420P/422P/444P/411P/GRAY8/YUVJ*), SAR branches
  (square/non-square/unknown), interlacing (progressive/TFF/BFF),
  color range (MPEG/JPEG/unspecified), write_packet path via raw
  frame, and unsupported format rejection.
  Lines: 32.2% -> 47.9%, Branches: 30.0% -> 77.1%

Signed-off-by: Soham Kute <officialsohamkute@gmail.com>
---
 libavcodec/Makefile             |   1 +
 libavcodec/tests/h261_parser.c  | 125 +++++++++++++++++++++++++
 libavformat/Makefile            |   1 +
 libavformat/tests/yuv4mpegenc.c | 160 ++++++++++++++++++++++++++++++++
 libavutil/tests/file.c          |  18 +++-
 tests/fate/libavcodec.mak       |   5 +
 tests/fate/libavformat.mak      |   5 +
 tests/fate/libavutil.mak        |   5 +
 8 files changed, 317 insertions(+), 3 deletions(-)
 create mode 100644 libavcodec/tests/h261_parser.c
 create mode 100644 libavformat/tests/yuv4mpegenc.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 50ac7d712b..0d0917dd57 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1379,6 +1379,7 @@ TESTPROGS-$(CONFIG_MJPEG_ENCODER)         += mjpegenc_huffman
 TESTPROGS-$(HAVE_MMX)                     += motion
 TESTPROGS-$(CONFIG_MPEGVIDEO)             += mpeg12framerate
 TESTPROGS-$(CONFIG_H264_METADATA_BSF)     += h264_levels
+TESTPROGS-$(CONFIG_H261_DECODER)           += h261_parser
 TESTPROGS-$(CONFIG_HEVC_METADATA_BSF)     += h265_levels
 TESTPROGS-$(CONFIG_RANGECODER)            += rangecoder
 TESTPROGS-$(CONFIG_SNOW_ENCODER)          += snowenc
diff --git a/libavcodec/tests/h261_parser.c b/libavcodec/tests/h261_parser.c
new file mode 100644
index 0000000000..93b14d6d4c
--- /dev/null
+++ b/libavcodec/tests/h261_parser.c
@@ -0,0 +1,125 @@
+/*
+ * 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 "libavcodec/avcodec.h"
+#include "libavutil/log.h"
+
+/*
+ * H.261 Picture Start Code (PSC): 20 zero bits followed by 1 bit.
+ * Byte layout: 0x00 0x01 0x00 ...
+ * Next bits: temporal_ref(5), split_screen(1), camera(1), freeze(1),
+ *            source_format(1): 0=QCIF, 1=CIF
+ */
+
+/* Minimal CIF frame: source_format bit = 1 */
+static const uint8_t cif_frame[] = {
+    0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* Minimal QCIF frame: source_format bit = 0 */
+static const uint8_t qcif_frame[] = {
+    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* Garbage with no PSC */
+static const uint8_t garbage[] = {
+    0xff, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78,
+};
+
+/* PSC not at offset 0 */
+static const uint8_t psc_mid[] = {
+    0xff, 0xab,
+    0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+};
+
+int main(void)
+{
+    AVCodecParserContext *parser;
+    AVCodecContext       *avctx;
+    uint8_t              *out;
+    int                   out_size, ret;
+
+    av_log_set_level(AV_LOG_QUIET);
+
+    parser = av_parser_init(AV_CODEC_ID_H261);
+    if (!parser)
+        return 0; /* skip if not compiled in */
+
+    /* A codec-independent context — no decoder required */
+    avctx = avcodec_alloc_context3(NULL);
+    if (!avctx) {
+        av_parser_close(parser);
+        return 1;
+    }
+
+    /* flush (buf_size == 0) */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           NULL, 0, AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    /* garbage — no PSC */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           garbage, sizeof(garbage),
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    /* valid CIF frame */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           cif_frame, sizeof(cif_frame),
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    /* valid QCIF frame */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           qcif_frame, sizeof(qcif_frame),
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    /* PSC not at start of buffer */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           psc_mid, sizeof(psc_mid),
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    /* split input across two calls */
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           cif_frame, 1,
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_parser_parse2(parser, avctx, &out, &out_size,
+                           cif_frame + 1, sizeof(cif_frame) - 1,
+                           AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
+    if (ret < 0)
+        goto fail;
+
+    av_parser_close(parser);
+    avcodec_free_context(&avctx);
+    return 0;
+
+fail:
+    av_parser_close(parser);
+    avcodec_free_context(&avctx);
+    return 1;
+}
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 5b8564bf54..e49fb4a445 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -781,6 +781,7 @@ FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK)   += fifo_muxer
 TESTPROGS-$(CONFIG_FIFO_MUXER)           += $(FIFO-MUXER-TESTPROGS-yes)
 TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh
 TESTPROGS-$(CONFIG_MOV_MUXER)            += movenc
+TESTPROGS-$(CONFIG_YUV4MPEGPIPE_MUXER)    += yuv4mpegenc
 TESTPROGS-$(CONFIG_NETWORK)              += noproxy
 TESTPROGS-$(CONFIG_SRTP)                 += srtp
 TESTPROGS-$(CONFIG_IMF_DEMUXER)          += imf
diff --git a/libavformat/tests/yuv4mpegenc.c b/libavformat/tests/yuv4mpegenc.c
new file mode 100644
index 0000000000..75128648f8
--- /dev/null
+++ b/libavformat/tests/yuv4mpegenc.c
@@ -0,0 +1,160 @@
+/*
+ * 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 "libavformat/avformat.h"
+#include "libavformat/avio.h"
+#include "libavcodec/codec_par.h"
+#include "libavcodec/packet.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixfmt.h"
+
+static int mux_once(enum AVPixelFormat pix_fmt,
+                    AVRational sar, enum AVFieldOrder field_order,
+                    enum AVColorRange color_range,
+                    int expect_fail)
+{
+    AVFormatContext   *oc  = NULL;
+    AVStream          *st;
+    uint8_t           *buf = NULL;
+    int                ret;
+
+    ret = avformat_alloc_output_context2(&oc, NULL, "yuv4mpegpipe", NULL);
+    if (ret < 0)
+        return ret;
+
+    st = avformat_new_stream(oc, NULL);
+    if (!st) {
+        ret = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->format      = pix_fmt;
+    st->codecpar->width       = 16;
+    st->codecpar->height      = 16;
+    st->codecpar->field_order = field_order;
+    st->codecpar->color_range = color_range;
+
+    st->sample_aspect_ratio   = sar;
+    st->time_base             = (AVRational){ 1, 25 };
+    st->avg_frame_rate        = (AVRational){ 25, 1 };
+
+    ret = avio_open_dyn_buf(&oc->pb);
+    if (ret < 0)
+        goto end;
+
+    ret = avformat_write_header(oc, NULL);
+    if (ret < 0) {
+        avio_close_dyn_buf(oc->pb, &buf);
+        oc->pb = NULL;
+        av_free(buf);
+        goto end;
+    }
+
+    /* Exercise write_packet with a valid raw YUV420P frame */
+    if (pix_fmt == AV_PIX_FMT_YUV420P) {
+        AVPacket *pkt = av_packet_alloc();
+        if (pkt) {
+            /* YUV420P 16x16: Y=256, U=64, V=64 = 384 bytes */
+            if (av_new_packet(pkt, 384) == 0) {
+                pkt->stream_index = 0;
+                pkt->pts = pkt->dts = 0;
+                pkt->duration = 1;
+                av_write_frame(oc, pkt);
+            }
+            av_packet_free(&pkt);
+        }
+    }
+
+    av_write_trailer(oc);
+    avio_close_dyn_buf(oc->pb, &buf);
+    oc->pb = NULL;
+    av_free(buf);
+
+end:
+    if (oc->pb) {
+        avio_close_dyn_buf(oc->pb, &buf);
+        av_free(buf);
+        oc->pb = NULL;
+    }
+    avformat_free_context(oc);
+
+    if (expect_fail)
+        return (ret < 0) ? 0 : AVERROR(EINVAL);
+    return ret;
+}
+
+int main(void)
+{
+    int ret;
+    const AVRational sar11 = { 1, 1 };
+    const AVRational sar43 = { 4, 3 };
+    const AVRational sar01 = { 0, 1 };
+
+    av_log_set_level(AV_LOG_QUIET);
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 1;
+
+    ret = mux_once(AV_PIX_FMT_YUV422P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 2;
+
+    ret = mux_once(AV_PIX_FMT_YUV444P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 3;
+
+    ret = mux_once(AV_PIX_FMT_GRAY8, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 4;
+
+    ret = mux_once(AV_PIX_FMT_YUV411P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 5;
+
+    ret = mux_once(AV_PIX_FMT_YUVJ420P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 6;
+
+    ret = mux_once(AV_PIX_FMT_YUVJ422P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 7;
+
+    ret = mux_once(AV_PIX_FMT_YUVJ444P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 8;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar43, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 9;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar01, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 10;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar11, AV_FIELD_TT, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 11;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar11, AV_FIELD_BB, AVCOL_RANGE_UNSPECIFIED, 0);
+    if (ret < 0) return 12;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_MPEG, 0);
+    if (ret < 0) return 13;
+
+    ret = mux_once(AV_PIX_FMT_YUV420P, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_JPEG, 0);
+    if (ret < 0) return 14;
+
+    /* unsupported pixel format must fail */
+    ret = mux_once(AV_PIX_FMT_RGB24, sar11, AV_FIELD_PROGRESSIVE, AVCOL_RANGE_UNSPECIFIED, 1);
+    if (ret < 0) return 15;
+
+    return 0;
+}
diff --git a/libavutil/tests/file.c b/libavutil/tests/file.c
index 0b151de9a1..ede337646d 100644
--- a/libavutil/tests/file.c
+++ b/libavutil/tests/file.c
@@ -18,15 +18,27 @@
 
 #include "libavutil/file.c"
 
-int main(void)
+int main(int argc, char **argv)
 {
+    const char *path = argc > 1 ? argv[1] : "file.c";
     uint8_t *buf;
     size_t size;
-    if (av_file_map("file.c", &buf, &size, 0, NULL) < 0)
-        return 1;
 
+    if (av_file_map(path, &buf, &size, 0, NULL) < 0)
+        return 1;
     buf[0] = 's';
     printf("%s", buf);
     av_file_unmap(buf, size);
+
+    if (av_file_map("no_such_file_xyz", &buf, &size, 0, NULL) >= 0) {
+        av_file_unmap(buf, size);
+        return 2;
+    }
+
+    if (av_file_map("no_such_file_xyz", &buf, &size, 1, NULL) >= 0) {
+        av_file_unmap(buf, size);
+        return 3;
+    }
+
     return 0;
 }
diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak
index e2d616e307..426bbe976c 100644
--- a/tests/fate/libavcodec.mak
+++ b/tests/fate/libavcodec.mak
@@ -116,3 +116,8 @@ fate-libavcodec-htmlsubtitles: CMD = run libavcodec/tests/htmlsubtitles$(EXESUF)
 
 FATE-$(CONFIG_AVCODEC) += $(FATE_LIBAVCODEC-yes)
 fate-libavcodec: $(FATE_LIBAVCODEC-yes)
+
+FATE_LIBAVCODEC-$(CONFIG_H261_DECODER) += fate-h261-parser
+fate-h261-parser: libavcodec/tests/h261_parser$(EXESUF)
+fate-h261-parser: CMD = run libavcodec/tests/h261_parser$(EXESUF)
+fate-h261-parser: CMP = null
diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak
index 3b3a8a1177..a0349ac762 100644
--- a/tests/fate/libavformat.mak
+++ b/tests/fate/libavformat.mak
@@ -34,3 +34,8 @@ fate-seek_utils: CMP = null
 FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes)
 FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT)
 fate-libavformat: $(FATE_LIBAVFORMAT)
+
+FATE_LIBAVFORMAT-$(CONFIG_YUV4MPEGPIPE_MUXER) += fate-yuv4mpegenc
+fate-yuv4mpegenc: libavformat/tests/yuv4mpegenc$(EXESUF)
+fate-yuv4mpegenc: CMD = run libavformat/tests/yuv4mpegenc$(EXESUF)
+fate-yuv4mpegenc: CMP = null
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 6bf03b2438..18b3257853 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -182,3 +182,8 @@ fate-uuid: CMP = null
 FATE_LIBAVUTIL += $(FATE_LIBAVUTIL-yes)
 FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL)
 fate-libavutil: $(FATE_LIBAVUTIL)
+
+FATE_LIBAVUTIL += fate-file
+fate-file: libavutil/tests/file$(EXESUF)
+fate-file: CMD = run libavutil/tests/file$(EXESUF) libavutil/tests/file.c
+fate-file: CMP = null
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

                 reply	other threads:[~2026-02-21  5:50 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=177165191131.25.15704043415661500015@29965ddac10e \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git