#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, "stimeout", "2000000", 0); //设置超时断开连接时间,单位微秒 av_dict_set(&avdic, "max_delay", "3000", 0); //设置最大时延 av_dict_set(&avdic, "tune", "zerolatency", 0); av_dict_set(&avdic, "preset", "ultrafast", 0); 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;istreams[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."; 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"; }