视觉SLAM十四讲 Ubuntu20.04 Pangolin 环境配置

本文详细介绍了在Ubuntu 20.04环境下配置Pangolin用于视觉SLAM过程中遇到的AV_PIX_FMT_XVMC_MPEG2_MC和AVFMT_RAWPICTURE编译错误,提供了相应的代码修改建议。涉及修改FindFFMPEG.cmake和ffmpeg.cpp文件,以确保ORB-SLAM2的顺利编译。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

视觉SLAM十四讲 Ubuntu20.04 Pangolin 环境配置

一. github下载源代码

选择0.5版本的,要不然版本装高了编译ORB-SLAM2会遇到问题

二. 报错及处理

  1. error: ‘AV_PIX_FMT_XVMC_MPEG2_MC’ was not declared in this scope
    详细报错信息

/home/andy/Downloads/Pangolin/src/video/drivers/ffmpeg.cpp: In function ‘std::__cxx11::string pangolin::FfmpegFmtToString(AVPixelFormat)’:
/home/andy/Downloads/Pangolin/src/video/drivers/ffmpeg.cpp:41:41: error: ‘AV_PIX_FMT_XVMC_MPEG2_MC’ was not declared in this scope

参考:https://github.com/stevenlovegrove/Pangolin/pull/318/files?diff=split&w=0
解决办法:在/Pangolin/CMakeModules/FindFFMPEG.cmake中63,64行

        sizeof(AVFormatContext::max_analyze_duration2);
      }" HAVE_FFMPEG_MAX_ANALYZE_DURATION2

换成

        sizeof(AVFormatContext::max_analyze_duration);
      }" HAVE_FFMPEG_MAX_ANALYZE_DURATION

/Pangolin/src/video/drivers/ffmpeg.cpp中第37行 namespace pangolin上面加上

#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER

第78,79行

TEST_PIX_FMT_RETURN(XVMC_MPEG2_MC); 
TEST_PIX_FMT_RETURN(XVMC_MPEG2_IDCT);

改为

#ifdef FF_API_XVMC
    TEST_PIX_FMT_RETURN(XVMC_MPEG2_MC);
    TEST_PIX_FMT_RETURN(XVMC_MPEG2_IDCT);
#endif

101-105行

    TEST_PIX_FMT_RETURN(VDPAU_H264);
    TEST_PIX_FMT_RETURN(VDPAU_MPEG1);
    TEST_PIX_FMT_RETURN(VDPAU_MPEG2);
    TEST_PIX_FMT_RETURN(VDPAU_WMV3);
    TEST_PIX_FMT_RETURN(VDPAU_VC1);

改为

#ifdef FF_API_VDPAU
    TEST_PIX_FMT_RETURN(VDPAU_H264);
    TEST_PIX_FMT_RETURN(VDPAU_MPEG1);
    TEST_PIX_FMT_RETURN(VDPAU_MPEG2);
    TEST_PIX_FMT_RETURN(VDPAU_WMV3);
    TEST_PIX_FMT_RETURN(VDPAU_VC1);
#endif

127行

	TEST_PIX_FMT_RETURN(VDPAU_MPEG4);

改为

#ifdef FF_API_VDPAU
    TEST_PIX_FMT_RETURN(VDPAU_MPEG4);
#endif
  1. error: ‘AVFMT_RAWPICTURE’ was not declared in this scope

#define TEST_PIX_FMT_RETURN(fmt) case AV_PIX_FMT_##fmt: return #fmt; /home/andy/Downloads/Pangolin/src/video/drivers/ffmpeg.cpp: In member
function ‘void
pangolin::FfmpegVideoOutputStream::WriteFrame(AVFrame*)’:
/home/andy/Downloads/Pangolin/src/video/drivers/ffmpeg.cpp:572:39:
error: ‘AVFMT_RAWPICTURE’ was not declared in this scope
if (recorder.oc->oformat->flags & AVFMT_RAWPICTURE) {

解决办法,在Pangolin/include/pangolin/video/drivers/ffmpeg.h开头加上

#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#define AVFMT_RAWPICTURE 0x0020

参考: https://www.jianshu.com/p/da49a712410f

很抱歉,我无法提供完整的程序代码。但我可以给出一些参考: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/time.h> #include <linux/videodev2.h> #include "rk_mpi.h" #include "rk_venc.h" #define TAG "mpi_h264enc_test" #define VIDEO_WIDTH 1920 #define VIDEO_HEIGHT 1080 #define VIDEO_FPS 30 #define FRAME_NUM 1000 typedef struct { int fd; void *start; size_t length; } camera_t; static camera_t *camera_open(int id) { camera_t *camera = (camera_t *)malloc(sizeof(camera_t)); if (camera == NULL) { printf("[%s] malloc camera_t failed\n", TAG); return NULL; } char dev_name[16]; sprintf(dev_name, "/dev/video%d", id); camera->fd = open(dev_name, O_RDWR); if (camera->fd < 0) { printf("[%s] open %s failed\n", TAG, dev_name); free(camera); return NULL; } struct v4l2_capability cap; if (ioctl(camera->fd, VIDIOC_QUERYCAP, &cap) < 0) { printf("[%s] VIDIOC_QUERYCAP failed\n", TAG); close(camera->fd); free(camera); return NULL; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { printf("[%s] %s is not a video capture device\n", TAG, dev_name); close(camera->fd); free(camera); return NULL; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { printf("[%s] %s does not support streaming i/o\n", TAG, dev_name); close(camera->fd); free(camera); return NULL; } struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = VIDEO_WIDTH; fmt.fmt.pix.height = VIDEO_HEIGHT; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_NONE; if (ioctl(camera->fd, VIDIOC_S_FMT, &fmt) < 0) { printf("[%s] VIDIOC_S_FMT failed\n", TAG); close(camera->fd); free(camera); return NULL; } 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 (ioctl(camera->fd, VIDIOC_REQBUFS, &req) < 0) { printf("[%s] VIDIOC_REQBUFS failed\n", TAG); close(camera->fd); free(camera); return NULL; } struct v4l2_buffer buf; for (int i = 0; i < req.count; i++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(camera->fd, VIDIOC_QUERYBUF, &buf) < 0) { printf("[%s] VIDIOC_QUERYBUF failed\n", TAG); close(camera->fd); free(camera); return NULL; } camera->start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, camera->fd, buf.m.offset); if (camera->start == MAP_FAILED) { printf("[%s] mmap failed\n", TAG); close(camera->fd); free(camera); return NULL; } camera->length = buf.length; if (ioctl(camera->fd, VIDIOC_QBUF, &buf) < 0) { printf("[%s] VIDIOC_QBUF failed\n", TAG); munmap(camera->start, camera->length); close(camera->fd); free(camera); return NULL; } } enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(camera->fd, VIDIOC_STREAMON, &type) < 0) { printf("[%s] VIDIOC_STREAMON failed\n", TAG); close(camera->fd); free(camera); return NULL; } return camera; } static void camera_close(camera_t *camera) { if (camera != NULL) { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ioctl(camera->fd, VIDIOC_STREAMOFF, &type); for (int i = 0; i < 4; i++) { munmap(camera->start, camera->length); } close(camera->fd); free(camera); } } static int camera_capture(camera_t *camera, unsigned char *buffer, int *length) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(camera->fd, VIDIOC_DQBUF, &buf) < 0) { return -1; } memcpy(buffer, camera->start, buf.bytesused); *length = buf.bytesused; if (ioctl(camera->fd, VIDIOC_QBUF, &buf) < 0) { return -1; } return 0; } static void *camera_thread(void *arg) { camera_t *camera = (camera_t *)arg; unsigned char *buffer = (unsigned char *)malloc(camera->length); if (buffer == NULL) { printf("[%s] malloc buffer failed\n", TAG); return NULL; } int length = 0; while (1) { if (camera_capture(camera, buffer, &length) == 0) { // do something with captured frame } usleep(1000); } free(buffer); return NULL; } int main(int argc, char **argv) { RK_MPI_SYS_Init(); RK_U32 u32Width = VIDEO_WIDTH; RK_U32 u32Height = VIDEO_HEIGHT; RK_U32 u32Fps = VIDEO_FPS; RK_U32 u32BitRate = u32Width * u32Height * 3 / 2 * u32Fps; RK_U32 u32KeyFrameInterval = u32Fps; RK_U32 u32Profile = 66; // H264 PROFILE_HIGH MPP_CHN_S stChnAttr; stChnAttr.mChnId = 0; stChnAttr.mModId = RK_ID_VENC; stChnAttr.mDevId = 0; stChnAttr.mWidth = u32Width; stChnAttr.mHeight = u32Height; stChnAttr.mFps = u32Fps; stChnAttr.mBitRate = u32BitRate; stChnAttr.mProfile = u32Profile; stChnAttr.mLevel = 41; // H264 LEVEL4_1 stChnAttr.mPixelFormat = RK_FMT_YUV420SP; stChnAttr.mRotation = 0; stChnAttr.mMirror = 0; stChnAttr.mFlip = 0; stChnAttr.mDrmMode = 0; stChnAttr.mDrmFd = -1; if (RK_MPI_VENC_CreateChn(0, &stChnAttr) != RK_SUCCESS) { printf("[%s] create venc chn failed\n", TAG); return -1; } if (RK_MPI_VENC_RegisterChn(0, 0, 0) != RK_SUCCESS) { printf("[%s] register venc chn failed\n", TAG); return -1; } MPP_CHN_S stSrcChn; stSrcChn.mModId = RK_ID_VI; stSrcChn.mDevId = 0; stSrcChn.mChnId = 0; MPP_CHN_S stDestChn; stDestChn.mModId = RK_ID_VENC; stDestChn.mDevId = 0; stDestChn.mChnId = 0; RK_MPI_SYS_Bind(&stSrcChn, &stDestChn); camera_t *camera = camera_open(0); if (camera != NULL) { pthread_t tid; pthread_create(&tid, NULL, camera_thread, camera); } RK_S32 s32Ret = RK_SUCCESS; MPP_FRAME_S stFrame; memset(&stFrame, 0, sizeof(stFrame)); stFrame.mModId = RK_ID_VENC; stFrame.mChannelId = 0; stFrame.mWidth = u32Width; stFrame.mHeight = u32Height; stFrame.mField = RK_FIELD_NONE; stFrame.mFrameType = RK_CODEC_FRAME_SPS_PPS_I; stFrame.mCompressMode = COMPRESS_MODE_NONE; stFrame.mBitWidth = 10; stFrame.mColor = MPP_FMT_YUV420SP; for (int i = 0; i < FRAME_NUM; i++) { s32Ret = RK_MPI_VENC_GetFrm(0, &stFrame, RK_TRUE); if (s32Ret != RK_SUCCESS) { printf("[%s] venc get frame failed\n", TAG); goto done; } unsigned char *y = (unsigned char *)stFrame.mVirAddr[0]; unsigned char *uv = (unsigned char *)stFrame.mVirAddr[1]; int y_len = stFrame.mWidth * stFrame.mHeight; int uv_len = stFrame.mWidth * stFrame.mHeight / 2; RK_MPI_VENC_RcCfg rc_cfg; memset(&rc_cfg, 0, sizeof(rc_cfg)); rc_cfg.mRcMode = VENC_RC_MODE_H264CBR; rc_cfg.mBitRate = u32BitRate; rc_cfg.mFrmRate = u32Fps; rc_cfg.mGop = u32KeyFrameInterval; rc_cfg.mQpMin = 30; rc_cfg.mQpMax = 51; rc_cfg.mQpInit = 35; rc_cfg.mMaxReEncodeTimes = 5; rc_cfg.mMaxQPDelta = 10; rc_cfg.mMaxBitRateTolerance = 1000; RK_MPI_VENC_SetRcCfg(0, &rc_cfg); RK_MPI_VENC_H264Cfg h264_cfg; memset(&h264_cfg, 0, sizeof(h264_cfg)); h264_cfg.mProfile = u32Profile; h264_cfg.mLevel = 41; h264_cfg.mEntropyMode = VENC_ENTROPY_MODE_CABAC; h264_cfg.mCabacInitIdc = 0; h264_cfg.mSliceNum = 2; h264_cfg.mSliceMode = VENC_H264_SLICEMODE_SINGLE; RK_MPI_VENC_SetH264Cfg(0, &h264_cfg); RK_MPI_VENC_H264Vui h264_vui; memset(&h264_vui, 0, sizeof(h264_vui)); h264_vui.mAspectRatioIdc = 0; h264_vui.mOverScanInfo = 0; h264_vui.mBitstreamRestriction = 0; RK_MPI_VENC_SetH264Vui(0, &h264_vui); RK_MPI_VENC_H264Sei h264_sei; memset(&h264_sei, 0, sizeof(h264_sei)); h264_sei.mRecoveryPoint = 0; h264_sei.mRecoveryPointInfoPresent = 0; h264_sei.mBufferingPeriod = 0; h264_sei.mPictureTiming = 0; RK_MPI_VENC_SetH264Sei(0, &h264_sei); MPP_ENC_CFG_S stMppEncCfg; memset(&stMppEncCfg, 0, sizeof(stMppEncCfg)); stMppEncCfg.mRcCfg = &rc_cfg; stMppEncCfg.mGopCfg = NULL; stMppEncCfg.mH264Cfg = &h264_cfg; stMppEncCfg.mH264VuiCfg = &h264_vui; stMppEncCfg.mH264SeiCfg = &h264_sei; RK_MPI_VENC_SetMppCfg(0, &stMppEncCfg); MPP_ENC_SEI_S stEncSei; memset(&stEncSei, 0, sizeof(stEncSei)); stEncSei.mEncSeiMode = MPP_ENC_SEI_MODE_ALL; RK_MPI_VENC_SetExtCfg(0, ENC_CFG_SEI, &stEncSei); RK_MPI_VENC_SendFrame(0, y, uv, y_len, uv_len); RK_MPI_VENC_ReleaseFrm(0, &stFrame); usleep(1000 * 1000 / u32Fps); } done: if (RK_MPI_VENC_UnRegisterChn(0, 0, 0) != RK_SUCCESS) { printf("[%s] unregister venc chn failed\n", TAG); } if (RK_MPI_VENC_DestroyChn(0) != RK_SUCCESS) { printf("[%s] destroy venc chn failed\n", TAG); } RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn); if (camera != NULL) { camera_close(camera); } RK_MPI_SYS_Exit(); return 0; } ``` 这是一个基于 Rockchip RK3399 平台的 H.264 编码程序,程序中包含了使用 MPP 接口对 H.264 编码器进行配置的相关代码,可以根据需要进行修改。注意,本程序只是一个示例程序,不保证可以直接编译通过并运行。
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值