diff options
author | boogie | 2023-01-30 11:14:13 +0100 |
---|---|---|
committer | boogie | 2023-01-30 11:14:13 +0100 |
commit | f4cc880714a8be1012e22dfcfbbc4d28ed127b86 (patch) | |
tree | 3a1e081c2b05e65e7b3099113bf3253c1e205c51 /0002-rkmpp-4.patch | |
download | aur-f4cc880714a8be1012e22dfcfbbc4d28ed127b86.tar.gz |
initial
Diffstat (limited to '0002-rkmpp-4.patch')
-rw-r--r-- | 0002-rkmpp-4.patch | 2771 |
1 files changed, 2771 insertions, 0 deletions
diff --git a/0002-rkmpp-4.patch b/0002-rkmpp-4.patch new file mode 100644 index 000000000000..5c8734c1535a --- /dev/null +++ b/0002-rkmpp-4.patch @@ -0,0 +1,2771 @@ +From 9590c16111eb27ba8cb1b5c46ea57dc9052e82ed Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Wed, 4 Sep 2019 17:24:37 +0800 +Subject: [PATCH 01/16] avcodec/rkmppdec: Clear eos flag after reset + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index a60962dc86..3654437268 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -544,6 +544,7 @@ static void rkmpp_flush(AVCodecContext *avctx) + ret = decoder->mpi->reset(decoder->ctx); + if (ret == MPP_OK) { + decoder->first_packet = 1; ++ decoder->eos_reached = 0; + } else + av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret); + } +-- +2.39.0 + + +From 43fc7807c58999a57d4c407dcda0d3d2fac7405b Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Wed, 4 Sep 2019 17:27:46 +0800 +Subject: [PATCH 02/16] avcodec/rkmppdec: Compatible with old reordered_opaque + and pkt_pts + +Some users might still using these deprecated APIs. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 3654437268..6256abe63c 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -93,6 +93,9 @@ static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, in + int ret; + MppPacket packet; + ++ if (!pts || pts == AV_NOPTS_VALUE) ++ pts = avctx->reordered_opaque; ++ + // create the MPP packet + ret = mpp_packet_init(&packet, buffer, size); + if (ret != MPP_OK) { +@@ -398,6 +401,12 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) + frame->width = mpp_frame_get_width(mppframe); + frame->height = mpp_frame_get_height(mppframe); + frame->pts = mpp_frame_get_pts(mppframe); ++#if FF_API_PKT_PTS ++ FF_DISABLE_DEPRECATION_WARNINGS ++ frame->pkt_pts = frame->pts; ++ FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ frame->reordered_opaque = frame->pts; + frame->color_range = mpp_frame_get_color_range(mppframe); + frame->color_primaries = mpp_frame_get_color_primaries(mppframe); + frame->color_trc = mpp_frame_get_color_trc(mppframe); +-- +2.39.0 + + +From 6b5e686cea5638fe6c2c92eeaaabe16d9a72121b Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Wed, 19 May 2021 09:55:03 +0800 +Subject: [PATCH 03/16] rkmppdec: Remove frame buffer limit + +It would hang when reaching the limit. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 6256abe63c..96696e84dc 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -39,7 +39,6 @@ + #include "libavutil/log.h" + + #define RECEIVE_FRAME_TIMEOUT 100 +-#define FRAMEGROUP_MAX_FRAMES 16 + #define INPUT_MAX_PACKETS 4 + + typedef struct { +@@ -241,13 +240,6 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + +- ret = mpp_buffer_group_limit_config(decoder->frame_group, 0, FRAMEGROUP_MAX_FRAMES); +- if (ret) { +- av_log(avctx, AV_LOG_ERROR, "Failed to set buffer group limit (code = %d)\n", ret); +- ret = AVERROR_UNKNOWN; +- goto fail; +- } +- + decoder->first_packet = 1; + + av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n"); +-- +2.39.0 + + +From 668ec8c36d1112c5c4939ddc3d3b7cff487cedc1 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Thu, 20 May 2021 10:19:15 +0800 +Subject: [PATCH 04/16] avcodec/rkmppdec: Rework decoding flow + +Stop using the deprecated MPP_DEC_GET_STREAM_COUNT API. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 526 ++++++++++++++++++++++-------------------- + 1 file changed, 270 insertions(+), 256 deletions(-) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 96696e84dc..7c28378120 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -38,17 +38,15 @@ + #include "libavutil/imgutils.h" + #include "libavutil/log.h" + +-#define RECEIVE_FRAME_TIMEOUT 100 +-#define INPUT_MAX_PACKETS 4 +- + typedef struct { + MppCtx ctx; + MppApi *mpi; + MppBufferGroup frame_group; + +- char first_packet; +- char eos_reached; ++ int8_t eos; ++ int8_t draining; + ++ AVPacket packet; + AVBufferRef *frames_ref; + AVBufferRef *device_ref; + } RKMPPDecoder; +@@ -85,47 +83,13 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat) + } + } + +-static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, int64_t pts) ++static int rkmpp_close_decoder(AVCodecContext *avctx) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- int ret; +- MppPacket packet; +- +- if (!pts || pts == AV_NOPTS_VALUE) +- pts = avctx->reordered_opaque; +- +- // create the MPP packet +- ret = mpp_packet_init(&packet, buffer, size); +- if (ret != MPP_OK) { +- av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret); +- return AVERROR_UNKNOWN; +- } +- +- mpp_packet_set_pts(packet, pts); +- +- if (!buffer) +- mpp_packet_set_eos(packet); + +- ret = decoder->mpi->decode_put_packet(decoder->ctx, packet); +- if (ret != MPP_OK) { +- if (ret == MPP_ERR_BUFFER_FULL) { +- av_log(avctx, AV_LOG_DEBUG, "Buffer full writing %d bytes to decoder\n", size); +- ret = AVERROR(EAGAIN); +- } else +- ret = AVERROR_UNKNOWN; +- } +- else +- av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", size); ++ av_packet_unref(&decoder->packet); + +- mpp_packet_deinit(&packet); +- +- return ret; +-} +- +-static int rkmpp_close_decoder(AVCodecContext *avctx) +-{ +- RKMPPDecodeContext *rk_context = avctx->priv_data; + av_buffer_unref(&rk_context->decoder_ref); + return 0; + } +@@ -151,14 +115,32 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data) + av_free(decoder); + } + ++static int rkmpp_prepare_decoder(AVCodecContext *avctx) ++{ ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ MppPacket packet; ++ int ret; ++ ++ // send extra data ++ if (avctx->extradata_size) { ++ ret = mpp_packet_init(&packet, avctx->extradata, avctx->extradata_size); ++ if (ret < 0) ++ return AVERROR_UNKNOWN; ++ ret = decoder->mpi->decode_put_packet(decoder->ctx, packet); ++ mpp_packet_deinit(&packet); ++ if (ret < 0) ++ return AVERROR_UNKNOWN; ++ } ++ return 0; ++} ++ + static int rkmpp_init_decoder(AVCodecContext *avctx) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = NULL; + MppCodingType codectype = MPP_VIDEO_CodingUnused; + int ret; +- RK_S64 paramS64; +- RK_S32 paramS32; + + avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; + +@@ -201,6 +183,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + ++ ret = 1; ++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_PARSER_FAST_MODE, &ret); ++ + // initialize mpp + ret = mpp_init(decoder->ctx, MPP_CTX_DEC, codectype); + if (ret != MPP_OK) { +@@ -209,26 +194,9 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + +- // make decode calls blocking with a timeout +- paramS32 = MPP_POLL_BLOCK; +- ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK, ¶mS32); +- if (ret != MPP_OK) { +- av_log(avctx, AV_LOG_ERROR, "Failed to set blocking mode on MPI (code = %d).\n", ret); +- ret = AVERROR_UNKNOWN; +- goto fail; +- } +- +- paramS64 = RECEIVE_FRAME_TIMEOUT; +- ret = decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_BLOCK_TIMEOUT, ¶mS64); +- if (ret != MPP_OK) { +- av_log(avctx, AV_LOG_ERROR, "Failed to set block timeout on MPI (code = %d).\n", ret); +- ret = AVERROR_UNKNOWN; +- goto fail; +- } +- + ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION); + if (ret) { +- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve buffer group (code = %d)\n", ret); ++ av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret); + ret = AVERROR_UNKNOWN; + goto fail; + } +@@ -240,7 +208,13 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + +- decoder->first_packet = 1; ++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_DISABLE_ERROR, NULL); ++ ++ ret = rkmpp_prepare_decoder(avctx); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to prepare decoder (code = %d)\n", ret); ++ goto fail; ++ } + + av_log(avctx, AV_LOG_DEBUG, "RKMPP decoder initialized successfully.\n"); + +@@ -261,44 +235,6 @@ fail: + return ret; + } + +-static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt) +-{ +- RKMPPDecodeContext *rk_context = avctx->priv_data; +- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- int ret; +- +- // handle EOF +- if (!avpkt->size) { +- av_log(avctx, AV_LOG_DEBUG, "End of stream.\n"); +- decoder->eos_reached = 1; +- ret = rkmpp_write_data(avctx, NULL, 0, 0); +- if (ret) +- av_log(avctx, AV_LOG_ERROR, "Failed to send EOS to decoder (code = %d)\n", ret); +- return ret; +- } +- +- // on first packet, send extradata +- if (decoder->first_packet) { +- if (avctx->extradata_size) { +- ret = rkmpp_write_data(avctx, avctx->extradata, +- avctx->extradata_size, +- avpkt->pts); +- if (ret) { +- av_log(avctx, AV_LOG_ERROR, "Failed to write extradata to decoder (code = %d)\n", ret); +- return ret; +- } +- } +- decoder->first_packet = 0; +- } +- +- // now send packet +- ret = rkmpp_write_data(avctx, avpkt->data, avpkt->size, avpkt->pts); +- if (ret && ret!=AVERROR(EAGAIN)) +- av_log(avctx, AV_LOG_ERROR, "Failed to write data to decoder (code = %d)\n", ret); +- +- return ret; +-} +- + static void rkmpp_release_frame(void *opaque, uint8_t *data) + { + AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data; +@@ -312,7 +248,7 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data) + av_free(desc); + } + +-static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) ++static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +@@ -327,156 +263,164 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) + MppFrameFormat mppformat; + uint32_t drmformat; + ++ // should not provide any frame after EOS ++ if (decoder->eos) ++ return AVERROR_EOF; ++ ++ decoder->mpi->control(decoder->ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&timeout); ++ + ret = decoder->mpi->decode_get_frame(decoder->ctx, &mppframe); + if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) { +- av_log(avctx, AV_LOG_ERROR, "Failed to get a frame from MPP (code = %d)\n", ret); +- goto fail; ++ av_log(avctx, AV_LOG_ERROR, "Failed to get frame (code = %d)\n", ret); ++ return AVERROR_UNKNOWN; + } + +- if (mppframe) { +- // Check whether we have a special frame or not +- if (mpp_frame_get_info_change(mppframe)) { +- AVHWFramesContext *hwframes; ++ if (!mppframe) { ++ av_log(avctx, AV_LOG_DEBUG, "Timeout getting decoded frame.\n"); ++ return AVERROR(EAGAIN); ++ } + +- av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n", +- (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe), +- (int)mpp_frame_get_fmt(mppframe)); ++ if (mpp_frame_get_eos(mppframe)) { ++ av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n"); ++ decoder->eos = 1; ++ ret = AVERROR_EOF; ++ goto fail; ++ } + +- avctx->width = mpp_frame_get_width(mppframe); +- avctx->height = mpp_frame_get_height(mppframe); ++ if (mpp_frame_get_discard(mppframe)) { ++ av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n"); ++ ret = AVERROR(EAGAIN); ++ goto fail; ++ } + +- decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); ++ if (mpp_frame_get_errinfo(mppframe)) { ++ av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n"); ++ ret = AVERROR_UNKNOWN; ++ goto fail; ++ } + +- av_buffer_unref(&decoder->frames_ref); ++ if (mpp_frame_get_info_change(mppframe)) { ++ AVHWFramesContext *hwframes; + +- decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref); +- if (!decoder->frames_ref) { +- ret = AVERROR(ENOMEM); +- goto fail; +- } ++ av_log(avctx, AV_LOG_INFO, "Decoder noticed an info change (%dx%d), format=%d\n", ++ (int)mpp_frame_get_width(mppframe), (int)mpp_frame_get_height(mppframe), ++ (int)mpp_frame_get_fmt(mppframe)); + +- mppformat = mpp_frame_get_fmt(mppframe); +- drmformat = rkmpp_get_frameformat(mppformat); ++ avctx->width = mpp_frame_get_width(mppframe); ++ avctx->height = mpp_frame_get_height(mppframe); + +- hwframes = (AVHWFramesContext*)decoder->frames_ref->data; +- hwframes->format = AV_PIX_FMT_DRM_PRIME; +- hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE; +- hwframes->width = avctx->width; +- hwframes->height = avctx->height; +- ret = av_hwframe_ctx_init(decoder->frames_ref); +- if (ret < 0) +- goto fail; ++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe); ++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + +- // here decoder is fully initialized, we need to feed it again with data +- ret = AVERROR(EAGAIN); +- goto fail; +- } else if (mpp_frame_get_eos(mppframe)) { +- av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n"); +- decoder->eos_reached = 1; +- ret = AVERROR_EOF; +- goto fail; +- } else if (mpp_frame_get_discard(mppframe)) { +- av_log(avctx, AV_LOG_DEBUG, "Received a discard frame.\n"); +- ret = AVERROR(EAGAIN); +- goto fail; +- } else if (mpp_frame_get_errinfo(mppframe)) { +- av_log(avctx, AV_LOG_ERROR, "Received a errinfo frame.\n"); +- ret = AVERROR_UNKNOWN; ++ av_buffer_unref(&decoder->frames_ref); ++ ++ decoder->frames_ref = av_hwframe_ctx_alloc(decoder->device_ref); ++ if (!decoder->frames_ref) { ++ ret = AVERROR(ENOMEM); + goto fail; + } + +- // here we should have a valid frame +- av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n"); ++ mppformat = mpp_frame_get_fmt(mppframe); ++ drmformat = rkmpp_get_frameformat(mppformat); ++ ++ hwframes = (AVHWFramesContext*)decoder->frames_ref->data; ++ hwframes->format = AV_PIX_FMT_DRM_PRIME; ++ hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE; ++ hwframes->width = avctx->width; ++ hwframes->height = avctx->height; ++ ret = av_hwframe_ctx_init(decoder->frames_ref); ++ if (!ret) ++ ret = AVERROR(EAGAIN); ++ ++ goto fail; ++ } + +- // setup general frame fields +- frame->format = AV_PIX_FMT_DRM_PRIME; +- frame->width = mpp_frame_get_width(mppframe); +- frame->height = mpp_frame_get_height(mppframe); +- frame->pts = mpp_frame_get_pts(mppframe); ++ // here we should have a valid frame ++ av_log(avctx, AV_LOG_DEBUG, "Received a frame.\n"); ++ ++ // now setup the frame buffer info ++ buffer = mpp_frame_get_buffer(mppframe); ++ if (!buffer) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get the frame buffer, frame is dropped (code = %d)\n", ret); ++ ret = AVERROR(EAGAIN); ++ goto fail; ++ } ++ ++ // setup general frame fields ++ frame->format = avctx->pix_fmt; ++ frame->width = mpp_frame_get_width(mppframe); ++ frame->height = mpp_frame_get_height(mppframe); ++ frame->pts = mpp_frame_get_pts(mppframe); + #if FF_API_PKT_PTS +- FF_DISABLE_DEPRECATION_WARNINGS +- frame->pkt_pts = frame->pts; +- FF_ENABLE_DEPRECATION_WARNINGS ++ FF_DISABLE_DEPRECATION_WARNINGS; ++ frame->pkt_pts = frame->pts; ++ FF_ENABLE_DEPRECATION_WARNINGS; + #endif +- frame->reordered_opaque = frame->pts; +- frame->color_range = mpp_frame_get_color_range(mppframe); +- frame->color_primaries = mpp_frame_get_color_primaries(mppframe); +- frame->color_trc = mpp_frame_get_color_trc(mppframe); +- frame->colorspace = mpp_frame_get_colorspace(mppframe); ++ frame->reordered_opaque = frame->pts; ++ frame->color_range = mpp_frame_get_color_range(mppframe); ++ frame->color_primaries = mpp_frame_get_color_primaries(mppframe); ++ frame->color_trc = mpp_frame_get_color_trc(mppframe); ++ frame->colorspace = mpp_frame_get_colorspace(mppframe); + +- mode = mpp_frame_get_mode(mppframe); +- frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED); +- frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); ++ mode = mpp_frame_get_mode(mppframe); ++ frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED); ++ frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); + +- mppformat = mpp_frame_get_fmt(mppframe); +- drmformat = rkmpp_get_frameformat(mppformat); ++ mppformat = mpp_frame_get_fmt(mppframe); ++ drmformat = rkmpp_get_frameformat(mppformat); + +- // now setup the frame buffer info +- buffer = mpp_frame_get_buffer(mppframe); +- if (buffer) { +- desc = av_mallocz(sizeof(AVDRMFrameDescriptor)); +- if (!desc) { +- ret = AVERROR(ENOMEM); +- goto fail; +- } ++ desc = av_mallocz(sizeof(AVDRMFrameDescriptor)); ++ if (!desc) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } + +- desc->nb_objects = 1; +- desc->objects[0].fd = mpp_buffer_get_fd(buffer); +- desc->objects[0].size = mpp_buffer_get_size(buffer); +- +- desc->nb_layers = 1; +- layer = &desc->layers[0]; +- layer->format = drmformat; +- layer->nb_planes = 2; +- +- layer->planes[0].object_index = 0; +- layer->planes[0].offset = 0; +- layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe); +- +- layer->planes[1].object_index = 0; +- layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe); +- layer->planes[1].pitch = layer->planes[0].pitch; +- +- // we also allocate a struct in buf[0] that will allow to hold additionnal information +- // for releasing properly MPP frames and decoder +- framecontextref = av_buffer_allocz(sizeof(*framecontext)); +- if (!framecontextref) { +- ret = AVERROR(ENOMEM); +- goto fail; +- } ++ desc->nb_objects = 1; ++ desc->objects[0].fd = mpp_buffer_get_fd(buffer); ++ desc->objects[0].size = mpp_buffer_get_size(buffer); + +- // MPP decoder needs to be closed only when all frames have been released. +- framecontext = (RKMPPFrameContext *)framecontextref->data; +- framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref); +- framecontext->frame = mppframe; ++ desc->nb_layers = 1; ++ layer = &desc->layers[0]; ++ layer->format = drmformat; ++ layer->nb_planes = 2; + +- frame->data[0] = (uint8_t *)desc; +- frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame, +- framecontextref, AV_BUFFER_FLAG_READONLY); ++ layer->planes[0].object_index = 0; ++ layer->planes[0].offset = 0; ++ layer->planes[0].pitch = mpp_frame_get_hor_stride(mppframe); + +- if (!frame->buf[0]) { +- ret = AVERROR(ENOMEM); +- goto fail; +- } ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe); ++ layer->planes[1].pitch = layer->planes[0].pitch; + +- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref); +- if (!frame->hw_frames_ctx) { +- ret = AVERROR(ENOMEM); +- goto fail; +- } ++ // we also allocate a struct in buf[0] that will allow to hold additionnal information ++ // for releasing properly MPP frames and decoder ++ framecontextref = av_buffer_allocz(sizeof(*framecontext)); ++ if (!framecontextref) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } + +- return 0; +- } else { +- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret); +- mpp_frame_deinit(&mppframe); +- } +- } else if (decoder->eos_reached) { +- return AVERROR_EOF; +- } else if (ret == MPP_ERR_TIMEOUT) { +- av_log(avctx, AV_LOG_DEBUG, "Timeout when trying to get a frame from MPP\n"); ++ // MPP decoder needs to be closed only when all frames have been released. ++ framecontext = (RKMPPFrameContext *)framecontextref->data; ++ framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref); ++ framecontext->frame = mppframe; ++ ++ frame->data[0] = (uint8_t *)desc; ++ frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame, ++ framecontextref, AV_BUFFER_FLAG_READONLY); ++ ++ if (!frame->buf[0]) { ++ ret = AVERROR(ENOMEM); ++ goto fail; + } + +- return AVERROR(EAGAIN); ++ frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref); ++ if (!frame->hw_frames_ctx) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ return 0; + + fail: + if (mppframe) +@@ -494,60 +438,130 @@ fail: + return ret; + } + ++static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *packet) ++{ ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ MppPacket mpkt; ++ int64_t pts = packet->pts; ++ int ret; ++ ++ // avoid sending new data after EOS ++ if (decoder->draining) ++ return AVERROR_EOF; ++ ++ if (!pts || pts == AV_NOPTS_VALUE) ++ pts = avctx->reordered_opaque; ++ ++ ret = mpp_packet_init(&mpkt, packet->data, packet->size); ++ if (ret != MPP_OK) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to init MPP packet (code = %d)\n", ret); ++ return AVERROR_UNKNOWN; ++ } ++ ++ mpp_packet_set_pts(mpkt, pts); ++ ++ ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt); ++ mpp_packet_deinit(&mpkt); ++ ++ if (ret != MPP_OK) { ++ av_log(avctx, AV_LOG_DEBUG, "Buffer full\n"); ++ return AVERROR(EAGAIN); ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "Wrote %d bytes to decoder\n", packet->size); ++ return 0; ++} ++ ++static int rkmpp_send_eos(AVCodecContext *avctx) ++{ ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ MppPacket mpkt; ++ int ret; ++ ++ ret = mpp_packet_init(&mpkt, NULL, 0); ++ if (ret != MPP_OK) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to init EOS packet (code = %d)\n", ret); ++ return AVERROR_UNKNOWN; ++ } ++ ++ mpp_packet_set_eos(mpkt); ++ ++ do { ++ ret = decoder->mpi->decode_put_packet(decoder->ctx, mpkt); ++ } while (ret != MPP_OK); ++ mpp_packet_deinit(&mpkt); ++ ++ decoder->draining = 1; ++ ++ return 0; ++} ++ + static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- int ret = MPP_NOK; +- AVPacket pkt = {0}; +- RK_S32 usedslots, freeslots; +- +- if (!decoder->eos_reached) { +- // we get the available slots in decoder +- ret = decoder->mpi->control(decoder->ctx, MPP_DEC_GET_STREAM_COUNT, &usedslots); +- if (ret != MPP_OK) { +- av_log(avctx, AV_LOG_ERROR, "Failed to get decoder used slots (code = %d).\n", ret); +- return ret; +- } ++ AVPacket *packet = &decoder->packet; ++ int ret; + +- freeslots = INPUT_MAX_PACKETS - usedslots; +- if (freeslots > 0) { +- ret = ff_decode_get_packet(avctx, &pkt); +- if (ret < 0 && ret != AVERROR_EOF) { ++ // no more frames after EOS ++ if (decoder->eos) ++ return AVERROR_EOF; ++ ++ // draining remain frames ++ if (decoder->draining) ++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK); ++ ++ while (1) { ++ if (!packet->size) { ++ ret = ff_decode_get_packet(avctx, packet); ++ if (ret == AVERROR_EOF) { ++ av_log(avctx, AV_LOG_DEBUG, "End of stream.\n"); ++ // send EOS and start draining ++ rkmpp_send_eos(avctx); ++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK); ++ } else if (ret == AVERROR(EAGAIN)) { ++ // not blocking so that we can feed new data ASAP ++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_NON_BLOCK); ++ } else if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to get packet (code = %d)\n", ret); + return ret; + } +- +- ret = rkmpp_send_packet(avctx, &pkt); +- av_packet_unref(&pkt); +- +- if (ret < 0) { +- av_log(avctx, AV_LOG_ERROR, "Failed to send packet to decoder (code = %d)\n", ret); ++ } else { ++ // send pending data to decoder ++ ret = rkmpp_send_packet(avctx, packet); ++ if (ret == AVERROR(EAGAIN)) { ++ // some streams might need more packets to start returning frames ++ ret = rkmpp_get_frame(avctx, frame, 1); ++ if (ret != AVERROR(EAGAIN)) ++ return ret; ++ } else if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to send data (code = %d)\n", ret); + return ret; ++ } else { ++ av_packet_unref(packet); ++ packet->size = 0; + } + } +- +- // make sure we keep decoder full +- if (freeslots > 1) +- return AVERROR(EAGAIN); + } +- +- return rkmpp_retrieve_frame(avctx, frame); + } + + static void rkmpp_flush(AVCodecContext *avctx) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- int ret = MPP_NOK; + + av_log(avctx, AV_LOG_DEBUG, "Flush.\n"); + +- ret = decoder->mpi->reset(decoder->ctx); +- if (ret == MPP_OK) { +- decoder->first_packet = 1; +- decoder->eos_reached = 0; +- } else +- av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret); ++ decoder->mpi->reset(decoder->ctx); ++ ++ rkmpp_prepare_decoder(avctx); ++ ++ decoder->eos = 0; ++ decoder->draining = 0; ++ ++ av_packet_unref(&decoder->packet); + } + + static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { +-- +2.39.0 + + +From 3f94c029c3eeca764c63e32435e8ca8241a87dfc Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Fri, 21 May 2021 04:23:36 +0800 +Subject: [PATCH 05/16] HACK: avcodec/rkmppdec: Force aligning coded width and + height to 64 + +The chromium would try to align planes' width and height to 32, which +might break the plane buffers' contiguous required by RGA. + +Passing a 64-aligned coded width and height to avoid that. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 7c28378120..bae3ca6cb5 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -309,6 +309,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + avctx->width = mpp_frame_get_width(mppframe); + avctx->height = mpp_frame_get_height(mppframe); + ++ // chromium would align planes' width and height to 32, adding this ++ // hack to avoid breaking the plane buffers' contiguous. ++ avctx->coded_width = FFALIGN(avctx->width, 64); ++ avctx->coded_height = FFALIGN(avctx->height, 64); ++ + decoder->mpi->control(decoder->ctx, MPP_DEC_SET_FRAME_INFO, (MppParam) mppframe); + decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + +-- +2.39.0 + + +From 804808de6c6af583b71526ff9e11196e1515e542 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Thu, 20 May 2021 10:20:17 +0800 +Subject: [PATCH 06/16] HACK: avcodec/rkmppdec: Support outputing YUV420P + +Lots of users support YUV420P format rather than DRM_PRIME. + +Support RGA accelerated format conversion. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + configure | 7 ++- + libavcodec/rkmppdec.c | 120 +++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 125 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index 89af70d72f..9e08481e11 100755 +--- a/configure ++++ b/configure +@@ -345,6 +345,7 @@ External library support: + --enable-omx enable OpenMAX IL code [no] + --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] + --enable-rkmpp enable Rockchip Media Process Platform code [no] ++ --enable-librga enable Rockchip RGA 2D accel via librga [autodetect] + --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect] + --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] + --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] +@@ -1848,6 +1849,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" + videotoolbox + v4l2_m2m + xvmc ++ librga + " + + # catchall list of things that require external libs to link +@@ -6539,10 +6541,13 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP + check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || + die "ERROR: openssl not found"; } + enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init ++enabled librga && check_lib librga rga/RgaApi.h c_RkRgaInit -lrga && prepend rkmpp_deps "librga" + enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create && + require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create && + { enabled libdrm || +- die "ERROR: rkmpp requires --enable-libdrm"; } ++ die "ERROR: rkmpp requires --enable-libdrm"; } && ++ { enabled librga || ++ warn "using rkmpp without librga"; } + } + enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index bae3ca6cb5..c621e687e0 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -38,6 +38,11 @@ + #include "libavutil/imgutils.h" + #include "libavutil/log.h" + ++#if CONFIG_LIBRGA ++#include <rga/rga.h> ++#include <rga/RgaApi.h> ++#endif ++ + typedef struct { + MppCtx ctx; + MppApi *mpi; +@@ -83,6 +88,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat) + } + } + ++#if CONFIG_LIBRGA ++static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat) ++{ ++ switch (mppformat) { ++ case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP; ++ case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B; ++ default: return RK_FORMAT_UNKNOWN; ++ } ++} ++#endif ++ + static int rkmpp_close_decoder(AVCodecContext *avctx) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; +@@ -142,7 +158,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + MppCodingType codectype = MPP_VIDEO_CodingUnused; + int ret; + +- avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; ++ avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); + + // create a decoder and a ref to it + decoder = av_mallocz(sizeof(RKMPPDecoder)); +@@ -248,6 +264,95 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data) + av_free(desc); + } + ++static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame, ++ MppFrame mppframe, MppBuffer buffer) ++{ ++ char *src = mpp_buffer_get_ptr(buffer); ++ char *dst_y = frame->data[0]; ++ char *dst_u = frame->data[1]; ++ char *dst_v = frame->data[2]; ++#if CONFIG_LIBRGA ++ RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe)); ++#endif ++ int width = mpp_frame_get_width(mppframe); ++ int height = mpp_frame_get_height(mppframe); ++ int hstride = mpp_frame_get_hor_stride(mppframe); ++ int vstride = mpp_frame_get_ver_stride(mppframe); ++ int y_pitch = frame->linesize[0]; ++ int u_pitch = frame->linesize[1]; ++ int v_pitch = frame->linesize[2]; ++ int i, j; ++ ++#if CONFIG_LIBRGA ++ rga_info_t src_info = {0}; ++ rga_info_t dst_info = {0}; ++ int dst_height = (dst_u - dst_y) / y_pitch; ++ ++ static int rga_supported = 1; ++ static int rga_inited = 0; ++ ++ if (!rga_supported) ++ goto bail; ++ ++ if (!rga_inited) { ++ if (c_RkRgaInit() < 0) { ++ rga_supported = 0; ++ av_log(avctx, AV_LOG_WARNING, "RGA not available\n"); ++ goto bail; ++ } ++ rga_inited = 1; ++ } ++ ++ if (format == RK_FORMAT_UNKNOWN) ++ goto bail; ++ ++ if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 || ++ dst_u != dst_y + y_pitch * dst_height || ++ dst_v != dst_u + u_pitch * dst_height / 2) ++ goto bail; ++ ++ src_info.fd = mpp_buffer_get_fd(buffer); ++ src_info.mmuFlag = 1; ++ rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride, ++ format); ++ ++ dst_info.virAddr = dst_y; ++ dst_info.mmuFlag = 1; ++ rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height, ++ y_pitch, dst_height, RK_FORMAT_YCbCr_420_P); ++ ++ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) ++ goto bail; ++ ++ return 0; ++ ++bail: ++#endif ++ if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) { ++ av_log(avctx, AV_LOG_WARNING, "Unable to convert\n"); ++ return -1; ++ } ++ ++ av_log(avctx, AV_LOG_WARNING, "Doing slow software conversion\n"); ++ ++ for (i = 0; i < frame->height; i++) ++ memcpy(dst_y + i * y_pitch, src + i * hstride, frame->width); ++ ++ src += hstride * vstride; ++ ++ for (i = 0; i < frame->height / 2; i++) { ++ for (j = 0; j < frame->width; j++) { ++ dst_u[j] = src[2 * j + 0]; ++ dst_v[j] = src[2 * j + 1]; ++ } ++ dst_u += u_pitch; ++ dst_v += v_pitch; ++ src += hstride; ++ } ++ ++ return 0; ++} ++ + static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; +@@ -355,6 +460,16 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + frame->format = avctx->pix_fmt; + frame->width = mpp_frame_get_width(mppframe); + frame->height = mpp_frame_get_height(mppframe); ++ ++ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) { ++ ret = ff_get_buffer(avctx, frame, 0); ++ if (ret < 0) ++ goto out; ++ ++ ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer); ++ goto out; ++ } ++ + frame->pts = mpp_frame_get_pts(mppframe); + #if FF_API_PKT_PTS + FF_DISABLE_DEPRECATION_WARNINGS; +@@ -427,6 +542,7 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + + return 0; + ++out: + fail: + if (mppframe) + mpp_frame_deinit(&mppframe); +@@ -571,6 +687,7 @@ static void rkmpp_flush(AVCodecContext *avctx) + + static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { + HW_CONFIG_INTERNAL(DRM_PRIME), ++ HW_CONFIG_INTERNAL(YUV420P), + NULL + }; + +@@ -595,6 +712,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { + .priv_class = &rkmpp_##NAME##_dec_class, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ ++ AV_PIX_FMT_YUV420P, \ + AV_PIX_FMT_NONE}, \ + .hw_configs = rkmpp_hw_configs, \ + .bsfs = BSFS, \ +-- +2.39.0 + + +From ad6f4d3518eea4795f457b81d44d27da943be982 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Mon, 27 Sep 2021 10:20:54 +0800 +Subject: [PATCH 07/16] avcodec/rkmppdec: Support logging fps + +Set env FFMPEG_RKMPP_LOG_FPS=1 to enable it. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 46 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index c621e687e0..82834c27a6 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -25,6 +25,7 @@ + #include <rockchip/rk_mpi.h> + #include <time.h> + #include <unistd.h> ++#include <sys/time.h> + + #include "avcodec.h" + #include "decode.h" +@@ -43,6 +44,8 @@ + #include <rga/RgaApi.h> + #endif + ++#define FPS_UPDATE_INTERVAL 120 ++ + typedef struct { + MppCtx ctx; + MppApi *mpi; +@@ -54,6 +57,11 @@ typedef struct { + AVPacket packet; + AVBufferRef *frames_ref; + AVBufferRef *device_ref; ++ ++ char print_fps; ++ ++ uint64_t last_fps_time; ++ uint64_t frames; + } RKMPPDecoder; + + typedef struct { +@@ -156,6 +164,7 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + RKMPPDecodeContext *rk_context = avctx->priv_data; + RKMPPDecoder *decoder = NULL; + MppCodingType codectype = MPP_VIDEO_CodingUnused; ++ char *env; + int ret; + + avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); +@@ -167,6 +176,10 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + ++ env = getenv("FFMPEG_RKMPP_LOG_FPS"); ++ if (env != NULL) ++ decoder->print_fps = !!atoi(env); ++ + rk_context->decoder_ref = av_buffer_create((uint8_t *)decoder, sizeof(*decoder), rkmpp_release_decoder, + NULL, AV_BUFFER_FLAG_READONLY); + if (!rk_context->decoder_ref) { +@@ -353,6 +366,36 @@ bail: + return 0; + } + ++static void rkmpp_update_fps(AVCodecContext *avctx) ++{ ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ struct timeval tv; ++ uint64_t curr_time; ++ float fps; ++ ++ if (!decoder->print_fps) ++ return; ++ ++ if (!decoder->last_fps_time) { ++ gettimeofday(&tv, NULL); ++ decoder->last_fps_time = tv.tv_sec * 1000 + tv.tv_usec / 1000; ++ } ++ ++ if (++decoder->frames % FPS_UPDATE_INTERVAL) ++ return; ++ ++ gettimeofday(&tv, NULL); ++ curr_time = tv.tv_sec * 1000 + tv.tv_usec / 1000; ++ ++ fps = 1000.0f * FPS_UPDATE_INTERVAL / (curr_time - decoder->last_fps_time); ++ decoder->last_fps_time = curr_time; ++ ++ av_log(avctx, AV_LOG_INFO, ++ "[FFMPEG RKMPP] FPS: %6.1f || Frames: %" PRIu64 "\n", ++ fps, decoder->frames); ++} ++ + static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; +@@ -456,6 +499,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + goto fail; + } + ++ rkmpp_update_fps(avctx); ++ + // setup general frame fields + frame->format = avctx->pix_fmt; + frame->width = mpp_frame_get_width(mppframe); +@@ -681,6 +726,7 @@ static void rkmpp_flush(AVCodecContext *avctx) + + decoder->eos = 0; + decoder->draining = 0; ++ decoder->last_fps_time = decoder->frames = 0; + + av_packet_unref(&decoder->packet); + } +-- +2.39.0 + + +From 8b7cfe72359520a7f1cae3b3ce935a2ea549f705 Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Thu, 5 Jan 2023 22:41:48 +0100 +Subject: [PATCH 08/16] HACK: libavcodec & rkmppdec: Add + FF_CODEC_CAP_CONTIGUOUS_BUFFERS + +Add FF_CODEC_CAP_CONTIGUOUS_BUFFERS to alloc contiguous buffers. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/decode.c | 23 +++++++++++++++++++++++ + libavcodec/internal.h | 4 ++++ + libavcodec/rkmppdec.c | 19 ++++++++++--------- + 3 files changed, 37 insertions(+), 9 deletions(-) + +diff --git a/libavcodec/decode.c b/libavcodec/decode.c +index 936e5d63da..dfd9ed656d 100644 +--- a/libavcodec/decode.c ++++ b/libavcodec/decode.c +@@ -1549,6 +1549,14 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) + + for (i = 0; i < 4; i++) { + pool->linesize[i] = linesize[i]; ++ ++ if (avctx->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) { ++ if (!i) ++ size[0] += size[1] + size[2] + size[3]; ++ else ++ continue; ++ } ++ + if (size[i]) { + if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) { + ret = AVERROR(EINVAL); +@@ -1675,6 +1683,21 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) + + pic->data[i] = pic->buf[i]->data; + } ++ ++ if (s->codec->caps_internal & FF_CODEC_CAP_CONTIGUOUS_BUFFERS) { ++ int size; ++ ++ for (i = 1; i < 4; i++) { ++ pic->linesize[i] = pool->linesize[i]; ++ av_buffer_unref(pic->buf[i]); ++ } ++ ++ size = av_image_fill_pointers(pic->data, pic->format, pic->height, ++ pic->buf[0]->data, pic->linesize); ++ if (size < 0 || size > pic->buf[0]->size) ++ goto fail; ++ } ++ + for (; i < AV_NUM_DATA_POINTERS; i++) { + pic->data[i] = NULL; + pic->linesize[i] = 0; +diff --git a/libavcodec/internal.h b/libavcodec/internal.h +index d889c1883e..47e6a1d13b 100644 +--- a/libavcodec/internal.h ++++ b/libavcodec/internal.h +@@ -89,6 +89,10 @@ + */ + #define FF_CODEC_TAGS_END -1 + ++/** ++ * The decoder requires contiguous buffers. ++ */ ++#define FF_CODEC_CAP_CONTIGUOUS_BUFFERS (1 << 31) + + #ifdef TRACE + # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 82834c27a6..a05c77977d 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -501,20 +501,15 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + + rkmpp_update_fps(avctx); + +- // setup general frame fields +- frame->format = avctx->pix_fmt; +- frame->width = mpp_frame_get_width(mppframe); +- frame->height = mpp_frame_get_height(mppframe); +- + if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) { + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + goto out; +- +- ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer); +- goto out; + } +- ++ // setup general frame fields ++ frame->format = avctx->pix_fmt; ++ frame->width = mpp_frame_get_width(mppframe); ++ frame->height = mpp_frame_get_height(mppframe); + frame->pts = mpp_frame_get_pts(mppframe); + #if FF_API_PKT_PTS + FF_DISABLE_DEPRECATION_WARNINGS; +@@ -531,6 +526,11 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED); + frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); + ++ if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) { ++ ret = rkmpp_convert_frame(avctx, frame, mppframe, buffer); ++ goto out; ++ } ++ + mppformat = mpp_frame_get_fmt(mppframe); + drmformat = rkmpp_get_frameformat(mppformat); + +@@ -757,6 +757,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { + .flush = rkmpp_flush, \ + .priv_class = &rkmpp_##NAME##_dec_class, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ ++ .caps_internal = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ + AV_PIX_FMT_YUV420P, \ + AV_PIX_FMT_NONE}, \ +-- +2.39.0 + + +From d1ab43ce9ccb0b832dc1bd620785a1a455e15bed Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Mon, 13 Dec 2021 15:44:43 +0800 +Subject: [PATCH 09/16] HACK: avcodec/rkmppdec: Define DRM_FORMAT_NV12_10 + +DRM_FORMAT_NV12_10 is a downstream custom format for Rockchip. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index a05c77977d..2aa3ee2a30 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -44,6 +44,10 @@ + #include <rga/RgaApi.h> + #endif + ++#ifndef DRM_FORMAT_NV12_10 ++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2') ++#endif ++ + #define FPS_UPDATE_INTERVAL 120 + + typedef struct { +@@ -89,9 +93,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat) + { + switch (mppformat) { + case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12; +-#ifdef DRM_FORMAT_NV12_10 + case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV12_10; +-#endif + default: return 0; + } + } +-- +2.39.0 + + +From 486ff6b9a813c48bca125b04a33088c5b3bf512d Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Wed, 15 Dec 2021 15:34:48 +0800 +Subject: [PATCH 10/16] avcodec/rkmppdec: Support NV16 + +The MPP might output NV16 format. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 2aa3ee2a30..82288cad03 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -94,6 +94,17 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat) + switch (mppformat) { + case MPP_FMT_YUV420SP: return DRM_FORMAT_NV12; + case MPP_FMT_YUV420SP_10BIT: return DRM_FORMAT_NV12_10; ++ case MPP_FMT_YUV422SP: return DRM_FORMAT_NV16; ++ default: return 0; ++ } ++} ++ ++static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat) ++{ ++ switch (mppformat) { ++ case MPP_FMT_YUV420SP: return AV_PIX_FMT_NV12; ++ case MPP_FMT_YUV420SP_10BIT: return AV_PIX_FMT_NONE; ++ case MPP_FMT_YUV422SP: return AV_PIX_FMT_NV16; + default: return 0; + } + } +@@ -104,6 +115,7 @@ static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat) + switch (mppformat) { + case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP; + case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B; ++ case MPP_FMT_YUV422SP: return RK_FORMAT_YCbCr_422_SP; + default: return RK_FORMAT_UNKNOWN; + } + } +@@ -476,11 +488,10 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + } + + mppformat = mpp_frame_get_fmt(mppframe); +- drmformat = rkmpp_get_frameformat(mppformat); + + hwframes = (AVHWFramesContext*)decoder->frames_ref->data; + hwframes->format = AV_PIX_FMT_DRM_PRIME; +- hwframes->sw_format = drmformat == DRM_FORMAT_NV12 ? AV_PIX_FMT_NV12 : AV_PIX_FMT_NONE; ++ hwframes->sw_format = rkmpp_get_avformat(mppformat); + hwframes->width = avctx->width; + hwframes->height = avctx->height; + ret = av_hwframe_ctx_init(decoder->frames_ref); +-- +2.39.0 + + +From 7bf50d04f27c963a1bac402beb04f8f13a3773a4 Mon Sep 17 00:00:00 2001 +From: Jeffy Chen <jeffy.chen@rock-chips.com> +Date: Wed, 23 Mar 2022 14:20:16 +0800 +Subject: [PATCH 11/16] avcodec/rkmppdec: Support sync mode + +Some people just don't know how to handle async APIs :( + +Support sync mode by waiting for decode result after feeding any packets. + +Set env "FFMPEG_RKMPP_SYNC" to enable it. + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + libavcodec/rkmppdec.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 82288cad03..c8b400e910 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -66,6 +66,8 @@ typedef struct { + + uint64_t last_fps_time; + uint64_t frames; ++ ++ char sync; + } RKMPPDecoder; + + typedef struct { +@@ -170,6 +172,13 @@ static int rkmpp_prepare_decoder(AVCodecContext *avctx) + if (ret < 0) + return AVERROR_UNKNOWN; + } ++ ++ if (getenv("FFMPEG_RKMPP_SYNC")) { ++ // wait for decode result after feeding any packets ++ decoder->sync = 1; ++ ret = 1; ++ decoder->mpi->control(decoder->ctx, MPP_DEC_SET_IMMEDIATE_OUT, &ret); ++ } + return 0; + } + +@@ -721,6 +730,10 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame) + } else { + av_packet_unref(packet); + packet->size = 0; ++ ++ // blocked waiting for decode result ++ if (decoder->sync) ++ return rkmpp_get_frame(avctx, frame, MPP_TIMEOUT_BLOCK); + } + } + } +-- +2.39.0 + + +From 8725010e4431bc5f8933e0389b195ba7f8a8fa46 Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Thu, 5 Jan 2023 23:04:45 +0100 +Subject: [PATCH 12/16] avcodec/rkmppdec: Add H263/MPEG1/MPEG2/MPEG4 + +Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> +--- + configure | 4 ++++ + libavcodec/Makefile | 4 ++++ + libavcodec/allcodecs.c | 4 ++++ + libavcodec/rkmppdec.c | 8 ++++++++ + 4 files changed, 20 insertions(+) + +diff --git a/configure b/configure +index 9e08481e11..6e72375e09 100755 +--- a/configure ++++ b/configure +@@ -3074,6 +3074,7 @@ ac3_mf_encoder_deps="mediafoundation" + av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS" + h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" + h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" ++h263_rkmpp_decoder_deps="rkmpp" + h264_amf_encoder_deps="amf" + h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" + h264_cuvid_decoder_deps="cuvid" +@@ -3119,6 +3120,7 @@ mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode" + mp3_mf_encoder_deps="mediafoundation" + mpeg1_cuvid_decoder_deps="cuvid" + mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m" ++mpeg1_rkmpp_decoder_deps="rkmpp" + mpeg2_crystalhd_decoder_select="crystalhd" + mpeg2_cuvid_decoder_deps="cuvid" + mpeg2_mmal_decoder_deps="mmal" +@@ -3127,6 +3129,7 @@ mpeg2_qsv_decoder_select="qsvdec" + mpeg2_qsv_encoder_select="qsvenc" + mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" + mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" ++mpeg2_rkmpp_decoder_deps="rkmpp" + mpeg4_crystalhd_decoder_select="crystalhd" + mpeg4_cuvid_decoder_deps="cuvid" + mpeg4_mediacodec_decoder_deps="mediacodec" +@@ -3134,6 +3137,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_rkmpp_decoder_deps="rkmpp" + msmpeg4_crystalhd_decoder_select="crystalhd" + nvenc_h264_encoder_select="h264_nvenc_encoder" + nvenc_hevc_encoder_select="hevc_nvenc_encoder" +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index b3d284d7d0..345b6a5816 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -364,6 +364,7 @@ OBJS-$(CONFIG_H263_ENCODER) += mpeg4video.o \ + h263.o ituh263enc.o h263data.o + OBJS-$(CONFIG_H263_V4L2M2M_DECODER) += v4l2_m2m_dec.o + OBJS-$(CONFIG_H263_V4L2M2M_ENCODER) += v4l2_m2m_enc.o ++OBJS-$(CONFIG_H263_RKMPP_DECODER) += rkmppdec.o + OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ + h264_direct.o h264_loopfilter.o \ + h264_mb.o h264_picture.o \ +@@ -488,6 +489,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o + OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o + OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o + OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o ++OBJS-$(CONFIG_MPEG1_RKMPP_DECODER) += rkmppdec.o + OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o + OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec.o + OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o +@@ -497,6 +499,7 @@ OBJS-$(CONFIG_MPEG2_CUVID_DECODER) += cuviddec.o + OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o + OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o + OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o ++OBJS-$(CONFIG_MPEG2_RKMPP_DECODER) += rkmppdec.o + OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o + OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o + OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o +@@ -504,6 +507,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_RKMPP_DECODER) += rkmppdec.o + OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o + OBJS-$(CONFIG_MSA1_DECODER) += mss3.o + OBJS-$(CONFIG_MSCC_DECODER) += mscc.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index 2e9a3581de..5b2d8abe80 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -140,6 +140,7 @@ extern AVCodec ff_h263_decoder; + extern AVCodec ff_h263i_decoder; + extern AVCodec ff_h263p_encoder; + extern AVCodec ff_h263p_decoder; ++extern AVCodec ff_h263_rkmpp_decoder; + extern AVCodec ff_h263_v4l2m2m_decoder; + extern AVCodec ff_h264_decoder; + extern AVCodec ff_h264_crystalhd_decoder; +@@ -199,11 +200,14 @@ extern AVCodec ff_mpeg2video_decoder; + extern AVCodec ff_mpeg4_encoder; + extern AVCodec ff_mpeg4_decoder; + extern AVCodec ff_mpeg4_crystalhd_decoder; ++extern AVCodec ff_mpeg4_rkmpp_decoder; + extern AVCodec ff_mpeg4_v4l2m2m_decoder; + extern AVCodec ff_mpeg4_mmal_decoder; + extern AVCodec ff_mpegvideo_decoder; ++extern AVCodec ff_mpeg1_rkmpp_decoder; + extern AVCodec ff_mpeg1_v4l2m2m_decoder; + extern AVCodec ff_mpeg2_mmal_decoder; ++extern AVCodec ff_mpeg2_rkmpp_decoder; + extern AVCodec ff_mpeg2_crystalhd_decoder; + extern AVCodec ff_mpeg2_v4l2m2m_decoder; + extern AVCodec ff_mpeg2_qsv_decoder; +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index c8b400e910..79baab932d 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -83,10 +83,14 @@ typedef struct { + static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx) + { + switch (avctx->codec_id) { ++ case AV_CODEC_ID_H263: return MPP_VIDEO_CodingH263; + case AV_CODEC_ID_H264: return MPP_VIDEO_CodingAVC; + case AV_CODEC_ID_HEVC: return MPP_VIDEO_CodingHEVC; + case AV_CODEC_ID_VP8: return MPP_VIDEO_CodingVP8; + case AV_CODEC_ID_VP9: return MPP_VIDEO_CodingVP9; ++ case AV_CODEC_ID_MPEG1VIDEO: /* fallthrough */ ++ case AV_CODEC_ID_MPEG2VIDEO: return MPP_VIDEO_CodingMPEG2; ++ case AV_CODEC_ID_MPEG4: return MPP_VIDEO_CodingMPEG4; + default: return MPP_VIDEO_CodingUnused; + } + } +@@ -792,7 +796,11 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { + .wrapper_name = "rkmpp", \ + }; + ++RKMPP_DEC(h263, AV_CODEC_ID_H263, NULL) + RKMPP_DEC(h264, AV_CODEC_ID_H264, "h264_mp4toannexb") + RKMPP_DEC(hevc, AV_CODEC_ID_HEVC, "hevc_mp4toannexb") + RKMPP_DEC(vp8, AV_CODEC_ID_VP8, NULL) + RKMPP_DEC(vp9, AV_CODEC_ID_VP9, NULL) ++RKMPP_DEC(mpeg1, AV_CODEC_ID_MPEG1VIDEO, NULL) ++RKMPP_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO, NULL) ++RKMPP_DEC(mpeg4, AV_CODEC_ID_MPEG4, "mpeg4_unpack_bframes") +-- +2.39.0 + + +From a1795f4a3ea85a4b499765a66427db8d39c844da Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Fri, 6 Jan 2023 20:39:23 +0100 +Subject: [PATCH 13/16] allow nv15 and allow probing + +--- + libavcodec/rkmppdec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 79baab932d..93c426eeb3 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -45,7 +45,7 @@ + #endif + + #ifndef DRM_FORMAT_NV12_10 +-#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '2') ++#define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5') + #endif + + #define FPS_UPDATE_INTERVAL 120 +@@ -786,7 +786,7 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { + .receive_frame = rkmpp_receive_frame, \ + .flush = rkmpp_flush, \ + .priv_class = &rkmpp_##NAME##_dec_class, \ +- .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ ++ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ + .caps_internal = FF_CODEC_CAP_CONTIGUOUS_BUFFERS, \ + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ + AV_PIX_FMT_YUV420P, \ +-- +2.39.0 + + +From 73f8dc251ae7111b2f8ce9c4084071e157765e33 Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Fri, 6 Jan 2023 21:36:04 +0100 +Subject: [PATCH 14/16] priotrize the rkmpp variants first + +--- + libavcodec/allcodecs.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index 5b2d8abe80..409e7f33e4 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -135,25 +135,25 @@ extern AVCodec ff_gif_encoder; + extern AVCodec ff_gif_decoder; + extern AVCodec ff_h261_encoder; + extern AVCodec ff_h261_decoder; ++extern AVCodec ff_h263_rkmpp_decoder; + extern AVCodec ff_h263_encoder; + extern AVCodec ff_h263_decoder; + extern AVCodec ff_h263i_decoder; + extern AVCodec ff_h263p_encoder; + extern AVCodec ff_h263p_decoder; +-extern AVCodec ff_h263_rkmpp_decoder; + extern AVCodec ff_h263_v4l2m2m_decoder; ++extern AVCodec ff_h264_rkmpp_decoder; + extern AVCodec ff_h264_decoder; + extern AVCodec ff_h264_crystalhd_decoder; + extern AVCodec ff_h264_v4l2m2m_decoder; + extern AVCodec ff_h264_mediacodec_decoder; + extern AVCodec ff_h264_mmal_decoder; + extern AVCodec ff_h264_qsv_decoder; +-extern AVCodec ff_h264_rkmpp_decoder; + extern AVCodec ff_hap_encoder; + extern AVCodec ff_hap_decoder; ++extern AVCodec ff_hevc_rkmpp_decoder; + extern AVCodec ff_hevc_decoder; + extern AVCodec ff_hevc_qsv_decoder; +-extern AVCodec ff_hevc_rkmpp_decoder; + extern AVCodec ff_hevc_v4l2m2m_decoder; + extern AVCodec ff_hnm4_video_decoder; + extern AVCodec ff_hq_hqa_decoder; +@@ -193,21 +193,21 @@ extern AVCodec ff_mjpegb_decoder; + extern AVCodec ff_mmvideo_decoder; + extern AVCodec ff_mobiclip_decoder; + extern AVCodec ff_motionpixels_decoder; ++extern AVCodec ff_mpeg1_rkmpp_decoder; + extern AVCodec ff_mpeg1video_encoder; + extern AVCodec ff_mpeg1video_decoder; + extern AVCodec ff_mpeg2video_encoder; + extern AVCodec ff_mpeg2video_decoder; ++extern AVCodec ff_mpeg4_rkmpp_decoder; + extern AVCodec ff_mpeg4_encoder; + extern AVCodec ff_mpeg4_decoder; + extern AVCodec ff_mpeg4_crystalhd_decoder; +-extern AVCodec ff_mpeg4_rkmpp_decoder; + extern AVCodec ff_mpeg4_v4l2m2m_decoder; + extern AVCodec ff_mpeg4_mmal_decoder; + extern AVCodec ff_mpegvideo_decoder; +-extern AVCodec ff_mpeg1_rkmpp_decoder; + extern AVCodec ff_mpeg1_v4l2m2m_decoder; +-extern AVCodec ff_mpeg2_mmal_decoder; + extern AVCodec ff_mpeg2_rkmpp_decoder; ++extern AVCodec ff_mpeg2_mmal_decoder; + extern AVCodec ff_mpeg2_crystalhd_decoder; + extern AVCodec ff_mpeg2_v4l2m2m_decoder; + extern AVCodec ff_mpeg2_qsv_decoder; +@@ -360,11 +360,11 @@ extern AVCodec ff_vp6_decoder; + extern AVCodec ff_vp6a_decoder; + extern AVCodec ff_vp6f_decoder; + extern AVCodec ff_vp7_decoder; +-extern AVCodec ff_vp8_decoder; + extern AVCodec ff_vp8_rkmpp_decoder; ++extern AVCodec ff_vp8_decoder; + extern AVCodec ff_vp8_v4l2m2m_decoder; +-extern AVCodec ff_vp9_decoder; + extern AVCodec ff_vp9_rkmpp_decoder; ++extern AVCodec ff_vp9_decoder; + extern AVCodec ff_vp9_v4l2m2m_decoder; + extern AVCodec ff_vqa_decoder; + extern AVCodec ff_webp_decoder; +-- +2.39.0 + + +From 15cc4a4c861e6c0cb527e023332d875a75b6b732 Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Fri, 13 Jan 2023 22:27:01 +0100 +Subject: [PATCH 15/16] rkmpp: interface with kernel directly for rga and ditch + librga + +credit goes to icecream95: https://gitlab.com/-/snippets/2460396 +--- + libavcodec/rga.h | 574 ++++++++++++++++++++++++++++++++++++++++++ + libavcodec/rkmppdec.c | 272 ++++++++++++++++---- + 2 files changed, 803 insertions(+), 43 deletions(-) + create mode 100644 libavcodec/rga.h + +diff --git a/libavcodec/rga.h b/libavcodec/rga.h +new file mode 100644 +index 0000000000..9595558de0 +--- /dev/null ++++ b/libavcodec/rga.h +@@ -0,0 +1,574 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _RGA_DRIVER_H_ ++#define _RGA_DRIVER_H_ ++ ++/* Use 'r' as magic number */ ++#define RGA_IOC_MAGIC 'r' ++#define RGA_IOW(nr, type) _IOW(RGA_IOC_MAGIC, nr, type) ++#define RGA_IOR(nr, type) _IOR(RGA_IOC_MAGIC, nr, type) ++#define RGA_IOWR(nr, type) _IOWR(RGA_IOC_MAGIC, nr, type) ++ ++#define RGA_IOC_GET_DRVIER_VERSION RGA_IOR(0x1, struct rga_version_t) ++#define RGA_IOC_GET_HW_VERSION RGA_IOR(0x2, struct rga_hw_versions_t) ++#define RGA_IOC_IMPORT_BUFFER RGA_IOWR(0x3, struct rga_buffer_pool) ++#define RGA_IOC_RELEASE_BUFFER RGA_IOW(0x4, struct rga_buffer_pool) ++#define RGA_IOC_REQUEST_CREATE RGA_IOR(0x5, uint32_t) ++#define RGA_IOC_REQUEST_SUBMIT RGA_IOWR(0x6, struct rga_user_request) ++#define RGA_IOC_REQUEST_CONFIG RGA_IOWR(0x7, struct rga_user_request) ++#define RGA_IOC_REQUEST_CANCEL RGA_IOWR(0x8, uint32_t) ++ ++#define RGA_BLIT_SYNC 0x5017 ++#define RGA_BLIT_ASYNC 0x5018 ++#define RGA_FLUSH 0x5019 ++#define RGA_GET_RESULT 0x501a ++#define RGA_GET_VERSION 0x501b ++#define RGA_CACHE_FLUSH 0x501c ++ ++#define RGA2_GET_VERSION 0x601b ++#define RGA_IMPORT_DMA 0x601d ++#define RGA_RELEASE_DMA 0x601e ++ ++#define RGA_TASK_NUM_MAX 50 ++ ++#define RGA_OUT_OF_RESOURCES -10 ++#define RGA_MALLOC_ERROR -11 ++ ++#define SCALE_DOWN_LARGE 1 ++#define SCALE_UP_LARGE 1 ++ ++#define RGA_BUFFER_POOL_SIZE_MAX 40 ++ ++#define RGA3_MAJOR_VERSION_MASK (0xF0000000) ++#define RGA3_MINOR_VERSION_MASK (0x0FF00000) ++#define RGA3_SVN_VERSION_MASK (0x000FFFFF) ++ ++#define RGA2_MAJOR_VERSION_MASK (0xFF000000) ++#define RGA2_MINOR_VERSION_MASK (0x00F00000) ++#define RGA2_SVN_VERSION_MASK (0x000FFFFF) ++ ++#define RGA_MODE_ROTATE_0 (1<<0) ++#define RGA_MODE_ROTATE_90 (1<<1) ++#define RGA_MODE_ROTATE_180 (1<<2) ++#define RGA_MODE_ROTATE_270 (1<<3) ++#define RGA_MODE_X_MIRROR (1<<4) ++#define RGA_MODE_Y_MIRROR (1<<5) ++ ++#define RGA_MODE_CSC_BT601L (1<<0) ++#define RGA_MODE_CSC_BT601F (1<<1) ++#define RGA_MODE_CSC_BT709 (1<<2) ++#define RGA_MODE_CSC_BT2020 (1<<3) ++ ++#define RGA_MODE_ROTATE_MASK (\ ++ RGA_MODE_ROTATE_0 | \ ++ RGA_MODE_ROTATE_90 | \ ++ RGA_MODE_ROTATE_180 | \ ++ RGA_MODE_ROTATE_270 | \ ++ RGA_MODE_X_MIRROR | \ ++ RGA_MODE_Y_MIRROR) ++ ++enum rga_memory_type { ++ RGA_DMA_BUFFER = 0, ++ RGA_VIRTUAL_ADDRESS, ++ RGA_PHYSICAL_ADDRESS, ++ RGA_DMA_BUFFER_PTR, ++}; ++ ++enum rga_scale_up_mode { ++ RGA_SCALE_UP_NONE = 0x0, ++ RGA_SCALE_UP_BIC = 0x1, ++}; ++ ++enum rga_scale_down_mode { ++ RGA_SCALE_DOWN_NONE = 0x0, ++ RGA_SCALE_DOWN_AVG = 0x1, ++}; ++ ++/* RGA process mode enum */ ++enum { ++ BITBLT_MODE = 0x0, ++ COLOR_PALETTE_MODE = 0x1, ++ COLOR_FILL_MODE = 0x2, ++ /* used by rga2 */ ++ UPDATE_PALETTE_TABLE_MODE = 0x6, ++ UPDATE_PATTEN_BUF_MODE = 0x7, ++}; /*render mode*/ ++ ++/* RGA rd_mode */ ++enum { ++ RGA_RASTER_MODE = 0x1 << 0, ++ RGA_FBC_MODE = 0x1 << 1, ++ RGA_TILE_MODE = 0x1 << 2, ++}; ++ ++enum { ++ RGA_CONTEXT_NONE = 0x0, ++ RGA_CONTEXT_SRC_FIX_ENABLE = 0x1 << 0, ++ RGA_CONTEXT_SRC_CACHE_INFO = 0x1 << 1, ++ RGA_CONTEXT_SRC_MASK = RGA_CONTEXT_SRC_FIX_ENABLE | ++ RGA_CONTEXT_SRC_CACHE_INFO, ++ RGA_CONTEXT_PAT_FIX_ENABLE = 0x1 << 2, ++ RGA_CONTEXT_PAT_CACHE_INFO = 0x1 << 3, ++ RGA_CONTEXT_PAT_MASK = RGA_CONTEXT_PAT_FIX_ENABLE | ++ RGA_CONTEXT_PAT_CACHE_INFO, ++ RGA_CONTEXT_DST_FIX_ENABLE = 0x1 << 4, ++ RGA_CONTEXT_DST_CACHE_INFO = 0x1 << 5, ++ RGA_CONTEXT_DST_MASK = RGA_CONTEXT_DST_FIX_ENABLE | ++ RGA_CONTEXT_DST_CACHE_INFO, ++}; ++ ++/* RGA feature */ ++enum { ++ RGA_COLOR_FILL = 0x1 << 0, ++ RGA_COLOR_PALETTE = 0x1 << 1, ++ RGA_COLOR_KEY = 0x1 << 2, ++ RGA_ROP_CALCULATE = 0x1 << 3, ++ RGA_NN_QUANTIZE = 0x1 << 4, ++ RGA_OSD_BLEND = 0x1 << 5, ++ RGA_DITHER = 0x1 << 6, ++ RGA_MOSAIC = 0x1 << 7, ++ RGA_YIN_YOUT = 0x1 << 8, ++ RGA_YUV_HDS = 0x1 << 9, ++ RGA_YUV_VDS = 0x1 << 10, ++ RGA_OSD = 0x1 << 11, ++ RGA_PRE_INTR = 0x1 << 12, ++}; ++ ++enum rga_surf_format { ++ RGA_FORMAT_RGBA_8888 = 0x0, ++ RGA_FORMAT_RGBX_8888 = 0x1, ++ RGA_FORMAT_RGB_888 = 0x2, ++ RGA_FORMAT_BGRA_8888 = 0x3, ++ RGA_FORMAT_RGB_565 = 0x4, ++ RGA_FORMAT_RGBA_5551 = 0x5, ++ RGA_FORMAT_RGBA_4444 = 0x6, ++ RGA_FORMAT_BGR_888 = 0x7, ++ ++ RGA_FORMAT_YCbCr_422_SP = 0x8, ++ RGA_FORMAT_YCbCr_422_P = 0x9, ++ RGA_FORMAT_YCbCr_420_SP = 0xa, ++ RGA_FORMAT_YCbCr_420_P = 0xb, ++ ++ RGA_FORMAT_YCrCb_422_SP = 0xc, ++ RGA_FORMAT_YCrCb_422_P = 0xd, ++ RGA_FORMAT_YCrCb_420_SP = 0xe, ++ RGA_FORMAT_YCrCb_420_P = 0xf, ++ ++ RGA_FORMAT_BPP1 = 0x10, ++ RGA_FORMAT_BPP2 = 0x11, ++ RGA_FORMAT_BPP4 = 0x12, ++ RGA_FORMAT_BPP8 = 0x13, ++ ++ RGA_FORMAT_Y4 = 0x14, ++ RGA_FORMAT_YCbCr_400 = 0x15, ++ ++ RGA_FORMAT_BGRX_8888 = 0x16, ++ ++ RGA_FORMAT_YVYU_422 = 0x18, ++ RGA_FORMAT_YVYU_420 = 0x19, ++ RGA_FORMAT_VYUY_422 = 0x1a, ++ RGA_FORMAT_VYUY_420 = 0x1b, ++ RGA_FORMAT_YUYV_422 = 0x1c, ++ RGA_FORMAT_YUYV_420 = 0x1d, ++ RGA_FORMAT_UYVY_422 = 0x1e, ++ RGA_FORMAT_UYVY_420 = 0x1f, ++ ++ RGA_FORMAT_YCbCr_420_SP_10B = 0x20, ++ RGA_FORMAT_YCrCb_420_SP_10B = 0x21, ++ RGA_FORMAT_YCbCr_422_SP_10B = 0x22, ++ RGA_FORMAT_YCrCb_422_SP_10B = 0x23, ++ ++ RGA_FORMAT_BGR_565 = 0x24, ++ RGA_FORMAT_BGRA_5551 = 0x25, ++ RGA_FORMAT_BGRA_4444 = 0x26, ++ ++ RGA_FORMAT_ARGB_8888 = 0x28, ++ RGA_FORMAT_XRGB_8888 = 0x29, ++ RGA_FORMAT_ARGB_5551 = 0x2a, ++ RGA_FORMAT_ARGB_4444 = 0x2b, ++ RGA_FORMAT_ABGR_8888 = 0x2c, ++ RGA_FORMAT_XBGR_8888 = 0x2d, ++ RGA_FORMAT_ABGR_5551 = 0x2e, ++ RGA_FORMAT_ABGR_4444 = 0x2f, ++ ++ RGA_FORMAT_RGBA_2BPP = 0x30, ++ ++ RGA_FORMAT_UNKNOWN = 0x100, ++}; ++ ++#define RGA_SCHED_PRIORITY_DEFAULT 0 ++#define RGA_SCHED_PRIORITY_MAX 6 ++ ++#define RGA_VERSION_SIZE 16 ++#define RGA_HW_SIZE 5 ++ ++struct rga_version_t { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t revision; ++ uint8_t str[RGA_VERSION_SIZE]; ++}; ++ ++struct rga_hw_versions_t { ++ struct rga_version_t version[RGA_HW_SIZE]; ++ uint32_t size; ++}; ++ ++struct rga_memory_parm { ++ uint32_t width; ++ uint32_t height; ++ uint32_t format; ++ ++ uint32_t size; ++}; ++ ++struct rga_external_buffer { ++ uint64_t memory; ++ uint32_t type; ++ ++ uint32_t handle; ++ struct rga_memory_parm memory_parm; ++ ++ uint8_t reserve[252]; ++}; ++ ++struct rga_buffer_pool { ++ uint64_t buffers_ptr; ++ uint32_t size; ++}; ++ ++struct rga_color_fill_t { ++ int16_t gr_x_a; ++ int16_t gr_y_a; ++ int16_t gr_x_b; ++ int16_t gr_y_b; ++ int16_t gr_x_g; ++ int16_t gr_y_g; ++ int16_t gr_x_r; ++ int16_t gr_y_r; ++}; ++ ++/***************************************/ ++/* porting from rga.h for msg convert */ ++/***************************************/ ++ ++struct rga_fading_t { ++ uint8_t b; ++ uint8_t g; ++ uint8_t r; ++ uint8_t res; ++}; ++ ++struct rga_mmu_t { ++ uint8_t mmu_en; ++ uint64_t base_addr; ++ /* ++ * [0] mmu enable [1] src_flush [2] dst_flush ++ * [3] CMD_flush [4~5] page size ++ */ ++ uint32_t mmu_flag; ++}; ++ ++struct rga_rect_t { ++ uint16_t xmin; ++ /* width - 1 */ ++ uint16_t xmax; ++ uint16_t ymin; ++ /* height - 1 */ ++ uint16_t ymax; ++}; ++ ++struct rga_point_t { ++ uint16_t x; ++ uint16_t y; ++}; ++ ++struct rga_line_draw_t { ++ /* LineDraw_start_point */ ++ struct rga_point_t start_point; ++ /* LineDraw_end_point */ ++ struct rga_point_t end_point; ++ /* LineDraw_color */ ++ uint32_t color; ++ /* (enum) LineDrawing mode sel */ ++ uint32_t flag; ++ /* range 1~16 */ ++ uint32_t line_width; ++}; ++ ++/* color space convert coefficient. */ ++struct rga_csc_coe { ++ int16_t r_v; ++ int16_t g_y; ++ int16_t b_u; ++ int32_t off; ++}; ++ ++struct rga_full_csc { ++ uint8_t flag; ++ struct rga_csc_coe coe_y; ++ struct rga_csc_coe coe_u; ++ struct rga_csc_coe coe_v; ++}; ++ ++struct rga_mosaic_info { ++ uint8_t enable; ++ uint8_t mode; ++}; ++ ++/* MAX(min, (max - channel_value)) */ ++struct rga_osd_invert_factor { ++ uint8_t alpha_max; ++ uint8_t alpha_min; ++ uint8_t yg_max; ++ uint8_t yg_min; ++ uint8_t crb_max; ++ uint8_t crb_min; ++}; ++ ++struct rga_color { ++ union { ++ struct { ++ uint8_t red; ++ uint8_t green; ++ uint8_t blue; ++ uint8_t alpha; ++ }; ++ uint32_t value; ++ }; ++}; ++ ++struct rga_osd_bpp2 { ++ uint8_t ac_swap; // ac swap flag ++ // 0: CA ++ // 1: AC ++ uint8_t endian_swap; // rgba2bpp endian swap ++ // 0: Big endian ++ // 1: Little endian ++ struct rga_color color0; ++ struct rga_color color1; ++}; ++ ++struct rga_osd_mode_ctrl { ++ uint8_t mode; // OSD cal mode: ++ // 0b'1: statistics mode ++ // 1b'1: auto inversion overlap mode ++ uint8_t direction_mode; // horizontal or vertical ++ // 0: horizontal ++ // 1: vertical ++ uint8_t width_mode; // using @fix_width or LUT width ++ // 0: fix width ++ // 1: LUT width ++ uint16_t block_fix_width; // OSD block fixed width ++ // real width = (fix_width + 1) * 2 ++ uint8_t block_num; // OSD block num ++ uint16_t flags_index; // auto invert flags index ++ ++ /* invertion config */ ++ uint8_t color_mode; // selete color ++ // 0: src1 color ++ // 1: config data color ++ uint8_t invert_flags_mode; // invert flag selete ++ // 0: use RAM flag ++ // 1: usr last result ++ uint8_t default_color_sel; // default color mode ++ // 0: default is bright ++ // 1: default is dark ++ uint8_t invert_enable; // invert channel enable ++ // 1 << 0: alpha enable ++ // 1 << 1: Y/G disable ++ // 1 << 3: C/RB disable ++ uint8_t invert_mode; // invert cal mode ++ // 0: normal(max-data) ++ // 1: swap ++ uint8_t invert_thresh; // if luma > thresh, osd_flag to be 1 ++ uint8_t unfix_index; // OSD width config index ++}; ++ ++struct rga_osd_info { ++ uint8_t enable; ++ ++ struct rga_osd_mode_ctrl mode_ctrl; ++ struct rga_osd_invert_factor cal_factor; ++ struct rga_osd_bpp2 bpp2_info; ++ ++ union { ++ struct { ++ uint32_t last_flags0; ++ uint32_t last_flags1; ++ }; ++ uint64_t last_flags; ++ }; ++ ++ union { ++ struct { ++ uint32_t cur_flags0; ++ uint32_t cur_flags1; ++ }; ++ uint64_t cur_flags; ++ }; ++}; ++ ++struct rga_pre_intr_info { ++ uint8_t enable; ++ ++ uint8_t read_intr_en; ++ uint8_t write_intr_en; ++ uint8_t read_hold_en; ++ uint32_t read_threshold; ++ uint32_t write_start; ++ uint32_t write_step; ++}; ++ ++struct rga_img_info_t { ++ /* yrgb mem addr */ ++ uint64_t yrgb_addr; ++ /* cb/cr mem addr */ ++ uint64_t uv_addr; ++ /* cr mem addr */ ++ uint64_t v_addr; ++ /* definition by RK_FORMAT */ ++ uint32_t format; ++ ++ uint16_t act_w; ++ uint16_t act_h; ++ uint16_t x_offset; ++ uint16_t y_offset; ++ ++ uint16_t vir_w; ++ uint16_t vir_h; ++ ++ uint16_t endian_mode; ++ /* useless */ ++ uint16_t alpha_swap; ++ ++ /* used by RGA3 */ ++ uint16_t rotate_mode; ++ uint16_t rd_mode; ++ ++ uint16_t is_10b_compact; ++ uint16_t is_10b_endian; ++ ++ uint16_t enable; ++}; ++ ++struct rga_req { ++ /* (enum) process mode sel */ ++ uint8_t render_mode; ++ ++ struct rga_img_info_t src; ++ struct rga_img_info_t dst; ++ struct rga_img_info_t pat; ++ ++ /* rop4 mask addr */ ++ uint64_t rop_mask_addr; ++ /* LUT addr */ ++ uint64_t LUT_addr; ++ ++ /* dst clip window default value is dst_vir */ ++ /* value from [0, w-1] / [0, h-1]*/ ++ struct rga_rect_t clip; ++ ++ /* dst angle default value 0 16.16 scan from table */ ++ int32_t sina; ++ /* dst angle default value 0 16.16 scan from table */ ++ int32_t cosa; ++ ++ /* alpha rop process flag */ ++ /* ([0] = 1 alpha_rop_enable) */ ++ /* ([1] = 1 rop enable) */ ++ /* ([2] = 1 fading_enable) */ ++ /* ([3] = 1 PD_enable) */ ++ /* ([4] = 1 alpha cal_mode_sel) */ ++ /* ([5] = 1 dither_enable) */ ++ /* ([6] = 1 gradient fill mode sel) */ ++ /* ([7] = 1 AA_enable) */ ++ uint16_t alpha_rop_flag; ++ ++ /* 0 nearst / 1 bilnear / 2 bicubic */ ++ uint8_t scale_mode; ++ ++ /* color key max */ ++ uint32_t color_key_max; ++ /* color key min */ ++ uint32_t color_key_min; ++ ++ /* foreground color */ ++ uint32_t fg_color; ++ /* background color */ ++ uint32_t bg_color; ++ ++ /* color fill use gradient */ ++ struct rga_color_fill_t gr_color; ++ ++ struct rga_line_draw_t line_draw_info; ++ ++ struct rga_fading_t fading; ++ ++ /* porter duff alpha mode sel */ ++ uint8_t PD_mode; ++ ++ /* global alpha value */ ++ uint8_t alpha_global_value; ++ ++ /* rop2/3/4 code scan from rop code table*/ ++ uint16_t rop_code; ++ ++ /* [2] 0 blur 1 sharp / [1:0] filter_type*/ ++ uint8_t bsfilter_flag; ++ ++ /* (enum) color palette 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ ++ uint8_t palette_mode; ++ ++ /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ ++ uint8_t yuv2rgb_mode; ++ ++ /* 0/big endian 1/little endian*/ ++ uint8_t endian_mode; ++ ++ /* (enum) rotate mode */ ++ /* 0x0, no rotate */ ++ /* 0x1, rotate */ ++ /* 0x2, x_mirror */ ++ /* 0x3, y_mirror */ ++ uint8_t rotate_mode; ++ ++ /* 0 solid color / 1 pattern color */ ++ uint8_t color_fill_mode; ++ ++ /* mmu information */ ++ struct rga_mmu_t mmu_info; ++ ++ /* ([0~1] alpha mode) */ ++ /* ([2~3] rop mode) */ ++ /* ([4] zero mode en) */ ++ /* ([5] dst alpha mode) */ ++ /* ([6] alpha output mode sel) 0 src / 1 dst*/ ++ uint8_t alpha_rop_mode; ++ ++ uint8_t src_trans_mode; ++ ++ uint8_t dither_mode; ++ ++ /* full color space convert */ ++ struct rga_full_csc full_csc; ++ ++ int32_t in_fence_fd; ++ uint8_t core; ++ uint8_t priority; ++ int32_t out_fence_fd; ++ ++ uint8_t handle_flag; ++ ++ /* RGA2 1106 add */ ++ struct rga_mosaic_info mosaic_info; ++ ++ uint8_t uvhds_mode; ++ uint8_t uvvds_mode; ++ ++ struct rga_osd_info osd_info; ++ ++ struct rga_pre_intr_info pre_intr_info; ++ ++ uint8_t reservr[59]; ++}; ++#endif /*_RGA_DRIVER_H_*/ +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 93c426eeb3..325150f483 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -18,6 +18,10 @@ + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ ++#ifdef _POSIX_C_SOURCE ++#undef _POSIX_C_SOURCE ++#endif ++#define _POSIX_C_SOURCE 200809L /* for O_CLOEXEC */ + + #include <drm_fourcc.h> + #include <pthread.h> +@@ -26,6 +30,9 @@ + #include <time.h> + #include <unistd.h> + #include <sys/time.h> ++#include <sys/mman.h> ++#include <linux/dma-heap.h> ++#include <fcntl.h> + + #include "avcodec.h" + #include "decode.h" +@@ -38,11 +45,8 @@ + #include "libavutil/hwcontext_drm.h" + #include "libavutil/imgutils.h" + #include "libavutil/log.h" ++#include "rga.h" + +-#if CONFIG_LIBRGA +-#include <rga/rga.h> +-#include <rga/RgaApi.h> +-#endif + + #ifndef DRM_FORMAT_NV12_10 + #define DRM_FORMAT_NV12_10 fourcc_code('N', 'A', '1', '5') +@@ -50,11 +54,16 @@ + + #define FPS_UPDATE_INTERVAL 120 + ++struct rkmpp_dma_buffer; + typedef struct { + MppCtx ctx; + MppApi *mpi; + MppBufferGroup frame_group; + ++ int dma_fd; ++ struct rkmpp_dma_buffer *dma_cache; ++ int rga_fd; ++ + int8_t eos; + int8_t draining; + +@@ -115,17 +124,15 @@ static uint32_t rkmpp_get_avformat(MppFrameFormat mppformat) + } + } + +-#if CONFIG_LIBRGA + static uint32_t rkmpp_get_rgaformat(MppFrameFormat mppformat) + { + switch (mppformat) { +- case MPP_FMT_YUV420SP: return RK_FORMAT_YCbCr_420_SP; +- case MPP_FMT_YUV420SP_10BIT: return RK_FORMAT_YCbCr_420_SP_10B; +- case MPP_FMT_YUV422SP: return RK_FORMAT_YCbCr_422_SP; +- default: return RK_FORMAT_UNKNOWN; ++ case MPP_FMT_YUV420SP: return RGA_FORMAT_YCbCr_420_SP; ++ case MPP_FMT_YUV420SP_10BIT: return RGA_FORMAT_YCbCr_420_SP_10B; ++ case MPP_FMT_YUV422SP: return RGA_FORMAT_YCbCr_422_SP; ++ default: return RGA_FORMAT_UNKNOWN; + } + } +-#endif + + static int rkmpp_close_decoder(AVCodecContext *avctx) + { +@@ -138,6 +145,8 @@ static int rkmpp_close_decoder(AVCodecContext *avctx) + return 0; + } + ++static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer); ++ + static void rkmpp_release_decoder(void *opaque, uint8_t *data) + { + RKMPPDecoder *decoder = (RKMPPDecoder *)data; +@@ -153,6 +162,20 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data) + decoder->frame_group = NULL; + } + ++ rkmpp_buffer_free(decoder->dma_cache); ++ decoder->dma_cache = NULL; ++ ++ if (decoder->dma_fd) { ++ close(decoder->dma_fd); ++ decoder->dma_fd = 0; ++ } ++ ++ if (decoder->rga_fd) { ++ close(decoder->rga_fd); ++ decoder->rga_fd = 0; ++ } ++ ++ + av_buffer_unref(&decoder->frames_ref); + av_buffer_unref(&decoder->device_ref); + +@@ -250,13 +273,27 @@ static int rkmpp_init_decoder(AVCodecContext *avctx) + goto fail; + } + +- ret = mpp_buffer_group_get_internal(&decoder->frame_group, MPP_BUFFER_TYPE_ION); ++ ret = mpp_buffer_group_get_internal(&decoder->frame_group, ++ MPP_BUFFER_TYPE_DMA_HEAP); ++ + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Failed to get buffer group (code = %d)\n", ret); + ret = AVERROR_UNKNOWN; + goto fail; + } + ++ decoder->dma_fd = open("/dev/dma_heap/system-dma32", O_RDWR); ++ if (decoder->dma_fd < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to open system-dma32 heap\n"); ++ ret = AVERROR_UNKNOWN; ++ goto fail; ++ } ++ ++ decoder->rga_fd = open("/dev/rga", O_RDWR); ++ if (decoder->dma_fd < 0) { ++ av_log(avctx, AV_LOG_WARNING, "Failed to open RGA\n"); ++ } ++ + ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP, decoder->frame_group); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Failed to assign buffer group (code = %d)\n", ret); +@@ -307,13 +344,14 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data) + static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame, + MppFrame mppframe, MppBuffer buffer) + { ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ + char *src = mpp_buffer_get_ptr(buffer); + char *dst_y = frame->data[0]; + char *dst_u = frame->data[1]; + char *dst_v = frame->data[2]; +-#if CONFIG_LIBRGA +- RgaSURF_FORMAT format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe)); +-#endif ++ enum rga_surf_format format = rkmpp_get_rgaformat(mpp_frame_get_fmt(mppframe)); + int width = mpp_frame_get_width(mppframe); + int height = mpp_frame_get_height(mppframe); + int hstride = mpp_frame_get_hor_stride(mppframe); +@@ -321,29 +359,41 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame, + int y_pitch = frame->linesize[0]; + int u_pitch = frame->linesize[1]; + int v_pitch = frame->linesize[2]; +- int i, j; ++ int i, j, ret; + +-#if CONFIG_LIBRGA +- rga_info_t src_info = {0}; +- rga_info_t dst_info = {0}; + int dst_height = (dst_u - dst_y) / y_pitch; + +- static int rga_supported = 1; +- static int rga_inited = 0; ++ struct rga_req req = { ++ .src = { ++ .yrgb_addr = mpp_buffer_get_fd(buffer), ++ .v_addr = hstride * vstride, ++ .format = format, ++ .act_w = width, ++ .act_h = height, ++ .vir_w = hstride, ++ .vir_h = vstride, ++ .rd_mode = RGA_RASTER_MODE, ++ }, ++ .dst = { ++ .uv_addr = (uintptr_t) dst_y, ++ .v_addr = (uintptr_t) dst_u, ++ .format = RGA_FORMAT_YCbCr_420_P, ++ .act_w = width, ++ .act_h = height, ++ .vir_w = y_pitch, ++ .vir_h = dst_height, ++ .rd_mode = RGA_RASTER_MODE, ++ }, ++ .mmu_info = { ++ .mmu_en = 1, ++ .mmu_flag = 0x80000521, ++ }, ++ }; + +- if (!rga_supported) ++ if (decoder->rga_fd < 0) + goto bail; + +- if (!rga_inited) { +- if (c_RkRgaInit() < 0) { +- rga_supported = 0; +- av_log(avctx, AV_LOG_WARNING, "RGA not available\n"); +- goto bail; +- } +- rga_inited = 1; +- } +- +- if (format == RK_FORMAT_UNKNOWN) ++ if (format == RGA_FORMAT_UNKNOWN) + goto bail; + + if (u_pitch != y_pitch / 2 || v_pitch != y_pitch / 2 || +@@ -351,23 +401,13 @@ static int rkmpp_convert_frame(AVCodecContext *avctx, AVFrame *frame, + dst_v != dst_u + u_pitch * dst_height / 2) + goto bail; + +- src_info.fd = mpp_buffer_get_fd(buffer); +- src_info.mmuFlag = 1; +- rga_set_rect(&src_info.rect, 0, 0, width, height, hstride, vstride, +- format); +- +- dst_info.virAddr = dst_y; +- dst_info.mmuFlag = 1; +- rga_set_rect(&dst_info.rect, 0, 0, frame->width, frame->height, +- y_pitch, dst_height, RK_FORMAT_YCbCr_420_P); +- +- if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) ++ ret = ioctl(decoder->rga_fd, RGA_BLIT_SYNC, &req); ++ if (ret < 0) + goto bail; + + return 0; + + bail: +-#endif + if (mpp_frame_get_fmt(mppframe) != MPP_FMT_YUV420SP) { + av_log(avctx, AV_LOG_WARNING, "Unable to convert\n"); + return -1; +@@ -423,6 +463,150 @@ static void rkmpp_update_fps(AVCodecContext *avctx) + fps, decoder->frames); + } + ++struct rkmpp_dma_buffer { ++ int fd; ++ void *cpu; ++ size_t size; ++ struct rkmpp_dma_buffer **cache; ++}; ++ ++static void rkmpp_buffer_free(struct rkmpp_dma_buffer *buffer) ++{ ++ if (!buffer) ++ return; ++ ++ munmap(buffer->cpu, buffer->size); ++ close(buffer->fd); ++ av_free(buffer); ++} ++ ++static void rkmpp_buffer_cache(void *opaque, uint8_t *data) ++{ ++ struct rkmpp_dma_buffer *buffer = opaque; ++ ++ if (!buffer) ++ return; ++ ++ if (*buffer->cache) ++ rkmpp_buffer_free(buffer); ++ else ++ *buffer->cache = buffer; ++} ++ ++static struct rkmpp_dma_buffer *rkmpp_buffer_alloc(RKMPPDecoder *decoder, size_t size) ++{ ++ struct rkmpp_dma_buffer *buffer; ++ int ret; ++ ++ struct dma_heap_allocation_data alloc = { ++ .len = size, ++ .fd_flags = O_CLOEXEC | O_RDWR, ++ }; ++ ++ if (decoder->dma_cache) { ++ struct rkmpp_dma_buffer *cached = decoder->dma_cache; ++ decoder->dma_cache = NULL; ++ ++ if (cached->size == size) { ++ return cached; ++ } ++ ++ rkmpp_buffer_free(cached); ++ } ++ ++ ret = ioctl(decoder->dma_fd, DMA_HEAP_IOCTL_ALLOC, &alloc); ++ if (ret == -1) ++ return NULL; ++ ++ buffer = av_mallocz(sizeof(*buffer)); ++ buffer->fd = alloc.fd; ++ buffer->size = alloc.len; ++ buffer->cpu = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, ++ MAP_SHARED, buffer->fd, 0); ++ buffer->cache = &decoder->dma_cache; ++ ++ return buffer; ++} ++ ++static int rkmpp_get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags) ++{ ++ RKMPPDecodeContext *rk_context = avctx->priv_data; ++ RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; ++ ++ int ret; ++ ++ int linesize[4]; ++ int stride_align[AV_NUM_DATA_POINTERS]; ++ int w = pic->width; ++ int h = pic->height; ++ int unaligned; ++ ptrdiff_t linesize1[4]; ++ size_t size[4]; ++ ++ struct rkmpp_dma_buffer *buffer; ++ ++ int total; ++ ++ avcodec_align_dimensions2(avctx, &w, &h, stride_align); ++ ++ do { ++ // NOTE: do not align linesizes individually, this breaks e.g. assumptions ++ // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 ++ ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w); ++ if (ret < 0) ++ goto fail; ++ // increase alignment of w for next try (rhs gives the lowest bit set in w) ++ w += w & ~(w - 1); ++ ++ unaligned = 0; ++ for (int i = 0; i < 4; i++) ++ unaligned |= linesize[i] % stride_align[i]; ++ } while (unaligned); ++ ++ for (int i = 0; i < 4; i++) ++ linesize1[i] = linesize[i]; ++ ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1); ++ if (ret < 0) ++ goto fail; ++ ++ size[0] += size[1] + size[2] + size[3]; ++ size[0] += 16 + STRIDE_ALIGN - 1; ++ ++ buffer = rkmpp_buffer_alloc(decoder, size[0]); ++ if (!buffer) ++ goto fail; ++ ++ av_log(avctx, AV_LOG_DEBUG, "Allocated buffer of size %zi -> %p (CPU %p)\n", size[0], buffer, buffer->cpu); ++ ++ memset(pic->data, 0, sizeof(pic->data)); ++ pic->extended_data = pic->data; ++ ++ pic->linesize[0] = linesize[0]; ++ pic->buf[0] = av_buffer_create(buffer->cpu, size[0], ++ rkmpp_buffer_cache, buffer, 0); ++ pic->data[0] = pic->buf[0]->data; ++ ++ for (int i = 1; i < 4; i++) ++ pic->linesize[i] = linesize[i]; ++ ++ total = av_image_fill_pointers(pic->data, pic->format, pic->height, ++ pic->buf[0]->data, pic->linesize); ++ if (total < 0 || total > pic->buf[0]->size) ++ goto fail; ++ ++ for (int i = 4; i < AV_NUM_DATA_POINTERS; i++) { ++ pic->data[i] = NULL; ++ pic->linesize[i] = 0; ++ } ++ ++ return 0; ++ ++fail: ++ av_frame_unref(pic); ++ return AVERROR(ENOMEM); ++} ++ ++ + static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + { + RKMPPDecodeContext *rk_context = avctx->priv_data; +@@ -528,6 +712,8 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + rkmpp_update_fps(avctx); + + if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) { ++ avctx->get_buffer2 = rkmpp_get_buffer2; ++ + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + goto out; +-- +2.39.0 + + +From 44ccb8a4f398dbb05c2bd2fd9a0dcd56ca8ceb54 Mon Sep 17 00:00:00 2001 +From: boogie <boogiepop@gmx.com> +Date: Tue, 17 Jan 2023 01:02:19 +0100 +Subject: [PATCH 16/16] ugliest hack: vp8&9 color space workaround + +--- + libavcodec/rkmppdec.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c +index 325150f483..ad9208f0e6 100644 +--- a/libavcodec/rkmppdec.c ++++ b/libavcodec/rkmppdec.c +@@ -734,6 +734,21 @@ static int rkmpp_get_frame(AVCodecContext *avctx, AVFrame *frame, int timeout) + frame->color_trc = mpp_frame_get_color_trc(mppframe); + frame->colorspace = mpp_frame_get_colorspace(mppframe); + ++ /* ugliest hack in the world: firefox does not probe with avformat, so it does not ++ * have any idea about the frame format, instead tries to guess with decoder profile ++ * matches. Since this decoder does not provide any profile, it just sets color pro- ++ * file to 0 which RGB. This causes funny coloring on video decode. ++ * I set this manually to most popular BT709 colorspace for VP8&9. This worksaround ++ * youtube problems, but does not work always. At least there is no need to run this ++ * on each frame... But yeah it is too late and i dont care. ++ */ ++ if ((avctx->codec_id == AV_CODEC_ID_VP8 || avctx->codec_id == AV_CODEC_ID_VP9 ) \ ++ && avctx->profile == FF_PROFILE_UNKNOWN && !frame->colorspace){ ++ frame->color_primaries = AVCOL_PRI_BT709; ++ frame->color_trc = AVCOL_TRC_BT709; ++ frame->colorspace = AVCOL_SPC_BT709; ++ } ++ + mode = mpp_frame_get_mode(mppframe); + frame->interlaced_frame = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_DEINTERLACED); + frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); +-- +2.39.0 + |