FFmpeg入门详解之122:Qt5 FFmpeg本地摄像头采集预览实战

6.Qt5+FFmpeg本地摄像头采集预览实战

源码工程:S26_Test2

FFmpeg命令行处理摄像头

ffmpeg -list_devices true -f dshow -i dummy

命令执行后输出的结果如下(注:中文的设备会出现乱码的情况)。

列表显示设备的名称很重要,输入的时候都是使用“-f dshow -i video="{设备名}"”的方式。

获取摄像头数据(保存为本地文件或者发送实时流)

编码为H.264,保存为本地文件

下面这条命令,实现了从摄像头读取数据并编码为H.264,最后保存成mycamera.mkv。

ffmpeg -f dshow -i video="Lenovo EasyCamera" -vcodec libx264  mycamera001.flv

ffplay直接播放摄像头的数据

使用ffplay可以直接播放摄像头的数据,命令如下:

ffplay -f dshow -i video="Lenovo EasyCamera"

如果设备名称正确的话,会直接打开本机的摄像头,

FFmpeg+SDL2.0显示本地摄像头

/***********************

步骤是什么?

回忆:FFmpeg大体架构、流程

1.打开流协议:(本地文件、rtsp、rtmp、摄像头)

2.分析流信息:(video,audio,subtitle,......)

3.封装、解封装:

4.编码、解码:

5.渲染、推流:

---------》数据结构、API:

AVFormatContext:大管家婆

avformat_open_input

avformat_find_stream_info

av_read_packet: AVPacket, AVFrame

avcodec_send_packet

avcodec_receive_frame:AVCodecContext

sws_scale(,,,:::yuv422,420, yuyv, uyvy, yv12,yu12, nv12,nv21)

:SwsContext

***********************/

工程配置文件:.pro

:添加头文件目录、库文件

INCLUDEPATH += $$PWD/../FFmpeg431dev/include

INCLUDEPATH += $$PWD/../SDL2/include

LIBS    +=  $$PWD/../FFmpeg431dev/lib/avcodec.lib \

            $$PWD/../FFmpeg431dev/lib/avdevice.lib \

            $$PWD/../FFmpeg431dev/lib/avfilter.lib \

            $$PWD/../FFmpeg431dev/lib/avformat.lib \

            $$PWD/../FFmpeg431dev/lib/avutil.lib \

            $$PWD/../FFmpeg431dev/lib/postproc.lib \

            $$PWD/../FFmpeg431dev/lib/swresample.lib \

            $$PWD/../FFmpeg431dev/lib/swscale.lib

LIBS    +=  $$PWD/../SDL2/lib/x86/SDL2.lib

LIBS    +=  $$PWD/../SDL2/lib/x86/SDL2main.lib

一个坑:

undefined reference to `vtable for’”问题的原因及解决方法

QT中,类要支持信号与槽机制,需要继承自QObject并在头文件开头添加Q_OBJECT宏.

如果使用QtCreator创建类时,没有选择继承自QObject类或其子类,

而在创建后手工修改继承自QObject并手工添加Q_OBJECT宏,

则在编译时有可能会出现”undefined reference to `vtable for’…….”错误.

解决方法: 把新创建的类从项目中移除(注意:不要从磁盘上删除),

然后再添加进来,QtCreator就会重新解析此类,

再编译就不再会出现上述错误.

又一个坑2:

16:58:37: 程序异常结束。

16:58:37: The process was ended forcefully.

原因:运行时缺少dll

又一个坑3:

no documents matching "ui"

无法添加槽函数,导致信号发出后槽函数接收不到信号

原因1:未在类定义中添加Q_OBJECT

原因2:信号或槽指向的对象未实例化

原因3: 多处包含相同的"ui_XXX.h"头文件

查找/添加槽错误

在UI文件中右键转到槽发生错误,弹窗提示如下:

查找或添加槽错误

The class containing "UI::XXX" could mot be found in :\..\.XXX.cpp.Please verify the #include_directives.

可将.pro文件中,SOURCE+=后面的.cpp文件名全部删除,HEADERS+=后面的.h文件名全部删除重新构建后,再次右键项目文件选择“Add Existing Directory”重新加载文件并重新编译工程。

此时再次添加槽函数

弹窗提示如下:

查找/添加槽错误

No documents matching "ui_XXX.h" could be found .Rebuilding the project might help.

此时并不需要重新编译,直接重启Qt Creator即可。

添加头文件:.h

//必须加以下内容,否则编译不能通过,为了兼容C和C99标准
#ifndef INT64_C
#define INT64_C
#define UINT64_C
#endif
//引入ffmpeg头文件
#include <iostream>
extern "C"
{
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libavdevice/avdevice.h>
    #include <libavfilter/avfilter.h>
    #include <libavutil/imgutils.h>
    #include <SDL.h>
    #include <SDL_main.h>
};
#undef main
#include <QObject>
#include <qmutex.h>
#include <qstring.h>
本地摄像头的信息
printf("------------av_dump_format-------------------\n");
    av_dump_format(pAVFmtCtx, 0, NULL, 0);
    /*
    Input #0, dshow, from '(null)':
        Duration: N/A, bitrate: N/A
        Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, 30 fps, 30 tbr, 10000k tbn
    */
/ 1. open local camera
/ 2. find stream info
/ 3. open codec : decoder
/ 4. sws_scale :yuyv422--->yuv420p
/ 5. SDL2.0 
/ 6. demux , decode 
/ 7. render

// calculate the bytes of one image

av_frame_alloc

av_image_get_buffer_size

av_image_fill_arrays

问题:为什么第二次Start就无法显示窗口呢?

objFmpg.SetStopped(0);

FFmpeg+Qt显示摄像头

mutex.lock();

sws_scale(pSwsContext2,

(const uint8_t* const )pFrameYUV->data,

pFrameYUV->linesize,0,

videoHeight, pAVPicture.data, pAVPicture.linesize);

 //发送获取一帧图像信号

QImage image(pAVPicture.data[0],videoWidth,videoHeight,QImage::Format_RGB888);

emit GetImage(image);

mutex.unlock();

为什么不显示呢? 

connect:信号、槽,绑定

为什么窗口可以放大,不能缩小呢?

///作业:请大家自行修改下边这段代码,改造成不用SDL

    //一帧一帧读取视频

//    int frameFinished=0;

//    while (true){

//        if (av_read_frame(pFormatCtx, packet) >= 0){

//            if(pAVPacket.stream_index == videoStreamIndex){

//                qDebug()<<"开始解码"<<QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");

//                decode(pCodecCtx, packet, pFrame, pFrameYUV, img_convert_ctx/*, fp_yu*/);

//                /avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, &pAVPacket);

//                mutex.lock();

//                sws_scale(pSwsContext2,(const uint8_t* const *)pFrameYUV->data,pFrameYUV->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);

//                //发送获取一帧图像信号

//                QImage image(pAVPicture.data[0],videoWidth,videoHeight,QImage::Format_RGB888);

//                emit GetImage(image);

//                mutex.unlock();

//                /// -re  : 帧率

//                QThread::msleep(33);

//            }

//        }

//        av_free_packet(packet);//释放资源,否则内存会一直上升

//    }

大家好,我的第一本书正式出版了,可以在京东各大店铺抢购哦。

《FFmpeg入门详解--音视频原理及应用:梅会东:清华大学出版社》

京东自营链接:https://item.jd.com/13377793.html
京东其它链接:https://search.jd.com/Search?keyword=FFmpeg%E5%85%A5%E9%97%A8%E8%AF%A6%E8%A7%A3--%E9%9F%B3%E8%A7%86%E9%A2%91%E5%8E%9F%E7%90%86%E5%8F%8A%E5%BA%94%E7%94%A8&enc=utf-8&suggest=1.his.0.0&wq=&pvid=24e80535073b4e1f98e30a3e6963fe81
 

 

出书过程非常艰辛,来回校正了好几遍,后续还有FFmpeg系列的其它图书。

第一本:FFmpeg入门详解--音视频原理及应用--梅会东--清华大学出版社

第二本:FFmpeg入门详解--流媒体直播原理及应用--梅会东--清华大学出版社

第三本:FFmpeg入门详解--命令行及音视频特效原理及应用--梅会东--清华大学出版社

第四本:FFmpeg入门详解--SDK二次开发及直播美颜原理及应用--梅会东--清华大学出版社

===================================

猜你喜欢

转载自blog.csdn.net/teachermei/article/details/127729608