#include "CVideoLive.h"
CVideoLive::CVideoLive()
{
}
CVideoLive::~CVideoLive()
{
}
void CVideoLive::StartPlay()
{
this->start();
}
void CVideoLive::run()
{
QByteArray ba = mFileName.toLocal8Bit(); // must
char *cFilePath = ba.data();
AVFormatContext *mFormatContext;//使用完毕需要手动释放
AVCodecContext *mCodecContext;//使用完毕需要手动释放
AVCodec *mCodec;
AVFrame *mFrame, *mFrameRGB;//mFrame储存解码后的原始数据, mFrameRGB是储存转为RGB之后的数据
uint8_t *out_buffer;
AVPacket *mVideoPacket;
static struct SwsContext *mSwsContext;
av_register_all();
avformat_network_init();
mFormatContext = avformat_alloc_context();
if(avformat_open_input(&mFormatContext,cFilePath,NULL,NULL) != 0)
{
qDebug() << "流文件打开失败!";
return;
}
if(avformat_find_stream_info(mFormatContext,NULL) < 0)
{
qDebug() << "流文件读取头文件失败!";
return;
}
int iVideoNuber = -1;//记录视频流在流列表中的位置 ;
//遍历mFormatContext中所有流,判断其是否为视频流,是,记录其在所有流数组的位置 即是下标。
for(int i = 0; i < mFormatContext->nb_streams; i++)
{
if(mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
iVideoNuber = i;
}
}
if(iVideoNuber == -1)
{
qDebug() << "未找到视频流";
return;
}
mCodecContext = mFormatContext->streams[iVideoNuber]->codec;
mCodec = avcodec_find_decoder(mCodecContext->codec_id);
if(NULL == mCodec)
{
qDebug() << "视频解码器创建失败!";
return;
}
if(avcodec_open2(mCodecContext,mCodec,NULL) != 0)//打开视频流解码器
{
qDebug() << "视频解码器打开失败!";
return;
}
mVState.sFormatCont = mFormatContext;
mVState.sCodecCont = mCodecContext;
mVState.sCodec = mCodec;
mFrame = av_frame_alloc();
mFrameRGB = av_frame_alloc();
//初始化一个sws_Context,后面转码用
mSwsContext = sws_getContext(mCodecContext->width,mCodecContext->height,mCodecContext->pix_fmt
,mCodecContext->width,mCodecContext->height,
PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
//计算一下储存图片的大小,用来初始化容器
int numBytes = avpicture_get_size(PIX_FMT_RGB32, mCodecContext->width,mCodecContext->height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) mFrameRGB, out_buffer, PIX_FMT_RGB32,
mCodecContext->width, mCodecContext->height);
int y_size = mCodecContext->width * mCodecContext->height;
mVideoPacket = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet
av_new_packet(mVideoPacket, y_size); //分配packet的数据,我觉得更像是初始化packet大小
//输出视频流消息
av_dump_format(mFormatContext,0,cFilePath,0);
int iPicturePtr = 0;
/*以上初始化准备工作完毕,下面循环取数据,发送出去*/
while(1)
{
if(av_read_frame(mFormatContext,mVideoPacket) < 0)
{
qDebug() << "视频播放完毕";
break;
}
if(mVideoPacket->stream_index == iVideoNuber)//判断此流的索引是否为之前检测到的视频流
{
if(avcodec_decode_video2(mCodecContext,mFrame,&iPicturePtr,mVideoPacket) < 0)
{
qDebug() << "解码错误";
return;
}
if (iPicturePtr)
{
sws_scale(mSwsContext,(uint8_t const * const *) mFrame->data,
mFrame->linesize, 0, mCodecContext->height, mFrameRGB->data,
mFrameRGB->linesize);
//把这个RGB数据 用QImage加载
QImage tmpImg((uchar *)out_buffer,mCodecContext->width,mCodecContext->height,QImage::Format_RGB32);
QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示
emit sig_GetOneFrame(image); //发送信号
}
av_free_packet(mVideoPacket);//每一次使用完,都要清空,不然会出问题
msleep(30); //停一停 不然放的太快了
}
}
/*使用完毕要释放的*/
av_free(out_buffer);
av_free(mFrameRGB);
av_free(mFrame);
avcodec_close(mCodecContext);
avformat_close_input(&mFormatContext);
}
评论0
最新资源