How to improve hardware decode with ffmpeg

Important: unclear posts may not receive useful answers.

Description

What MCU/Processor/Board and compiler are you using?

radxa zero 3E (rk3566)

What LVGL version are you using?

version=9.3.0-dev

What do you want to achieve?

improve FPS with rockchip Media Process Platform (MPP) with LVGL.

What have you tried so far?

I compiled the ffmpeg with codec support from nyanmisaka repo
And validate Using basics commands to display a full-hd mp4 (h264) video.
(I don`t care about audio)

ffplay -codec:v h264_rkmpp -an ~/video/video.mp4  -loop 0

and logging with

watch -n1 cat /proc/mpp_service/sessions-summary

and alls works great. “low” cpu usage and fluid video.

Now with LVGL.

Code to reproduce

Using lv_port_linux with wayland (tested on sdl and x11 too)

/*******************************************************************
 *
 * main.c - LVGL simulator for GNU/Linux
 *
 * Based on the original file from the repository
 *
 * @note eventually this file won't contain a main function and will
 * become a library supporting all major operating systems
 *
 * To see how each driver is initialized check the
 * 'src/lib/display_backends' directory
 *
 * - Clean up
 * - Support for multiple backends at once
 *   2025 EDGEMTech Ltd.
 *
 * Author: EDGEMTech Ltd, Erik Tagirov (erik.tagirov@edgemtech.ch)
 *
 ******************************************************************/
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
#include <sched.h>

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"

#include "src/lib/driver_backends.h"
#include "src/lib/simulator_util.h"
#include "src/lib/simulator_settings.h"

#define PATH_PREFIX "/home/elmer/Downloads/videos/"

/* Internal functions */
static void configure_simulator(int argc, char **argv);
static void print_lvgl_version(void);
static void print_usage(void);

/* contains the name of the selected backend if user
 * has specified one on the command line */
static char *selected_backend;

/* Global simulator settings, defined in lv_linux_backend.c */
extern simulator_settings_t settings;
lv_obj_t * player_video;

/**
 * @brief Print LVGL version
 */
static void print_lvgl_version(void)
{
    fprintf(stdout, "%d.%d.%d-%s\n",
            LVGL_VERSION_MAJOR,
            LVGL_VERSION_MINOR,
            LVGL_VERSION_PATCH,
            LVGL_VERSION_INFO);
}

/**
 * @brief Print usage information
 */
static void print_usage(void)
{
    fprintf(stdout, "\nlvglsim [-V] [-B] [-b backend_name] [-W window_width] [-H window_height]\n\n");
    fprintf(stdout, "-V print LVGL version\n");
    fprintf(stdout, "-B list supported backends\n");
}

/**
 * @brief Configure simulator
 * @description process arguments recieved by the program to select
 * appropriate options
 * @param argc the count of arguments in argv
 * @param argv The arguments
 */
static void configure_simulator(int argc, char **argv)
{
    int opt = 0;
    char *backend_name;

    selected_backend = NULL;
    driver_backends_register();

    /* Default values */
    // TODO: take the screen size from the environment variable
    settings.window_width = atoi(getenv("LV_SIM_WINDOW_WIDTH") ? : "1080");
    settings.window_height = atoi(getenv("LV_SIM_WINDOW_HEIGHT") ? : "1920");

    /* Parse the command-line options. */
    while ((opt = getopt (argc, argv, "b:fmW:H:BVh")) != -1) {
        switch (opt) {
        case 'h':
            print_usage();
            exit(EXIT_SUCCESS);
            break;
        case 'V':
            print_lvgl_version();
            exit(EXIT_SUCCESS);
            break;
        case 'B':
            driver_backends_print_supported();
            exit(EXIT_SUCCESS);
            break;
        case 'b':
            if (driver_backends_is_supported(optarg) == 0) {
                die("error no such backend: %s\n", optarg);
            }
            selected_backend = strdup(optarg);
            break;
        case 'W':
            settings.window_width = atoi(optarg);
            break;
        case 'H':
            settings.window_height = atoi(optarg);
            break;
        case ':':
            print_usage();
            die("Option -%c requires an argument.\n", optopt);
            break;
        case '?':
            print_usage();
            die("Unknown option -%c.\n", optopt);
        }
    }
}

/**
 * @brief entry point
 * @description start a demo
 * @param argc the count of arguments in argv
 * @param argv The arguments
 */
int main(int argc, char **argv)
{
    configure_simulator(argc, argv);

    lv_init();

    /* Initialize the configured backend */
    if (driver_backends_init_backend(selected_backend) == -1) {
        die("Failed to initialize display backend");
    }

    /* Enable for EVDEV support */
    #if LV_USE_EVDEV
    if (driver_backends_init_backend("EVDEV") == -1) {
        die("Failed to initialize evdev");
    }
    #endif

    lv_obj_t * player = lv_ffmpeg_player_create(lv_screen_active());
    lv_ffmpeg_player_set_src(player, "/home/toletus/videos/video");
    lv_ffmpeg_player_set_auto_restart(player, true);
    lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_START);
    lv_obj_center(player);

    driver_backends_run_loop();

    return 0;
}

And got 8 fps 100% cpu usage with the same video
and no registry on the mpp summary

watch -n0.1 cat /proc/mpp_service/sessions-summary 

so I modifyed the ffmpeg_open_codec_context on lv_ffmpeg.c to open h264 rkmpp decoder

static int ffmpeg_open_codec_context(int * stream_idx,
                                     AVCodecContext ** dec_ctx, AVFormatContext * fmt_ctx,
                                     enum AVMediaType type)
{
    int ret;
    int stream_index;
    AVStream * st;
    const AVCodec * dec = NULL;
    AVDictionary * opts = NULL;

    ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
    if(ret < 0) {
        LV_LOG_ERROR("Could not find %s stream in input file",
                     av_get_media_type_string(type));
        return ret;
    }
    else {
        stream_index = ret;
        st = fmt_ctx->streams[stream_index];

        /* find decoder for the stream */
        if(st->codecpar->codec_id == AV_CODEC_ID_H264){
            LV_LOG_USER("\n ############### Using Rockchip codec! ###############\n");
            dec = avcodec_find_decoder_by_name("h264_rkmpp");
        }
        else{
            LV_LOG_USER("\n ############### Using standard codec! ###############\n");
            dec = avcodec_find_decoder(st->codecpar->codec_id);
        }
        if(dec == NULL) {
            LV_LOG_ERROR("Failed to find %s codec",
                         av_get_media_type_string(type));
            return AVERROR(EINVAL);
        }

        /* Allocate a codec context for the decoder */
        *dec_ctx = avcodec_alloc_context3(dec);
        if(*dec_ctx == NULL) {
            LV_LOG_ERROR("Failed to allocate the %s codec context",
                         av_get_media_type_string(type));
            return AVERROR(ENOMEM);
        }

        /* Copy codec parameters from input stream to output codec context */
        if((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) {
            LV_LOG_ERROR(
                "Failed to copy %s codec parameters to decoder context",
                av_get_media_type_string(type));
            return ret;
        }

        /* Init the decoders */
        if((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) {
            LV_LOG_ERROR("Failed to open %s codec",
                         av_get_media_type_string(type));
            return ret;
        }

        *stream_idx = stream_index;
    }

    return 0;
}

output log

Couldn't open plugin directory: No such file or directory
No plugins found, falling back on no decorations
[User]  (2.223, +2223)   init_pointer_evdev: Using evdev automatic discovery. evdev.c:161
... evdev discovery log
[User]  (2.225, +0)      discovery_cb: new 'REL' device discovered evdev.c:110
[User]  (2.317, +92)     ffmpeg_open_codec_context: 
 ############### Using Rockchip codec! ###############
 lv_ffmpeg.c:573
mpp[35594]: mpp_info: mpp version: unknown mpp version for missing VCS info
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/toletus/videos/video':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42mp41isomavc1
    creation_time   : 2020-06-16T19:32:12.000000Z
  Duration: 00:00:14.64, start: 0.000000, bitrate: N/A
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1066x1920, 5583 kb/s, 25 fps, 25 tbr, 25 tbn (default)
    Metadata:
      creation_time   : 2020-06-16T19:32:12.000000Z
      handler_name    : L-SMASH Video Handler
      vendor_id       : [0][0][0][0]
      encoder         : AVC Coding

an I got a variation fps from 8 to 16 fps but with frame drop and registry on the mpp summary

Screenshot and video

with standard lvgl source (automatic decoder).
standard-decoder (1)

with modified lvgl source (rockchip codec)
rkmpp-decoder (2)

So, any idea how can I improve this?