PR #22446 opened by Jun Zhao (mypopydev)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22446
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22446.patch

The recent five commits focus on improving the robustness and correctness of 
FFmpeg's documentation examples (doc/examples). These fixes address issues such 
as incorrect API usage (replacing avformat_close_input with 
avio_closep/avformat_free_context for output contexts), cross-platform data 
corruption (enforcing binary mode for raw YUV input on Windows), unsafe file 
operations (adding missing NULL checks for fopen), and silent error suppression 
(fixing invalid fwrite return value checks). Additionally, they correct logic 
for dumping multi-plane raw video frames (NV12/P010) by respecting per-plane 
line sizes, preventing buffer over-reads and corrupted output.
  Collectively, these changes enhance the reliability and safety of the example 
code


From 97b5ea3aa6fa74acd131fb6ebb9caec8e2d2fc72 Mon Sep 17 00:00:00 2001
From: Jun Zhao <[email protected]>
Date: Sun, 8 Mar 2026 22:44:17 +0800
Subject: [PATCH 1/5] doc/examples: fix output context cleanup in transcode
 examples
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

avformat_close_input() is designed for input format contexts only.
Using it on output contexts is API misuse — it accesses iformat
(which is NULL for output contexts) and does not follow the correct
output cleanup path.

Replace with the proper pattern already used in remux.c and
transcode.c: avio_closep() to close the IO handle, followed by
avformat_free_context() to free the format context.

Signed-off-by: Jun Zhao <[email protected]>
---
 doc/examples/qsv_transcode.c   | 4 +++-
 doc/examples/vaapi_transcode.c | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/doc/examples/qsv_transcode.c b/doc/examples/qsv_transcode.c
index c3f507e8e6..b4230e7a38 100644
--- a/doc/examples/qsv_transcode.c
+++ b/doc/examples/qsv_transcode.c
@@ -430,7 +430,9 @@ int main(int argc, char **argv)
 
 end:
     avformat_close_input(&ifmt_ctx);
-    avformat_close_input(&ofmt_ctx);
+    if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
+        avio_closep(&ofmt_ctx->pb);
+    avformat_free_context(ofmt_ctx);
     avcodec_free_context(&decoder_ctx);
     avcodec_free_context(&encoder_ctx);
     av_buffer_unref(&hw_device_ctx);
diff --git a/doc/examples/vaapi_transcode.c b/doc/examples/vaapi_transcode.c
index e1b7a43883..dba37d4bcb 100644
--- a/doc/examples/vaapi_transcode.c
+++ b/doc/examples/vaapi_transcode.c
@@ -294,7 +294,9 @@ int main(int argc, char **argv)
 
 end:
     avformat_close_input(&ifmt_ctx);
-    avformat_close_input(&ofmt_ctx);
+    if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
+        avio_closep(&ofmt_ctx->pb);
+    avformat_free_context(ofmt_ctx);
     avcodec_free_context(&decoder_ctx);
     avcodec_free_context(&encoder_ctx);
     av_buffer_unref(&hw_device_ctx);
-- 
2.52.0


From 369353b42ae024ffc610f7955d983b75bd64640a Mon Sep 17 00:00:00 2001
From: Jun Zhao <[email protected]>
Date: Sun, 8 Mar 2026 22:48:46 +0800
Subject: [PATCH 2/5] doc/examples/vaapi_encode: open raw YUV input in binary
 mode

fopen() with "r" opens the file in text mode, which on Windows
translates \r\n to \n, corrupting raw NV12 pixel data. Use "rb"
to open in binary mode, matching the output file which already
uses "w+b".

Signed-off-by: Jun Zhao <[email protected]>
---
 doc/examples/vaapi_encode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/examples/vaapi_encode.c b/doc/examples/vaapi_encode.c
index 330a6524ef..d4381776ca 100644
--- a/doc/examples/vaapi_encode.c
+++ b/doc/examples/vaapi_encode.c
@@ -118,7 +118,7 @@ int main(int argc, char *argv[])
     height = atoi(argv[2]);
     size   = width * height;
 
-    if (!(fin = fopen(argv[3], "r"))) {
+    if (!(fin = fopen(argv[3], "rb"))) {
         fprintf(stderr, "Fail to open input file : %s\n", strerror(errno));
         return -1;
     }
-- 
2.52.0


From a52862ee5e94cf7cc6c6e6b395313fc3d558e687 Mon Sep 17 00:00:00 2001
From: Jun Zhao <[email protected]>
Date: Sun, 8 Mar 2026 22:49:38 +0800
Subject: [PATCH 3/5] doc/examples/decode_video: check fopen return value in
 pgm_save

pgm_save() passes the FILE pointer from fopen() directly to
fprintf() and fwrite() without a NULL check. If fopen() fails
(e.g. permission denied or disk full), this causes a NULL pointer
dereference and crash.

Signed-off-by: Jun Zhao <[email protected]>
---
 doc/examples/decode_video.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/doc/examples/decode_video.c b/doc/examples/decode_video.c
index b0b3a6ae92..9d92ebbe9c 100644
--- a/doc/examples/decode_video.c
+++ b/doc/examples/decode_video.c
@@ -42,7 +42,11 @@ static void pgm_save(unsigned char *buf, int wrap, int 
xsize, int ysize,
     FILE *f;
     int i;
 
-    f = fopen(filename,"wb");
+    f = fopen(filename, "wb");
+    if (!f) {
+        fprintf(stderr, "Could not open %s\n", filename);
+        return;
+    }
     fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
     for (i = 0; i < ysize; i++)
         fwrite(buf + i * wrap, 1, xsize, f);
-- 
2.52.0


From b8ec487b4c7f3aaa02024f99dfaad5002cababb8 Mon Sep 17 00:00:00 2001
From: Jun Zhao <[email protected]>
Date: Sun, 8 Mar 2026 22:52:51 +0800
Subject: [PATCH 4/5] doc/examples/hw_decode: fix fwrite error check

fwrite() returns size_t (unsigned), so comparing its return value
with < 0 is always false and write errors are silently ignored.
Check against the expected byte count instead.

Signed-off-by: Jun Zhao <[email protected]>
---
 doc/examples/hw_decode.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/examples/hw_decode.c b/doc/examples/hw_decode.c
index ce18814760..7c73d59d93 100644
--- a/doc/examples/hw_decode.c
+++ b/doc/examples/hw_decode.c
@@ -132,8 +132,9 @@ static int decode_write(AVCodecContext *avctx, AVPacket 
*packet)
             goto fail;
         }
 
-        if ((ret = fwrite(buffer, 1, size, output_file)) < 0) {
+        if (fwrite(buffer, 1, size, output_file) != size) {
             fprintf(stderr, "Failed to dump raw data.\n");
+            ret = -1;
             goto fail;
         }
 
-- 
2.52.0


From 52f08b0eb36de01e01d5635d3057d3346275de9d Mon Sep 17 00:00:00 2001
From: Jun Zhao <[email protected]>
Date: Sun, 8 Mar 2026 22:55:37 +0800
Subject: [PATCH 5/5] doc/examples/qsv_decode: fix raw frame dump for chroma
 planes

The output loop used sw_frame->width as the write size for all
planes. This is only correct for NV12 where the interleaved UV
plane happens to have the same byte width as the Y plane. For
other pixel formats (e.g. YUV420P where U/V planes are half
width, or P010 where samples are 2 bytes), the output would be
corrupted.

Use av_image_get_linesize() to compute the correct byte width
for each plane based on the actual pixel format.

Signed-off-by: Jun Zhao <[email protected]>
---
 doc/examples/qsv_decode.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/doc/examples/qsv_decode.c b/doc/examples/qsv_decode.c
index ec91109480..cdfde89652 100644
--- a/doc/examples/qsv_decode.c
+++ b/doc/examples/qsv_decode.c
@@ -39,6 +39,7 @@
 #include <libavutil/error.h>
 #include <libavutil/hwcontext.h>
 #include <libavutil/hwcontext_qsv.h>
+#include <libavutil/imgutils.h>
 #include <libavutil/mem.h>
 
 static int get_format(AVCodecContext *avctx, const enum AVPixelFormat 
*pix_fmts)
@@ -88,9 +89,16 @@ static int decode_packet(AVCodecContext *decoder_ctx,
             goto fail;
         }
 
-        for (i = 0; i < FF_ARRAY_ELEMS(sw_frame->data) && sw_frame->data[i]; 
i++)
-            for (j = 0; j < (sw_frame->height >> (i > 0)); j++)
-                avio_write(output_ctx, sw_frame->data[i] + j * 
sw_frame->linesize[i], sw_frame->width);
+        for (i = 0; i < FF_ARRAY_ELEMS(sw_frame->data) && sw_frame->data[i]; 
i++) {
+            int h = sw_frame->height >> (i > 0);
+            int linesize = av_image_get_linesize(sw_frame->format, 
sw_frame->width, i);
+            if (linesize < 0) {
+                ret = linesize;
+                goto fail;
+            }
+            for (j = 0; j < h; j++)
+                avio_write(output_ctx, sw_frame->data[i] + j * 
sw_frame->linesize[i], linesize);
+        }
 
 fail:
         av_frame_unref(sw_frame);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to