From ebd28b57f90ddf2016428afe7f50a0f9278eb404 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:14:39 +0800 Subject: [PATCH 1/8] FFmpeg: omxdec: optimize with omx zero copy feature Signed-off-by: Som Qin --- ...-optimize-with-omx-zero-copy-feature.patch | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 package/ffmpeg/0022-omxdec-optimize-with-omx-zero-copy-feature.patch diff --git a/package/ffmpeg/0022-omxdec-optimize-with-omx-zero-copy-feature.patch b/package/ffmpeg/0022-omxdec-optimize-with-omx-zero-copy-feature.patch new file mode 100644 index 00000000..76bb9a78 --- /dev/null +++ b/package/ffmpeg/0022-omxdec-optimize-with-omx-zero-copy-feature.patch @@ -0,0 +1,155 @@ +From 640ea14c3ca4536dce22a24153ac37d752009412 Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 11:38:04 +0800 +Subject: [PATCH 1/8] omxdec optimize with omx zero copy feature + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 63 ++++++++++++++++++++++++++++++++++----------- + 1 file changed, 48 insertions(+), 15 deletions(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index 1bb08b1..c518542 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -342,6 +342,8 @@ typedef struct OMXCodecContext { + pthread_cond_t input_cond; + pthread_mutex_t output_mutex; + pthread_cond_t output_cond; ++ pthread_mutex_t disableEVnt_mutex; ++ pthread_cond_t disableEVnt_cond; + + pthread_mutex_t state_mutex; + pthread_cond_t state_cond; +@@ -419,7 +421,7 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + OMX_PARAM_PORTDEFINITIONTYPE out_port_params = { 0 }; + OMX_PORT_PARAM_TYPE video_port_params = { 0 }; + OMX_ERRORTYPE err; +- int i; ++ int i, num; + + switch (event) { + case OMX_EventError: +@@ -438,6 +440,11 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + pthread_mutex_unlock(&s->state_mutex); + } else if (data1 == OMX_CommandPortDisable) { + av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" disabled\n", (uint32_t) data2); ++ if (data2 == 1) { ++ pthread_mutex_lock(&s->disableEVnt_mutex); ++ pthread_cond_broadcast(&s->disableEVnt_cond); ++ pthread_mutex_unlock(&s->disableEVnt_mutex); ++ } + } else if (data1 == OMX_CommandPortEnable) { + av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" enabled\n", (uint32_t) data2); + } else { +@@ -470,6 +477,32 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + dec_pix_fmt = out_port_params.format.video.eColorFormat; + + av_log(s->avctx, AV_LOG_VERBOSE, "w:%d, h:%d, fmt:%d\n", dec_out_width, dec_out_height, dec_pix_fmt); ++ if (!s->num_out_buffers) { ++ s->num_out_buffers = out_port_params.nBufferCountActual; ++ s->out_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); ++ s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); ++ ++ if (!s->out_buffer_headers || !s->done_out_buffers) ++ return AVERROR(ENOMEM); ++ ++ OMX_SendCommand(s->handle, OMX_CommandPortEnable, 1, NULL); ++ ++ for (num = 0; num < s->num_out_buffers && err == OMX_ErrorNone; num++) ++ err = OMX_AllocateBuffer(s->handle, &s->out_buffer_headers[num], s->out_port, s, out_port_params.nBufferSize); ++ ++ if (err != OMX_ErrorNone) { ++ av_log(s->avctx, AV_LOG_ERROR, "err %x (%d) on line %d\n", err, err, __LINE__); ++ return AVERROR_UNKNOWN; ++ } ++ s->num_out_buffers = num; ++ ++ for (num = 0; num < s->num_out_buffers && err == OMX_ErrorNone; num++) ++ err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[num]); ++ if (err != OMX_ErrorNone) { ++ for (; num < s->num_out_buffers; num++) ++ s->done_out_buffers[s->num_done_out_buffers++] = s->out_buffer_headers[num]; ++ } ++ } + } + } + break; +@@ -866,15 +899,18 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role) + CHECK(err); + err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params); + CHECK(err); +- s->num_out_buffers = out_port_params.nBufferCountActual; ++ ++ OMX_SendCommand(s->handle, OMX_CommandPortDisable, 1, NULL); ++ pthread_mutex_lock(&s->disableEVnt_mutex); ++ pthread_cond_wait(&s->disableEVnt_cond, &s->disableEVnt_mutex); ++ pthread_mutex_unlock(&s->disableEVnt_mutex); + + err = OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateIdle, NULL); + CHECK(err); + s->in_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers); + s->free_in_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers); +- s->out_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); +- s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); +- if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers) ++ ++ if (!s->in_buffer_headers || !s->free_in_buffers) + return AVERROR(ENOMEM); + + for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) { +@@ -887,10 +923,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role) + } + CHECK(err); + s->num_in_buffers = i; +- for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++) +- err = OMX_AllocateBuffer(s->handle, &s->out_buffer_headers[i], s->out_port, s, out_port_params.nBufferSize); +- CHECK(err); +- s->num_out_buffers = i; ++ + if (wait_for_state(s, OMX_StateIdle) < 0) { + av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateIdle\n"); + return AVERROR_UNKNOWN; +@@ -901,12 +934,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role) + av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateExecuting\n"); + return AVERROR_UNKNOWN; + } +- for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++) +- err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[i]); +- if (err != OMX_ErrorNone) { +- for (; i < s->num_out_buffers; i++) +- s->done_out_buffers[s->num_done_out_buffers++] = s->out_buffer_headers[i]; +- } ++ + for (i = 0; i < s->num_in_buffers; i++) + s->free_in_buffers[s->num_free_in_buffers++] = s->in_buffer_headers[i]; + return err != OMX_ErrorNone ? AVERROR_UNKNOWN : 0; +@@ -952,6 +980,8 @@ static av_cold void cleanup(OMXCodecContext *s) + 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); +@@ -984,6 +1014,8 @@ static av_cold int omx_decode_init(AVCodecContext *avctx) + pthread_cond_init(&s->input_cond, NULL); + pthread_mutex_init(&s->output_mutex, NULL); + pthread_cond_init(&s->output_cond, NULL); ++ pthread_mutex_init(&s->disableEVnt_mutex, NULL); ++ pthread_cond_init(&s->disableEVnt_cond, NULL); + s->mutex_cond_inited = 1; + s->avctx = avctx; + s->state = OMX_StateLoaded; +@@ -1009,6 +1041,7 @@ static av_cold int omx_decode_init(AVCodecContext *avctx) + + if ((ret = find_component(s->omx_context, avctx, role, s->component_name, sizeof(s->component_name))) < 0) + goto fail; ++ strcat(s->component_name, ".internal"); + + av_log(avctx, AV_LOG_INFO, "Using %s\n", s->component_name); + +-- +2.25.1 + From d7f3ff06a70c07755f74f43d53f4bd818d2c0935 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:15:38 +0800 Subject: [PATCH 2/8] FFmpeg: omxdec : add output buffers release callback to reduce memcpy Signed-off-by: Som Qin --- ...t-buffers-release-callback-to-reduce.patch | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 package/ffmpeg/0023-omxdec-add-output-buffers-release-callback-to-reduce.patch diff --git a/package/ffmpeg/0023-omxdec-add-output-buffers-release-callback-to-reduce.patch b/package/ffmpeg/0023-omxdec-add-output-buffers-release-callback-to-reduce.patch new file mode 100644 index 00000000..4828f868 --- /dev/null +++ b/package/ffmpeg/0023-omxdec-add-output-buffers-release-callback-to-reduce.patch @@ -0,0 +1,252 @@ +From 0f054a4a66e82d8f644acb8bf2a0b637cfee9aa8 Mon Sep 17 00:00:00 2001 +From: Som Qin +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 +--- + 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 + #include + ++#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 + From 206fb55497bb5d59c359cfe99533680a52e7c615 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:16:39 +0800 Subject: [PATCH 3/8] FFmpeg: Omxdec: Fix omx decoder fill frames pts incorrect Signed-off-by: Som Qin --- ...mx-decoder-fill-frames-pts-incorrect.patch | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 package/ffmpeg/0024-Fix-omx-decoder-fill-frames-pts-incorrect.patch diff --git a/package/ffmpeg/0024-Fix-omx-decoder-fill-frames-pts-incorrect.patch b/package/ffmpeg/0024-Fix-omx-decoder-fill-frames-pts-incorrect.patch new file mode 100644 index 00000000..4dbf13a2 --- /dev/null +++ b/package/ffmpeg/0024-Fix-omx-decoder-fill-frames-pts-incorrect.patch @@ -0,0 +1,34 @@ +From e0e6de3a210675444850c826bf5611b8d29228bf Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 13:47:48 +0800 +Subject: [PATCH 3/8] Fix omx decoder fill frames pts incorrect + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index afcba9b..f71e4bf 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -1217,7 +1217,15 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + pkt->size, pkt->pts, pkt->dts, pkt->duration); + av_log(avctx, AV_LOG_VERBOSE, "avctx->pts_correction_last_pts: %ld avctx->pts_correction_last_dts: %ld\n", + avctx->pts_correction_last_pts, avctx->pts_correction_last_dts); +- OMXDecodeQueuePush(&s->decode_pts_queue, pkt->dts); ++ if (pkt->dts != AV_NOPTS_VALUE) { ++ OMXDecodeQueuePush(&s->decode_pts_queue, pkt->dts); ++ } else { ++ if (OMXDecodeQueueEmpty(&s->decode_pts_queue)) { ++ OMXDecodeQueuePush(&s->decode_pts_queue, 0); ++ } else { ++ OMXDecodeQueuePush(&s->decode_pts_queue, s->decode_pts_queue.tail->val + pkt->duration); ++ } ++ } + if (pkt->size) { + + //VPU init and fill buffer slow, so empty buf sleep to send before get vpu fill buf. +-- +2.25.1 + From 1633a84ba83296d8b7e42fa3ae0f10704cb6960d Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:17:35 +0800 Subject: [PATCH 4/8] FFmpeg: Omxdec: Fix mjpg_omx buffer err Signed-off-by: Som Qin --- .../0025-Omxdec-Fix-mjpg_omx-buffer-err.patch | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 package/ffmpeg/0025-Omxdec-Fix-mjpg_omx-buffer-err.patch diff --git a/package/ffmpeg/0025-Omxdec-Fix-mjpg_omx-buffer-err.patch b/package/ffmpeg/0025-Omxdec-Fix-mjpg_omx-buffer-err.patch new file mode 100644 index 00000000..b3a3ec93 --- /dev/null +++ b/package/ffmpeg/0025-Omxdec-Fix-mjpg_omx-buffer-err.patch @@ -0,0 +1,106 @@ +From e3866de00ce3b6508c7636c9f96b1b1dfeab530a Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 13:50:10 +0800 +Subject: [PATCH 4/8] Omxdec: Fix mjpg_omx buffer err + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 77 ++++++++++++++++++++++++++++++++------------- + 1 file changed, 55 insertions(+), 22 deletions(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index f71e4bf..05e37d0 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -1329,33 +1329,66 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + s->got_eos = 1; + +- avframe->width = avctx->width; +- avframe->height = avctx->height; ++ if (avctx->codec->id == AV_CODEC_ID_HEVC || ++ avctx->codec->id == AV_CODEC_ID_H264) { ++ 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 = ff_decode_frame_props(avctx, avframe); +- if(ret < 0) { +- av_log(avctx, AV_LOG_ERROR, "Unable to fill buffer props\n"); +- goto end; +- } ++ ret = omx_buf_to_swframe(s, avframe, buffer); ++ if(ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to alloce frame\n"); ++ goto end; ++ } + +- ret = omx_buf_to_swframe(s, avframe, buffer); +- if(ret < 0) { +- av_log(avctx, AV_LOG_ERROR, "Unable to alloce frame\n"); +- goto end; +- } ++ if (pkt->pts) { ++ if (OMXDecodeQueueEmpty(&s->decode_pts_queue) != 0){ ++ av_log(avctx, AV_LOG_ERROR, "The queue of decode pts is empty.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); ++ OMXDecodeQueuePop(&s->decode_pts_queue); ++ } ++ s->decode_flag += 1; ++ *got_packet = 1; + +- if (pkt->pts) { +- if (OMXDecodeQueueEmpty(&s->decode_pts_queue) != 0){ +- av_log(avctx, AV_LOG_ERROR, "The queue of decode pts is empty.\n"); +- return AVERROR_INVALIDDATA; ++ return ret; ++ ++ } else if (avctx->codec->id == AV_CODEC_ID_MPEG4 || ++ avctx->codec->id == AV_CODEC_ID_MJPEG) { ++ ++ uint8_t *dst[4]; ++ int linesize[4]; ++ if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\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); ++ goto end; + } +- avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); +- OMXDecodeQueuePop(&s->decode_pts_queue); +- } +- s->decode_flag += 1; +- *got_packet = 1; + +- return ret; ++ 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"); ++ return AVERROR_INVALIDDATA; ++ } ++ avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); ++ OMXDecodeQueuePop(&s->decode_pts_queue); ++ } ++ s->decode_flag += 1; ++ *got_packet = 1; ++ } + + end: + err = OMX_FillThisBuffer(s->handle, buffer); +-- +2.25.1 + From a00db16d4e93da3563b28bfb6f0ee4043e9ada74 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:18:25 +0800 Subject: [PATCH 5/8] FFmpeg: Omxdec: Add flush callback of sf omx decoder Signed-off-by: Som Qin --- ...Add-flush-callback-of-sf-omx-decoder.patch | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 package/ffmpeg/0026-Omxdec-Add-flush-callback-of-sf-omx-decoder.patch diff --git a/package/ffmpeg/0026-Omxdec-Add-flush-callback-of-sf-omx-decoder.patch b/package/ffmpeg/0026-Omxdec-Add-flush-callback-of-sf-omx-decoder.patch new file mode 100644 index 00000000..ec4bafe7 --- /dev/null +++ b/package/ffmpeg/0026-Omxdec-Add-flush-callback-of-sf-omx-decoder.patch @@ -0,0 +1,88 @@ +From b8af55868ea8b2b68ef06fee2eb8a19b16fdb79d Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 13:53:57 +0800 +Subject: [PATCH 5/8] Omxdec: Add flush callback of sf omx decoder + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index 05e37d0..d268454 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -365,6 +365,7 @@ typedef struct OMXCodecContext { + OMX_U32 scale_height; + OMX_U32 rotation; + OMX_U32 mirror; ++ OMX_U32 skip; + char *crop_expr; + struct { + int x; +@@ -1310,6 +1311,11 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + } + break; + } ++ ++ if(s->skip) { ++ s->skip--; ++ goto end; ++ } + //if (!buffer) + // break; + // if(!s->first_get_outbuffer) +@@ -1401,6 +1407,18 @@ end: + return ret; + } + ++static void omx_decode_flush(AVCodecContext *avctx) ++{ ++ OMXCodecContext *s = avctx->priv_data; ++ ++ av_log(avctx, AV_LOG_VERBOSE, "Flushing buffer\n"); ++ ++ while(!OMXDecodeQueueEmpty(&s->decode_pts_queue)) { ++ OMXDecodeQueuePop(&s->decode_pts_queue); ++ s->skip++; ++ } ++} ++ + static av_cold int omx_decode_end(AVCodecContext *avctx) + { + OMXCodecContext *s = avctx->priv_data; +@@ -1465,6 +1483,7 @@ AVCodec ff_mpeg4_omx_decoder = { + .init = omx_decode_init, + .decode = omx_decode_frame, + .close = omx_decode_end, ++ .flush = omx_decode_flush, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &omx_mpeg4dec_class, +@@ -1485,6 +1504,7 @@ AVCodec ff_h264_omx_decoder = { + .init = omx_decode_init, + .decode = omx_decode_frame, + .close = omx_decode_end, ++ .flush = omx_decode_flush, + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &omx_h264dec_class, +@@ -1506,6 +1526,7 @@ AVCodec ff_hevc_omx_decoder = { + .init = omx_decode_init, + .decode = omx_decode_frame, + .close = omx_decode_end, ++ .flush = omx_decode_flush, + .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), + .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +@@ -1528,6 +1549,7 @@ AVCodec ff_mjpeg_omx_decoder = { + .init = omx_decode_init, + .decode = omx_decode_frame, + .close = omx_decode_end, ++ .flush = omx_decode_flush, + .capabilities = AV_CODEC_CAP_DR1, + .max_lowres = 3, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +-- +2.25.1 + From 49af7f57e623e9db3e7aeb842d274127fa3ba937 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:20:24 +0800 Subject: [PATCH 6/8] FFmpeg: Omxdec: Remove the global variables in omxdec Signed-off-by: Som Qin --- ...e-global-variables-in-omxdec-it-make.patch | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 package/ffmpeg/0027-Omxdec-Remove-the-global-variables-in-omxdec-it-make.patch diff --git a/package/ffmpeg/0027-Omxdec-Remove-the-global-variables-in-omxdec-it-make.patch b/package/ffmpeg/0027-Omxdec-Remove-the-global-variables-in-omxdec-it-make.patch new file mode 100644 index 00000000..ed72fc12 --- /dev/null +++ b/package/ffmpeg/0027-Omxdec-Remove-the-global-variables-in-omxdec-it-make.patch @@ -0,0 +1,86 @@ +From d44bd33ca4fa0975f284279916f8709282bfe020 Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 13:57:24 +0800 +Subject: [PATCH 6/8] Omxdec: Remove the global variables in omxdec, it make + issue in mutithread. + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index d268454..aa3ddea 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -48,10 +48,6 @@ + #include "internal.h" + #include "profiles.h" + +-int evnet_bufferflag; +-int dec_out_height; +-int dec_out_width; +-int dec_pix_fmt; + + #ifdef OMX_SKIP64BIT + static OMX_TICKS to_omx_ticks(int64_t value) +@@ -354,6 +350,9 @@ typedef struct OMXCodecContext { + int mutex_cond_inited; + + int eos_sent, got_eos, evnet_bufferflag, first_get_outbuffer; ++ int dec_out_height; ++ int dec_out_width; ++ int dec_pix_fmt; + + int extradata_sent; + int has_cleanup; +@@ -475,11 +474,11 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + } + if (port_params.eDir == OMX_DirOutput) { + out_port_params = port_params; +- dec_out_width = out_port_params.format.video.nFrameWidth; +- dec_out_height = out_port_params.format.video.nFrameHeight; +- dec_pix_fmt = out_port_params.format.video.eColorFormat; ++ s->dec_out_width = out_port_params.format.video.nFrameWidth; ++ s->dec_out_height = out_port_params.format.video.nFrameHeight; ++ s->dec_pix_fmt = out_port_params.format.video.eColorFormat; + +- av_log(s->avctx, AV_LOG_VERBOSE, "w:%d, h:%d, fmt:%d\n", dec_out_width, dec_out_height, dec_pix_fmt); ++ av_log(s->avctx, AV_LOG_VERBOSE, "w:%d, h:%d, fmt:%d\n", s->dec_out_width, s->dec_out_height, s->dec_pix_fmt); + if (!s->num_out_buffers) { + s->num_out_buffers = out_port_params.nBufferCountActual; + s->out_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers); +@@ -511,7 +510,7 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + break; + case OMX_EventBufferFlag: + av_log(s->avctx, AV_LOG_VERBOSE, "OMX decoder competd set event_bufferflag\n"); +- evnet_bufferflag = 1; ++ s->evnet_bufferflag = 1; + default: + av_log(s->avctx, AV_LOG_VERBOSE, "OMX event %d %"PRIx32" %"PRIx32"\n", + event, (uint32_t) data1, (uint32_t) data2); +@@ -1306,7 +1305,7 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + /*eos is sent wait for vpu evnet_bufferflag to get all frames + mjpeg: sent a frame, then wait for a decoder frame + */ +- if((s->eos_sent && !evnet_bufferflag) || (avctx->codec_id == AV_CODEC_ID_MJPEG )) { ++ if((s->eos_sent && !s->evnet_bufferflag) || (avctx->codec_id == AV_CODEC_ID_MJPEG )) { + continue; + } + break; +@@ -1326,9 +1325,9 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + goto end; + } + +- avctx->width = dec_out_width; +- avctx->height = dec_out_height; +- avctx->pix_fmt = omx_map_color_format(avctx, dec_pix_fmt); ++ avctx->width = s->dec_out_width; ++ avctx->height = s->dec_out_height; ++ avctx->pix_fmt = omx_map_color_format(avctx, s->dec_pix_fmt); + s->stride = avctx->width; + s->plane_size = avctx->height; + +-- +2.25.1 + From a1956c4b7196c850f3ca59cf9916b7c6dd18683b Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:21:58 +0800 Subject: [PATCH 7/8] FFmpeg: Omxdec: no longer send eos when processing zero size pkt Signed-off-by: Som Qin --- ...-send-eos-when-processing-zero-size-.patch | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 package/ffmpeg/0028-Omxdec-no-longer-send-eos-when-processing-zero-size-.patch diff --git a/package/ffmpeg/0028-Omxdec-no-longer-send-eos-when-processing-zero-size-.patch b/package/ffmpeg/0028-Omxdec-no-longer-send-eos-when-processing-zero-size-.patch new file mode 100644 index 00000000..32b4643e --- /dev/null +++ b/package/ffmpeg/0028-Omxdec-no-longer-send-eos-when-processing-zero-size-.patch @@ -0,0 +1,59 @@ +From d9ac2081cfb04a0d519e9bf57b6b68d12eefadb0 Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 13:59:25 +0800 +Subject: [PATCH 7/8] Omxdec: no longer send eos when processing zero size pkt + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 28 +--------------------------- + 1 file changed, 1 insertion(+), 27 deletions(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index aa3ddea..47fb482 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -1268,29 +1268,6 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err); + return AVERROR_UNKNOWN; + } +- } else if (!s->eos_sent) { +- +- // if(!s->first_get_outbuffer) +- // av_usleep(1000000); +- buffer = get_buffer(&s->input_mutex, &s->input_cond, +- &s->num_free_in_buffers, s->free_in_buffers, 1); +- +- if(!buffer) { +- av_log(avctx, AV_LOG_ERROR, "get_buffer NULL\n"); +- return AVERROR(ENOMEM); +- } +- +- buffer->nFilledLen = 0; +- buffer->nFlags = OMX_BUFFERFLAG_EOS; +- buffer->pAppPrivate = buffer->pOutputPortPrivate = NULL; +- +- err = OMX_EmptyThisBuffer(s->handle, buffer); +- if (err != OMX_ErrorNone) { +- append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); +- av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err); +- return AVERROR_UNKNOWN; +- } +- s->eos_sent = 1; + } + + while (!*got_packet && ret == 0 && !s->got_eos) { +@@ -1302,10 +1279,7 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + !pkt || had_partial); + + if (!buffer) { +- /*eos is sent wait for vpu evnet_bufferflag to get all frames +- mjpeg: sent a frame, then wait for a decoder frame +- */ +- if((s->eos_sent && !s->evnet_bufferflag) || (avctx->codec_id == AV_CODEC_ID_MJPEG )) { ++ if( avctx->codec_id == AV_CODEC_ID_MJPEG ) { + continue; + } + break; +-- +2.25.1 + From 0ed0fe882c35721566998ca7190bc422a70e4e31 Mon Sep 17 00:00:00 2001 From: Som Qin Date: Fri, 4 Aug 2023 14:22:40 +0800 Subject: [PATCH 8/8] FFmpeg: Omxdec: optimize buffer method for mjpg decoder Signed-off-by: Som Qin --- ...imize-buffer-method-for-mjpg-decoder.patch | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 package/ffmpeg/0029-Omxdec-optimize-buffer-method-for-mjpg-decoder.patch diff --git a/package/ffmpeg/0029-Omxdec-optimize-buffer-method-for-mjpg-decoder.patch b/package/ffmpeg/0029-Omxdec-optimize-buffer-method-for-mjpg-decoder.patch new file mode 100644 index 00000000..f922b694 --- /dev/null +++ b/package/ffmpeg/0029-Omxdec-optimize-buffer-method-for-mjpg-decoder.patch @@ -0,0 +1,150 @@ +From cc356de583854b257b52b8bf79eb519b7da34c9d Mon Sep 17 00:00:00 2001 +From: Som Qin +Date: Fri, 4 Aug 2023 14:02:26 +0800 +Subject: [PATCH 8/8] Omxdec: optimize buffer method for mjpg decoder + +Signed-off-by: Som Qin +--- + libavcodec/omxdec.c | 88 +++++++++++++++------------------------------ + 1 file changed, 28 insertions(+), 60 deletions(-) + +diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c +index 47fb482..b38e3b9 100755 +--- a/libavcodec/omxdec.c ++++ b/libavcodec/omxdec.c +@@ -437,7 +437,8 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O + if (data1 == OMX_CommandStateSet) { + pthread_mutex_lock(&s->state_mutex); + s->state = data2; +- av_log(s->avctx, AV_LOG_VERBOSE, "OMX state changed to %"PRIu32"\n", (uint32_t) data2); ++ if (!s->has_cleanup) ++ av_log(s->avctx, AV_LOG_VERBOSE, "OMX state changed to %"PRIu32"\n", (uint32_t) data2); + pthread_cond_broadcast(&s->state_cond); + pthread_mutex_unlock(&s->state_mutex); + } else if (data1 == OMX_CommandPortDisable) { +@@ -1180,11 +1181,14 @@ static int omx_buf_to_swframe(OMXCodecContext *s, AVFrame *frame, OMX_BUFFERHEAD + switch (s->avctx->pix_fmt) { + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_NV21: ++ case AV_PIX_FMT_NV16: + frame->linesize[1] = linesize[1]; + frame->data[1] = dst[1]; + break; + + case AV_PIX_FMT_YUV420P: ++ case AV_PIX_FMT_YUV422P: ++ case AV_PIX_FMT_YUV444P: + frame->linesize[1] = linesize[1]; + frame->linesize[2] = linesize[2]; + frame->data[1] = dst[1]; +@@ -1279,9 +1283,6 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + !pkt || had_partial); + + if (!buffer) { +- if( avctx->codec_id == AV_CODEC_ID_MJPEG ) { +- continue; +- } + break; + } + +@@ -1308,66 +1309,33 @@ static int omx_decode_frame(AVCodecContext *avctx, void *data, + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + s->got_eos = 1; + +- if (avctx->codec->id == AV_CODEC_ID_HEVC || +- avctx->codec->id == AV_CODEC_ID_H264) { +- 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 = omx_buf_to_swframe(s, avframe, buffer); +- if(ret < 0) { +- av_log(avctx, AV_LOG_ERROR, "Unable to alloce frame\n"); +- goto end; +- } +- +- if (pkt->pts) { +- if (OMXDecodeQueueEmpty(&s->decode_pts_queue) != 0){ +- av_log(avctx, AV_LOG_ERROR, "The queue of decode pts is empty.\n"); +- return AVERROR_INVALIDDATA; +- } +- avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); +- OMXDecodeQueuePop(&s->decode_pts_queue); +- } +- s->decode_flag += 1; +- *got_packet = 1; +- +- return ret; +- +- } else if (avctx->codec->id == AV_CODEC_ID_MPEG4 || +- avctx->codec->id == AV_CODEC_ID_MJPEG) { ++ avframe->width = avctx->width; ++ avframe->height = avctx->height; + +- uint8_t *dst[4]; +- int linesize[4]; +- if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) { +- av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); +- goto end; +- } ++ 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); +- goto end; +- } ++ 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"); +- return AVERROR_INVALIDDATA; +- } +- avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); +- OMXDecodeQueuePop(&s->decode_pts_queue); ++ if (pkt->pts) { ++ if (OMXDecodeQueueEmpty(&s->decode_pts_queue) != 0){ ++ av_log(avctx, AV_LOG_ERROR, "The queue of decode pts is empty.\n"); ++ return AVERROR_INVALIDDATA; + } +- s->decode_flag += 1; +- *got_packet = 1; ++ avframe->pts = OMXDecodeQueueFront(&s->decode_pts_queue); ++ OMXDecodeQueuePop(&s->decode_pts_queue); + } ++ s->decode_flag += 1; ++ *got_packet = 1; ++ ++ return ret; + + end: + err = OMX_FillThisBuffer(s->handle, buffer); +@@ -1523,7 +1491,7 @@ AVCodec ff_mjpeg_omx_decoder = { + .decode = omx_decode_frame, + .close = omx_decode_end, + .flush = omx_decode_flush, +- .capabilities = AV_CODEC_CAP_DR1, ++ .capabilities = AV_CODEC_CAP_DELAY, + .max_lowres = 3, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_class = &omx_mjpegdec_class, +-- +2.25.1 +