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".