MPP编码入门(后附demo代码链接)
mpp编码流程介绍
整个编码分为mpp_create,mpp_init,
再通过mpp的接口mpi->control接口来进行参数设置.一般需要配置三类信息:
码率控制方式(MPPEncRcCfg),通过命令MPP_ENC_RC_CFG配置;
输入控制配置(MppEncPrepCfg),通过命令MPP_ENC_SET_PREP_CFG配置;
协议控制配置(MppEncCodecCfg),通过命令MPP_ENC_SET_CODEC_CFG配置;
详细配置细节会在下面代码注释中给出。
配置完mpp以后就可以通过mpi->encode_put_frame向编码器输入图片(注:图像的格式和数据对其有着严格要求,具体细则会在后续给出),再通过mpi->encode_get_packet获取编码好的包,再写入相应文件即可。
为了方便理解和使用,我将mpp的编码封装成了一个class,只需要再定义对象时给出编码器初始化的数据(包括输入图像的首地址、数据格式、宽高,输出视频流的编码格式、FPS以及输出文件路径),后续的使用则只需要通过“process_image(uint8_t *p)”接口向对象喂图片即可,编码器会自动将图像编码然后存入视频流文件。
编码器class定义头文件
其中结构体“MPP_ENC_DATA ”为编码器create和init时所需要的数据,class中定义了它的一个变量,这样整个编码器的配置都可以由这个MPP_ENC_DATA变量给出。
编码器在定义时需要向构造函数提供:输出文件路径,输入图像的首地址、宽高、数据格式,输出视频流的编码格式、FPS以及gop等配置信息。
init_mpp() 用于初始化mpp编码器,它会在构造函数中调用;
destroy_mpp();用于销毁mpp编码器;
process_image(uint8_t *p);为用户使用接口,输出图像的首地址,编码图像并存入文件;
read_yuv_image 用于读取输入图像的内存中的数据,并且将其对齐成mpp所需要的按16位对齐的格式。文章来源:https://www.toymoban.com/news/detail-431130.html
#ifndef ENCODER_H
#define ENCODER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <string.h>
#include <errno.h>
#include <rk_mpi.h>
#include "mpp_err.h"
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
#define MPP_ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
struct MPP_ENC_DATA //编码所需要的数据
{
// global flow control flag
uint32_t frm_eos;
uint32_t pkt_eos;
uint32_t frame_count;
uint64_t stream_size;
// base flow context
MppCtx ctx;
MppApi *mpi;
MppEncPrepCfg prep_cfg;
MppEncRcCfg rc_cfg;
MppEncCodecCfg codec_cfg;
// input / output
MppBuffer frm_buf;
MppEncSeiMode sei_mode;
uint32_t width;
uint32_t height;
uint32_t hor_stride;
uint32_t ver_stride;
MppFrameFormat fmt = MPP_FMT_YUV422_YUYV;
MppCodingType type = MPP_VIDEO_CodingAVC;
uint32_t num_frames;
// resources
size_t frame_size;
int32_t gop = 60;
int32_t fps = 30;
int32_t bps;
FILE *fp_output;
};
class Encoder
{
public:
Encoder(char* outPutFileName, uint32_t width,uint32_t height,
MppFrameFormat fmt = MPP_FMT_YUV422_YUYV,
MppCodingType type = MPP_VIDEO_CodingAVC,
uint32_t fps = 30, uint32_t gop = 60);
~Encoder();
bool process_image(uint8_t *p);
private:
MPP_ENC_DATA mpp_enc_data;
MPP_RET read_yuv_image(uint8_t *buf, uint8_t *image, uint32_t width, uint32_t height,
uint32_t hor_stride, uint32_t ver_stride, MppFrameFormat fmt);
void init_mpp();
void destroy_mpp();
};
#endif // ENCODER_H
编码器class代码解读
构造函数:文章来源地址https://www.toymoban.com/news/detail-431130.html
//输入文件名、图像宽高、输入图像格式、输出视频流类型、fps、gop
Encoder::Encoder(char* outPutFileName,uint32_t width,uint32_t height,
MppFrameFormat fmt,MppCodingType type,
uint32_t fps, uint32_t gop)
{
memset(&mpp_enc_data, 0, sizeof(mpp_enc_data));
mpp_enc_data.width = width;
mpp_enc_data.height = height;
//mpp编码图像的行和列都是按16位对齐的,如果输出的行列不是16的整数,则需要在编码时将数据按照16位对齐。
//此函数就是为了得到行列补齐16整除的数据,比如行是30,通过MPP_ALIGN(30,16);的输出就是32;
mpp_enc_data.hor_stride = MPP_ALIGN
到了这里,关于RK3399Pro-硬件编解码器MPP库快速上手--(二)MPP编码入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!