extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libavformat/avio.h"
#include "libavutil/imgutils.h"
}
#include <QString>
#include <QDebug>
#include <QImage>
int videoToImage(const QString &audioPath,const QString&outputDir){
AVFormatContext* formatContext=avformat_alloc_context(); //配置設定fomat上下文
if(avformat_open_input(&formatContext,audioPath.toLocal8Bit().data(),nullptr,nullptr)!=0){ //打開輸入流
qDebug()<<"can`t open the file.";
return -1;
}
av_dump_format(formatContext,0,audioPath.toLocal8Bit(),0); //在終端列印
if(avformat_find_stream_info(formatContext, nullptr)!=0){ //加載輸入流中的資訊
qDebug()<<"can`t find stream infomation";
return -1;
}
int videoStreamIndex=-1;
for(uint i=0;i<formatContext->nb_streams;i++){
if(formatContext->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){ //查找第一個視訊流(一個視訊中可能有多個流(音頻+視訊))
videoStreamIndex=i;
break;
}
}
if(videoStreamIndex==-1){
qDebug()<<"didn`t find a video stream";
return -1;
}
AVCodecParameters *codecParam=formatContext->streams[videoStreamIndex]->codecpar; //擷取編解碼器的參數集
AVCodec* codec=avcodec_find_decoder(codecParam->codec_id); //擷取編解碼器
AVCodecContext* codecContext=avcodec_alloc_context3(nullptr); //擷取編解碼上下文
avcodec_parameters_to_context(codecContext,codecParam); //根據編解碼器參數填充編解碼上下文
if(codec==nullptr){
qDebug()<<"can`t find codec.";
return -1;
}
if( avcodec_open2(codecContext,codec,nullptr)!=0){ //開啟編解碼器
qDebug()<<"can`t open codec";
return -1;
}
AVPacket *packet = av_packet_alloc(); //配置設定一個資料包
AVFrame* frame=av_frame_alloc(); //配置設定一個視訊幀
QImage output(codecParam->width,codecParam->height,QImage::Format_RGB888); //構造一個QImage用作輸出
int outputLineSize[3]; //構造AVFrame到QImage所需要的資料
av_image_fill_linesizes(outputLineSize,AV_PIX_FMT_RGB24,codecParam->width);
uint8_t *outputDst[]={output.bits()};
//構造一個格式轉換上下文
SwsContext *imgConvertContext=sws_getContext(codecParam->width,codecParam->height,(AVPixelFormat)codecParam->format,codecParam->width,codecParam->height,AV_PIX_FMT_BGR24,SWS_BICUBIC,NULL,NULL,NULL);
int index = 0;
while (true) {
if(av_read_frame(formatContext,packet)<0)
break;
if(packet->stream_index==videoStreamIndex){
if(avcodec_send_packet(codecContext,packet)!=0)
continue;
if(avcodec_receive_frame(codecContext,frame)!=0)
continue;
sws_scale(imgConvertContext,frame->data,frame->linesize,0,codecParam->height,outputDst,outputLineSize);
output.save(outputDir + QString::number(index++)+".jpg");
}
}
av_frame_free(&frame);
av_packet_free(&packet);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
}
int main(int argc, char *argv[])
{
videoToImage("./test.mp4","./images/");
return 0;
}