基于RK3399的MPP库实现的视频编码

Posted Geek.Fan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于RK3399的MPP库实现的视频编码相关的知识,希望对你有一定的参考价值。

        本项目实现主要是通过对采集的摄像头或相机输入的视频数据,经过RKMPP的MPP库接口实现视频编码,输出H264的编码数据。

代码实现如下:

camerareader.h

#ifndef CAMERAREADER_H
#define CAMERAREADER_H

#include <stdint.h>

class CameraReader


public:
    CameraReader();

    void start();

private:
    bool process_image(uint8_t *p, int size);
    int read_frame(int fd);
    void main_loop(int fd);
    void stop_capturing(int fd);
    int start_capturing(int fd);
    void uninit_device(void);
    int init_read(unsigned int buffer_size);
    int init_mmap(int fd);
    int init_device(int fd);
    void init_mpp();
    void close_device(int fd);
    void destroy_mpp();
    int open_device(void);

private:
    int camera_fd;
;

#endif // CAMERAREADER_H

 camerareader.c

#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 "camerareader.h"

#define CAMERA_WIDTH 1280
#define CAMERA_HEIGHT 720
#define FORCE_FORMAT 1
#define DEVICE_FILE "/dev/video1"
#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;
	MppCodingType type;
	uint32_t num_frames;

	// resources
	size_t frame_size;

	int32_t gop;
	int32_t fps;
	int32_t bps;

	FILE *fp_output;
;

enum IO_METHOD

    IO_METHOD_READ,
    IO_METHOD_MMAP,
    //IO_METHOD_USERPTR,
;

struct buffer

    void   *start;
    size_t  length;
;

static struct buffer *buffers;
static unsigned int n_buffers;
static IO_METHOD io_method;

static MPP_ENC_DATA mpp_enc_data;

CameraReader::CameraReader()




static void cleanup(void *p)

    free(p);


static int xioctl(int fh, int request, void *arg)

    int r;
    do
    
        r = ioctl(fh, request, arg);
     while (-1 == r && EINTR == errno);

    return r;


static uint8_t check_pix(int a)

    if(a < 0)
        a = 0;
    else if(a > 255)
        a = 255;

    return a;



bool CameraReader::process_image(uint8_t *p, int size)

	MPP_RET ret = MPP_OK;
    if(size != CAMERA_WIDTH * CAMERA_HEIGHT * 2)
    
        fprintf(stderr, "Invalid image data buffer!\\n");
        return true;
    

    MppFrame frame = NULL;
    MppPacket packet = NULL;
    void *buf = mpp_buffer_get_ptr(mpp_enc_data.frm_buf);

    //TODO: improve performance here?
    memcpy(buf, p, size);

    ret = mpp_frame_init(&frame);
    if (ret)
    
    	printf("mpp_frame_init failed\\n");
    	return true;
    

    mpp_frame_set_width(frame, mpp_enc_data.width);
    mpp_frame_set_height(frame, mpp_enc_data.height);
    mpp_frame_set_hor_stride(frame, mpp_enc_data.hor_stride);
    mpp_frame_set_ver_stride(frame, mpp_enc_data.ver_stride);
    mpp_frame_set_fmt(frame, mpp_enc_data.fmt);
    mpp_frame_set_buffer(frame, mpp_enc_data.frm_buf);
    mpp_frame_set_eos(frame, mpp_enc_data.frm_eos);

    ret = mpp_enc_data.mpi->encode_put_frame(mpp_enc_data.ctx, frame);
    if (ret)
    
    	printf("mpp encode put frame failed\\n");
    	return true;
    

    ret = mpp_enc_data.mpi->encode_get_packet(mpp_enc_data.ctx, &packet);
    if (ret)
    
    	printf("mpp encode get packet failed\\n");
    	return true;
    

    if (packet)
    
    	// write packet to file here
    	void *ptr   = mpp_packet_get_pos(packet);
    	size_t len  = mpp_packet_get_length(packet);

    	mpp_enc_data.pkt_eos = mpp_packet_get_eos(packet);

    	if (mpp_enc_data.fp_output)
    		fwrite(ptr, 1, len, mpp_enc_data.fp_output);
    	mpp_packet_deinit(&packet);

    	printf("encoded frame %d size %d\\n", mpp_enc_data.frame_count, len);
    	mpp_enc_data.stream_size += len;
    	mpp_enc_data.frame_count++;

    	if (mpp_enc_data.pkt_eos)
    	
    		printf("found last packet\\n");
    	
    

    if (mpp_enc_data.num_frames && mpp_enc_data.frame_count >= mpp_enc_data.num_frames)
    
    	printf("encode max %d frames", mpp_enc_data.frame_count);
    	return false;
    

    if (mpp_enc_data.frm_eos && mpp_enc_data.pkt_eos)
    	return false;

    return true;


int CameraReader::read_frame(int fd)

    struct v4l2_buffer buf;

    switch (io_method)
    
    case IO_METHOD_READ:
        if (read(fd, buffers[0].start, buffers[0].length) == -1)
        
            if(errno == EAGAIN || errno == EINTR)
            
                return 0;
            
            else
            
                fprintf(stderr, "read failed: %d, %s\\n", errno, strerror(errno));
                return -1;
            
        

        if(!process_image((uint8_t*)buffers[0].start, buffers[0].length))
        
        	return -2;
        
        break;

    case IO_METHOD_MMAP:
        memset(&buf, 0, sizeof(buf));

        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;

        if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1)
        
            if(errno == EAGAIN || errno == EINTR)
            
                return 0;
            
            else
            
                fprintf(stderr, "set VIDIOC_DQBUF failed: %d, %s\\n", errno, strerror(errno));
                return -1;
            
        

        if(buf.index < n_buffers)
        
            if(!process_image((uint8_t*)buffers[buf.index].start, buf.bytesused))
            
            	return -2;
            
            if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
            
                fprintf(stderr, "set VIDIOC_QBUF failed: %d, %s\\n", errno, strerror(errno));
                return -1;
            
        
        break;
    

    return 0;


void CameraReader::main_loop(int fd)

    int r;
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    for (;;)
    
        struct timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 0;

        fd_set rdset = fds;

        r = select(fd + 1, &rdset, NULL, NULL, &tv);

        if(r > 0)
        
            if(read_frame(fd) == -2)
            	break;
        
        else if(r == 0)
        
            fprintf(stderr, "select timeout\\\\n");
        
        else
        
            if (EINTR == errno || EAGAIN == errno)
                continue;
            fprintf(stderr, "select failed: %d, %s\\n", errno, strerror(errno));
            break;
        
        /* EAGAIN - continue select loop. */
    


void CameraReader::stop_capturing(int fd)

    enum v4l2_buf_type type;

    switch (io_method)
    
    case IO_METHOD_READ:
        /* Nothing to do. */
        break;
    case IO_METHOD_MMAP:
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        xioctl(fd, VIDIOC_STREAMOFF, &type);
        break;
    


int CameraReader::start_capturing(int fd)

    unsigned int i;
    enum v4l2_buf_type type;

    switch (io_method)
    
    case IO_METHOD_READ:
        /* Nothing to do. */
        break;
    case IO_METHOD_MMAP:
        for (i = 0; i < n_buffers; ++i)
        
            struct v4l2_buffer buf;
            memset(&buf, 0, sizeof(buf));

            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            buf.index = i;

            if (xioctl(fd, VIDIOC_QBUF, &buf) == -1)
            
                fprintf(stderr, "set VIDIOC_QBUF failed: %d, %s\\n", errno, strerror(errno));
                return -1;
            
        
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (xioctl(fd, VIDIOC_STREAMON, &type) == -1)
        
            fprintf(stderr, "set VIDIOC_STREAMON failed: %d, %s\\n", errno, strerror(errno));
            return -1;
        
        break;
    

    return 0;


void CameraReader::uninit_device(void)

    unsigned int i;

    switch (io_method)
    
    case IO_METHOD_READ:
        free(buffers[0].start);
        break;
    case IO_METHOD_MMAP:
        for (i = 0; i < n_buffers; ++i)
            munmap(buffers[i].start, buffers[i].length);
        break;
    

    free(buffers);


int CameraReader::init_read(unsigned int buffer_size)

    buffers = (buffer*)calloc(1, sizeof(*buffers));

    if (!buffers)
    
        fprintf(stderr, "Out of memory\\n");
        return -1;
    

    buffers[0].length = buffer_size;
    buffers[0].start = malloc(buffer_size);

    if (!buffers[0].start)
    
        fprintf(stderr, "Out of memory\\n");
        return -1;
    

    return 0;


int CameraReader::init_mmap(int fd)

    struct v4l2_requestbuffers req;
    memset(&req, 0, sizeof(req));

    req.count = 4;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

    if(xioctl(fd, VIDIOC_REQBUFS, &req) == -1)
    
        fprintf(stderr, "set VIDIOC_REQBUFS failed: %d, %s\\n", errno, strerror(errno));
        return -1;
    

    if (req.count < 2)
    
        fprintf(stderr, "Insufficient buffer memory on %s\\n",
                DEVICE_FILE);
        return -1;
    

    buffers = (buffer*)calloc(req.count, sizeof(*buffers));

    if (!buffers)
    
        fprintf(stderr, "Out of memory\\n");
        return -1;
    

    for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
    
        struct v4l2_buffer buf;
        memset(&buf, 0, sizeof(buf));

        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = n_buffers;

        if (xioctl(fd, VIDIOC_QUERYBUF, &buf) == -1)
        
            fprintf(stderr, "set VIDIOC_QUERYBUF %u failed: %d, %s\\n", n_buffers, errno, strerror(errno));
            return -1;
        

        buffers[n_buffers].length = buf.length;
        buffers[n_buffers].start =
                mmap(NULL /* start anywhere */,
                     buf.length,
                     PROT_READ | PROT_WRITE /* required */,
                     MAP_SHARED /* recommended */,
                     fd, buf.m.offset);

        if (MAP_FAILED == buffers[n_buffers].start)
        
            fprintf(stderr, "mmap %u failed: %d, %s\\n", n_buffers, errno, strerror(errno));
            return -1;
        
    

    return 0;


void CameraReader::init_mpp()

	MPP_RET ret = MPP_OK;
	memset(&mpp_enc_data, 0, sizeof(mpp_enc_data));

	mpp_enc_data.width = CAMERA_WIDTH;
	mpp_enc_data.height = CAMERA_HEIGHT;
	mpp_enc_data.hor_stride = MPP_ALIGN(mpp_enc_data.width, 16);
	mpp_enc_data.ver_stride = MPP_ALIGN(mpp_enc_data.height, 16);
	mpp_enc_data.fmt = MPP_FMT_YUV422_YUYV;
	mpp_enc_data.frame_size = mpp_enc_data.hor_stride * mpp_enc_data.ver_stride * 2;
	mpp_enc_data.type = MPP_VIDEO_CodingAVC;
	mpp_enc_data.num_frames = 2000;

	ret = mpp_buffer_get(NULL, &mpp_enc_data.frm_buf, mpp_enc_data.frame_size);
	if (ret)
	
		printf("failed to get buffer for input frame ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	ret = mpp_create(&mpp_enc_data.ctx, &mpp_enc_data.mpi);
	if (ret)
	
		printf("mpp_create failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	ret = mpp_init(mpp_enc_data.ctx, MPP_CTX_ENC, mpp_enc_data.type);
	if (ret)
	
		printf("mpp_init failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	mpp_enc_data.fps = 20;
	mpp_enc_data.gop = 60;
	mpp_enc_data.bps = mpp_enc_data.width * mpp_enc_data.height / 8 * mpp_enc_data.fps;

	mpp_enc_data.prep_cfg.change        = MPP_ENC_PREP_CFG_CHANGE_INPUT |
			MPP_ENC_PREP_CFG_CHANGE_ROTATION |
			MPP_ENC_PREP_CFG_CHANGE_FORMAT;
	mpp_enc_data.prep_cfg.width         = mpp_enc_data.width;
	mpp_enc_data.prep_cfg.height        = mpp_enc_data.height;
	mpp_enc_data.prep_cfg.hor_stride    = mpp_enc_data.hor_stride;
	mpp_enc_data.prep_cfg.ver_stride    = mpp_enc_data.ver_stride;
	mpp_enc_data.prep_cfg.format        = mpp_enc_data.fmt;
	mpp_enc_data.prep_cfg.rotation      = MPP_ENC_ROT_0;
	ret = mpp_enc_data.mpi->control(mpp_enc_data.ctx, MPP_ENC_SET_PREP_CFG, &mpp_enc_data.prep_cfg);
	if (ret)
	
		printf("mpi control enc set prep cfg failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	mpp_enc_data.rc_cfg.change  = MPP_ENC_RC_CFG_CHANGE_ALL;
	mpp_enc_data.rc_cfg.rc_mode = MPP_ENC_RC_MODE_CBR;
	mpp_enc_data.rc_cfg.quality = MPP_ENC_RC_QUALITY_MEDIUM;

	if (mpp_enc_data.rc_cfg.rc_mode == MPP_ENC_RC_MODE_CBR)
	
		/* constant bitrate has very small bps range of 1/16 bps */
		mpp_enc_data.rc_cfg.bps_target   = mpp_enc_data.bps;
		mpp_enc_data.rc_cfg.bps_max      = mpp_enc_data.bps * 17 / 16;
		mpp_enc_data.rc_cfg.bps_min      = mpp_enc_data.bps * 15 / 16;
	
	else if (mpp_enc_data.rc_cfg.rc_mode ==  MPP_ENC_RC_MODE_VBR)
	
		if (mpp_enc_data.rc_cfg.quality == MPP_ENC_RC_QUALITY_CQP)
		
			/* constant QP does not have bps */
			mpp_enc_data.rc_cfg.bps_target   = -1;
			mpp_enc_data.rc_cfg.bps_max      = -1;
			mpp_enc_data.rc_cfg.bps_min      = -1;
		
		else
		
			/* variable bitrate has large bps range */
			mpp_enc_data.rc_cfg.bps_target   = mpp_enc_data.bps;
			mpp_enc_data.rc_cfg.bps_max      = mpp_enc_data.bps * 17 / 16;
			mpp_enc_data.rc_cfg.bps_min      = mpp_enc_data.bps * 1 / 16;
		
	

	/* fix input / output frame rate */
	mpp_enc_data.rc_cfg.fps_in_flex      = 0;
	mpp_enc_data.rc_cfg.fps_in_num       = mpp_enc_data.fps;
	mpp_enc_data.rc_cfg.fps_in_denorm    = 1;
	mpp_enc_data.rc_cfg.fps_out_flex     = 0;
	mpp_enc_data.rc_cfg.fps_out_num      = mpp_enc_data.fps;
	mpp_enc_data.rc_cfg.fps_out_denorm   = 1;

	mpp_enc_data.rc_cfg.gop              = mpp_enc_data.gop;
	mpp_enc_data.rc_cfg.skip_cnt         = 0;

	ret = mpp_enc_data.mpi->control(mpp_enc_data.ctx, MPP_ENC_SET_RC_CFG, &mpp_enc_data.rc_cfg);
	if (ret)
	
		printf("mpi control enc set rc cfg failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	mpp_enc_data.codec_cfg.coding = mpp_enc_data.type;
	switch (mpp_enc_data.codec_cfg.coding)
	
	case MPP_VIDEO_CodingAVC :
	
		mpp_enc_data.codec_cfg.h264.change = MPP_ENC_H264_CFG_CHANGE_PROFILE |
				MPP_ENC_H264_CFG_CHANGE_ENTROPY |
				MPP_ENC_H264_CFG_CHANGE_TRANS_8x8;
		/*
		 * H.264 profile_idc parameter
		 * 66  - Baseline profile
		 * 77  - Main profile
		 * 100 - High profile
		 */
		mpp_enc_data.codec_cfg.h264.profile  = 100;
		/*
		 * H.264 level_idc parameter
		 * 10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
		 * 20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
		 * 30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
		 * 40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
		 * 50 / 51 / 52         - 4K@30fps
		 */
		mpp_enc_data.codec_cfg.h264.level    = 31;
		mpp_enc_data.codec_cfg.h264.entropy_coding_mode  = 1;
		mpp_enc_data.codec_cfg.h264.cabac_init_idc  = 0;
		mpp_enc_data.codec_cfg.h264.transform8x8_mode = 1;
	
	break;
	case MPP_VIDEO_CodingMJPEG :
	
		mpp_enc_data.codec_cfg.jpeg.change  = MPP_ENC_JPEG_CFG_CHANGE_QP;
		mpp_enc_data.codec_cfg.jpeg.quant   = 10;
	
	break;
	case MPP_VIDEO_CodingVP8 :
	case MPP_VIDEO_CodingHEVC :
	default :
	
		printf("support encoder coding type %d\\n", mpp_enc_data.codec_cfg.coding);
	
	break;
	
	ret = mpp_enc_data.mpi->control(mpp_enc_data.ctx, MPP_ENC_SET_CODEC_CFG, &mpp_enc_data.codec_cfg);
	if (ret)
	
		printf("mpi control enc set codec cfg failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	/* optional */
	mpp_enc_data.sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
	ret = mpp_enc_data.mpi->control(mpp_enc_data.ctx, MPP_ENC_SET_SEI_CFG, &mpp_enc_data.sei_mode);
	if (ret)
	
		printf("mpi control enc set sei cfg failed ret %d\\n", ret);
		goto MPP_INIT_OUT;
	

	mpp_enc_data.fp_output = fopen("/tmp/output.h264", "wb+");
	if (mpp_enc_data.type == MPP_VIDEO_CodingAVC)
	
		MppPacket packet = NULL;
		ret = mpp_enc_data.mpi->control(mpp_enc_data.ctx, MPP_ENC_GET_EXTRA_INFO, &packet);
		if (ret)
		
			printf("mpi control enc get extra info failed\\n");
			goto MPP_INIT_OUT;
		

		/* get and write sps/pps for H.264 */
		if (packet)
		
			void *ptr   = mpp_packet_get_pos(packet);
			size_t len  = mpp_packet_get_length(packet);

			if (mpp_enc_data.fp_output)
				fwrite(ptr, 1, len, mpp_enc_data.fp_output);

			packet = NULL;
		
	

	return;

MPP_INIT_OUT:

    if (mpp_enc_data.ctx)
    
        mpp_destroy(mpp_enc_data.ctx);
        mpp_enc_data.ctx = NULL;
    

    if (mpp_enc_data.frm_buf)
    
        mpp_buffer_put(mpp_enc_data.frm_buf);
        mpp_enc_data.frm_buf = NULL;
    

    printf("init mpp failed!\\n");


void CameraReader::destroy_mpp()

	MPP_RET ret = MPP_OK;
	ret = mpp_enc_data.mpi->reset(mpp_enc_data.ctx);
	if (ret)
	
		printf("mpi->reset failed\\n");
	

	if (mpp_enc_data.ctx)
	
		mpp_destroy(mpp_enc_data.ctx);
		mpp_enc_data.ctx = NULL;
	

	if (mpp_enc_data.frm_buf)
	
		mpp_buffer_put(mpp_enc_data.frm_buf);
		mpp_enc_data.frm_buf = NULL;
	

	fclose(mpp_enc_data.fp_output);


int CameraReader::init_device(int fd)

    struct v4l2_capability cap;
    struct v4l2_cropcap cropcap;
    struct v4l2_crop crop;
    struct v4l2_format fmt;
    unsigned int min;

    if(xioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)
    
        fprintf(stderr, "get VIDIOC_QUERYCAP error: %d, %s\\n", errno, strerror(errno));
        return -1;
    

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
    
        fprintf(stderr, "%s is not video capture device\\n",
                DEVICE_FILE);
        return -1;
    

    if (!(cap.capabilities & V4L2_CAP_STREAMING))
    
        fprintf(stderr, "%s does not support streaming i/o\\n", DEVICE_FILE);

        if (!(cap.capabilities & V4L2_CAP_READWRITE))
        
            fprintf(stderr, "%s does not support read i/o\\n", DEVICE_FILE);
            return -1;
        
        io_method = IO_METHOD_READ;
    
    else
    
        io_method = IO_METHOD_MMAP;
    


    /* Select video input, video standard and tune here. */


    memset(&cropcap, 0, sizeof(cropcap));
    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (xioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
    
        memset(&crop, 0, sizeof(crop));
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c = cropcap.defrect; /* reset to default */

        if (xioctl(fd, VIDIOC_S_CROP, &crop) == -1)
        
            fprintf(stderr, "set VIDIOC_S_CROP failed: %d, %s\\n", errno, strerror(errno));
        
    
    else
    
        fprintf(stderr, "get VIDIOC_CROPCAP failed: %d, %s\\n", errno, strerror(errno));
    

    /* Enum pixel format */
    for(int i=0; i<20; i++)
    
        struct v4l2_fmtdesc fmtdesc;
        fmtdesc.index = i;
        fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if(xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == -1)
            break;

        printf("%d: %s\\n", i, fmtdesc.description);
    


    memset(&fmt, 0, sizeof(fmt));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (FORCE_FORMAT)
    
        fmt.fmt.pix.width       = CAMERA_WIDTH;
        fmt.fmt.pix.height      = CAMERA_HEIGHT;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;

        if (xioctl(fd, VIDIOC_S_FMT, &fmt) == -1)
        
            fprintf(stderr, "get VIDIOC_S_FMT failed: %d, %s\\n", errno, strerror(errno));
            return -1;
        

        /* Note VIDIOC_S_FMT may change width and height. */
    
    else
    
        /* Preserve original settings as set by v4l2-ctl for example */
        if (xioctl(fd, VIDIOC_G_FMT, &fmt) == -1)
        
            fprintf(stderr, "get VIDIOC_G_FMT failed: %d, %s\\n", errno, strerror(errno));
            return -1;
        
    

    /* Buggy driver paranoia. */
    min = fmt.fmt.pix.width * 2;
    if (fmt.fmt.pix.bytesperline < min)
        fmt.fmt.pix.bytesperline = min;
    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
    if (fmt.fmt.pix.sizeimage < min)
        fmt.fmt.pix.sizeimage = min;

    if(io_method == IO_METHOD_MMAP)
        return init_mmap(fd);
    else
        return init_read(fmt.fmt.pix.sizeimage);


void CameraReader::close_device(int fd)

    close(fd);


int CameraReader::open_device(void)

    struct stat st;
    if (stat(DEVICE_FILE, &st) == -1)
    
        fprintf(stderr, "Cannot identify '%s': %d, %s\\n",
                DEVICE_FILE, errno, strerror(errno));
        return -1;
    

    if (!S_ISCHR(st.st_mode))
    
        fprintf(stderr, "%s is not device", DEVICE_FILE);
        return -1;
    

    int fd = open(DEVICE_FILE, O_RDWR /* required */ | O_NONBLOCK, 0);
    if (fd == -1)
    
        fprintf(stderr, "Cannot open '%s': %d, %s\\\\n",
                DEVICE_FILE, errno, strerror(errno));
        return -1;
    

    return fd;


void CameraReader::start()

    camera_fd = open_device();
    init_device(camera_fd);
    init_mpp();
    start_capturing(camera_fd);
    main_loop(camera_fd);
    stop_capturing(camera_fd);
    destroy_mpp();
    uninit_device();
    close_device(camera_fd);

main.cpp

#include "camerareader.h"


int main(int argc, char *argv[])

	CameraReader reader;
	reader.start();
    return 0;

以上是关于基于RK3399的MPP库实现的视频编码的主要内容,如果未能解决你的问题,请参考以下文章

基于rk3399 (Linux)的多视频窗口播放器

多路RTSP流解码:最高可支持12路视频编解码

基于RK3399OpenHarmony富设备软件音频解码方案

友善RK3399/NanoPC-T4开发板wiringPi Python库访问GPIO外设实例讲解 -申嵌视频

RK3399应用开发 | 编译安装 mesa 3D 图形库(23.0.0)

RK3399应用开发 | 编译安装 mesa 3D 图形库(23.0.0)