d7f3ff06a7
Signed-off-by: Som Qin <som.qin@starfivetech.com>
253 lines
9.0 KiB
Diff
253 lines
9.0 KiB
Diff
From 0f054a4a66e82d8f644acb8bf2a0b637cfee9aa8 Mon Sep 17 00:00:00 2001
|
|
From: Som Qin <som.qin@starfivetech.com>
|
|
Date: Fri, 4 Aug 2023 11:52:49 +0800
|
|
Subject: [PATCH 2/8] omxdec : add output buffers release callback to reduce
|
|
memcpy
|
|
|
|
Signed-off-by: Som Qin <som.qin@starfivetech.com>
|
|
---
|
|
libavcodec/allcodecs.c | 8 +--
|
|
libavcodec/omxdec.c | 131 +++++++++++++++++++++++++++++++++++------
|
|
2 files changed, 116 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
|
|
index 69627df..cb5b3d7 100644
|
|
--- a/libavcodec/allcodecs.c
|
|
+++ b/libavcodec/allcodecs.c
|
|
@@ -29,6 +29,10 @@
|
|
#include "avcodec.h"
|
|
#include "version.h"
|
|
|
|
+extern AVCodec ff_h264_omx_decoder;
|
|
+extern AVCodec ff_hevc_omx_encoder;
|
|
+extern AVCodec ff_hevc_omx_decoder;
|
|
+extern AVCodec ff_mjpeg_omx_decoder;
|
|
extern AVCodec ff_a64multi_encoder;
|
|
extern AVCodec ff_a64multi5_encoder;
|
|
extern AVCodec ff_aasc_decoder;
|
|
@@ -792,9 +796,6 @@ extern AVCodec ff_h264_cuvid_decoder;
|
|
extern AVCodec ff_h264_mf_encoder;
|
|
extern AVCodec ff_h264_nvenc_encoder;
|
|
extern AVCodec ff_h264_omx_encoder;
|
|
-extern AVCodec ff_h264_omx_decoder;
|
|
-extern AVCodec ff_hevc_omx_encoder;
|
|
-extern AVCodec ff_hevc_omx_decoder;
|
|
extern AVCodec ff_h264_qsv_encoder;
|
|
extern AVCodec ff_h264_v4l2m2m_encoder;
|
|
extern AVCodec ff_h264_vaapi_encoder;
|
|
@@ -817,7 +818,6 @@ extern AVCodec ff_libkvazaar_encoder;
|
|
extern AVCodec ff_mjpeg_cuvid_decoder;
|
|
extern AVCodec ff_mjpeg_qsv_encoder;
|
|
extern AVCodec ff_mjpeg_qsv_decoder;
|
|
-extern AVCodec ff_mjpeg_omx_decoder;
|
|
extern AVCodec ff_mjpeg_vaapi_encoder;
|
|
extern AVCodec ff_mp3_mf_encoder;
|
|
extern AVCodec ff_mpeg1_cuvid_decoder;
|
|
diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c
|
|
index c518542..afcba9b 100755
|
|
--- a/libavcodec/omxdec.c
|
|
+++ b/libavcodec/omxdec.c
|
|
@@ -34,6 +34,7 @@
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
|
|
+#include "libavcodec/decode.h"
|
|
#include "libavutil/avstring.h"
|
|
#include "libavutil/avutil.h"
|
|
#include "libavutil/common.h"
|
|
@@ -355,6 +356,7 @@ typedef struct OMXCodecContext {
|
|
int eos_sent, got_eos, evnet_bufferflag, first_get_outbuffer;
|
|
|
|
int extradata_sent;
|
|
+ int has_cleanup;
|
|
|
|
uint8_t *output_buf;
|
|
int output_buf_size;
|
|
@@ -943,6 +945,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
|
|
static av_cold void cleanup(OMXCodecContext *s)
|
|
{
|
|
int i, executing;
|
|
+ OMX_BUFFERHEADERTYPE *buffer;
|
|
|
|
pthread_mutex_lock(&s->state_mutex);
|
|
executing = s->state == OMX_StateExecuting;
|
|
@@ -953,17 +956,24 @@ static av_cold void cleanup(OMXCodecContext *s)
|
|
wait_for_state(s, OMX_StateIdle);
|
|
OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
|
|
for (i = 0; i < s->num_in_buffers; i++) {
|
|
- OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
|
+ buffer = get_buffer(&s->input_mutex, &s->input_cond,
|
|
&s->num_free_in_buffers, s->free_in_buffers, 1);
|
|
if (s->input_zerocopy)
|
|
buffer->pBuffer = NULL;
|
|
OMX_FreeBuffer(s->handle, s->in_port, buffer);
|
|
}
|
|
- for (i = 0; i < s->num_out_buffers; i++) {
|
|
- OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->output_mutex, &s->output_cond,
|
|
- &s->num_done_out_buffers, s->done_out_buffers, 1);
|
|
+
|
|
+ while (buffer = get_buffer(&s->output_mutex, &s->output_cond,
|
|
+ &s->num_done_out_buffers, s->done_out_buffers, 0)) {
|
|
OMX_FreeBuffer(s->handle, s->out_port, buffer);
|
|
+ s->num_out_buffers--;
|
|
+ }
|
|
+
|
|
+ if (s->num_out_buffers) {
|
|
+ s->has_cleanup = 1;
|
|
+ return;
|
|
}
|
|
+
|
|
wait_for_state(s, OMX_StateLoaded);
|
|
}
|
|
if (s->handle) {
|
|
@@ -1099,6 +1109,94 @@ fail:
|
|
return ret;
|
|
}
|
|
|
|
+static void omx_free_out_buffer(void *opaque, uint8_t *unused)
|
|
+{
|
|
+ OMX_ERRORTYPE err;
|
|
+ OMX_BUFFERHEADERTYPE *buffer = opaque;
|
|
+ OMXCodecContext *s = buffer->pAppPrivate;
|
|
+
|
|
+ if (!s->has_cleanup) {
|
|
+ err = OMX_FillThisBuffer(s->handle, buffer);
|
|
+ if (err != OMX_ErrorNone) {
|
|
+ append_buffer(&s->output_mutex, &s->output_cond, &s->num_done_out_buffers, s->done_out_buffers, buffer);
|
|
+ av_log(s->avctx, AV_LOG_ERROR, "OMX_FillThisBuffer failed, err: %x\n", err);
|
|
+ }
|
|
+ } else {
|
|
+ OMX_FreeBuffer(s->handle, s->out_port, buffer);
|
|
+ s->num_out_buffers--;
|
|
+ if (!s->num_out_buffers) {
|
|
+ wait_for_state(s, OMX_StateLoaded);
|
|
+ if (s->handle) {
|
|
+ s->omx_context->ptr_FreeHandle(s->handle);
|
|
+ s->handle = NULL;
|
|
+ }
|
|
+
|
|
+ omx_deinit(s->omx_context);
|
|
+ s->omx_context = NULL;
|
|
+ if (s->mutex_cond_inited) {
|
|
+ pthread_cond_destroy(&s->state_cond);
|
|
+ pthread_mutex_destroy(&s->state_mutex);
|
|
+ pthread_cond_destroy(&s->input_cond);
|
|
+ pthread_mutex_destroy(&s->input_mutex);
|
|
+ pthread_cond_destroy(&s->output_cond);
|
|
+ pthread_mutex_destroy(&s->output_mutex);
|
|
+ pthread_cond_destroy(&s->disableEVnt_cond);
|
|
+ pthread_mutex_destroy(&s->disableEVnt_mutex);
|
|
+ s->mutex_cond_inited = 0;
|
|
+ }
|
|
+ OMXDecodeQueueDestory(&s->decode_pts_queue);
|
|
+ av_freep(&s->decode_pts_queue);
|
|
+ av_freep(&s->in_buffer_headers);
|
|
+ av_freep(&s->out_buffer_headers);
|
|
+ av_freep(&s->free_in_buffers);
|
|
+ av_freep(&s->done_out_buffers);
|
|
+ av_freep(&s->output_buf);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static int omx_buf_to_swframe(OMXCodecContext *s, AVFrame *frame, OMX_BUFFERHEADERTYPE *buffer)
|
|
+{
|
|
+ int ret;
|
|
+ uint8_t *dst[4];
|
|
+ int linesize[4];
|
|
+
|
|
+ frame->buf[0] = av_buffer_create((char *)buffer->pBuffer, buffer->nFilledLen, omx_free_out_buffer, buffer, 0);
|
|
+
|
|
+ if (!frame->buf[0])
|
|
+ return AVERROR(ENOMEM);
|
|
+
|
|
+ ret = av_image_fill_arrays(dst, linesize, buffer->pBuffer,
|
|
+ s->avctx->pix_fmt, s->stride, s->plane_size, 1);
|
|
+ if (ret < 0){
|
|
+ av_log(s->avctx, AV_LOG_ERROR, "av_image_fill_arrays ret:%d\n", ret);
|
|
+ return AVERROR(EINVAL);
|
|
+ }
|
|
+
|
|
+ frame->linesize[0] = linesize[0];
|
|
+ frame->data[0] = frame->buf[0]->data;
|
|
+
|
|
+ /* fixup special cases */
|
|
+ switch (s->avctx->pix_fmt) {
|
|
+ case AV_PIX_FMT_NV12:
|
|
+ case AV_PIX_FMT_NV21:
|
|
+ frame->linesize[1] = linesize[1];
|
|
+ frame->data[1] = dst[1];
|
|
+ break;
|
|
+
|
|
+ case AV_PIX_FMT_YUV420P:
|
|
+ frame->linesize[1] = linesize[1];
|
|
+ frame->linesize[2] = linesize[2];
|
|
+ frame->data[1] = dst[1];
|
|
+ frame->data[2] = dst[2];
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
static int omx_decode_frame(AVCodecContext *avctx, void *data,
|
|
int *got_packet, AVPacket *pkt)
|
|
@@ -1111,9 +1209,6 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
|
|
|
|
AVFrame *avframe = data;
|
|
|
|
- uint8_t *dst[4];
|
|
- int linesize[4];
|
|
-
|
|
av_log(avctx, AV_LOG_VERBOSE, "s->decode_flag: %d\n", s->decode_flag);
|
|
av_log(avctx, AV_LOG_VERBOSE, "avctx->time_base: %d/%d \n", avctx->time_base.num, avctx->time_base.den);
|
|
av_log(avctx, AV_LOG_VERBOSE, "avctx->pkt_timebase: %d/%d \n", avctx->pkt_timebase.num, avctx->pkt_timebase.den);
|
|
@@ -1226,20 +1321,21 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
|
|
if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
|
|
s->got_eos = 1;
|
|
|
|
- if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) {
|
|
- av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n");
|
|
+ avframe->width = avctx->width;
|
|
+ avframe->height = avctx->height;
|
|
+
|
|
+ ret = ff_decode_frame_props(avctx, avframe);
|
|
+ if(ret < 0) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Unable to fill buffer props\n");
|
|
goto end;
|
|
}
|
|
|
|
- ret = av_image_fill_arrays(dst, linesize, buffer->pBuffer,
|
|
- avctx->pix_fmt, s->stride, s->plane_size, 1);
|
|
- if (ret < 0){
|
|
- av_log(avctx, AV_LOG_ERROR, "av_image_fill_arrays ret:%d\n", ret);
|
|
+ ret = omx_buf_to_swframe(s, avframe, buffer);
|
|
+ if(ret < 0) {
|
|
+ av_log(avctx, AV_LOG_ERROR, "Unable to alloce frame\n");
|
|
goto end;
|
|
}
|
|
|
|
- av_image_copy(avframe->data, avframe->linesize, (const uint8_t**)dst, linesize,
|
|
- avctx->pix_fmt, avctx->width, avctx->height);
|
|
if (pkt->pts) {
|
|
if (OMXDecodeQueueEmpty(&s->decode_pts_queue) != 0){
|
|
av_log(avctx, AV_LOG_ERROR, "The queue of decode pts is empty.\n");
|
|
@@ -1251,10 +1347,7 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data,
|
|
s->decode_flag += 1;
|
|
*got_packet = 1;
|
|
|
|
- /*
|
|
- if ((ret = av_frame_ref(data, avframe)) < 0)
|
|
- goto end;
|
|
- */
|
|
+ return ret;
|
|
|
|
end:
|
|
err = OMX_FillThisBuffer(s->handle, buffer);
|
|
--
|
|
2.25.1
|
|
|