diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 4e14d09c7c..e137e7e820 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -30,6 +30,7 @@
 #include "codec_internal.h"
 #include "decode.h"
 #include "hwconfig.h"
+#include "refstruct.h"
 #include "libavutil/buffer.h"
 #include "libavutil/common.h"
 #include "libavutil/frame.h"
@@ -57,12 +58,12 @@ typedef struct {
 
 typedef struct {
     AVClass *av_class;
-    AVBufferRef *decoder_ref;
+    RKMPPDecoder *decoder;           ///< RefStruct reference
 } RKMPPDecodeContext;
 
 typedef struct {
     MppFrame frame;
-    AVBufferRef *decoder_ref;
+    const RKMPPDecoder *decoder_ref; ///< RefStruct reference
 } RKMPPFrameContext;
 
 static MppCodingType rkmpp_get_codingtype(AVCodecContext *avctx)
@@ -90,7 +91,7 @@ static uint32_t rkmpp_get_frameformat(MppFrameFormat mppformat)
 static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, int64_t pts)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    RKMPPDecoder *decoder = rk_context->decoder;
     int ret;
     MppPacket packet;
 
@@ -125,13 +126,13 @@ static int rkmpp_write_data(AVCodecContext *avctx, uint8_t *buffer, int size, in
 static int rkmpp_close_decoder(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    av_buffer_unref(&rk_context->decoder_ref);
+    ff_refstruct_unref(&rk_context->decoder);
     return 0;
 }
 
-static void rkmpp_release_decoder(void *opaque, uint8_t *data)
+static void rkmpp_release_decoder(FFRefStructOpaque unused, void *obj)
 {
-    RKMPPDecoder *decoder = (RKMPPDecoder *)data;
+    RKMPPDecoder *decoder = obj;
 
     if (decoder->mpi) {
         decoder->mpi->reset(decoder->ctx);
@@ -146,8 +147,6 @@ static void rkmpp_release_decoder(void *opaque, uint8_t *data)
 
     av_buffer_unref(&decoder->frames_ref);
     av_buffer_unref(&decoder->device_ref);
-
-    av_free(decoder);
 }
 
 static int rkmpp_init_decoder(AVCodecContext *avctx)
@@ -162,19 +161,13 @@ static int rkmpp_init_decoder(AVCodecContext *avctx)
     avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
 
     // create a decoder and a ref to it
-    decoder = av_mallocz(sizeof(RKMPPDecoder));
+    decoder = ff_refstruct_alloc_ext(sizeof(*decoder), 0,
+                                     NULL, rkmpp_release_decoder);
     if (!decoder) {
         ret = AVERROR(ENOMEM);
         goto fail;
     }
-
-    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) {
-        av_free(decoder);
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
+    rk_context->decoder = decoder;
 
     av_log(avctx, AV_LOG_DEBUG, "Initializing RKMPP decoder.\n");
 
@@ -270,7 +263,7 @@ fail:
 static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    RKMPPDecoder *decoder = rk_context->decoder;
     int ret;
 
     // handle EOF
@@ -312,7 +305,7 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
     RKMPPFrameContext *framecontext = (RKMPPFrameContext *)framecontextref->data;
 
     mpp_frame_deinit(&framecontext->frame);
-    av_buffer_unref(&framecontext->decoder_ref);
+    ff_refstruct_unref(&framecontext->decoder_ref);
     av_buffer_unref(&framecontextref);
 
     av_free(desc);
@@ -321,7 +314,7 @@ static void rkmpp_release_frame(void *opaque, uint8_t *data)
 static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    RKMPPDecoder *decoder = rk_context->decoder;
     RKMPPFrameContext *framecontext = NULL;
     AVBufferRef *framecontextref = NULL;
     int ret;
@@ -449,11 +442,6 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
 
             // 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);
-            if (!framecontext->decoder_ref) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
             framecontext->frame = mppframe;
 
             frame->data[0]  = (uint8_t *)desc;
@@ -464,6 +452,7 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
                 ret = AVERROR(ENOMEM);
                 goto fail;
             }
+            framecontext->decoder_ref = ff_refstruct_ref(rk_context->decoder);
 
             frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref);
             if (!frame->hw_frames_ctx) {
@@ -488,9 +477,6 @@ fail:
     if (mppframe)
         mpp_frame_deinit(&mppframe);
 
-    if (framecontext)
-        av_buffer_unref(&framecontext->decoder_ref);
-
     if (framecontextref)
         av_buffer_unref(&framecontextref);
 
@@ -503,7 +489,7 @@ fail:
 static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    RKMPPDecoder *decoder = rk_context->decoder;
     int ret = MPP_NOK;
     AVPacket pkt = {0};
     RK_S32 usedslots, freeslots;
@@ -543,7 +529,7 @@ static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 static void rkmpp_flush(AVCodecContext *avctx)
 {
     RKMPPDecodeContext *rk_context = avctx->priv_data;
-    RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data;
+    RKMPPDecoder *decoder = rk_context->decoder;
     int ret = MPP_NOK;
 
     av_log(avctx, AV_LOG_DEBUG, "Flush.\n");
