593 lines
22 KiB
Diff
593 lines
22 KiB
Diff
From 7757b33d16cc70e2f5a182cad8f9f9ee375874b2 Mon Sep 17 00:00:00 2001
|
|
From: fuqiang <qiang.fu@spacemit.com>
|
|
Date: Fri, 29 Mar 2024 10:45:11 +0800
|
|
Subject: [PATCH] stcodec support video encode
|
|
|
|
---
|
|
configure | 7 +
|
|
libavcodec/Makefile | 7 +
|
|
libavcodec/allcodecs.c | 7 +
|
|
libavcodec/stcodecenc.c | 417 ++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 438 insertions(+)
|
|
create mode 100755 libavcodec/stcodecenc.c
|
|
|
|
diff --git a/configure b/configure
|
|
index 473d30e..c14c5c1 100755
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -3095,6 +3095,7 @@ h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m"
|
|
h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf"
|
|
h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m"
|
|
h264_stcodec_decoder_deps="stcodec"
|
|
+h264_stcodec_encoder_deps="stcodec"
|
|
hevc_amf_encoder_deps="amf"
|
|
hevc_cuvid_decoder_deps="cuvid"
|
|
hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf"
|
|
@@ -3113,12 +3114,15 @@ hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m"
|
|
hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf"
|
|
hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m"
|
|
hevc_stcodec_decoder_deps="stcodec"
|
|
+hevc_stcodec_encoder_deps="stcodec"
|
|
mjpeg_cuvid_decoder_deps="cuvid"
|
|
mjpeg_qsv_decoder_select="qsvdec"
|
|
mjpeg_qsv_encoder_deps="libmfx"
|
|
mjpeg_qsv_encoder_select="qsvenc"
|
|
mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
|
|
mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode"
|
|
+mjpeg_stcodec_decoder_deps="stcodec"
|
|
+mjpeg_stcodec_encoder_deps="stcodec"
|
|
mp3_mf_encoder_deps="mediafoundation"
|
|
mpeg1_cuvid_decoder_deps="cuvid"
|
|
mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m"
|
|
@@ -3137,6 +3141,7 @@ mpeg4_mmal_decoder_deps="mmal"
|
|
mpeg4_omx_encoder_deps="omx"
|
|
mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
|
|
mpeg4_v4l2m2m_encoder_deps="v4l2_m2m mpeg4_v4l2_m2m"
|
|
+mpeg4_stcodec_decoder_deps="stcodec"
|
|
msmpeg4_crystalhd_decoder_select="crystalhd"
|
|
nvenc_h264_encoder_select="h264_nvenc_encoder"
|
|
nvenc_hevc_encoder_select="hevc_nvenc_encoder"
|
|
@@ -3153,6 +3158,7 @@ vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8"
|
|
vp8_vaapi_encoder_select="vaapi_encode"
|
|
vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m"
|
|
vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m"
|
|
+vp8_stcodec_decoder_deps="stcodec"
|
|
vp9_cuvid_decoder_deps="cuvid"
|
|
vp9_mediacodec_decoder_deps="mediacodec"
|
|
vp9_qsv_decoder_select="qsvdec"
|
|
@@ -3162,6 +3168,7 @@ vp9_vaapi_encoder_select="vaapi_encode"
|
|
vp9_qsv_encoder_deps="libmfx MFX_CODEC_VP9"
|
|
vp9_qsv_encoder_select="qsvenc"
|
|
vp9_v4l2m2m_decoder_deps="v4l2_m2m vp9_v4l2_m2m"
|
|
+vp9_stcodec_decoder_deps="stcodec"
|
|
wmv3_crystalhd_decoder_select="crystalhd"
|
|
av1_qsv_decoder_select="qsvdec"
|
|
|
|
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
|
|
index ff56ed6..e8e18f3 100644
|
|
--- a/libavcodec/Makefile
|
|
+++ b/libavcodec/Makefile
|
|
@@ -386,6 +386,7 @@ OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
|
OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
|
OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
|
OBJS-$(CONFIG_H264_STCODEC_DECODER) += stcodecdec.o
|
|
+OBJS-$(CONFIG_H264_STCODEC_ENCODER) += stcodecenc.o
|
|
OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o
|
|
OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o
|
|
OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
|
|
@@ -407,6 +408,7 @@ OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level
|
|
OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
|
OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
|
OBJS-$(CONFIG_HEVC_STCODEC_DECODER) += stcodecdec.o
|
|
+OBJS-$(CONFIG_HEVC_STCODEC_ENCODER) += stcodecenc.o
|
|
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
|
|
OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
|
|
canopus.o
|
|
@@ -461,6 +463,8 @@ OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o
|
|
OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o
|
|
OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o
|
|
OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o
|
|
+OBJS-$(CONFIG_MJPEG_STCODEC_DECODER) += stcodecdec.o
|
|
+OBJS-$(CONFIG_MJPEG_STCODEC_ENCODER) += stcodecenc.o
|
|
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o
|
|
OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o
|
|
OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o
|
|
@@ -506,6 +510,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o
|
|
OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o
|
|
OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
|
OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
|
+OBJS-$(CONFIG_MPEG4_STCODEC_DECODER) += stcodecdec.o
|
|
OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o
|
|
OBJS-$(CONFIG_MSA1_DECODER) += mss3.o
|
|
OBJS-$(CONFIG_MSCC_DECODER) += mscc.o
|
|
@@ -722,6 +727,7 @@ OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
|
|
OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o
|
|
OBJS-$(CONFIG_VP8_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
|
OBJS-$(CONFIG_VP8_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
|
+OBJS-$(CONFIG_VP8_STCODEC_DECODER) += stcodecdec.o
|
|
OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9recon.o \
|
|
vp9block.o vp9prob.o vp9mvs.o vp56rac.o \
|
|
vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
|
|
@@ -732,6 +738,7 @@ OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
|
|
OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o
|
|
OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o
|
|
OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
|
+OBJS-$(CONFIG_VP9_STCODEC_DECODER) += stcodecdec.o
|
|
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
|
|
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o
|
|
OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackdata.o wavpackenc.o
|
|
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
|
|
index 9981106..79bf666 100644
|
|
--- a/libavcodec/allcodecs.c
|
|
+++ b/libavcodec/allcodecs.c
|
|
@@ -149,12 +149,14 @@ extern AVCodec ff_h264_mmal_decoder;
|
|
extern AVCodec ff_h264_qsv_decoder;
|
|
extern AVCodec ff_h264_rkmpp_decoder;
|
|
extern AVCodec ff_h264_stcodec_decoder;
|
|
+extern AVCodec ff_h264_stcodec_encoder;
|
|
extern AVCodec ff_hap_encoder;
|
|
extern AVCodec ff_hap_decoder;
|
|
extern AVCodec ff_hevc_decoder;
|
|
extern AVCodec ff_hevc_qsv_decoder;
|
|
extern AVCodec ff_hevc_rkmpp_decoder;
|
|
extern AVCodec ff_hevc_stcodec_decoder;
|
|
+extern AVCodec ff_hevc_stcodec_encoder;
|
|
extern AVCodec ff_hevc_v4l2m2m_decoder;
|
|
extern AVCodec ff_hnm4_video_decoder;
|
|
extern AVCodec ff_hq_hqa_decoder;
|
|
@@ -191,6 +193,8 @@ extern AVCodec ff_mimic_decoder;
|
|
extern AVCodec ff_mjpeg_encoder;
|
|
extern AVCodec ff_mjpeg_decoder;
|
|
extern AVCodec ff_mjpegb_decoder;
|
|
+extern AVCodec ff_mjpeg_stcodec_decoder;
|
|
+extern AVCodec ff_mjpeg_stcodec_encoder;
|
|
extern AVCodec ff_mmvideo_decoder;
|
|
extern AVCodec ff_mobiclip_decoder;
|
|
extern AVCodec ff_motionpixels_decoder;
|
|
@@ -203,6 +207,7 @@ extern AVCodec ff_mpeg4_decoder;
|
|
extern AVCodec ff_mpeg4_crystalhd_decoder;
|
|
extern AVCodec ff_mpeg4_v4l2m2m_decoder;
|
|
extern AVCodec ff_mpeg4_mmal_decoder;
|
|
+extern AVCodec ff_mpeg4_stcodec_decoder;
|
|
extern AVCodec ff_mpegvideo_decoder;
|
|
extern AVCodec ff_mpeg1_v4l2m2m_decoder;
|
|
extern AVCodec ff_mpeg2_mmal_decoder;
|
|
@@ -361,9 +366,11 @@ extern AVCodec ff_vp7_decoder;
|
|
extern AVCodec ff_vp8_decoder;
|
|
extern AVCodec ff_vp8_rkmpp_decoder;
|
|
extern AVCodec ff_vp8_v4l2m2m_decoder;
|
|
+extern AVCodec ff_vp8_stcodec_decoder;
|
|
extern AVCodec ff_vp9_decoder;
|
|
extern AVCodec ff_vp9_rkmpp_decoder;
|
|
extern AVCodec ff_vp9_v4l2m2m_decoder;
|
|
+extern AVCodec ff_vp9_stcodec_decoder;
|
|
extern AVCodec ff_vqa_decoder;
|
|
extern AVCodec ff_webp_decoder;
|
|
extern AVCodec ff_wcmv_decoder;
|
|
diff --git a/libavcodec/stcodecenc.c b/libavcodec/stcodecenc.c
|
|
new file mode 100755
|
|
index 0000000..eeaa41a
|
|
--- /dev/null
|
|
+++ b/libavcodec/stcodecenc.c
|
|
@@ -0,0 +1,417 @@
|
|
+/*
|
|
+ * Spacemit MPP Video Encoder
|
|
+ * Copyright 2022-2023 SPACEMIT. All rights reserved.
|
|
+ *
|
|
+ * 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 <drm_fourcc.h>
|
|
+#include <fcntl.h>
|
|
+#include <linux/dma-buf.h>
|
|
+#include <linux/dma-heap.h>
|
|
+#include <pthread.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <sys/mman.h>
|
|
+#include <time.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include "avcodec.h"
|
|
+#include "internal.h"
|
|
+#include "encode.h"
|
|
+#include "h264_parse.h"
|
|
+#include "hevc_parse.h"
|
|
+#include "hwconfig.h"
|
|
+#include "libavutil/buffer.h"
|
|
+#include "libavutil/common.h"
|
|
+#include "libavutil/frame.h"
|
|
+#include "libavutil/hwcontext.h"
|
|
+#include "libavutil/hwcontext_drm.h"
|
|
+#include "libavutil/imgutils.h"
|
|
+#include "libavutil/log.h"
|
|
+#include "venc.h"
|
|
+
|
|
+#define PACKET_SIZE (2 * 1024 * 1024)
|
|
+
|
|
+typedef struct {
|
|
+ MppVencCtx* pVencCtx;
|
|
+ MppPacket* pPacket;
|
|
+ MppFrame* pFrame;
|
|
+
|
|
+ char first_packet;
|
|
+ char eos_reached;
|
|
+
|
|
+ AVBufferRef* frames_ref;
|
|
+ AVBufferRef* device_ref;
|
|
+} STCODECEncoder;
|
|
+
|
|
+typedef struct {
|
|
+ AVClass* av_class;
|
|
+ AVBufferRef* encoder_ref;
|
|
+} STCODECEncodeContext;
|
|
+
|
|
+typedef struct {
|
|
+ MppFrame* pFrame;
|
|
+ AVBufferRef* encoder_ref;
|
|
+} STCODECFrameContext;
|
|
+
|
|
+static MppCodingType stcodec_get_codingtype(AVCodecContext* avctx) {
|
|
+ switch (avctx->codec_id) {
|
|
+ case AV_CODEC_ID_H264:
|
|
+ return CODING_H264;
|
|
+ case AV_CODEC_ID_HEVC:
|
|
+ return CODING_H265;
|
|
+ case AV_CODEC_ID_VP8:
|
|
+ return CODING_VP8;
|
|
+ case AV_CODEC_ID_VP9:
|
|
+ return CODING_VP9;
|
|
+ case AV_CODEC_ID_MJPEG:
|
|
+ return CODING_MJPEG;
|
|
+ default:
|
|
+ return CODING_UNKNOWN;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int get_stride(int width, int align) {
|
|
+ return (width + align - 1) & (~(align - 1));
|
|
+}
|
|
+
|
|
+static int stcodec_send_frame(AVCodecContext* avctx, const AVFrame* frame) {
|
|
+ STCODECEncodeContext* st_context = avctx->priv_data;
|
|
+ STCODECEncoder* encoder = (STCODECEncoder*)st_context->encoder_ref->data;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (frame != NULL) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "@@@@@@@@ format:%d fd:%d %p %p\n",
|
|
+ frame->format,
|
|
+ ((AVDRMFrameDescriptor*)(frame->data[0]))->objects[0].fd,
|
|
+ frame->data[0], frame->data[1]);
|
|
+ FRAME_SetEos(encoder->pFrame, 0);
|
|
+ if (frame->format == AV_PIX_FMT_NV12) {
|
|
+ FRAME_SetDataUsedNum(encoder->pFrame, 2);
|
|
+ FRAME_SetDataPointer(encoder->pFrame, 0, frame->data[0]);
|
|
+ FRAME_SetDataPointer(encoder->pFrame, 1, frame->data[1]);
|
|
+ // FRAME_SetDataPointer(encoder->pFrame, 2, frame->data[2]);
|
|
+ } else if (frame->format == AV_PIX_FMT_DRM_PRIME) {
|
|
+ void* vaddr =
|
|
+ mmap(NULL, ((AVDRMFrameDescriptor*)(frame->data[0]))->objects[0].size,
|
|
+ PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
+ ((AVDRMFrameDescriptor*)(frame->data[0]))->objects[0].fd, 0);
|
|
+ FRAME_SetDataUsedNum(encoder->pFrame, 2);
|
|
+ FRAME_SetDataPointer(encoder->pFrame, 0, (U8*)vaddr);
|
|
+ FRAME_SetDataPointer(encoder->pFrame, 1,
|
|
+ ((U8*)vaddr) + frame->width * frame->height);
|
|
+ // FRAME_SetDataPointer(encoder->pFrame, 2,
|
|
+ // ((U8*)vaddr) + frame->width * frame->height * 5 /
|
|
+ // 4);
|
|
+ } else {
|
|
+ }
|
|
+ ret = VENC_Encode(encoder->pVencCtx, FRAME_GetBaseData(encoder->pFrame));
|
|
+ } else {
|
|
+ FRAME_SetEos(encoder->pFrame, 1);
|
|
+ av_log(avctx, AV_LOG_ERROR, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ bigbig %d\n",
|
|
+ FRAME_GetEos(encoder->pFrame));
|
|
+ // FRAME_SetDataUsedNum(encoder->pFrame, 0);
|
|
+ ret = VENC_Encode(encoder->pVencCtx, FRAME_GetBaseData(encoder->pFrame));
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int stcodec_receive_packet(AVCodecContext* avctx, AVPacket* avpkt) {
|
|
+ STCODECEncodeContext* st_context = avctx->priv_data;
|
|
+ STCODECEncoder* encoder = (STCODECEncoder*)st_context->encoder_ref->data;
|
|
+ int ret = -1;
|
|
+ AVFrame* frame = av_frame_alloc();
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 0.\n");
|
|
+ // if (!frame->buf[0]) {
|
|
+ ret = ff_encode_get_frame(avctx, frame);
|
|
+
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 0. RET = %d\n",
|
|
+ ret);
|
|
+ if (ret < 0 && ret != AVERROR_EOF) return ret;
|
|
+
|
|
+ if (ret == AVERROR_EOF) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 get eos\n");
|
|
+ frame = NULL;
|
|
+ }
|
|
+ //}
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 1.\n");
|
|
+ ret = stcodec_send_frame(avctx, frame);
|
|
+ if (ret != AVERROR(EAGAIN)) av_frame_unref(frame);
|
|
+
|
|
+ if (ret < 0 && ret != AVERROR(EAGAIN)) return ret;
|
|
+
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 2.\n");
|
|
+ // return ff_v4l2_context_dequeue_packet(capture, avpkt);
|
|
+haha:
|
|
+ ret = VENC_RequestOutputStreamBuffer(encoder->pVencCtx,
|
|
+ PACKET_GetBaseData(encoder->pPacket));
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 2. ret = %d\n",
|
|
+ ret);
|
|
+ if (ret == MPP_OK) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 3.\n");
|
|
+ avpkt->size = PACKET_GetLength(encoder->pPacket);
|
|
+ av_log(avctx, AV_LOG_DEBUG, "1111111111111111111111111111111 4. %d=%d %p\n",
|
|
+ PACKET_GetLength(encoder->pPacket), avpkt->size,
|
|
+ PACKET_GetDataPointer(encoder->pPacket));
|
|
+ av_new_packet(avpkt, avpkt->size);
|
|
+ memcpy(avpkt->data, PACKET_GetDataPointer(encoder->pPacket), avpkt->size);
|
|
+ av_log(avctx, AV_LOG_ERROR, "1111111111111111111111111111111 5.\n");
|
|
+ VENC_ReturnOutputStreamBuffer(encoder->pVencCtx,
|
|
+ PACKET_GetBaseData(encoder->pPacket));
|
|
+ } else if (ret == MPP_CODER_NO_DATA) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "get no data.\n");
|
|
+ // return AVERROR(EAGAIN);
|
|
+ goto haha;
|
|
+ } else if (ret == MPP_CODER_EOS) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "get EOS.\n");
|
|
+ return AVERROR_EOF;
|
|
+ } else {
|
|
+ av_log(avctx, AV_LOG_ERROR, "get ???. %d\n", ret);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static av_cold int stcodec_close_encoder(AVCodecContext* avctx) {
|
|
+ STCODECEncodeContext* st_context = avctx->priv_data;
|
|
+ av_log(NULL, AV_LOG_ERROR, "stcodec close encoder\n");
|
|
+ av_buffer_unref(&st_context->encoder_ref);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void stcodec_release_encoder(void* opaque, uint8_t* data) {
|
|
+ STCODECEncoder* encoder = (STCODECEncoder*)data;
|
|
+ if (encoder->pVencCtx) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "stcodec release encoder\n");
|
|
+ VENC_ResetChannel(encoder->pVencCtx);
|
|
+ VENC_DestoryChannel(encoder->pVencCtx);
|
|
+ encoder->pVencCtx = NULL;
|
|
+ }
|
|
+ av_buffer_unref(&encoder->frames_ref);
|
|
+ av_buffer_unref(&encoder->device_ref);
|
|
+ av_free(encoder);
|
|
+}
|
|
+
|
|
+static av_cold int stcodec_init_encoder(AVCodecContext* avctx) {
|
|
+ STCODECEncodeContext* st_context = avctx->priv_data;
|
|
+ STCODECEncoder* encoder = NULL;
|
|
+
|
|
+ MppCodingType codectype = CODING_UNKNOWN;
|
|
+ int ret;
|
|
+
|
|
+ if (avctx->width > 4096 || avctx->height > 2160 || avctx->width <= 640 ||
|
|
+ avctx->height <= 480) {
|
|
+ av_log(avctx, AV_LOG_ERROR,
|
|
+ "STCODEC-ENC do not support the size, too big or too small!\n");
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
|
|
+ // avctx->pix_fmt = AV_PIX_FMT_NV12;
|
|
+ // avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
|
|
+ av_log(avctx, AV_LOG_ERROR, "======================== Use pixel format %d\n",
|
|
+ avctx->pix_fmt);
|
|
+
|
|
+ // create a encoder and a ref to it
|
|
+ encoder = av_mallocz(sizeof(STCODECEncoder));
|
|
+ if (!encoder) {
|
|
+ av_log(avctx, AV_LOG_ERROR,
|
|
+ "Failed to av_mallocz STCODECEncoder encoder\n");
|
|
+ ret = AVERROR(ENOMEM);
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ st_context->encoder_ref =
|
|
+ av_buffer_create((uint8_t*)encoder, sizeof(*encoder),
|
|
+ stcodec_release_encoder, NULL, AV_BUFFER_FLAG_READONLY);
|
|
+ if (!st_context->encoder_ref) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to create ref of STCODECEncoder!\n");
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR(ENOMEM);
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ av_log(avctx, AV_LOG_DEBUG, "Initializing STCODEC encoder.\n");
|
|
+
|
|
+ codectype = stcodec_get_codingtype(avctx);
|
|
+ if (codectype == CODING_UNKNOWN) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Unknown codec type (%d).\n", avctx->codec_id);
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+ /*
|
|
+ ret = mpp_check_support_format(MPP_CTX_DEC, codectype);
|
|
+ if (ret != MPP_OK) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Codec type (%d) unsupported by MPP\n",
|
|
+ avctx->codec_id); ret = AVERROR_UNKNOWN; goto fail;
|
|
+ }
|
|
+ */
|
|
+
|
|
+ // Create the MPP context
|
|
+ encoder->pVencCtx = VENC_CreateChannel();
|
|
+ if (!encoder->pVencCtx) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to create STCODEC VENC channel.\n");
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // set para
|
|
+ encoder->pVencCtx->stVencPara.eCodingType = codectype;
|
|
+ encoder->pVencCtx->stVencPara.nWidth = avctx->width;
|
|
+ encoder->pVencCtx->stVencPara.nHeight = avctx->height;
|
|
+ encoder->pVencCtx->stVencPara.nStride = get_stride(avctx->width, 8);
|
|
+ encoder->pVencCtx->stVencPara.PixelFormat = PIXEL_FORMAT_NV12;
|
|
+ encoder->pVencCtx->eCodecType = CODEC_V4L2_LINLONV5V7;
|
|
+ encoder->pVencCtx->stVencPara.nBitrate = 5000000;
|
|
+ encoder->pVencCtx->stVencPara.nFrameRate = 30;
|
|
+ av_log(avctx, AV_LOG_ERROR, "(widthxheight = %d x %d).\n", avctx->width,
|
|
+ avctx->height);
|
|
+
|
|
+ // venc init
|
|
+ ret = VENC_Init(encoder->pVencCtx);
|
|
+ if (ret != MPP_OK) {
|
|
+ av_log(avctx, AV_LOG_ERROR,
|
|
+ "Failed to initialize STCODEC VENC (ret = %d).\n", ret);
|
|
+ VENC_DestoryChannel(encoder->pVencCtx);
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // mpp packet init
|
|
+ encoder->pPacket = PACKET_Create();
|
|
+ if (!encoder->pPacket) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to initialize STCODEC packet.\n");
|
|
+ VENC_DestoryChannel(encoder->pVencCtx);
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+ PACKET_Alloc(encoder->pPacket, PACKET_SIZE);
|
|
+
|
|
+ // mpp frame init
|
|
+ encoder->pFrame = FRAME_Create();
|
|
+ if (!encoder->pFrame) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to initialize STCODEC frame.\n");
|
|
+ PACKET_Destory(encoder->pPacket);
|
|
+ VENC_DestoryChannel(encoder->pVencCtx);
|
|
+ av_free(encoder);
|
|
+ ret = AVERROR_UNKNOWN;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ VENC_SetParam(encoder->pVencCtx, &(encoder->pVencCtx->stVencPara));
|
|
+
|
|
+ /*
|
|
+ // make decode calls blocking with a timeout
|
|
+ paramS32 = MPP_POLL_BLOCK;
|
|
+ ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK,
|
|
+ ¶mS32);
|
|
+
|
|
+ paramS64 = RECEIVE_FRAME_TIMEOUT;
|
|
+ ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK_TIMEOUT,
|
|
+ ¶mS64);
|
|
+
|
|
+ ret = mpp_buffer_group_get_internal(&decoder->frame_group,
|
|
+ MPP_BUFFER_TYPE_ION);
|
|
+ ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP,
|
|
+ decoder->frame_group);
|
|
+
|
|
+ ret = mpp_buffer_group_limit_config(decoder->frame_group, 0,
|
|
+ FRAMEGROUP_MAX_FRAMES);
|
|
+ */
|
|
+ // decoder->first_packet = 1;
|
|
+
|
|
+ av_log(avctx, AV_LOG_DEBUG, "STCODEC encoder initialized successfully.\n");
|
|
+ /*
|
|
+ encoder->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
|
|
+ if (!encoder->device_ref) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to av_hwdevice_ctx_alloc\n");
|
|
+ ret = AVERROR(ENOMEM);
|
|
+ goto fail;
|
|
+ }
|
|
+ ret = av_hwdevice_ctx_init(encoder->device_ref);
|
|
+ if (ret < 0) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Failed to av_hwdevice_ctx_init\n");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ AVHWFramesContext* hwframes;
|
|
+ avctx->width = avctx->width;
|
|
+ avctx->height = avctx->height;
|
|
+ encoder->frames_ref = av_hwframe_ctx_alloc(encoder->device_ref);
|
|
+ if (!encoder->frames_ref) {
|
|
+ ret = AVERROR(ENOMEM);
|
|
+ goto fail;
|
|
+ }
|
|
+ hwframes = (AVHWFramesContext*)encoder->frames_ref->data;
|
|
+ hwframes->format = AV_PIX_FMT_YUV420P;//AV_PIX_FMT_DRM_PRIME;
|
|
+ hwframes->sw_format = AV_PIX_FMT_YUV420P;
|
|
+ hwframes->width = avctx->width;
|
|
+ hwframes->height = avctx->height;
|
|
+ ret = av_hwframe_ctx_init(encoder->frames_ref);
|
|
+ if (ret < 0) goto fail;
|
|
+ */
|
|
+ av_log(avctx, AV_LOG_ERROR, "Initialized successfully.\n");
|
|
+ return 0;
|
|
+
|
|
+fail:
|
|
+ av_log(avctx, AV_LOG_ERROR,
|
|
+ "Failed to initialize STCODEC encoder, please check!\n");
|
|
+ stcodec_close_encoder(avctx);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const AVCodecHWConfigInternal* const stcodec_hw_configs[] = {
|
|
+ HW_CONFIG_INTERNAL(DRM_PRIME), NULL};
|
|
+
|
|
+#define STCODEC_ENC_CLASS(NAME) \
|
|
+ static const AVClass stcodec_##NAME##_enc_class = { \
|
|
+ .class_name = "stcodec_" #NAME "_enc", \
|
|
+ .version = LIBAVUTIL_VERSION_INT, \
|
|
+ };
|
|
+
|
|
+#define STCODEC_ENC(NAME, ID) \
|
|
+ STCODEC_ENC_CLASS(NAME) \
|
|
+ AVCodec ff_##NAME##_stcodec_encoder = { \
|
|
+ .name = #NAME "_stcodec", \
|
|
+ .long_name = NULL_IF_CONFIG_SMALL(#NAME " (stcodec encoder)"), \
|
|
+ .type = AVMEDIA_TYPE_VIDEO, \
|
|
+ .id = ID, \
|
|
+ .priv_data_size = sizeof(STCODECEncodeContext), \
|
|
+ .priv_class = &stcodec_##NAME##_enc_class, \
|
|
+ .init = stcodec_init_encoder, \
|
|
+ .receive_packet = stcodec_receive_packet, \
|
|
+ .close = stcodec_close_encoder, \
|
|
+ .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
|
|
+ .wrapper_name = "stcodec", \
|
|
+ .pix_fmts = \
|
|
+ (const enum AVPixelFormat[]){AV_PIX_FMT_DRM_PRIME, AV_PIX_FMT_NV12, \
|
|
+ AV_PIX_FMT_NONE}, \
|
|
+ .hw_configs = stcodec_hw_configs, \
|
|
+ };
|
|
+
|
|
+STCODEC_ENC(h264, AV_CODEC_ID_H264)
|
|
+STCODEC_ENC(hevc, AV_CODEC_ID_HEVC)
|
|
+STCODEC_ENC(mjpeg, AV_CODEC_ID_MJPEG)
|
|
--
|
|
2.25.1
|
|
|