• GStreamer插件实列rockchipmpp


    尽管这些年arm发展取得了不少的进步,不过对于音视频的编解码仍然心有余力不足,好在芯片厂家在SOC里面提供了硬件加速能力。善于发挥出芯片的能力,才能打造出完美的应用.今天我们一起来探索一下rk3568上的为我们提供的多媒体加速能力-MPP,然后一起分析一下rk的gstreamer插件。

    MPP

    概述

    瑞芯微提供的媒体处理软件平台( Media Process Platform ,简称 MPP )是适用于瑞芯微芯片系列的 通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理,其目的是为了屏蔽不 同芯片的差异,为使用者提供统一的视频媒体处理接口(Media Process Interface ,缩写 MPI )。 MPP 提供的功能包括:
    • 视频解码
                     H.265 / H.264 / H.263 / VP9 / VP8 / MPEG-4 / MPEG-2 / MPEG-1 / VC1 / MJPEG
    •  视频编码
                     H.264 / VP8 / MJPEG
    • 视频处理
                     视频拷贝,缩放,色彩空间转换,场视频解交织(Deinterlace

    系统架构

    MPP 平台在系统架构的层次图如下图:
    • 硬件层 Hardware
            硬件层是瑞芯微系列芯片平台的视频编解码硬件加速模块,包括 VPU rkvdec rkvenc 等不同类型,不同功能的硬件加速器。
    • 内核驱动层 Kernel driver
            Linux 内核的编码器硬件设备驱动,以及相关的 mmu ,内存,时钟,电源管理模块等。
    • 操作系统层
            MPP 用户态的运行平台,如 Android 以及 Debian Linux 发行版
    • 应用层
            MPP 层通过 MPI 对接各种中间件软件,如 OpenMax ffmpeg gstreamer ,或者直接对接客户的上 层应用。

    MPI

    由于视频编解码与视频处理过程需要处理大量的数据交互,包括码流数据,图像数据以及内存数据, 同时还要处理与上层应用以及内核驱动的交叉关系,所以 MPP 设计了 MPI 接口,用于与上层交互。 本章节说明了 MPI 接口使用的数据结构,以及设计思路。
    MppMem C malloc 内存的封装。
    MppBuffer 为硬件用的 dmabuf 内存的封装。
    MppPacket 为一维缓存封装,可以从 MppMem MppBuffer 生成,主要用于表示码流数据。
    MppFrame 为二维帧数据封装,可以从 MppMem MppBuffer 生成,主要用于表示图像数据。
    使用 MppPacket MppFrame 就可以简单有效的完成一般的视频编解码工作。
    以视频解码为例,码流输入端把地址和大小赋值给 MppPacket ,通过 put_packet 接口输入,在输出 端通过 get_frame 接口得到输入图像 MppFrame ,即可完成最简单的视频解码过程。

    MPI Media Process Interface )是 MPP 提供给用户的接口,用于提供硬件编解码功能,以及一些必 要的相关功能。MPI 是通过 C 结构里的函数指针方式提供给用户,用户可以通过 MPP 上下文结构 MppCtx 与 MPI 接口结构 MppApi 组合使用来实现解码器与编码器的功能。

     

    如上图所示, mpp_create mpp_init mpp_destroy 是操作 MppCtx 接口的过程,其中 mpp_create 接 口也获取到了 MPI 接口结构体 MppApi ,真正的编码与解码过程是通过调用 MppApi 结构体里内的函数指针来实现,也就是上图中红框内的部分。红框内的函数调用分为编解码流程接口put/get_packet/frame 和相关的 control reset 接口。下文先描述编解码器接口,再对编解码器工作中的一些要点进行说明。

    rk gstreamer 插件

    rockchipmpp是rk公司开发的一个在gstreamer插件,主要把自己的MPP和GStreamer,结合起来,我们在使用是可以直接把相关代码放到gstreamer源码中编译即可。

    如下为它的源码

    1. ├── gstmppallocator.c
    2. ├── gstmppallocator.h
    3. ├── gstmppalphadecodebin.c
    4. ├── gstmppalphadecodebin.h
    5. ├── gstmpp.c
    6. ├── gstmppdec.c
    7. ├── gstmppdec.h
    8. ├── gstmppenc.c
    9. ├── gstmppenc.h
    10. ├── gstmpp.h
    11. ├── gstmpph264enc.c
    12. ├── gstmpph264enc.h
    13. ├── gstmpph265enc.c
    14. ├── gstmpph265enc.h
    15. ├── gstmppjpegdec.c
    16. ├── gstmppjpegdec.h
    17. ├── gstmppjpegenc.c
    18. ├── gstmppjpegenc.h
    19. ├── gstmppvideodec.c
    20. ├── gstmppvideodec.h
    21. ├── gstmppvp8enc.c
    22. ├── gstmppvp8enc.h
    23. ├── gstmppvpxalphadecodebin.c
    24. ├── gstmppvpxalphadecodebin.h

     gstmpp.c为统一的入口文件,在它里面注册其他插件,gstmppjpegdec.c为jpeg的解码文件,我们能以他们为例子分析一下这个rockchip的mpp插件

    gstreamer rkmpp 插件定义

    如下为rkmpp的定义

    1. GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    2. GST_VERSION_MINOR,
    3. rkmpp,
    4. "Rockchip Mpp Video Plugin",
    5. plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

    这个功能相当于面向对象语言的模板功能,由于C语言不支持模板功能,需要使用宏定义,来模拟模板功能,下面我们一起展开一下;

    1. #ifdef __cplusplus
    2. #define G_BEGIN_DECLS extern "C" {
    3. #define G_END_DECLS }
    4. #else
    5. #define G_BEGIN_DECLS
    6. #define G_END_DECLS
    7. #endif
    8. #if (0 || defined(_MSC_VER)) && !defined(GST_STATIC_COMPILATION)
    9. # define GST_PLUGIN_EXPORT __declspec(dllexport)
    10. # ifdef GST_EXPORTS
    11. # define GST_EXPORT __declspec(dllexport)
    12. # else
    13. # define GST_EXPORT __declspec(dllimport) extern
    14. # endif
    15. #else
    16. # if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
    17. # define GST_PLUGIN_EXPORT __attribute__ ((visibility ("default")))
    18. # define GST_EXPORT extern __attribute__ ((visibility ("default")))
    19. # else
    20. # define GST_PLUGIN_EXPORT
    21. # define GST_EXPORT extern
    22. # endif
    23. #endif
    24. #define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
    25. #define G_PASTE(identifier1,identifier2) G_PASTE_ARGS (identifier1, identifier2)
    26. #define GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin) \
    27. G_BEGIN_DECLS \
    28. GST_PLUGIN_EXPORT const GstPluginDesc * G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void); \
    29. GST_PLUGIN_EXPORT void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void); \
    30. \
    31. static const GstPluginDesc gst_plugin_desc = { \
    32. major, \
    33. minor, \
    34. G_STRINGIFY(name), \
    35. (gchar *) description, \
    36. init, \
    37. version, \
    38. license, \
    39. PACKAGE, \
    40. package, \
    41. origin, \
    42. __GST_PACKAGE_RELEASE_DATETIME, \
    43. GST_PADDING_INIT \
    44. }; \
    45. \
    46. const GstPluginDesc * \
    47. G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void) \
    48. { \
    49. return &gst_plugin_desc; \
    50. } \
    51. \
    52. void \
    53. G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void) \
    54. { \
    55. gst_plugin_register_static (major, minor, G_STRINGIFY(name), \
    56. description, init, version, license, \
    57. PACKAGE, package, origin); \
    58. } \
    59. G_END_DECLS

    这个宏定义主要生成gst_plugin_desc结构和gst_plugin_rkmpp_get_desc,gst_plugin_rkmpp_register,来的分析,把部分宏找出来直接用gcc命令生产:

    gcc  -E -P gst-define.c > gst-define_m.c

     大致代码如下

    1. __attribute__ ((visibility ("default"))) const GstPluginDesc * gst_plugin_rkmpp_get_desc (void);
    2. __attribute__ ((visibility ("default"))) void gst_plugin_rkmpp_register (void);
    3. static const GstPluginDesc gst_plugin_desc = { GST_VERSION_MAJOR, GST_VERSION_MINOR, G_STRINGIFY(rkmpp), (gchar *) "Rockchip Mpp Video Plugin", plugin_init, VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN, __GST_PACKAGE_RELEASE_DATETIME, GST_PADDING_INIT };
    4. const GstPluginDesc * gst_plugin_rkmpp_get_desc (void)
    5. { return &gst_plugin_desc; }
    6. void gst_plugin_rkmpp_register (void)
    7. { gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR, G_STRINGIFY(rkmpp), "Rockchip Mpp Video Plugin",
    8. plugin_init, VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
    9. }

    插件初始化

  • 相关阅读:
    Java之转换流的详细解析
    Jmeter(十六):jmeter场景的运行架构&配置远程负载机详解
    Spring Security是什么?(一)
    【自动驾驶】PETR/PETRv2/StreamPETR论文分析
    uniCloud云开发获取小程序用户openid
    Unity之NetCode多人网络游戏联机对战教程(4)--连接申请ConnectionApproval
    【面试题】JS 中这些继承方式你知道吗?
    知识点7--Docker的容器命令
    【大数据实训】基于赶集网租房信息的数据分析与可视化(七)
    【Python】四、程序顺序和分支控制结构
  • 原文地址:https://blog.csdn.net/hn_zhangkun/article/details/125557393