RKMPP 在FFmpeg上实现硬编解码

Posted Geek.Fan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RKMPP 在FFmpeg上实现硬编解码相关的知识,希望对你有一定的参考价值。

一、编译指令

--enable-cross-compile --cross-	 prefix=/home/cks/linux_sdk/buildroot/output/rockchip_rk3399pro/host/bin/aarch64-buildroot-linux-gnu- --sysroot=/home/cks/linux_sdk/buildroot/output/rockchip_rk3399pro/host/aarch64-buildroot-linux-gnu/sysroot --host-cc=/usr/bin/gcc --arch=aarch64 --target-os=linux --disable-stripping --pkg-config=/home/cks/fireFlyLinuxSdk/firefly/linux_sdk/buildroot/output/rockchip_rk3399pro/host/bin/pkg-config --disable-static --enable-shared --prefix=/usr --enable-avfilter --enable-version3 --enable-logging --enable-optimizations --disable-extra-warnings --enable-avdevice --enable-avcodec --enable-avformat --enable-network --disable-gray --enable-swscale-alpha --disable-small --enable-dct --enable-fft --enable-mdct --enable-rdft --disable-crystalhd --disable-dxva2 --enable-runtime-cpudetect --disable-hardcoded-tables --disable-mipsdsp --disable-mipsdspr2 --disable-msa --enable-hwaccels --disable-cuda --disable-cuvid --disable-nvenc --disable-avisynth --disable-frei0r --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-libcdio --disable-libdc1394 --disable-libgsm --disable-libilbc --disable-libvo-amrwbenc --disable-symver --disable-doc --disable-gpl --disable-nonfree --enable-ffmpeg --disable-ffplay --disable-ffserver --disable-avresample --disable-ffprobe --disable-postproc --enable-swscale --enable-indevs --enable-alsa --enable-outdevs --enable-pthreads --enable-zlib --disable-bzlib --disable-libfdk-aac --disable-gnutls --enable-openssl --disable-libopenh264 --enable-libvorbis --enable-muxer=ogg --enable-encoder=libvorbis --disable-vaapi --disable-vdpau --enable-rkmpp --enable-libdrm --disable-decoder=h264_v4l2m2m --disable-decoder=vp8_v4l2m2m --disable-decoder=mpeg2_v4l2m2m --disable-decoder=mpeg4_v4l2m2m --disable-encoder=h264_v4l2m2m --disable-encoder=vp8_v4l2m2m --disable-encoder=mpeg2_v4l2m2m --disable-encoder=mpeg4_v4l2m2m --disable-mmal --disable-omx --disable-omx-rpi --disable-libopencv --disable-libopus --disable-libvpx --disable-libass --disable-libbluray --enable-librtmp --disable-libmp3lame --disable-libmodplug --disable-libspeex --enable-libtheora --disable-libwavpack --disable-iconv --enable-libfreetype --enable-fontconfig --disable-libopenjpeg --disable-libx264 --disable-libx265 --disable-x86asm --disable-mmx --disable-sse --disable-sse2 --disable-sse3 --disable-ssse3 --disable-sse4 --disable-sse42 --disable-avx --disable-avx2 --disable-armv6 --disable-armv6t2 --enable-vfp --enable-neon --disable-altivec --extra-libs=-latomic --enable-pic --cpu=cortex-a72.cortex-a53

特别留意 --enable-rkmpp --enable-libdrm 因为mpp依赖drm相关的framebuffer。

ffmpeg rkmpp依赖mpp库librockchip_mpp.so

故在configure中

enabled rkmpp             &&   require_pkg_config rockchip_mpp rockchip_mpp rockchip/rk_mpi.h mpp_create ||
                                 die "ERROR : Rockchip MPP was not found.";  &&
                                enabled libdrm ||
                                 die "ERROR: rkmpp requires --enable-libdrm"; 
                             

依赖mpp 的 pkg lib/pkgconfig/rockchip_mpp.pc

内容如下:

prefix=/usr
exec_prefix=$prefix
libdir=$prefix/lib
includedir=$prefix/include

Name: rockchip_mpp
Description: Rockchip Media Process Platform
Requires.private:
Version: 1.3.8
Libs: -L$libdir -lrockchip_mpp
Libs.private:
Cflags: -I$includedir

二、rkmpp解码移植

libavcodec/Makefile:344:OBJS-$(CONFIG_H264_RKMPP_DECODER)      += rkmppdec.o
libavcodec/Makefile:361:OBJS-$(CONFIG_HEVC_RKMPP_DECODER)      += rkmppdec.o
libavcodec/Makefile:641:OBJS-$(CONFIG_VP8_RKMPP_DECODER)       += rkmppdec.o
libavcodec/Makefile:650:OBJS-$(CONFIG_VP9_RKMPP_DECODER)       += rkmppdec.o

 libavcodec/rkmppdec.c 

1、声明h264_rkmpp解码器

#define RKMPP_DEC_CLASS(NAME) \\
    static const AVClass rkmpp_##NAME##_dec_class =  \\
        .class_name = "rkmpp_" #NAME "_dec", \\
        .version    = LIBAVUTIL_VERSION_INT, \\
    ;

#define RKMPP_DEC(NAME, ID, BSFS) \\
    RKMPP_DEC_CLASS(NAME) \\
    AVCodec ff_##NAME##_rkmpp_decoder =  \\
        .name           = #NAME "_rkmpp", \\ //这里其实就是h264_rkmpp
        .long_name      = NULL_IF_CONFIG_SMALL(#NAME " (rkmpp)"), \\
        .type           = AVMEDIA_TYPE_VIDEO, \\
        .id             = ID, \\
        .priv_data_size = sizeof(RKMPPDecodeContext), \\
        .init           = rkmpp_init_decoder, \\
        .close          = rkmpp_close_decoder, \\
        .receive_frame  = rkmpp_receive_frame, \\
        .flush          = rkmpp_flush, \\
        .priv_class     = &rkmpp_##NAME##_dec_class, \\
        .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \\
        .caps_internal  = AV_CODEC_CAP_AVOID_PROBING, \\
        .pix_fmts       = (const enum AVPixelFormat[])  AV_PIX_FMT_DRM_PRIME, \\
                                                         AV_PIX_FMT_NONE, \\
        .bsfs           = BSFS, \\
    ;

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)

2、注册解码器h264_rkmpp

libavcodec/allcodecs.c

static void register_all(void)

REGISTER_DECODER(H264_RKMPP, h264_rkmpp);

3、rkmpp实现ffmpeg相关解码(初始化送帧解码取解码后码流)

1)找到codec

codec = avcodec_find_decoder_by_name("h264_rkmpp");

打开codec到上下文avcodec_open2(acc, codec, NULL)

2)往codec送h264原始码流

avcodec_send_packet(acc, pkt);

这里实际上就调用到

libavcodec/rkmppdec.c

static int rkmpp_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)

ret = ff_decode_get_packet(avctx, &pkt);

if (ret < 0 && ret != AVERROR_EOF) 

return ret;





ret = rkmpp_send_packet(avctx, &pkt);

3)获取解码后数据

avcodec_receive_frame(acc, frame);

实际上调用到底层mpp接口

static int rkmpp_receive_frame(AVCodecContext *avctx, AVFrame *frame)

rkmpp_retrieve_frame(avctx, frame);

以上是关于RKMPP 在FFmpeg上实现硬编解码的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg 编译支持 neon 和 硬编解码

RKMPP库快速上手--MPP解码入门

ffmpeg硬件编解码Nvidia GPU

RKMPP库快速上手--RKMPP功能及使用详解

H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持

iOS硬编解码相关知识