buildroot/package/ffmpeg/0006-update-version-fix-som...

704 lines
25 KiB
Diff

From 573266fb7c6d3747556269aadb66905cab788fcd Mon Sep 17 00:00:00 2001
From: fuqiang <qiang.fu@spacemit.com>
Date: Tue, 12 Mar 2024 08:56:22 +0800
Subject: [PATCH] update version: fix some bugs
---
libavcodec/stcodecdec.c | 477 +++++++++++++++++++++++++++++-----------
1 file changed, 346 insertions(+), 131 deletions(-)
diff --git a/libavcodec/stcodecdec.c b/libavcodec/stcodecdec.c
index 763e1b2..1d618b9 100755
--- a/libavcodec/stcodecdec.c
+++ b/libavcodec/stcodecdec.c
@@ -39,7 +39,8 @@
#include "libavutil/log.h"
#include "vdec.h"
-#define PACKET_SIZE (2 * 1024 * 1024)
+#define FREESLOTS_THRESHOLD 4
+#define DROPFRAME_NUM_AFTER_FLUSH 1
typedef struct {
MppVdecCtx* pVdecCtx;
@@ -49,6 +50,11 @@ typedef struct {
enum AVPixelFormat ePixFmt;
char eos_reached;
+ char no_pts;
+ char first_packet;
+ int64_t duration;
+ int64_t use_dts;
+ char flushed;
AVBufferRef* frames_ref;
AVBufferRef* device_ref;
@@ -76,17 +82,78 @@ static MppCodingType stcodec_get_codingtype(AVCodecContext* avctx) {
return CODING_VP9;
case AV_CODEC_ID_MJPEG:
return CODING_MJPEG;
+ case AV_CODEC_ID_VC1:
+ return CODING_VC1;
+ case AV_CODEC_ID_MPEG2VIDEO:
+ return CODING_MPEG2;
+ case AV_CODEC_ID_MPEG4:
+ return CODING_MPEG4;
+ case AV_CODEC_ID_AVS:
+ return CODING_AVS;
+ case AV_CODEC_ID_AVS2:
+ return CODING_AVS2;
default:
return CODING_UNKNOWN;
}
}
+static MppProfileType stcodec_get_profiletype(AVCodecContext* avctx) {
+ av_log(avctx, AV_LOG_DEBUG, "profile = %d\n", avctx->profile);
+ if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+ switch (avctx->profile) {
+ case FF_PROFILE_MPEG2_422:
+ return PROFILE_MPEG2_422;
+ case FF_PROFILE_MPEG2_HIGH:
+ return PROFILE_MPEG2_HIGH;
+ case FF_PROFILE_MPEG2_SNR_SCALABLE:
+ return PROFILE_MPEG2_SNR_SCALABLE;
+ case FF_PROFILE_MPEG2_MAIN:
+ return PROFILE_MPEG2_MAIN;
+ case FF_PROFILE_MPEG2_SIMPLE:
+ return PROFILE_MPEG2_SIMPLE;
+ default:
+ return PROFILE_UNKNOWN;
+ }
+ } else if (avctx->codec_id == AV_CODEC_ID_VC1) {
+ switch (avctx->profile) {
+ case FF_PROFILE_VC1_SIMPLE:
+ return PROFILE_VC1_SIMPLE;
+ case FF_PROFILE_VC1_MAIN:
+ return PROFILE_VC1_MAIN;
+ case FF_PROFILE_VC1_COMPLEX:
+ return PROFILE_VC1_COMPLEX;
+ case FF_PROFILE_VC1_ADVANCED:
+ return PROFILE_VC1_ADVANCED;
+ default:
+ return PROFILE_UNKNOWN;
+ }
+ } else if (avctx->codec_id == AV_CODEC_ID_MJPEG) {
+ switch (avctx->profile) {
+ case FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT:
+ return PROFILE_MJPEG_HUFFMAN_BASELINE_DCT;
+ case FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT:
+ return PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT;
+ case FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT:
+ return PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT;
+ case FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS:
+ return PROFILE_MJPEG_HUFFMAN_LOSSLESS;
+ case FF_PROFILE_MJPEG_JPEG_LS:
+ return PROFILE_MJPEG_JPEG_LS;
+ default:
+ return PROFILE_UNKNOWN;
+ }
+ } else {
+ return PROFILE_UNKNOWN;
+ }
+}
+
static int get_stride(int width, int align) {
return (width + align - 1) & (~(align - 1));
}
static int stcodec_send_data_to_decoder(AVCodecContext* avctx, uint8_t* buffer,
- int size, int64_t pts) {
+ int size, int64_t pts, int64_t dts,
+ int64_t duration) {
STCODECDecodeContext* st_context = avctx->priv_data;
STCODECDecoder* decoder = (STCODECDecoder*)st_context->decoder_ref->data;
int ret = 0;
@@ -102,7 +169,14 @@ static int stcodec_send_data_to_decoder(AVCodecContext* avctx, uint8_t* buffer,
PACKET_SetDataPointer(decoder->pPacket, buffer);
PACKET_SetLength(decoder->pPacket, size);
- PACKET_SetPts(decoder->pPacket, pts);
+ if (pts != AV_NOPTS_VALUE) {
+ PACKET_SetPts(decoder->pPacket, pts);
+ } else if (dts != AV_NOPTS_VALUE) {
+ PACKET_SetPts(decoder->pPacket, dts);
+ decoder->use_dts = 1;
+ } else {
+ decoder->no_pts = 1;
+ }
PACKET_SetEos(decoder->pPacket, 0);
av_log(avctx, AV_LOG_DEBUG, "input pts : %ld\n", pts);
}
@@ -135,12 +209,24 @@ static int stcodec_close_decoder(AVCodecContext* avctx) {
static void stcodec_release_stcodec_decoder(void* opaque, uint8_t* data) {
STCODECDecoder* decoder = (STCODECDecoder*)data;
+
+ if (decoder->pPacket) {
+ // PACKET_Free(decoder->pPacket);
+ PACKET_Destory(decoder->pPacket);
+ decoder->pPacket = NULL;
+ }
+
+ if (decoder->pFrame) {
+ FRAME_Destory(decoder->pFrame);
+ decoder->pFrame = NULL;
+ }
+
if (decoder->pVdecCtx) {
- av_log(NULL, AV_LOG_ERROR, "stcodec release decoder\n");
- VDEC_ResetChannel(decoder->pVdecCtx);
+ // VDEC_ResetChannel(decoder->pVdecCtx);
VDEC_DestoryChannel(decoder->pVdecCtx);
decoder->pVdecCtx = NULL;
}
+
av_buffer_unref(&decoder->frames_ref);
av_buffer_unref(&decoder->device_ref);
av_free(decoder);
@@ -151,9 +237,10 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
STCODECDecoder* decoder = NULL;
MppCodingType codectype = CODING_UNKNOWN;
int ret;
-/*
- if (avctx->width > 4096 || avctx->height > 2160 || avctx->width <= 640 ||
- avctx->height <= 480) {
+
+ if ((avctx->width > 4096 || avctx->height > 2304 || avctx->width <= 640 ||
+ avctx->height <= 480) &&
+ (avctx->width != 0 || avctx->height != 0)) {
av_log(avctx, AV_LOG_ERROR,
"STCODEC Decoder do not support the size (%d x %d), too big or too "
"small!\n",
@@ -161,9 +248,9 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
ret = AVERROR_UNKNOWN;
goto fail;
}
-*/
+
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);
+ av_log(avctx, AV_LOG_ERROR, "Use pixel format %d\n", avctx->pix_fmt);
// create a decoder and a ref to it
decoder = av_mallocz(sizeof(STCODECDecoder));
@@ -206,6 +293,7 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
// set para
decoder->pVdecCtx->stVdecPara.eCodingType = codectype;
+ decoder->pVdecCtx->stVdecPara.nProfile = stcodec_get_profiletype(avctx);
decoder->pVdecCtx->stVdecPara.bInputBlockModeEnable = MPP_FALSE;
decoder->pVdecCtx->stVdecPara.bOutputBlockModeEnable = MPP_TRUE;
decoder->pVdecCtx->stVdecPara.nWidth = avctx->width;
@@ -213,7 +301,12 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
decoder->pVdecCtx->stVdecPara.nStride = get_stride(avctx->width, 8);
decoder->pVdecCtx->stVdecPara.eOutputPixelFormat = PIXEL_FORMAT_NV12;
decoder->pVdecCtx->eCodecType = CODEC_V4L2_LINLONV5V7;
- decoder->pVdecCtx->stVdecPara.nScale = 1;
+ if (avctx->width >= 3840 || avctx->height >= 2160) {
+ av_log(avctx, AV_LOG_ERROR, "4K video, downscale!\n");
+ decoder->pVdecCtx->stVdecPara.nScale = 2;
+ } else {
+ decoder->pVdecCtx->stVdecPara.nScale = 1;
+ }
decoder->pVdecCtx->stVdecPara.nHorizonScaleDownRatio = 1;
decoder->pVdecCtx->stVdecPara.nVerticalScaleDownRatio = 1;
decoder->pVdecCtx->stVdecPara.nRotateDegree = 0;
@@ -225,37 +318,38 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
if (ret) {
av_log(avctx, AV_LOG_ERROR,
"Failed to initialize STCODEC VDEV (ret = %d).\n", ret);
- VDEC_DestoryChannel(decoder->pVdecCtx);
- av_free(decoder);
+ // VDEC_DestoryChannel(decoder->pVdecCtx);
+ // av_free(decoder);
ret = AVERROR_UNKNOWN;
goto fail;
}
- av_log(avctx, AV_LOG_ERROR, "init 1.\n");
// mpp packet init
decoder->pPacket = PACKET_Create();
if (!decoder->pPacket) {
av_log(avctx, AV_LOG_ERROR, "Failed to initialize STCODEC packet.\n");
- VDEC_DestoryChannel(decoder->pVdecCtx);
- av_free(decoder);
+ // VDEC_DestoryChannel(decoder->pVdecCtx);
+ // av_free(decoder);
ret = AVERROR_UNKNOWN;
goto fail;
}
- PACKET_Alloc(decoder->pPacket, PACKET_SIZE);
- av_log(avctx, AV_LOG_ERROR, "init 2.\n");
// mpp frame init
decoder->pFrame = FRAME_Create();
if (!decoder->pFrame) {
av_log(avctx, AV_LOG_ERROR, "Failed to initialize STCODEC frame.\n");
PACKET_Destory(decoder->pPacket);
- VDEC_DestoryChannel(decoder->pVdecCtx);
- av_free(decoder);
+ // VDEC_DestoryChannel(decoder->pVdecCtx);
+ // av_free(decoder);
ret = AVERROR_UNKNOWN;
goto fail;
}
- av_log(avctx, AV_LOG_ERROR, "init 3.\n");
+ decoder->first_packet = 1;
+ decoder->duration = 0;
+ decoder->use_dts = 0;
+ decoder->flushed = 0;
+
av_log(avctx, AV_LOG_DEBUG, "STCODEC decoder initialized successfully.\n");
decoder->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
@@ -264,37 +358,32 @@ static int stcodec_init_decoder(AVCodecContext* avctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
- av_log(avctx, AV_LOG_ERROR, "init 4.\n");
ret = av_hwdevice_ctx_init(decoder->device_ref);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to av_hwdevice_ctx_init\n");
goto fail;
}
- av_log(avctx, AV_LOG_ERROR, "init 5.\n");
-
- decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
- if (!decoder->frames_ref) {
- av_log(avctx, AV_LOG_ERROR, "Failed to av_hwframe_ctx_alloc\n");
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- av_log(avctx, AV_LOG_ERROR, "init 6.\n");
-
- AVHWFramesContext* hwframes;
- hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
- hwframes->format = AV_PIX_FMT_DRM_PRIME;
- hwframes->sw_format = AV_PIX_FMT_NV12;
- hwframes->width = avctx->width;
- hwframes->height = avctx->height;
- ret = av_hwframe_ctx_init(decoder->frames_ref);
- if (ret < 0) goto fail;
+ /*
+ decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
+ if (!decoder->frames_ref) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to av_hwframe_ctx_alloc\n");
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ AVHWFramesContext* hwframes;
+ hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+ hwframes->sw_format = AV_PIX_FMT_NV12;
+ hwframes->width = avctx->width;
+ hwframes->height = avctx->height;
+ ret = av_hwframe_ctx_init(decoder->frames_ref);
+ if (ret < 0) goto fail;
+ */
av_log(avctx, AV_LOG_DEBUG, "Initialized successfully.\n");
- av_log(avctx, AV_LOG_ERROR, "init 7.\n");
return 0;
fail:
- av_log(avctx, AV_LOG_ERROR, "init 8.\n");
av_log(avctx, AV_LOG_ERROR,
"Failed to initialize STCODEC decoder, please check!\n");
stcodec_close_decoder(avctx);
@@ -305,23 +394,57 @@ static int stcodec_send_packet(AVCodecContext* avctx, const AVPacket* avpkt) {
STCODECDecodeContext* st_context = avctx->priv_data;
STCODECDecoder* decoder = (STCODECDecoder*)st_context->decoder_ref->data;
int ret;
- av_log(avctx, AV_LOG_DEBUG, "start send packet, pts(%ld)\n", avpkt->pts);
+ av_log(avctx, AV_LOG_DEBUG,
+ "start send packet, pts(%ld) dts(%ld) duration(%ld)\n", avpkt->pts,
+ avpkt->dts, avpkt->duration);
// handle EOF
if (!avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "Get EOS from parser!\n");
decoder->eos_reached = 1;
// write a NULL data to decoder to inform it the EOS.
- ret = stcodec_send_data_to_decoder(avctx, NULL, 0, 0);
+ ret = stcodec_send_data_to_decoder(avctx, NULL, 0, 0, 0, 0);
if (ret)
av_log(avctx, AV_LOG_ERROR, "Failed to send EOS to decoder (ret = %d)\n",
ret);
return ret;
}
+ // on first packet, send extradata
+ if (decoder->first_packet) {
+ if (avctx->extradata_size) {
+ if (avctx->codec_id == AV_CODEC_ID_H264) {
+ ret = stcodec_send_data_to_decoder(avctx, avctx->extradata,
+ avctx->extradata_size, avpkt->pts,
+ avpkt->dts, avpkt->duration);
+ } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
+ ret = stcodec_send_data_to_decoder(avctx, avctx->extradata,
+ avctx->extradata_size, avpkt->pts,
+ avpkt->dts, avpkt->duration);
+ } else if (avctx->codec_id == AV_CODEC_ID_MJPEG) {
+ // do nothing.
+ } else if (avctx->codec_id == AV_CODEC_ID_MPEG4 ||
+ avctx->codec_id == AV_CODEC_ID_VC1) {
+ ret = stcodec_send_data_to_decoder(avctx, avctx->extradata,
+ avctx->extradata_size, avpkt->pts,
+ avpkt->dts, avpkt->duration);
+ if (ret) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to write extradata to decoder (ret = %d)\n", ret);
+ return ret;
+ } else {
+ av_log(avctx, AV_LOG_ERROR,
+ "OK! Write extradata to decoder (size = %d)\n",
+ avctx->extradata_size);
+ }
+ }
+ }
+ decoder->first_packet = 0;
+ }
+
// now send packet
- ret =
- stcodec_send_data_to_decoder(avctx, avpkt->data, avpkt->size, avpkt->pts);
+ ret = stcodec_send_data_to_decoder(avctx, avpkt->data, avpkt->size,
+ avpkt->pts, avpkt->dts, avpkt->duration);
if (ret) {
av_log(avctx, AV_LOG_DEBUG,
"Failed to write data to decoder (code = %d (%s))\n", ret,
@@ -351,6 +474,7 @@ static void stcodec_release_frame(void* opaque, uint8_t* data) {
AV_PIX_FMT_DRM_PRIME) {
av_free(desc);
}
+ FRAME_Destory(framecontext->pFrame);
av_buffer_unref(&framecontext->decoder_ref);
av_buffer_unref(&framecontextref);
}
@@ -373,15 +497,15 @@ static int stcodec_receive_frame(AVCodecContext* avctx, AVFrame* frame) {
// we get the available input queue num in decoder
VDEC_GetParam(decoder->pVdecCtx, &(decoder->pVdecPara));
freeslots = decoder->pVdecPara->nInputQueueLeftNum;
- av_log(avctx, AV_LOG_ERROR, "--------- Input queue left %d seat!!\n", freeslots);
+ av_log(avctx, AV_LOG_DEBUG, "Input queue left %d seat!!\n", freeslots);
- if (freeslots > 0) {
+ while (freeslots > 0) {
ret = ff_decode_get_packet(avctx, &pkt);
if (ret < 0 && ret != AVERROR_EOF) {
- av_log(avctx, AV_LOG_ERROR,
+ av_log(avctx, AV_LOG_DEBUG,
"Failed to ff_decode_get_packet (ret = %d (%s))\n", ret,
av_err2str(ret));
- return ret;
+ goto fail;
}
ret = stcodec_send_packet(avctx, &pkt);
@@ -391,114 +515,200 @@ static int stcodec_receive_frame(AVCodecContext* avctx, AVFrame* frame) {
av_log(avctx, AV_LOG_ERROR,
"Failed to send packet to decoder (code = %d (%s))\n", ret,
av_err2str(ret));
- return ret;
+ goto fail;
}
- }
- // make sure we keep decoder full
- VDEC_GetParam(decoder->pVdecCtx, &(decoder->pVdecPara));
- freeslots = decoder->pVdecPara->nInputQueueLeftNum;
- av_log(avctx, AV_LOG_ERROR, "========== Input queue left %d seat!!\n", freeslots);
- if (freeslots > 0) return AVERROR(EAGAIN);
+ // make sure we keep decoder full
+ VDEC_GetParam(decoder->pVdecCtx, &(decoder->pVdecPara));
+ freeslots = decoder->pVdecPara->nInputQueueLeftNum;
+ av_log(avctx, AV_LOG_DEBUG, "Input queue left %d seat!!\n", freeslots);
+ }
}
- ret = VDEC_RequestOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ do {
+ ret =
+ VDEC_RequestOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ if (ret == MPP_CODER_NULL_DATA) {
+ av_log(avctx, AV_LOG_ERROR, "null data, return\n");
+ VDEC_ReturnOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ }
+ } while (ret == MPP_CODER_NO_DATA || ret == MPP_CODER_NULL_DATA);
av_log(avctx, AV_LOG_DEBUG, "Request frame (ret = %d)\n", ret);
if (ret == MPP_CODER_EOS && mppframe == NULL) {
av_log(avctx, AV_LOG_ERROR, "EOS 1!\n");
- return AVERROR_EOF;
+ ret = AVERROR_EOF;
+ goto fail;
}
if (ret == MPP_CODER_EOS ||
FRAME_GetEos(mppframe) == 1 /* || decoder->eos_reached*/) {
av_log(avctx, AV_LOG_ERROR, "EOS 2!\n");
VDEC_ReturnOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
- return AVERROR_EOF;
+ ret = AVERROR_EOF;
+ goto fail;
}
- if (!ret) {
- av_log(NULL, AV_LOG_DEBUG, "stcodec request a frame\n");
+ if (ret == MPP_ERROR_FRAME) {
+ av_log(avctx, AV_LOG_ERROR, "error frame, need discard\n");
+ VDEC_ReturnOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ ret = AVERROR(EAGAIN);
+ goto fail;
+ }
- // setup general frame fields
- frame->format = avctx->pix_fmt;
- frame->width = avctx->width;
- frame->height = avctx->height;
- // frame->pts = FRAME_GetPts(decoder->pFrame);
- frame->interlaced_frame = 0;
- frame->top_field_first = 0;
-
- framecontextref = av_buffer_allocz(sizeof(*framecontext));
- if (!framecontextref) {
- av_log(avctx, AV_LOG_ERROR, "Failed to alloc AvBufferRef\n");
- ret = AVERROR(ENOMEM);
- return ret;
- }
+ if (ret == MPP_RESOLUTION_CHANGED) {
+ av_log(avctx, AV_LOG_ERROR,
+ "resolution changed!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ AVHWFramesContext* hwframes;
- // MPP decoder needs to be closed only when all frames have been released.
- framecontext = (STCODECFrameContext*)framecontextref->data;
- framecontext->decoder_ref = av_buffer_ref(st_context->decoder_ref);
- framecontext->pFrame = mppframe;
+ av_log(avctx, AV_LOG_DEBUG, "Decoder noticed an info change (%dx%d)\n",
+ decoder->pVdecCtx->stVdecPara.nWidth,
+ decoder->pVdecCtx->stVdecPara.nHeight);
- if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME) {
- desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
- if (!desc) {
- ret = AVERROR(ENOMEM);
- return ret;
- }
+ avctx->width = decoder->pVdecCtx->stVdecPara.nWidth;
+ avctx->height = decoder->pVdecCtx->stVdecPara.nHeight;
- desc->nb_objects = 1;
- desc->objects[0].fd = FRAME_GetFD(mppframe, 0);
- desc->objects[0].size = frame->width * frame->height * 3 / 2;
- av_log(avctx, AV_LOG_DEBUG, "fd=%d size=%ld\n", desc->objects[0].fd,
- desc->objects[0].size);
- desc->nb_layers = 1;
- layer = &desc->layers[0];
- layer->format = DRM_FORMAT_NV12;
- layer->nb_planes = 2;
-
- layer->planes[0].object_index = 0;
- layer->planes[0].offset = 0;
- layer->planes[0].pitch = frame->width;
-
- layer->planes[1].object_index = 0;
- layer->planes[1].offset = frame->width * frame->height;
- layer->planes[1].pitch = frame->width;
-
- frame->data[0] = (uint8_t*)desc;
- frame->buf[0] =
- av_buffer_create((uint8_t*)desc, sizeof(*desc), stcodec_release_frame,
- framecontextref, AV_BUFFER_FLAG_READONLY);
- } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
- frame->linesize[0] = get_stride(avctx->width, 8);
- frame->linesize[1] = get_stride(avctx->width, 8);
- frame->data[0] = FRAME_GetDataPointer(mppframe, 0);
- frame->data[1] = frame->data[0] + frame->width * frame->height;
- frame->buf[0] = av_buffer_create(
- (uint8_t*)(frame->data[0]), sizeof(frame->data[0]),
- stcodec_release_frame, framecontextref, AV_BUFFER_FLAG_READONLY);
- }
+ av_buffer_unref(&decoder->frames_ref);
- if (!frame->buf[0]) {
+ decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref);
+ if (!decoder->frames_ref) {
av_log(avctx, AV_LOG_ERROR,
- "Failed to create AVDRMFrameDescriptor ref\n");
+ "av_hwframe_ctx_alloc failed, please check\n");
ret = AVERROR(ENOMEM);
- return ret;
+ goto fail;
}
- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
- if (!frame->hw_frames_ctx) {
- av_log(avctx, AV_LOG_ERROR, "Failed to create hw_frames_ctx\n");
- ret = AVERROR(ENOMEM);
- return ret;
+ hwframes = (AVHWFramesContext*)decoder->frames_ref->data;
+ hwframes->format = AV_PIX_FMT_DRM_PRIME;
+ hwframes->sw_format = AV_PIX_FMT_NV12;
+ hwframes->width = avctx->width;
+ hwframes->height = avctx->height;
+ ret = av_hwframe_ctx_init(decoder->frames_ref);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_init failed, please check\n");
+ goto fail;
}
+ // here decoder is fully initialized, we need to feed it again with data
+ ret = AVERROR(EAGAIN);
+ goto fail;
+ }
+
+ if (!ret) {
+ av_log(NULL, AV_LOG_DEBUG, "stcodec request a frame\n");
+ if (!decoder->flushed) {
+ // setup general frame fields
+ frame->format = avctx->pix_fmt;
+ frame->width = avctx->width;
+ frame->height = avctx->height;
+ if (!decoder->no_pts) {
+ if (!decoder->use_dts) {
+ frame->pts = FRAME_GetPts(mppframe);
+ } else {
+ frame->pkt_dts = FRAME_GetPts(mppframe);
+ }
+ } else {
+ }
+ av_log(avctx, AV_LOG_DEBUG, "frame pts:%ld pkt_dts:%ld\n", frame->pts,
+ frame->pkt_dts);
+ frame->interlaced_frame = 0;
+ frame->top_field_first = 0;
+
+ framecontextref = av_buffer_allocz(sizeof(*framecontext));
+ if (!framecontextref) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to alloc AvBufferRef\n");
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ // MPP decoder needs to be closed only when all frames have been released.
+ framecontext = (STCODECFrameContext*)framecontextref->data;
+ framecontext->decoder_ref = av_buffer_ref(st_context->decoder_ref);
+ framecontext->pFrame = mppframe;
+
+ if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME) {
+ desc = av_mallocz(sizeof(AVDRMFrameDescriptor));
+ if (!desc) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ desc->nb_objects = 1;
+ desc->objects[0].fd = FRAME_GetFD(mppframe, 0);
+ desc->objects[0].size = frame->width * frame->height * 3 / 2;
+ av_log(avctx, AV_LOG_DEBUG, "fd=%d size=%ld\n", desc->objects[0].fd,
+ desc->objects[0].size);
+ desc->nb_layers = 1;
+ layer = &desc->layers[0];
+ layer->format = DRM_FORMAT_NV12;
+ layer->nb_planes = 2;
+
+ layer->planes[0].object_index = 0;
+ layer->planes[0].offset = 0;
+ layer->planes[0].pitch = frame->width;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = frame->width * frame->height;
+ layer->planes[1].pitch = frame->width;
+
+ frame->data[0] = (uint8_t*)desc;
+ frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc),
+ stcodec_release_frame, framecontextref,
+ AV_BUFFER_FLAG_READONLY);
+ } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
+ frame->linesize[0] = get_stride(avctx->width, 8);
+ frame->linesize[1] = get_stride(avctx->width, 8);
+ frame->data[0] = FRAME_GetDataPointer(mppframe, 0);
+ frame->data[1] = frame->data[0] + frame->width * frame->height;
+ frame->buf[0] = av_buffer_create(
+ (uint8_t*)(frame->data[0]), sizeof(frame->data[0]),
+ stcodec_release_frame, framecontextref, AV_BUFFER_FLAG_READONLY);
+ }
+
+ if (!frame->buf[0]) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to create AVDRMFrameDescriptor ref\n");
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
+ if (!frame->hw_frames_ctx) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to create hw_frames_ctx\n");
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ } else if (decoder->flushed < DROPFRAME_NUM_AFTER_FLUSH) {
+ VDEC_ReturnOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ av_log(avctx, AV_LOG_ERROR, "drop some frames after flush, num=%d\n",
+ decoder->flushed);
+ decoder->flushed++;
+ ret = AVERROR(EAGAIN);
+ goto fail;
+ } else if (decoder->flushed == DROPFRAME_NUM_AFTER_FLUSH) {
+ VDEC_ReturnOutputFrame(decoder->pVdecCtx, FRAME_GetBaseData(mppframe));
+ ret = AVERROR(EAGAIN);
+ av_log(avctx, AV_LOG_ERROR,
+ "drop some frames after flush finish, num=%d\n", decoder->flushed);
+ decoder->flushed = 0;
+ goto fail;
+ }
} else {
- // return AVERROR_UNKNOWN;
- return AVERROR(EAGAIN);
+ av_log(avctx, AV_LOG_ERROR, "should not be here, ret = %d\n", ret);
+ ret = AVERROR(EAGAIN);
+ goto fail;
}
return 0; // return AVERROR(EAGAIN);
+
+fail:
+ if (mppframe) FRAME_Destory(mppframe);
+ if (framecontext && framecontext->pFrame) FRAME_Destory(framecontext->pFrame);
+ if (framecontext) av_buffer_unref(&framecontext->decoder_ref);
+ if (framecontextref) av_buffer_unref(&framecontextref);
+ if (desc) av_free(desc);
+
+ return ret;
}
static void stcodec_flush(AVCodecContext* avctx) {
@@ -507,13 +717,18 @@ static void stcodec_flush(AVCodecContext* avctx) {
int ret = -1;
av_log(avctx, AV_LOG_ERROR, "Flush.\n");
-/*
- ret = VDEC_ResetChannel(decoder->pVdecCtx);
+
+ ret = VDEC_Flush(decoder->pVdecCtx);
if (ret)
- av_log(avctx, AV_LOG_ERROR, "Failed to reset VDEC Channel (code = %d)\n",
+ av_log(avctx, AV_LOG_ERROR, "Failed to flush VDEC Channel (code = %d)\n",
ret);
-*/
+
decoder->eos_reached = 0;
+ decoder->no_pts = 0;
+ decoder->first_packet = 1;
+ decoder->duration = 0;
+ decoder->use_dts = 0;
+ decoder->flushed = 1;
}
static const AVCodecHWConfigInternal* const stcodec_hw_configs[] = {
--
2.25.1