V4L2(Video for Linux2), 是专门为 linux 设备设计的一套视频框架。
以下代码包括uvc摄像头的V4L2视频捕获与h264软编码(使用x264库)
v4l2_video.h
#ifndef V4L2_VIDEO_H
#define V4L2_VIDEO_H
#include
#include
#include
#include "x264.h"
class V4L2_Video : public QObject
{
Q_OBJECT
public:
explicit V4L2_Video(QObject *parent = nullptr);
int init();
void start();
void stop();
int release();
int video_read(char **buffer, int *buffer_size);
int get_width();
int get_height();
int get_fps();
private:
typedef struct VideoBuffer
{
uint8_t *start;
unsigned int length;
enum nal_unit_type_e type;
}VideoBuffer;
int fd;
VideoBuffer *video_buffer;
bool m_is_start;
std::queue m_encode_queue; // 等待编码的帧队列
std::queue m_send_queue; // 等待发送的帧队列
pthread_mutex_t m_encode_queue_lock;
pthread_mutex_t m_send_queue_lock;
int frameHandle(VideoBuffer v_buffer);
void yuyv422ToYuv420p(int inWidth, int inHeight, uint8_t *pSrc, uint8_t *pDest);
static void *frame_process_thread(void *ptr);
static void *yuyv422_to_H264_thread(void *ptr);
signals:
public slots:
};
#endif // V4L2_VIDEO_H
v4l2_video.cpp
#include "v4l2_video.h"
#include
#include
#include
#include
#include
#include "mainwidget.h"
#define VIDEO_FILE "/dev/video8"
#define IMAGEWIDTH 640
#define IMAGEHEIGHT 480
#define VIDEO_FPS 25
#define ENCODE_QUEUE_FRAME_NUM 4
#define SEND_QUEUE_FRAME_NUM ENCODE_QUEUE_FRAME_NUM * 8
V4L2_Video::V4L2_Video(QObject *parent) : QObject(parent)
{
m_is_start = false;
pthread_mutex_init(&m_encode_queue_lock, nullptr);
pthread_mutex_init(&m_send_queue_lock, nullptr);
}
int V4L2_Video::init()
{
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_streamparm stream_parm;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
unsigned int buffer_n;
pthread_t thread_id;
int ret;
fd = open(VIDEO_FILE, O_RDWR);
if(fd == -1)
{
printf("Error opening V4L2 interface\n");
return -1;
}
// 查询设备属性
ioctl(fd, VIDIOC_QUERYCAP, &cap);
printf("Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\n",cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&0XFF);
//显示所有支持帧格式
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Support format:\n");
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-