h264bsd url https://github.com/oneam/h264bsd
./configure --enable-decoder="h264_bsd" --extra-cflags="-I<path>/h264bsd/src" 
--extra-ldflags="-L<path>/h264bsd/posix/lib" --extra-libs="-lh264bsd"
Test
./ffmpeg -y -codec:v h264_bsd -i <path>/h264bsd/test/test_640x360.h264 
./test_640x360.yuv

Signed-off-by: Shiqi Zhu <hiccup...@gmail.com>
---
 libavcodec/Makefile      |   1 +
 libavcodec/allcodecs.c   |   1 +
 libavcodec/h264bsd_dec.c | 183 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)
 create mode 100644 libavcodec/h264bsd_dec.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7bd1dbec9a..68cfc3abb5 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -419,6 +419,7 @@ OBJS-$(CONFIG_H264_DECODER)            += h264dec.o 
h264_cabac.o h264_cavlc.o \
                                           h264_slice.o h264data.o h274.o
 OBJS-$(CONFIG_H264_AMF_ENCODER)        += amfenc_h264.o
 OBJS-$(CONFIG_H264_AMF_DECODER)        += amfdec.o
+OBJS-$(CONFIG_H264_BSD_DECODER)        += h264bsd_dec.o
 OBJS-$(CONFIG_H264_CUVID_DECODER)      += cuviddec.o
 OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o
 OBJS-$(CONFIG_H264_MEDIACODEC_ENCODER) += mediacodecenc.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f10519617e..a752f83210 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -148,6 +148,7 @@ extern const FFCodec ff_h263i_decoder;
 extern const FFCodec ff_h263p_encoder;
 extern const FFCodec ff_h263p_decoder;
 extern const FFCodec ff_h263_v4l2m2m_decoder;
+extern const FFCodec ff_h264_bsd_decoder;
 extern const FFCodec ff_h264_decoder;
 extern const FFCodec ff_h264_v4l2m2m_decoder;
 extern const FFCodec ff_h264_mediacodec_decoder;
diff --git a/libavcodec/h264bsd_dec.c b/libavcodec/h264bsd_dec.c
new file mode 100644
index 0000000000..e687dbf8e3
--- /dev/null
+++ b/libavcodec/h264bsd_dec.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2025 Shiqi Zhu <hiccup...@gmail.com>
+ * 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
+ */
+
+/**
+ * @file
+ * MCV hardware video decoder
+ */
+
+#include "config_components.h"
+#include "avcodec.h"
+#include "codec_internal.h"
+#include "decode.h"
+#include "internal.h"
+#include "packet.h"
+#include "libavutil/opt.h"
+#include "libavutil/fifo.h"
+#include "h264bsd_decoder.h"
+
+typedef struct DecodeContext {
+    AVClass *av_class;
+    storage_t vdec;
+    AVCodecContext *avctx;
+    uint32_t ext_buffer_num;
+    int coded_width;
+    int coded_height;
+    enum AVPixelFormat format;
+} DecodeContext;
+
+static av_cold int h264_bsd_init_decoder(AVCodecContext *avctx)
+{
+    DecodeContext *x = avctx->priv_data;
+    int ret;
+
+    ret = h264bsdInit(&x->vdec, 0);
+    if (ret != 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to open hifi decoder\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    x->avctx = avctx;
+    x->format = AV_PIX_FMT_YUV420P;
+
+    return 0;
+}
+
+static av_cold int h264_bsd_close_decoder(AVCodecContext *avctx)
+{
+    DecodeContext *x = avctx->priv_data;
+    int ret;
+
+    x->avctx = NULL;
+    h264bsdShutdown(&x->vdec);
+
+    return 0;
+}
+
+static void h264_bsd_flush(AVCodecContext *avctx)
+{
+    DecodeContext *x = avctx->priv_data;
+
+    h264bsdFlushBuffer(&x->vdec);
+}
+
+static int h264_bsd_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+                              int *got_frame, AVPacket *avpkt)
+{
+    DecodeContext *x = avctx->priv_data;
+    int ret, i, w, h;
+    uint32_t readBytes;
+    int numPics = 0;
+    uint32_t picId, isIdrPic, numErrMbs;
+    uint8_t *data;
+
+    while (avpkt->size > 0) {
+        ret = h264bsdDecode(&x->vdec, avpkt->data, avpkt->size, 0, &readBytes);
+        avpkt->data += readBytes;
+        avpkt->size -= readBytes;
+        
+        switch (ret)
+        {
+        case H264BSD_PIC_RDY:
+            data = h264bsdNextOutputPicture(&x->vdec, &picId, &isIdrPic, 
&numErrMbs);
+            if (isIdrPic) {
+                av_log(avctx, AV_LOG_DEBUG, "IDR picture %d\n", picId);
+            } else {
+                av_log(avctx, AV_LOG_DEBUG, "Non-IDR picture %d\n", picId);
+            }
+            if (numErrMbs > 0) {
+                av_log(avctx, AV_LOG_DEBUG, "Picture %d has %d errors\n", 
picId, numErrMbs);
+            } else {
+                av_log(avctx, AV_LOG_DEBUG, "Picture %d has no errors\n", 
picId);
+            }
+
+            frame->width = avctx->width;
+            frame->height = avctx->height;
+            frame->format = x->format;
+            ret = avcodec_default_get_buffer2(avctx, frame, 0);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to get buffer\n");
+                return ret;
+            }
+
+            for (h = 0; h < frame->height; h++) {
+                memcpy(frame->data[0] + h * frame->linesize[0], data + h * 
x->coded_width, frame->width);
+            }
+            data += x->coded_width * x->coded_height;
+            w = x->coded_width >> 1;
+            for (i = 1; i < 3; i++) {
+                for (h = 0; h < (frame->height >> 1); h++) {
+                    memcpy(frame->data[i] + h * frame->linesize[i], data + h * 
w, frame->width >> 1);
+                }
+                data += w * h;
+            }
+            frame->pts = avpkt->pts;
+            frame->pkt_dts = avpkt->dts;
+            frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
+            *got_frame = 1;
+            break;
+        case H264BSD_HDRS_RDY:
+            x->coded_width = h264bsdPicWidth(&x->vdec) * 16;
+            x->coded_height = h264bsdPicHeight(&x->vdec) * 16;
+            av_log(avctx, AV_LOG_INFO, "Output dimensions: %dx%d\n", w, h);
+            break;
+        
+        case H264BSD_RDY:
+            av_log(avctx, AV_LOG_DEBUG, "Picture %d is ready\n", picId);
+            break;
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Error decoding frame: %d\n", ret);
+            goto out;
+        }
+    }
+
+out:
+    return avpkt->size;
+}
+
+#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+    {"ext_buffer_num", "extra buffer number", offsetof(DecodeContext, 
ext_buffer_num), AV_OPT_TYPE_INT, {.i64 = 1},   0,  16, VD},
+    {NULL}
+};
+
+static const AVClass h264_bsd_dec_class = {
+    .class_name = "h264_bsd_decoder",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_h264_bsd_decoder = {
+    .p.name = "h264_bsd",
+    CODEC_LONG_NAME("h264bsd video decoder for ffmpeg"),
+    .p.type = AVMEDIA_TYPE_VIDEO,
+    .p.id = AV_CODEC_ID_H264,
+    .priv_data_size = sizeof(DecodeContext),
+    .init = h264_bsd_init_decoder,
+    .close = h264_bsd_close_decoder,
+    FF_CODEC_DECODE_CB(h264_bsd_decode_frame),
+    .flush = h264_bsd_flush,
+    .p.priv_class = &h264_bsd_dec_class,
+    .bsfs = "h264_mp4toannexb",
+    .p.capabilities = AV_CODEC_CAP_DELAY,
+    .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, 
AV_PIX_FMT_NONE },
+    .p.wrapper_name = "ff_h264_bsd_decoder",
+    .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING, 
+};
\ No newline at end of file
-- 
2.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to