PR #24436 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24436
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24436.patch


>From 7caa4d585b28d42e2283f0b5a770cb523023d022 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 10 Sep 2026 00:03:40 -0300
Subject: [PATCH 1/4] avcodec/libxevd: set picture type and keyframe flag on
 the correct frames

The picture returned by xevd_pull() is not necessarely the one generated from
the packet last sent with xevd_decode().

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/libxevd.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/libavcodec/libxevd.c b/libavcodec/libxevd.c
index 520fdab7d8..28f3cc529c 100644
--- a/libavcodec/libxevd.c
+++ b/libavcodec/libxevd.c
@@ -27,6 +27,7 @@
 
 #include "libavutil/internal.h"
 #include "libavutil/common.h"
+#include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/pixfmt.h"
 #include "libavutil/imgutils.h"
@@ -295,7 +296,8 @@ static int libxevd_return_frame(AVCodecContext *avctx, 
AVFrame *frame,
     frame->pkt_dts = imgb->ts[XEVD_TS_DTS];
     frame->pts = imgb->ts[XEVD_TS_PTS];
 
-    av_packet_free(&pkt_au_imgb);
+    av_packet_free((AVPacket**)&imgb->pdata[0]);
+    av_freep(&imgb->pdata[1]);
 
     // xevd_pull uses pool of objects of type XEVD_IMGB.
     // The pool size is equal MAX_PB_SIZE (26), so release object when it is 
no more needed
@@ -364,13 +366,20 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
             bitb.addr = pkt_au->data + bs_read_pos;
             bitb.ssize = nalu_size;
             bitb.pdata[0] = pkt_au;
+            bitb.pdata[1] = av_mallocz(sizeof(stat.stype));
             bitb.ts[XEVD_TS_DTS] = pkt_au->dts;
 
+            if (!bitb.pdata[1]) {
+                av_packet_free(&pkt_au);
+                return AVERROR(ENOMEM);
+            }
+
             /* main decoding block */
             xevd_ret = xevd_decode(xectx->id, &bitb, &stat);
             if (XEVD_FAILED(xevd_ret)) {
                 av_log(avctx, AV_LOG_ERROR, "Failed to decode bitstream\n");
                 av_packet_free(&pkt_au);
+                av_freep(&bitb.pdata[1]);
 
                 return AVERROR_EXTERNAL;
             }
@@ -391,6 +400,8 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
 
             // stat.fnum - has negative value if the decoded data is not frame
             if (stat.fnum >= 0) {
+                // store stat.stype into the bitb.pdata[1] that will be 
retrieved in an image
+                *(int*)bitb.pdata[1] = stat.stype;
 
                 xevd_ret = xevd_pull(xectx->id, &imgb); // The function 
returns a valid image only if the return code is XEVD_OK
 
@@ -413,7 +424,7 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
                             return  AVERROR(EAGAIN);
                         }
                     } else {
-                        if (stat.stype == XEVD_ST_I) {
+                        if (*(int*)imgb->pdata[1] == XEVD_ST_I) {
                             frame->pict_type = AV_PICTURE_TYPE_I;
                             frame->flags |= AV_FRAME_FLAG_KEY;
                         }
@@ -441,6 +452,10 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
                 return AVERROR_EXTERNAL;
             }
 
+            if (*(int*)imgb->pdata[1] == XEVD_ST_I) {
+                frame->pict_type = AV_PICTURE_TYPE_I;
+                frame->flags |= AV_FRAME_FLAG_KEY;
+            }
             return libxevd_return_frame(avctx, frame, imgb, NULL);
         }
     }
-- 
2.52.0


>From ea0b99e8b4b613b94a50d108ac07c09e281ece0b Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 10 Sep 2026 00:04:22 -0300
Subject: [PATCH 2/4] avcodec/libxevd: rename to libxevd

"evc" must be used only by an eventual native decoder.

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/libxevd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/libxevd.c b/libavcodec/libxevd.c
index 28f3cc529c..ab7a2ebee2 100644
--- a/libavcodec/libxevd.c
+++ b/libavcodec/libxevd.c
@@ -484,7 +484,7 @@ static av_cold int libxevd_close(AVCodecContext *avctx)
 }
 
 const FFCodec ff_libxevd_decoder = {
-    .p.name             = "evc",
+    .p.name             = "libxevd",
     CODEC_LONG_NAME("EVC / MPEG-5 Essential Video Coding (EVC)"),
     .p.type             = AVMEDIA_TYPE_VIDEO,
     .p.id               = AV_CODEC_ID_EVC,
-- 
2.52.0


>From e8bca7e6ba56be673b80ebca0ad4b3eb9aedfe46 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 10 Sep 2026 00:14:12 -0300
Subject: [PATCH 3/4] avcodec/libxevd: fix draining code when unexpected codes
 are returned

libxevd appears to return positive values other than XEVD_OK in some 
circumstances,
which resulted in an endless loop of the decoder returning AVERROR_EXTERNAL 
until
stopped.

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/libxevd.c | 36 ++++++++++++++++++++----------------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/libavcodec/libxevd.c b/libavcodec/libxevd.c
index ab7a2ebee2..5810f6676c 100644
--- a/libavcodec/libxevd.c
+++ b/libavcodec/libxevd.c
@@ -435,28 +435,32 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
         }
     } else { // decoder draining mode handling
 
-        xevd_ret = xevd_pull(xectx->id, &imgb);
+        while (1) {
+            xevd_ret = xevd_pull(xectx->id, &imgb);
 
-        if (xevd_ret == XEVD_ERR_UNEXPECTED) { // draining process completed
-            av_log(avctx, AV_LOG_DEBUG, "Draining process completed\n");
+            if (xevd_ret == XEVD_ERR_UNEXPECTED) { // draining process 
completed
+                av_log(avctx, AV_LOG_DEBUG, "Draining process completed\n");
 
-            return AVERROR_EOF;
-        } else if (XEVD_FAILED(xevd_ret)) { // handle all other errors
-            av_log(avctx, AV_LOG_ERROR, "Failed to pull the decoded image 
(xevd error code: %d)\n", xevd_ret);
-
-            return AVERROR_EXTERNAL;
-        } else { // XEVD_OK
-            if (!imgb) {
-                av_log(avctx, AV_LOG_ERROR, "Invalid decoded image data\n");
+                return AVERROR_EOF;
+            } else if (XEVD_FAILED(xevd_ret)) { // handle all other errors
+                av_log(avctx, AV_LOG_ERROR, "Failed to pull the decoded image 
(xevd error code: %d)\n", xevd_ret);
 
                 return AVERROR_EXTERNAL;
-            }
+            } else if (xevd_ret == XEVD_OK) {
+                if (!imgb) {
+                    av_log(avctx, AV_LOG_ERROR, "Invalid decoded image 
data\n");
 
-            if (*(int*)imgb->pdata[1] == XEVD_ST_I) {
-                frame->pict_type = AV_PICTURE_TYPE_I;
-                frame->flags |= AV_FRAME_FLAG_KEY;
+                    continue;
+                }
+
+                if (*(int*)imgb->pdata[1] == XEVD_ST_I) {
+                    frame->pict_type = AV_PICTURE_TYPE_I;
+                    frame->flags |= AV_FRAME_FLAG_KEY;
+                }
+                return libxevd_return_frame(avctx, frame, imgb, NULL);
             }
-            return libxevd_return_frame(avctx, frame, imgb, NULL);
+            av_log(avctx, AV_LOG_WARNING, "Unexpected return code while 
draining (xevd error code: %d)\n", xevd_ret);
+            return AVERROR_EOF;
         }
     }
 
-- 
2.52.0


>From fafb0c72f026c93bf2d6b56a806fa8a20487a05d Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 10 Sep 2026 00:19:39 -0300
Subject: [PATCH 4/4] avcodec/libxevd: remove unused draining_mode variable

Signed-off-by: James Almer <[email protected]>
---
 libavcodec/libxevd.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/libavcodec/libxevd.c b/libavcodec/libxevd.c
index 5810f6676c..dd8ffb2f6a 100644
--- a/libavcodec/libxevd.c
+++ b/libavcodec/libxevd.c
@@ -52,7 +52,6 @@ typedef struct XevdContext {
 
     // If end of stream occurs it is required "flushing" (aka draining) the 
codec,
     // as the codec might buffer multiple frames or packets internally.
-    int draining_mode; // The flag is set if codec enters draining mode.
 
     AVPacket *pkt;     // access unit (a set of NAL units that are consecutive 
in decoding order and containing exactly one encoded image)
 } XevdContext;
@@ -236,7 +235,6 @@ static av_cold int libxevd_init(AVCodecContext *avctx)
         return AVERROR_EXTERNAL;
     }
 
-    xectx->draining_mode = 0;
     xectx->pkt = av_packet_alloc();
     if (!xectx->pkt) {
         av_log(avctx, AV_LOG_ERROR, "Cannot allocate memory for AVPacket\n");
@@ -329,10 +327,6 @@ static int libxevd_receive_frame(AVCodecContext *avctx, 
AVFrame *frame)
         av_packet_unref(pkt);
 
         return ret;
-    } else if(ret == AVERROR_EOF && xectx->draining_mode == 0) { // End of 
stream situations. Enter draining mode
-
-        xectx->draining_mode = 1;
-        av_packet_unref(pkt);
     }
 
     if (pkt->size > 0) {
@@ -481,7 +475,6 @@ static av_cold int libxevd_close(AVCodecContext *avctx)
         xectx->id = NULL;
     }
 
-    xectx->draining_mode = 0;
     av_packet_free(&xectx->pkt);
 
     return 0;
-- 
2.52.0

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

Reply via email to