|
|
|
|
#include "cffmpeg_decode.h"
|
|
|
|
|
Cffmpeg_decode::Cffmpeg_decode()
|
|
|
|
|
{
|
|
|
|
|
fmtCtx = avformat_alloc_context();
|
|
|
|
|
pkt = av_packet_alloc();
|
|
|
|
|
yuvFrame = av_frame_alloc();
|
|
|
|
|
rgbFrame = av_frame_alloc();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Cffmpeg_decode::~Cffmpeg_decode()
|
|
|
|
|
{
|
|
|
|
|
if(!pkt) av_packet_free(&pkt);
|
|
|
|
|
if(!yuvFrame) av_frame_free(&yuvFrame);
|
|
|
|
|
if(!rgbFrame) av_frame_free(&rgbFrame);
|
|
|
|
|
if(!videoCodecCtx) avcodec_free_context(&videoCodecCtx);
|
|
|
|
|
if(!videoCodecCtx) avcodec_close(videoCodecCtx);
|
|
|
|
|
if(!fmtCtx) avformat_close_input(&fmtCtx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Cffmpeg_decode::setUrl(QString url)
|
|
|
|
|
{
|
|
|
|
|
_url = url;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Cffmpeg_decode::open_input_file()
|
|
|
|
|
{
|
|
|
|
|
if(_url.isEmpty()) return 0;
|
|
|
|
|
|
|
|
|
|
AVDictionary* avdic = NULL;
|
|
|
|
|
av_dict_set(&avdic, "buffer_size", "2048000", 0); //设置缓存大小,1080p可将值调大
|
|
|
|
|
av_dict_set(&avdic, "rtsp_transport", "udp", 0); //以udp方式打开,如果以tcp方式打开将udp替换为tcp
|
|
|
|
|
av_dict_set(&avdic, "listen_timeout", "2", 0); //设置超时断开连接时间,单位微秒
|
|
|
|
|
av_dict_set(&avdic, "max_delay", "3000", 0); //设置最大时延
|
|
|
|
|
av_dict_set(&avdic, "tune", "zerolatency", 0);
|
|
|
|
|
av_dict_set(&avdic, "preset", "ultrafast", 0);
|
|
|
|
|
fmtCtx->flags |= AVFMT_FLAG_NONBLOCK;
|
|
|
|
|
if(avformat_open_input(&fmtCtx,_url.toLocal8Bit().data(),NULL,&avdic)<0){
|
|
|
|
|
printf("Cannot open input file.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(avformat_find_stream_info(fmtCtx,NULL)<0){
|
|
|
|
|
printf("Cannot find any stream in file.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int streamCnt=fmtCtx->nb_streams;
|
|
|
|
|
for(int i=0;i<streamCnt;i++){
|
|
|
|
|
if(fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
|
|
|
|
|
videoStreamIndex = i;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(videoStreamIndex==-1){
|
|
|
|
|
printf("Cannot find video stream in file.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AVCodecParameters *videoCodecPara = fmtCtx->streams[videoStreamIndex]->codecpar;
|
|
|
|
|
|
|
|
|
|
if(!(videoCodec = avcodec_find_decoder(videoCodecPara->codec_id))){
|
|
|
|
|
printf("Cannot find valid decode codec.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!(videoCodecCtx = avcodec_alloc_context3(videoCodec))){
|
|
|
|
|
printf("Cannot find valid decode codec context.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(avcodec_parameters_to_context(videoCodecCtx,videoCodecPara)<0){
|
|
|
|
|
printf("Cannot initialize parameters.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if(avcodec_open2(videoCodecCtx,videoCodec,NULL)<0){
|
|
|
|
|
printf("Cannot open codec.\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
img_ctx = sws_getContext(videoCodecCtx->width,
|
|
|
|
|
videoCodecCtx->height,
|
|
|
|
|
videoCodecCtx->pix_fmt,
|
|
|
|
|
videoCodecCtx->width,
|
|
|
|
|
videoCodecCtx->height,
|
|
|
|
|
AV_PIX_FMT_RGB32,
|
|
|
|
|
SWS_BICUBIC,NULL,NULL,NULL);
|
|
|
|
|
|
|
|
|
|
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32,videoCodecCtx->width,videoCodecCtx->height,1);
|
|
|
|
|
out_buffer = (unsigned char *)av_malloc(numBytes*sizeof(unsigned char));
|
|
|
|
|
|
|
|
|
|
int res = av_image_fill_arrays(
|
|
|
|
|
rgbFrame->data,rgbFrame->linesize,
|
|
|
|
|
out_buffer,AV_PIX_FMT_RGB32,
|
|
|
|
|
videoCodecCtx->width,videoCodecCtx->height,1);
|
|
|
|
|
if(res<0){
|
|
|
|
|
qDebug()<<"Fill arrays failed.";
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//线程里持续执行
|
|
|
|
|
void Cffmpeg_decode::run()
|
|
|
|
|
{
|
|
|
|
|
if(!open_input_file()){
|
|
|
|
|
qDebug()<<"Please open video file first.";
|
|
|
|
|
emit sendConnectFail(1);
|
|
|
|
|
IsstopPlay = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(av_read_frame(fmtCtx,pkt)>=0)
|
|
|
|
|
{
|
|
|
|
|
if(pkt->stream_index == videoStreamIndex){
|
|
|
|
|
if(avcodec_send_packet(videoCodecCtx,pkt)>=0){
|
|
|
|
|
int ret;
|
|
|
|
|
while((ret=avcodec_receive_frame(videoCodecCtx,yuvFrame))>=0)
|
|
|
|
|
{
|
|
|
|
|
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
|
|
|
|
return;
|
|
|
|
|
else if (ret < 0) {
|
|
|
|
|
fprintf(stderr, "Error during decoding\n");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
sws_scale(img_ctx,
|
|
|
|
|
yuvFrame->data,yuvFrame->linesize,
|
|
|
|
|
0,videoCodecCtx->height,
|
|
|
|
|
rgbFrame->data,rgbFrame->linesize);
|
|
|
|
|
|
|
|
|
|
QImage img(out_buffer,
|
|
|
|
|
videoCodecCtx->width,videoCodecCtx->height,
|
|
|
|
|
QImage::Format_RGB32);
|
|
|
|
|
emit sendQImage(img);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//int m_timeframe= ((double)videoCodecCtx->framerate.den / videoCodecCtx->framerate.num)*1000;
|
|
|
|
|
QThread::msleep(28);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
av_packet_unref(pkt);
|
|
|
|
|
}
|
|
|
|
|
if(IsstopPlay)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qDebug()<<"All video play done";
|
|
|
|
|
}
|