qq_22575563 2019-08-16 21:33 采纳率: 0%
浏览 987

在arm上利用Qt采集视频图像,能够保存采集的视频图像

我使用的是usb免驱摄像头,现在已经实现实时显示图像,并能够拍照保存,但无法实现保存视频。

以下是本程序的相关代码

main.cpp

#include "camera.h"
#include <QApplication>

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

    QApplication a(argc, argv);
    camera w;
    w.show();

    return a.exec();
}

camera.cpp

#include "camera.h"
#include "ui_camera.h"
#include <QDate>
#include <QTime>

void yuv422to420p(char *yuv422buf, char *yuv420pbuf,
                int width, int height)
{
        char *src, *dest, *dest2;
        int i, j;

        src = yuv422buf;
        dest = yuv420pbuf;
        for (i = 0; i < width * height * 2; i++) {
                if (i % 2 != 0) {
                        continue;
                }
                *dest++ = *(src + i);
        }

        src = yuv422buf;
        dest = yuv420pbuf + width * height;
        dest2 = dest + (width * height) / 4;
        for (i = 0; i < height; i += 2) {
                for (j = 1; j < width * 2; j += 4) {
                        *dest++ = *(src + i * width * 2 + j);
                        *dest2++ = *(src + i * width * 2 + j + 2);
                }
        }
}

/* yuv格式转换为rgb格式的算法处理函数 */
int convert_yuv_to_rgb_pixel(int y, int u, int v)
{
        unsigned int pixel32 = 0;
        unsigned char *pixel = (unsigned char *)&pixel32;
        int r, g, b;
        r = y + (1.370705 * (v-128));
        g = y - (0.698001 * (v-128)) - (0.337633 * (u-128));
        b = y + (1.732446 * (u-128));
        if(r > 255) r = 255;
        if(g > 255) g = 255;
        if(b > 255) b = 255;
        if(r < 0) r = 0;
        if(g < 0) g = 0;
        if(b < 0) b = 0;
        pixel[0] = r ;
        pixel[1] = g ;
        pixel[2] = b ;

        return pixel32;
}

/* yuv格式转换为rgb格式 */
int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
         unsigned int in, out = 0;
         unsigned int pixel_16;
         unsigned char pixel_24[3];
         unsigned int pixel32;
         int y0, u, y1, v;

         for(in = 0; in < width * height * 2; in += 4)
         {
                 pixel_16 =
                                 yuv[in + 3] << 24 |
                                 yuv[in + 2] << 16 |
                                 yuv[in + 1] <<  8 |
                                 yuv[in + 0];
                 y0 = (pixel_16 & 0x000000ff);
                 u  = (pixel_16 & 0x0000ff00) >>  8;
                 y1 = (pixel_16 & 0x00ff0000) >> 16;
                 v  = (pixel_16 & 0xff000000) >> 24;
                 pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
                 pixel_24[0] = (pixel32 & 0x000000ff);
                 pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
                 pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
                 rgb[out++] = pixel_24[0];
                 rgb[out++] = pixel_24[1];
                 rgb[out++] = pixel_24[2];
                 pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
                 pixel_24[0] = (pixel32 & 0x000000ff);
                 pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
                 pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
                 rgb[out++] = pixel_24[0];
                 rgb[out++] = pixel_24[1];
                 rgb[out++] = pixel_24[2];
         }
         return 0;
}

int camera::camera_init()
{
    int ret=0,i=0,count=0;
    struct v4l2_capability cap;             //视频设备的功能,对应命令VIDIOC_QUERYCAP
    struct v4l2_fmtdesc fmtdesc;            //视频格式描述符类型
    struct v4l2_format format;              //帧的格式,如宽度,高度等,对应命令VIDIOC_G_FMT、VIDIOC_S_FMT等
    struct v4l2_requestbuffers reqbuf;      //向驱动申请帧缓冲请求,包含申请的个数,对应命令VIDIOC_REQBUFS
    struct v4l2_buffer buf;                 //驱动中的一帧图像缓存,对应命令VIDIOC_QUERYBUF

    fmtdesc.index = 0;
    fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;      //传输流类型
    ret = ::ioctl(fd, VIDIOC_G_FMT, &format);       //'VIDIOC_G_FMT'——读取当前驱动的视频捕获格式
    if(ret < 0){
        perror("VIDIOC_G_FMT");
        exit(1);
    }

    printf("width:%d\n", format.fmt.pix.width);
    printf("height:%d\n", format.fmt.pix.height);
    printf("pixelformat:%x\n", format.fmt.pix.pixelformat);
    printf("field:%x\n", format.fmt.pix.field);
    printf("bytesperline:%d\n", format.fmt.pix.bytesperline);
    printf("sizeimage:%d\n", format.fmt.pix.sizeimage);
    printf("colorspace:%d\n", format.fmt.pix.colorspace);
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    format.fmt.pix.width = 640;
    format.fmt.pix.height = 480;
    format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;

    ret = ::ioctl(fd, VIDIOC_S_FMT, &format);
    if(ret < 0){
        fprintf(stderr, "Not support jepg");
        perror("VIDIOC_S_FMT");
        exit(1);
    }
    reqbuf.count = 3;
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    ret = ::ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
    if(ret < 0){
        perror("VIDIOC_REQBUFS");
        exit(1);
    }

    bufinf = (struct bufinfor *)calloc(reqbuf.count, sizeof(struct bufinfor));
    if(!bufinf){
        perror("calloc");
        exit(1);
    }
    for(count = 0; count < reqbuf.count; count++){
        buf.index = count;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ::ioctl(fd, VIDIOC_QUERYBUF, &buf);
        if(ret < 0){
            perror("VIDIOC_REQBUFS");
            exit(1);
        }
        bufinf[buf.index].length = buf.length;
        bufinf[buf.index].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
        if(!(bufinf[buf.index].start)){
            perror("mmap");
            exit(1);
        }
    }
    for(i = 0; i < reqbuf.count; i++){
        buf.index = i;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ::ioctl(fd, VIDIOC_QBUF, &buf);
        if(ret < 0){
            perror("VIDIOC_QBUF");
            exit(1);
        }
    }
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ::ioctl(fd, VIDIOC_STREAMON, &type);
    if(ret < 0){
        perror("VIDIOC_STREAMON");
        exit(1);
    }
    return 0;
}

camera::camera(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::camera)
{

    char devname[32];
    int i=0;
    int ret;
    struct v4l2_capability cap;
    ui->setupUi(this);
    while(i < 100)
    {
        sprintf(devname,"/dev/video%d",i++);

        fd = ::open(devname,O_RDWR);
        if(fd < 0)
        {
            continue;
        }

        ui->comboBox->addItem(QWidget::tr(devname));
        ::close(fd);
    }
}

camera::~camera()
{
    free(bufinf);

    ::close(fd);
    delete ui;
}
void camera::moveEvent(QMoveEvent *)
{
    this->move(QPoint(0,0));
}
void camera::resizeEvent(QResizeEvent *)
{
    this->showMaximized();
}


void camera::on_pushButton_2_clicked()
{
    take_photo();
}

static bool take = 0;

void camera::show_()
{
    int ret;
    unsigned char *rgb=new unsigned char [640 * 480 *3];
    struct v4l2_buffer buf;

    fd_set readset;
    FD_ZERO(&readset);
    FD_SET(fd, &readset);
    ret = select(fd + 1, &readset, NULL, NULL, NULL);
    if(ret < 0){
        perror("select");
        exit(1);
    }

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    ret = ioctl(fd, VIDIOC_DQBUF, &buf);
    if(ret < 0){
        perror("VIDIOC_DQBUF");
        exit(1);
    }

    convert_yuv_to_rgb_buffer((unsigned char *)bufinf[buf.index].start,rgb,640,480);
    ret = ioctl(fd, VIDIOC_QBUF, &buf);
    if(ret < 0){
        perror("VIDIOC_QBUF");
        exit(1);
    }

    QImage *mage = new QImage(rgb,640,480,QImage::Format_RGB888);
    if (take == 1)
    {
        mage->save(tr("%1.jpg").arg("/mnt/Photo/Photo_2019.04.15/IMG" + QDate::currentDate().toString("yyyyMMdd") + QTime::currentTime().toString("hhmmss")),"JPG");
//      mage->save(tr("%1.jpg").arg("/home/root/Photo/IMG" + QDate::currentDate().toString("yyyyMMdd") + QTime::currentTime().toString("hhmmss")),"JPG");
        take = 0;
    }
    QImage resultimg=mage->scaled(ui->label->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation);
    ui->label->setPixmap(QPixmap::fromImage(resultimg));
    delete mage;
    delete rgb;
}

void camera::take_photo()
{
    take = 1;
}

void camera::on_comboBox_activated(const QString &arg1)
{
    QString text=ui->comboBox->currentText();
    QByteArray devtext=text.toLatin1();
    char *devname=devtext.data();
    int ret;
    struct v4l2_capability cap;

    fd = ::open(devname, O_RDWR);

    if(fd < 0)
    {
        perror("open error");
    }
    camera::camera_init();
    QTimer *timer;
    timer=new QTimer();
    timer->setInterval(10);
    connect(timer,SIGNAL(timeout()),this,SLOT(show_()));
    timer->start(10);
    camera_flag=1;
}

void camera::on_pushButton_clicked()
{
    close();
}

camera.h

#ifndef CAMERA_H
#define CAMERA_H

#include <QMainWindow>
#include <QTimer>
#include <QImage>
#include <QPixmap>
#include <QDebug>
#include <QStringList>
#include <QByteArray>
#include <QComboBox>

extern "C"{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <time.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <jpeglib.h>
#include <linux/videodev2.h>
}

namespace Ui {
class camera;
}

struct bufinfor{
    void *start;
    unsigned int length;
};

class camera : public QMainWindow
{
    Q_OBJECT

public:
    explicit camera(QWidget *parent = 0);

    ~camera();

protected:
    void moveEvent(QMoveEvent *);
    void resizeEvent(QResizeEvent *);

private slots:
    int camera_init(void);
    void on_pushButton_2_clicked();
    void show_();
    void take_photo();
    void on_comboBox_activated(const QString &arg1);

    void on_pushButton_clicked();

private:
    Ui::camera *ui;
    int fd;
    int camera_flag;
    struct bufinfor *bufinf;
};

#endif // CAMERA_H

usbcamera.pro

#-------------------------------------------------
#
# Project created by QtCreator 2019-08-02T09:08:26
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = usbcamera
TEMPLATE = app
LIBS += -L. -ljpeg

SOURCES += main.cpp\
        camera.cpp

HEADERS  += camera.h

FORMS    += camera.ui

程序界面如下
图片说明
图片说明
求助大神该怎么保存拍摄的视频
非常感谢

  • 写回答

1条回答 默认 最新

  • 豆丷 2019-08-16 22:54
    关注

    试试把多帧图片保存为视频 这是我搜到的

    1.用Qt + opencv,opencv里面的cv::VideoWriter可以将图片写入视频文件

    2.需要使用第三方库实现,例如:ffmpeg

    3.https://blog.csdn.net/casun_li/article/details/70052986

    评论

报告相同问题?

悬赏问题

  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 逻辑谓词和消解原理的运用
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝