Qt学习之路|Qt项目-安防监控系统(解码编码转码)

目录
FFMPEG音视频处理
14.Decode.h .cpp
15.Decode_Replay.h .cpp
16.EncodeToH264.h .cpp
17.FTranceTomp4.h .cpp

FFMPEG音视频处理 Qt学习之路|Qt项目-安防监控系统(解码编码转码)
文章图片

Qt学习之路|Qt项目-安防监控系统(解码编码转码)
文章图片

Qt学习之路|Qt项目-安防监控系统(解码编码转码)
文章图片

14.Decode.h .cpp

#ifndef DECODE_H #define DECODE_H#include #include //调试 #include //图像 #include //线程 #include //字符串 #include //摄像头信息 #include //队列 #include "encodetoh264.h"//编码h264//当前C++兼容C语言 extern "C" { //avcodec:编解码(最重要的库) #include //avformat:封装格式处理 #include //swscale:视频像素数据格式转换 #include //avdevice:各种设备的输入输出 #include //avutil:工具库(大部分库都需要这个库的支持) #include }class Decode : public QThread { Q_OBJECT public: Decode(); //构造函数 void registerFFmpeg(); //注册组件 int open_camera(); //打开摄像头 int find_stream(); //流媒体数据-查找视频流信息 int find_decoder(); //查找解码器 void prepare_image(); //像素数据准备 void decode_frame(); //读取码流数据 static QList getcamera(); //获取摄像头 private: AVFormatContext *pformatContext; //封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息 AVCodecContext *codec; //编码器上下文结构体,保存了视频(音频)编解码相关信息 AVCodec *decoder; //每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体 AVPacket *pkt; //存储一帧压缩编码数据//存储一帧解码后像素(采样)数据 AVFrame *yuvpicture, *picture,*rgbpicture; //picture有损像素数据 yuvpicture去除有损数据的像素数据 SwsContext *swscontentRGB,*swscontentYUV; //图像转换上下文 uint8_t *bufferRGB,*bufferYUV; //缓存区 QImage img; //图像 int videoIndex; //记录视频流下标 int count; //统计 int interval; //间隔 EncodeToH264 *encodeObj; //编码目标h264 QString image_name; //图片名称 protected: void run(); signals: void sendImg(QImage img); public slots: }; #endif // DECODE_H

#include "decode.h"//构造 Decode::Decode() { this->videoIndex= -1; //记录视频流下标 this->count = 0; }//获取摄像头 QList Decode::getcamera() { QList cnames; cnames.clear(); QList cameras = QCameraInfo::availableCameras(); //获取摄像头到list for(int i=0; ipformatContext=avformat_alloc_context(); //获取摄像头 QList cnames=getcamera(); AVInputFormat *fmt = av_find_input_format("dshow"); char CameraName[256]; sprintf(CameraName, "video=%s", cnames[0].toStdString().c_str()); return avformat_open_input(&pformatContext,CameraName,fmt,nullptr); }//查找视频流信息 int Decode::find_stream() { //获取视频文件信息、流数据、视频流 int res= avformat_find_stream_info(pformatContext,nullptr); if(res!=0) { return res; } //查找是否存在视频流 for(int i=0; ipformatContext->nb_streams; i++) { if(pformatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { this->videoIndex = i; //找到视频流下标 break; } } return this->videoIndex; }//查找解码器 int Decode::find_decoder() { //找编解码器上下文结构体 this->codec = pformatContext->streams[videoIndex]->codec; //找解码器 this->decoder= avcodec_find_decoder(codec->codec_id); if(decoder == nullptr) { return -1; } //打开解码器 return avcodec_open2(codec,decoder,nullptr); }//像素数据准备 void Decode::prepare_image() { //一帧码流数据 this->pkt=(AVPacket *)malloc(sizeof (AVPacket)); //开空间 //准备像素数据 picture = av_frame_alloc(); yuvpicture = av_frame_alloc(); //yuvpicture去除有损数据的像素数据YUV420 rgbpicture = av_frame_alloc(); //rgbpicture去除有损数据的像素数据RGB32 yuvpicture->width = codec->width; yuvpicture->height = codec->height; yuvpicture->format = codec->pix_fmt; //----------------------RGB32像素数据准备---------------------------// //一帧图像数据大小 int imgaeBytesRGB = avpicture_get_size(AV_PIX_FMT_RGB32,this->codec->width,this->codec->height); //动态开辟空间 bufferRGB =(uint8_t *) av_malloc(imgaeBytesRGB *sizeof (uint8_t)); //图片填充 avpicture_fill((AVPicture *)rgbpicture,bufferRGB,AV_PIX_FMT_RGB32,this->codec->width,this->codec->height); //剔除规则 swscontentRGB = nullptr; //制订剔除规则 编码格式 swscontentRGB = sws_getContext(this->codec->width,this->codec->height,this->codec->pix_fmt, this->codec->width,this->codec->height,AV_PIX_FMT_RGB32, SWS_BICUBIC,nullptr,nullptr,nullptr); //----------------------YUV420P像素数据准备---------------------------// //一帧图像数据大小 int imgaeBytesYUV = avpicture_get_size(AV_PIX_FMT_YUV420P,codec->width,codec->height); //动态开辟空间 bufferYUV =(uint8_t *) av_malloc(imgaeBytesYUV *sizeof (uint8_t)); //图片填充 avpicture_fill((AVPicture *)yuvpicture,bufferYUV,AV_PIX_FMT_YUV420P,codec->width,codec->height); //剔除规则 swscontentYUV = nullptr; //制订剔除规则 编码格式 swscontentYUV = sws_getContext(codec->width,codec->height,codec->pix_fmt, codec->width,codec->height,AV_PIX_FMT_YUV420P, SWS_BICUBIC,nullptr,nullptr,nullptr); }//读取码流数据 void Decode::decode_frame() { int mark=0; this->image_name=encodeObj->getTime(); this->encodeObj = new EncodeToH264(); this->encodeObj->getHeightWidth(codec->width,codec->height); this->encodeObj->getName(image_name); this->encodeObj->start(); //一帧帧读取码流数据 while(av_read_frame(pformatContext,pkt)==0) { //读取码流数据 pkt if(videoIndex == pkt->stream_index) { int got_picture_ptr = -1; //解码picture:有损像素数据 avcodec_decode_video2(codec,picture,&got_picture_ptr,pkt); if(got_picture_ptr!=0) { //剔除 得到纯净YUVpicture sws_scale(swscontentYUV,picture->data,picture->linesize,0, picture->height,yuvpicture->data,yuvpicture->linesize); //剔除 得到纯净RGBpicture sws_scale(swscontentRGB,picture->data,picture->linesize,0, picture->height,rgbpicture->data,rgbpicture->linesize); img = QImage((uchar *)bufferRGB,codec->width,codec->height,QImage::Format_RGB32); //发送信号到播放界面 emit sendImg(img); //把YUV420P添加到队列中 EncodeToH264::Queue_AVFrame.enqueue(yuvpicture); this->interval=SetControl::getInstance()->getSetting_interval(); if(count==interval) { //这里存放的是video第一帧的图片 //写入数据库--传到另一边一起写入 if(mark==1) { this->image_name=encodeObj->getTime(); encodeObj->getName(image_name); } mark=1; QString path=SetControl::getInstance()->getSetting_imagepath()+"/"+image_name+".jpg"; this->count=0; img.save(path); } this->count++; } } //重置pkt av_packet_unref(pkt); } }//解码线程 void Decode::run() { //整个解码操作 //打开摄像头 registerFFmpeg(); if(open_camera()!= 0) { return; } //流媒体数据 if(find_stream()!= 0) { return; } //解码器 if(find_decoder()!= 0) { return; } //读取码流数据 prepare_image(); //解码 decode_frame(); }

15.Decode_Replay.h .cpp
#ifndef DECODE_REPLAY_H #define DECODE_REPLAY_H#include #include //调试 #include //图片 #include //线程 #include //字符串 #include //队列 #include //日期 #include "setcontrol.h"//设置控制层 #include "imagecontrol.h"//图像控制层//当前C++兼容C语言 extern "C" { //avcodec:编解码(最重要的库) #include //avformat:封装格式处理 #include //swscale:视频像素数据格式转换 #include //avdevice:各种设备的输入输出 #include //avutil:工具库(大部分库都需要这个库的支持) #include }class Decode_Replay : public QThread { Q_OBJECT public: Decode_Replay(QString path); //构造 ~Decode_Replay(); //析构 void registerFFmpeg(); //注册组件 int open_video(); //打开视频 int find_stream(); //流媒体数据-查找视频流信息 int find_decoder(); //查找解码器 void prepare_image(); //准备图片帧-像素数据准备 void decode_frame(); //读取码流数据 static QString replay_path; //回放路径 int status; //状态 int screenshots_mark; //截屏标志位 private: AVFormatContext *pformatContext; //封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息 AVCodecContext *codec; //编码器上下文结构体,保存了视频(音频)编解码相关信息 AVCodec *decoder; //每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体 AVPacket *pkt; //存储一帧压缩编码数据 AVFrame *picture,*rgbpicture; //picture有损像素数据 yuvpicture去除有损数据的像素数据 SwsContext *swscontentRGB; //图像转换上下文 uint8_t *bufferRGB; //缓存区 QImage img; //图像 int play_speed; //播放速度 int videoIndex; //记录视频流下标 QString getTime(); //获取日期时间 protected: void run(); //线程 signals: void sendImg2(QImage img); //发送图片public slots: void setSpeed(QString speed); //速度 }; #endif // DECODE_REPLAY_H

#include "decode_replay.h"QString Decode_Replay::replay_path=nullptr; //构造 Decode_Replay::Decode_Replay(QString path) { this->videoIndex= -1; //记录视频流下标 this->replay_path = path; this->play_speed=40; this->status=0; this->screenshots_mark=0; }//析构 Decode_Replay::~Decode_Replay(){}//注册组件 void Decode_Replay::registerFFmpeg() { av_register_all(); avdevice_register_all(); }//打开视频 int Decode_Replay::open_video() { this->pformatContext=avformat_alloc_context(); //封装格式上下文结构体,视频路径 return avformat_open_input(&pformatContext,replay_path.toStdString().c_str(),nullptr,nullptr); }//查找视频流信息 int Decode_Replay::find_stream() { //获取视频文件信息、流数据、视频流 int res= avformat_find_stream_info(pformatContext,nullptr); if(res!=0) { return res; } //查找是否存在视频流 for(int i=0; ipformatContext->nb_streams; i++) { if(pformatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { this->videoIndex = i; //找到视频流下标 break; } } return this->videoIndex; }//查找解码器 int Decode_Replay::find_decoder() { //找编解码器上下文结构体 this->codec = pformatContext->streams[videoIndex]->codec; //找解码器 this->decoder= avcodec_find_decoder(codec->codec_id); if(decoder == nullptr) { return -1; } //打开解码器 return avcodec_open2(codec,decoder,nullptr); }//像素数据准备 void Decode_Replay::prepare_image() { //一帧码流数据 this->pkt=(AVPacket *)malloc(sizeof (AVPacket)); //开空间 //准备像素数据 picture = av_frame_alloc(); rgbpicture = av_frame_alloc(); //rgbpicture去除有损数据的像素数据RGB32//----------------------RGB32像素数据准备---------------------------// //一帧图像数据大小 int imgaeBytesRGB = avpicture_get_size(AV_PIX_FMT_RGB32,this->codec->width,this->codec->height); //动态开辟空间 bufferRGB =(uint8_t *) av_malloc(imgaeBytesRGB *sizeof (uint8_t)); //图片填充 avpicture_fill((AVPicture *)rgbpicture,bufferRGB,AV_PIX_FMT_RGB32,this->codec->width,this->codec->height); //剔除规则 swscontentRGB = nullptr; //制订剔除规则 编码格式 swscontentRGB = sws_getContext(this->codec->width,this->codec->height,this->codec->pix_fmt, this->codec->width,this->codec->height,AV_PIX_FMT_RGB32, SWS_BICUBIC,nullptr,nullptr,nullptr); }//读取码流数据 void Decode_Replay::decode_frame() { //一帧帧读取码流数据 while(av_read_frame(pformatContext,pkt)==0) { while (status==1) { continue; } //读取码流数据 pkt if(videoIndex == pkt->stream_index) { int got_picture_ptr = -1; //解码picture:有损像素数据 avcodec_decode_video2(codec,picture,&got_picture_ptr,pkt); if(got_picture_ptr!=0) { //剔除 得到纯净RGBpicture sws_scale(swscontentRGB,picture->data,picture->linesize,0, picture->height,rgbpicture->data,rgbpicture->linesize); img = QImage((uchar *)bufferRGB,codec->width,codec->height,QImage::Format_RGB32); //发送信号到播放界面 msleep(this->play_speed); emit sendImg2(img); if(this->screenshots_mark==1) { QString image_name=this->getTime(); QString path=SetControl::getInstance()->getSetting_imagepath()+"/"+"shots_"+image_name+".jpg"; img.save(path); ImageControl::getInstance()->addImagePath(image_name, path); this->screenshots_mark=0; } } } //重置pkt av_packet_unref(pkt); } }//线程 void Decode_Replay::run() { //整个解码操作 //打开摄像头 registerFFmpeg(); if(open_video()!= 0) { return; } //流媒体数据 if(find_stream()!= 0) { return; } //解码器 if(find_decoder()!= 0) { return; } //读取码流数据 prepare_image(); decode_frame(); }void Decode_Replay::setSpeed(QString speed) { if(speed.compare("0.5X")==0) { this->play_speed=80; } else if(speed.compare("1X")==0) { this->play_speed=40; } else if(speed.compare("1.5X")==0) { this->play_speed=20; } else { this->play_speed=10; } }QString Decode_Replay::getTime() { QDateTime currentdatetime = QDateTime::currentDateTime(); QString currentdate = currentdatetime.toString("yyyyMMddHHmmss"); return currentdate; }

16.EncodeToH264.h .cpp
#ifndef ENCODETOH264_H #define ENCODETOH264_H#include #include //调试 #include //线程 #include //链表 #include //队列 #include //日期 #include "setcontrol.h"//设置控制层 #include "videocontrol.h"//视频控制层//当前C++兼容C语言 extern "C" { //avcodec:编解码(最重要的库) #include //avformat:封装格式处理 #include //swscale:视频像素数据格式转换 #include //avdevice:各种设备的输入输出 #include //avutil:工具库(大部分库都需要这个库的支持) #include }class EncodeToH264 : public QThread { Q_OBJECT public: EncodeToH264(); //构造 void registerEncode(); //注册组件 void guess_format(int width,int height); //猜测需要转换的格式 void encode_frame(AVFrame *yuvpicture); //编码码流数据 void writeTailer(); //写尾部 void getHeightWidth(int width,int height); //获取分辨率 void getName(QString name); //获取名字 static int frame_count; //流数 static QQueue Queue_AVFrame; //队列--避免像素数据丢失 QString getTime(); //获取日期时间--视频图片命名 QString path; QString video_path; static QString name; static int width; //分辨率 static int height; //分辨率 AVCodec *encoder; //每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体 AVOutputFormat *outformat; //输出文件容器格式 AVStream *newStream; //存储每一个视频/音频流信息的结构体 private: AVCodecContext *codecContext; //编码器上下文结构体,保存了视频(音频)编解码相关信息 AVFormatContext *pformatContext; //封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息 AVPacket *pkt; //存储一帧压缩编码数据 int pkt_index; //存储一帧压缩编码数据记录 int interval; //间隔 void run(); //线程 signals:public slots: }; #endif // ENCODETOH264_H

#include "encodetoh264.h"int EncodeToH264::frame_count=0; int EncodeToH264::width=0; int EncodeToH264::height=0; QQueue EncodeToH264::Queue_AVFrame; //队列 QString EncodeToH264::name=nullptr; //构造 EncodeToH264::EncodeToH264() { this->pkt_index = 0; this->interval = 0; this->registerEncode(); }//注册编码初始化 void EncodeToH264::registerEncode() { av_register_all(); }//猜测需要转换的格式 void EncodeToH264::guess_format(int width,int height) { pkt = av_packet_alloc(); pformatContext = avformat_alloc_context(); this->video_path=SetControl::getInstance()->getSetting_videopath(); this->path =video_path+"/"+name+".h264"; this->interval=SetControl::getInstance()->getSetting_interval(); this->outformat = av_guess_format(nullptr,path.toStdString().c_str(),nullptr); if(outformat == nullptr ) { return; } //设置输出格式 pformatContext->oformat = outformat; //打开视频流 输入输出上下文对象 输出文件路径 以写入方式操作 int res=avio_open(&pformatContext->pb,path.toStdString().c_str(),AVIO_FLAG_WRITE); if(res!=0) { return; } //创建视频流 this->newStream = avformat_new_stream(pformatContext,nullptr); if(newStream == nullptr) { return; } //编解码器上下文结构体 codecContext = newStream->codec; //设置基本信息 1266 968 codecContext->width=width; codecContext->height=height; codecContext->time_base={1,25}; //时间基,1s播放帧数 codecContext->bit_rate =400000; //码率 codecContext->framerate={25,1}; //帧率 codecContext->gop_size=10; //10帧为一组//影响清晰度 codecContext->qmax = 51; codecContext->qmin = 10; codecContext->max_b_frames = 0; //没有B帧 codecContext->pix_fmt = AV_PIX_FMT_YUV420P; //编码器格式 codecContext->codec_type = AVMEDIA_TYPE_VIDEO; //设置为视频流 codecContext->codec_id = outformat->video_codec; //编码器id//编码器 this->encoder = avcodec_find_encoder(codecContext->codec_id ); res = avcodec_open2(codecContext,encoder,nullptr); if(res != 0) { return; }//写入头部信息,编码器打开成功即可写入编码头部信息,完成编码前所有初始化工作 res = avformat_write_header(pformatContext,nullptr); if(res != 0) { return; } }//编码码流数据 void EncodeToH264::encode_frame(AVFrame *yuvpicture) { //yuv420p--->AVpacket--->写入h264文件 //发送一帧像素数据-->编码器 frameYUV像素数据 int res = avcodec_send_frame(codecContext,yuvpicture); if(res != 0) { return; } //编码的一帧像素数据给编码器进行编码的时候,可能一个AVPacket放不下,就需要两个AVPacket,循环处理去接收码流数据 while(res >= 0) { //接收一帧编码数据AVCodecContext *avctx,AVPacket *avpkt //显示时间基,保证显示的顺序,定义一个变量,每次加+1,每次开始编码的时候赋值为0 yuvpicture->pts = pkt_index++; //时间基--显示顺序 res = avcodec_receive_packet(codecContext,pkt); if(res == AVERROR(EAGAIN)|| res == AVERROR_EOF) { break; } //写入文件就可以写入一帧数据 av_interleaved_write_frame(pformatContext,pkt); } //pkt使用完后要重置 av_packet_unref(pkt); }//写尾部 void EncodeToH264::writeTailer() { av_write_trailer(pformatContext); //关闭输入流 avio_close(pformatContext->pb); //释放视频信息 avformat_free_context(pformatContext); }//线程 void EncodeToH264::run() { this->guess_format(this->width,this->height); while(1) { if(!Queue_AVFrame.isEmpty()) { //从队列取一帧进行编码,并从队列删除 this->encode_frame(this->Queue_AVFrame.dequeue()); frame_count++; cout<writeTailer(); this->guess_format(this->width,this->height); //写入数据库--将视频路径写入到数据库当中 VideoControl::getInstance()->addVideoPath(name+".h264",video_path+"/"+name+".jpg",video_path+"/"+name+".h264"); //初始化 frame_count = 0; } } } //写尾帧 this->writeTailer(); }//获取分辨率 void EncodeToH264::getHeightWidth(int width, int height) { this->width=width; this->height=height; }//获取名字 void EncodeToH264::getName(QString name) { this->name=name; }//获取日期时间--视频图片命名 QString EncodeToH264::getTime() { QDateTime currentdatetime = QDateTime::currentDateTime(); QString currentdate = currentdatetime.toString("yyyyMMddHHmmss"); return currentdate; }

17.FTranceTomp4.h .cpp
#ifndef FTRANCETOMP4_H #define FTRANCETOMP4_H#include #include //调试 #include //字符串 #include //日期 #include //消息框 #include #include //线程 #include "setcontrol.h"//设置控制层//当前C++兼容C语言 extern "C" { //avcodec:编解码(最重要的库) #include //avformat:封装格式处理 #include //swscale:视频像素数据格式转换 #include //avdevice:各种设备的输入输出 #include //avutil:工具库(大部分库都需要这个库的支持) #include }class FTranceTomp4 : public QThread { Q_OBJECT public: FTranceTomp4(); //构造 void openH264File(QString file); //打开编码的h264文件 void coverTomp4(); //转码为mp4文件 QString getTime(); //获取日期时间--文件命名 private: AVFormatContext *pFormatContext,*outFormatContext; //封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息 AVPacket *pkt; //存储一帧压缩编码数据 AVOutputFormat *outformat; //输出文件容器格式 int videoIndex,frameCount; AVStream *newStream; //存储每一个视频/音频流信息的结构体 signals:public slots: }; #endif // FTRANCETOMP4_H

#include "ftrancetomp4.h"//构造 FTranceTomp4::FTranceTomp4() { this->videoIndex =-1; this->frameCount = 0; pFormatContext = avformat_alloc_context(); outFormatContext =avformat_alloc_context(); pkt = av_packet_alloc(); }//打开h264文件 void FTranceTomp4::openH264File(QString file) { //注册组件 av_register_all(); QString path=SetControl::getInstance()->getSetting_videopath()+"/"+getTime()+".mp4"; //打开视频文件 int res= avformat_open_input(&pFormatContext,file.toStdString().c_str(),nullptr,nullptr); if(res!=0) { return; } //查找视频流 avformat_find_stream_info(pFormatContext,nullptr); if(res!=0) { return; } for(int i=0; inb_streams; i++) { if(pFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoIndex = i; break; } } if(videoIndex == -1) { return; } outformat = av_guess_format(nullptr,path.toStdString().c_str(),nullptr); if(outformat == nullptr ) { return; } //设置输出格式 outFormatContext->oformat = outformat; //打开视频流 输入输出上下文对象 输出文件路径 以写入方式操作 res=avio_open(&outFormatContext->pb,path.toStdString().c_str(),AVIO_FLAG_WRITE); if(res!=0) { return; } //创建视频流 this->newStream = avformat_new_stream(outFormatContext,nullptr); if(newStream == nullptr) { return; }//参数设置把输入h264编码器的参数给输出视频流进行使用 //参数1-目标视频流的编码器参数信息结构体,参数2-输入视频流的编码器参数信息结构体 avcodec_parameters_copy(newStream->codecpar,pFormatContext->streams[videoIndex]->codecpar); //写入头部信息 编码器打开成功即可写入编码头部信息,完成编码钱所有初始化工作 res = avformat_write_header(outFormatContext,nullptr); if(res != 0) { return; } }//转码mp4 void FTranceTomp4::coverTomp4() { while(av_read_frame(pFormatContext,pkt)==0) { //判断是不是视频流 if(pkt->stream_index == videoIndex) { //转码重新编码时间基设置时间间隔 //I帧首帧保存一 帧大部分 的重要的视频信息: P按照I帧: B按照左右两边的解码 //一组一组解码 frameCount++; //判断有没有设置显示时间基:没有设置的情况下 if(pkt->pts == AV_NOPTS_VALUE) { //时间基的转换 AVRational time_base1 = pFormatContext->streams[videoIndex]->time_base; //计算两帧之前的长度:转换 int64_t duration = (double)AV_TIME_BASE/ av_q2d(pFormatContext->streams[videoIndex]->r_frame_rate); //计算显示时间基--(当前帧数*两帧之间的长度)/(输入时间基 *AV_TIME_BASE) pkt->pts=(double)(frameCount*duration)/ (double)(av_q2d(time_base1)*AV_TIME_BASE); //解码时间基=显示时间基 pkt->dts = pkt->pts; pkt->duration = duration/(double)(av_q2d(time_base1)*AV_TIME_BASE); } else if (pkt->pts【Qt学习之路|Qt项目-安防监控系统(解码编码转码)】dts) { //时间基小于解码时间基 continue; } pkt->pts=av_rescale_q_rnd(pkt->pts, pFormatContext->streams[videoIndex]->time_base, newStream->time_base, (AVRounding)(AV_ROUND_INF|AV_ROUND_PASS_MINMAX)); //解码时间基的转换 pkt->dts=av_rescale_q_rnd(pkt->dts, pFormatContext->streams[videoIndex]->time_base, newStream->time_base, (AVRounding)(AV_ROUND_INF|AV_ROUND_PASS_MINMAX)); //数据的时长,以所属媒体流的时间基准为单位,末知则值为默认值0 pkt->duration=av_rescale_q(pkt->duration, pFormatContext->streams[videoIndex]->time_base, newStream->time_base); pkt->pos = -1; pkt->flags |= AV_PKT_FLAG_KEY; pkt->stream_index = 0; //写入数据到输出视频信息结构体汇总 av_interleaved_write_frame(outFormatContext,pkt); } //重置pkt av_packet_unref(pkt); } //写入尾帧 av_write_trailer(outFormatContext); //关闭编码器 avcodec_close(outFormatContext->streams[videoIndex]->codec); av_free(&outFormatContext->streams[videoIndex]->codec); //关闭输出流 avio_close(outFormatContext->pb); //释放输出文件容器格式 av_free(outFormatContext); //关闭输入流 avformat_close_input(&pFormatContext); //释放输入视频信息结构体 av_free(pFormatContext); //释放包 av_packet_free(&pkt); }//获取日期时间--视频图片命名 QString FTranceTomp4::getTime() { QDateTime currentdatetime = QDateTime::currentDateTime(); QString currentdate = currentdatetime.toString("yyyyMMddHHmmss"); return currentdate; }

    推荐阅读