rk3399rkmpp在ffmpeg上实现硬编解码
⼀、编译指令:
--enable-cross-compile --cross-prefix=/home/cks/fireFlyLinuxSdk/firefly/linux_sdk/buildroot/output/rockchip_rk3399pro/host/bin/aarch64-buildroot-linux-gnu---sysroot=/home/cks/fireFlyLinuxSdk/firefly/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/pk g-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 --en able-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-libo pencore-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-in devs --enable-alsa --enable-outdevs --enable-pthreads --enable-zlib --disable-bzlib --disable-libfdk-aac --disable-gnutls --enable-openssl --disable-libopenh 264 --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_v4l2 m2m --disable-encoder=vp8_v4l2m2m --disable-encoder=mpeg2_v4l2m2m --disable-encoder=mpeg4_v4l2m2m --disable-mmal --disable-omx --disable-o mx-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 --dis able-libx265 --disable-x86asm --disable-mmx --disable-sse --disable-sse2 --disable-sse3 --disable-ssse3 --disable-sse4 --disable-sse42 --disable-avx --dis able-avx2 --disable-armv6 --disable-armv6t2 --enable-vfp --enable-neon --disable-altivec --extra-libs=-latomic --enable-pic ---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解码器decoder
#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);