获取摄像头demo
videodecodethread.cpp
#include "videodecodethread.h"
VideodecodeThread::VideodecodeThread(QObject *parent)
:QThread(parent)
{
avdevice_register_all();
avformat_network_init();
}
VideodecodeThread::~VideodecodeThread()
{
if(pFormatCtx)
{
avformat_close_input(&pFormatCtx);
}
if(packet)
{
av_packet_free(&packet);
}
if(pAvCodecCtx)
{
avcodec_close(pAvCodecCtx);
}
if(pAvFrame)
{
av_free(pAvFrame);
}
}
void VideodecodeThread::run()
{
fmt = av_find_input_format("dshow");
av_dict_set(&options, "video_size", "640*480", 0);
av_dict_set(&options, "framerate", "30", 0);
ret = avformat_open_input(&pFormatCtx, "video=ov9734_azurewave_camera", fmt, &options);
if (ret < 0)
{
qDebug() << "Couldn't open input stream." << ret;
return;
}
ret = avformat_find_stream_info(pFormatCtx, &options);
if(ret < 0)
{
qDebug()<< "Couldn't find stream information.";
return;
}
videoIndex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pAvCodec, 0);
if(videoIndex < 0)
{
qDebug()<< "Couldn't av_find_best_stream.";
return;
}
pAvCodec = avcodec_find_decoder(pFormatCtx->streams[videoIndex]->codecpar->codec_id);
if(!pAvCodec)
{
qDebug()<< "Couldn't avcodec_find_decoder.";
return;
}
qDebug()<<"pAVCodec->name:" << QString::fromStdString(pAvCodec->name);
if(pFormatCtx->streams[videoIndex]->avg_frame_rate.den != 0)
{
float fps_ = pFormatCtx->streams[videoIndex]->avg_frame_rate.num / pFormatCtx->streams[videoIndex]->avg_frame_rate.den;
qDebug() <<"fps:" << fps_;
}
int64_t video_length_sec_ = pFormatCtx->duration/AV_TIME_BASE;
qDebug() <<"video_length_sec_:" << video_length_sec_;
pAvCodecCtx = avcodec_alloc_context3(pAvCodec);
if(!pAvCodecCtx)
{
qDebug()<< "Couldn't avcodec_alloc_context3.";
return;
}
ret = avcodec_parameters_to_context(pAvCodecCtx, pFormatCtx->streams[videoIndex]->codecpar);
if(ret < 0)
{
qDebug()<< "Couldn't avcodec_parameters_to_context.";
return;
}
ret = avcodec_open2(pAvCodecCtx, pAvCodec, nullptr);
if(ret!=0)
{
qDebug("avcodec_open2 %d", ret);
return;
}
pAvFrame = av_frame_alloc();
pAVFrameRGB = av_frame_alloc();
pSwsCtx = sws_getContext(pAvCodecCtx->width, pAvCodecCtx->height, pAvCodecCtx->pix_fmt,
pAvCodecCtx->width, pAvCodecCtx->height, AV_PIX_FMT_RGB32,
SWS_BICUBIC, NULL, NULL, NULL);
m_size = av_image_get_buffer_size(AVPixelFormat(AV_PIX_FMT_RGB32), pAvCodecCtx->width, pAvCodecCtx->height, 1);
buffer = (uint8_t*)av_malloc(m_size);
//为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间
av_image_fill_arrays(pAVFrameRGB->data, pAVFrameRGB->linesize, buffer, AV_PIX_FMT_RGB32, pAvCodecCtx->width, pAvCodecCtx->height, 1);
packet = av_packet_alloc();
av_new_packet(packet, pAvCodecCtx->width * pAvCodecCtx->height);
while(runFlag && !av_read_frame(pFormatCtx, packet))
{
if (packet->stream_index == videoIndex)
{
//解码一帧视频数据
int iGotPic = avcodec_send_packet(pAvCodecCtx, packet);
if(iGotPic != 0)
{
qDebug("VideoIndex avcodec_send_packet error :%d", iGotPic);
continue;
}
iGotPic = avcodec_receive_frame(pAvCodecCtx, pAvFrame);
if(iGotPic == 0){
//转换像素
sws_scale(pSwsCtx, (uint8_t const * const *)pAvFrame->data, pAvFrame->linesize, 0,
pAvFrame->height, pAVFrameRGB->data, pAVFrameRGB->linesize);
QImage desImage = QImage((uchar*)buffer, pAvCodecCtx->width,pAvCodecCtx->height,
QImage::Format_RGB32); //RGB32
emit sigSendQImage(desImage);//得到图片的时候触发信号
byte = QByteArray((char*)pAvFrame->data);
videoQueue.push(byte);
videoCount++;
msleep(25);
}
}
av_packet_unref(packet);
}
}
void VideodecodeThread::setRunFlag(bool flag)
{
runFlag = flag;
}
videodecodethread.h
#ifndef VIDEODECODETHREAD_H
#define VIDEODECODETHREAD_H
#include <QObject>
#include <QThread>
#include <QDebug>
#include <mutex>
#include <QImage>
#include "SharedVariables.h"
extern "C" {
#include "libavdevice/avdevice.h" // 调用输入设备需要的头文件
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "libavutil/pixfmt.h"
#include "libavutil/error.h"
#include "libswresample/swresample.h"
#include "libavfilter/avfilter.h"
}
class VideodecodeThread :public QThread
{
Q_OBJECT
public:
VideodecodeThread(QObject *parent = nullptr);
~VideodecodeThread();
void run() override;
void setRunFlag(bool flag);
signals:
void sigSendQImage(QImage);
private:
const AVInputFormat *fmt = nullptr;
AVFormatContext *pFormatCtx = nullptr;
AVDictionary *options = nullptr;
AVPacket *packet = nullptr;
AVFrame* pAvFrame = nullptr;
const AVCodec *pAvCodec = nullptr;
AVCodecContext *pAvCodecCtx = nullptr;
AVFrame* pAVFrameRGB = nullptr;
SwsContext* pSwsCtx = nullptr;
QByteArray byte;
int m_size = 0;
uint8_t* buffer = nullptr;
int ret = -1;
int videoIndex = -1;
bool runFlag = true;
int videoCount = 0;
};
#endif // VIDEODECODETHREAD_H
目前复用还有问题继续修改