cpp
复制代码
#include "decodetorgb32.h"
DecodeToRGB32::DecodeToRGB32()
{
}
//1、注册组件 2、打开视频
int DecodeToRGB32::openVideo(QString filename)
{
av_register_all();//注册所用组件
//全局结构体开空间
this->pFormatContext=avformat_alloc_context();
//打开输入视频文件
int res=avformat_open_input(&this->pFormatContext,filename.toUtf8(),nullptr,nullptr);
if(res!=0)
{
qDebug()<<"open_input fail"<<res;//不等于0,文件打开失败
}
return res;
}
//3、查找流媒体数据 4、查找视频流
int DecodeToRGB32::findStream()
{
//1.查找流媒体数据
int res= avformat_find_stream_info(this->pFormatContext,nullptr);
if(res<0)
{
qDebug()<<"find_stream_info fail"<<res;//小于0查找失败
return res;
}
//2.查看是否有视频流
for (int i=0;i<this->pFormatContext->nb_streams;i++)//输入视频的AVStream的个数
{// streams:输入视频的AVStream数组/codec:该流对应的AVCodecContext/编解码器类型
if(AVMEDIA_TYPE_VIDEO==this->pFormatContext->streams [i]->codec->codec_type)
{
this->video_index=i;
return 0;
}
}
return res;
}
//查找解码器,打开解码器
int DecodeToRGB32::openDecoder()
{
int res=-1;
//编解码器上下文结构体
this->pCodecContext=this->pFormatContext->streams[this->video_index]->codec;//编解码器的AVCodec
this->deocder= avcodec_find_decoder(this->pCodecContext->codec_id);//查找解码器
if(nullptr==this->deocder)
{
qDebug()<<"find_decoder fail"<<res;
return 1;
}
//打开解码器
res=avcodec_open2(this->pCodecContext,this->deocder,nullptr);
if(res!=0)
{
qDebug()<<"find_decoder fail"<<res;
}
return res;//0 找到了并打开 <0未打开解码器
}
void DecodeToRGB32::decodeRGB()
{
//7、准备数据
this->pkt =(AVPacket*)malloc(sizeof(AVPacket));//存储一帧压缩编码数据
int size =this->pCodecContext->width*this->pCodecContext->height;
av_new_packet(this->pkt,size);
//初始化像素数据
this->picture =av_frame_alloc();//创建一个存储解码的像素数结构体
this->picture->width=this->pCodecContext->width;
this->picture->height=this->pCodecContext->height;
this->picture->format=this->pCodecContext->pix_fmt;
this->pictureRGB=av_frame_alloc();
this->pictureRGB->width=this->pCodecContext->width;
this->pictureRGB->height=this->pCodecContext->height;
this->pictureRGB->format=this->pCodecContext->pix_fmt;
this->pictureYUV=av_frame_alloc();
this->pictureYUV->width=this->pCodecContext->width;
this->pictureYUV->height=this->pCodecContext->height;
this->pictureYUV->format=this->pCodecContext->pix_fmt;
//计算一帧RGB32的像素大小
int imgByte=avpicture_get_size(AV_PIX_FMT_RGB32,this->pCodecContext->width,this->pCodecContext->height);
//动态开空间
uint8_t*buffer=(uint8_t*)malloc(imgByte*sizeof(uint8_t));
//图片的数据填充
avpicture_fill((AVPicture*)this->pictureRGB,buffer,AV_PIX_FMT_RGB32,
this->pCodecContext->width,this->pCodecContext->height);
//制定转置的规则
SwsContext*swContext=sws_getContext(this->pCodecContext->width,this->pCodecContext->height,this->pCodecContext->pix_fmt,
this->pCodecContext->width,this->pCodecContext->height,AV_PIX_FMT_RGB32,
SWS_BICUBIC,nullptr,nullptr,nullptr);
/**准备YUV数据**********************/
//计算一帧YUV420P的像素大小
int imgByteYUV=avpicture_get_size(AV_PIX_FMT_YUV420P,this->pCodecContext->width,this->pCodecContext->height);
//动态开空间
uint8_t*bufferYUV=(uint8_t*)malloc(imgByte*sizeof(uint8_t));
//图片的数据填充
avpicture_fill((AVPicture*)this->pictureYUV,bufferYUV,AV_PIX_FMT_YUV420P,
this->pCodecContext->width,this->pCodecContext->height);
//制定转置的规则
SwsContext*swContextYUV=sws_getContext(this->pCodecContext->width,this->pCodecContext->height,this->pCodecContext->pix_fmt,
this->pCodecContext->width,this->pCodecContext->height,AV_PIX_FMT_YUV420P,
SWS_BICUBIC,nullptr,nullptr,nullptr);
int num=0;
FILE * pyuv=fopen("../fileOut/save.yuv","wb+");//二进制方式写入
char path[256]={0};
//8、读取码流数据、解封装 获取一帧压缩的码流数据
while(av_read_frame(this->pFormatContext,this->pkt)==0)//0成功
{
//判断码流数据类型是视频流
if(pkt->stream_index==this->video_index)
{
int got_num =-1;
//参数一:编解码器上下文结构体 二;AVFrame* 像素数据 三:int*标志位 四:一帧压缩码流数据
avcodec_decode_video2(this->pCodecContext,this->picture,&got_num,this->pkt);
if(got_num !=0)
{
qDebug()<<"解码成功:"<<num;
//剔除无效数据,获取纯净的RGB32数据
/**
* parmam1:转置规则
* srcSlice 数据
* srcStride 每一行的数据
* srcSliceY 从第几行开始扫描
* srcSliceH 图片高度
* dst 目标数据
* dstStrde 一行的宽度
* @brief sws_scale
*/
//存储图片 -播放
sws_scale(swContext,picture->data,picture->linesize,0,this->picture->height,
this->pictureRGB->data,this->pictureRGB->linesize);
//用于存储 size更小
sws_scale(swContextYUV,picture->data,picture->linesize,0,this->picture->height,
this->pictureYUV->data,this->pictureYUV->linesize);
fwrite(this->pictureYUV->data[0],this->pCodecContext->width*this->pCodecContext->height,1,pyuv);// 1 -Y
fwrite(this->pictureYUV->data[1],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);// 1/4 -U
fwrite(this->pictureYUV->data[2],this->pCodecContext->width*this->pCodecContext->height/4,1,pyuv);// 1/4 -V
//pictureRGB 转储为QImage
QImage img((uchar*)buffer,this->pictureRGB->width,this->pictureRGB->height,
QImage::Format_RGB32);
sprintf(path,"../fileOut/image%d.png",num);
img.save(path);
num++;
if(num>5) break;
}
}
}
qDebug()<<num;
fclose(pyuv);
}