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 <[email protected]> From fd605c7b0f8c8cbb1a107f94b218c60cd6aee3a9 Mon Sep 17 00:00:00 2001 From: Soham Kute <[email protected]> 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 <[email protected]> --- 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 -- [email protected] To unsubscribe send an email to [email protected]
