|
|
@ -1,25 +1,36 @@
|
|
|
|
#include "cffmpeg_decode.h"
|
|
|
|
#include "cffmpeg_decode.h"
|
|
|
|
// Cffmpeg_decode::Cffmpeg_decode() {
|
|
|
|
// Cffmpeg_decode::Cffmpeg_decode() {
|
|
|
|
Cffmpeg_decode::Cffmpeg_decode(QObject *parent) : QObject(parent) {
|
|
|
|
Cffmpeg_decode::Cffmpeg_decode(QObject *parent) : QObject(parent) {
|
|
|
|
fmtCtx = avformat_alloc_context();
|
|
|
|
inputFormatCtx = avformat_alloc_context();
|
|
|
|
pkt = av_packet_alloc();
|
|
|
|
outputFormatCtx = avformat_alloc_context();
|
|
|
|
|
|
|
|
inputPacket = av_packet_alloc();
|
|
|
|
|
|
|
|
outputPacket = av_packet_alloc();
|
|
|
|
yuvFrame = av_frame_alloc();
|
|
|
|
yuvFrame = av_frame_alloc();
|
|
|
|
rgbFrame = av_frame_alloc();
|
|
|
|
rgbFrame = av_frame_alloc();
|
|
|
|
|
|
|
|
avformat_network_init();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Cffmpeg_decode::~Cffmpeg_decode() {
|
|
|
|
Cffmpeg_decode::~Cffmpeg_decode() {
|
|
|
|
if (!pkt)
|
|
|
|
if (!inputPacket)
|
|
|
|
av_packet_free(&pkt);
|
|
|
|
av_packet_free(&inputPacket);
|
|
|
|
|
|
|
|
if (!outputPacket)
|
|
|
|
|
|
|
|
av_packet_free(&outputPacket);
|
|
|
|
if (!yuvFrame)
|
|
|
|
if (!yuvFrame)
|
|
|
|
av_frame_free(&yuvFrame);
|
|
|
|
av_frame_free(&yuvFrame);
|
|
|
|
if (!rgbFrame)
|
|
|
|
if (!rgbFrame)
|
|
|
|
av_frame_free(&rgbFrame);
|
|
|
|
av_frame_free(&rgbFrame);
|
|
|
|
if (!videoCodecCtx)
|
|
|
|
if (!encoderCtx)
|
|
|
|
avcodec_free_context(&videoCodecCtx);
|
|
|
|
avcodec_free_context(&encoderCtx);
|
|
|
|
if (!videoCodecCtx)
|
|
|
|
if (!encoderCtx)
|
|
|
|
avcodec_close(videoCodecCtx);
|
|
|
|
avcodec_close(encoderCtx);
|
|
|
|
if (!fmtCtx)
|
|
|
|
if (!decoderCtx)
|
|
|
|
avformat_close_input(&fmtCtx);
|
|
|
|
avcodec_free_context(&decoderCtx);
|
|
|
|
|
|
|
|
if (!decoderCtx)
|
|
|
|
|
|
|
|
avcodec_close(decoderCtx);
|
|
|
|
|
|
|
|
if (!inputFormatCtx)
|
|
|
|
|
|
|
|
avformat_close_input(&inputFormatCtx);
|
|
|
|
|
|
|
|
if (!outputFormatCtx)
|
|
|
|
|
|
|
|
avformat_close_input(&outputFormatCtx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Cffmpeg_decode::setUrl(QString url) { _url = url; }
|
|
|
|
void Cffmpeg_decode::setUrl(QString url) { _url = url; }
|
|
|
@ -28,76 +39,196 @@ bool Cffmpeg_decode::open_input_file() {
|
|
|
|
if (_url.isEmpty())
|
|
|
|
if (_url.isEmpty())
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//========================解码============================
|
|
|
|
AVDictionary *avdic = NULL;
|
|
|
|
AVDictionary *avdic = NULL;
|
|
|
|
// 设置缓存大小,1080p可将值调大
|
|
|
|
// 设置缓存大小,1080p可将值调大
|
|
|
|
av_dict_set(&avdic, "buffer_size", "2048000", 0);
|
|
|
|
av_dict_set(&avdic, "buffer_size", "2048000", 0);
|
|
|
|
// 以udp方式打开,如果以tcp方式打开将udp替换为tcp
|
|
|
|
// 以udp方式打开,如果以tcp方式打开将udp替换为tcp
|
|
|
|
av_dict_set(&avdic, "rtsp_transport", "udp", 0);
|
|
|
|
av_dict_set(&avdic, "rtsp_transport", "udp", 0);
|
|
|
|
// 设置超时断开连接时间,单位微秒//listen_timeout
|
|
|
|
// 设置超时断开连接时间,单位微秒//listen_timeout
|
|
|
|
av_dict_set(&avdic, "listen_timeout", "200000", 0);
|
|
|
|
//av_dict_set(&avdic, "listen_timeout", "200000", 0);
|
|
|
|
// av_dict_set(&avdic, "stimeout", "200000", 0);
|
|
|
|
av_dict_set(&avdic, "stimeout", "200000", 0);
|
|
|
|
av_dict_set(&avdic, "max_delay", "3", 0); // 设置最大时延
|
|
|
|
av_dict_set(&avdic, "max_delay", "3", 0); // 设置最大时延
|
|
|
|
av_dict_set(&avdic, "tune", "zerolatency", 0);
|
|
|
|
av_dict_set(&avdic, "tune", "zerolatency", 0);
|
|
|
|
av_dict_set(&avdic, "preset", "ultrafast", 0);
|
|
|
|
av_dict_set(&avdic, "preset", "ultrafast", 0);
|
|
|
|
fmtCtx->flags |= AVFMT_FLAG_NONBLOCK;
|
|
|
|
|
|
|
|
if (avformat_open_input(&fmtCtx, _url.toUtf8().data(), NULL, &avdic) < 0) {
|
|
|
|
inputFormatCtx->flags |= AVFMT_FLAG_NONBLOCK;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 打开输入流
|
|
|
|
|
|
|
|
if (avformat_open_input(&inputFormatCtx, _url.toUtf8().data(), NULL, &avdic) <0) {
|
|
|
|
printf("Cannot open input file.\n");
|
|
|
|
printf("Cannot open input file.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找流信息
|
|
|
|
if (avformat_find_stream_info(fmtCtx, NULL) < 0) {
|
|
|
|
if (avformat_find_stream_info(inputFormatCtx, NULL) < 0) {
|
|
|
|
printf("Cannot find any stream in file.\n");
|
|
|
|
printf("Cannot find any stream in file.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 从输入流中找到第一个视频流
|
|
|
|
int streamCnt = fmtCtx->nb_streams;
|
|
|
|
for (int i = 0; i < inputFormatCtx->nb_streams; i++) {
|
|
|
|
for (int i = 0; i < streamCnt; i++) {
|
|
|
|
if (inputFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
|
|
|
|
videoStreamIndex = i;
|
|
|
|
videoStreamIndex = i;
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (videoStreamIndex == -1) {
|
|
|
|
if (videoStreamIndex == -1) {
|
|
|
|
printf("Cannot find video stream in file.\n");
|
|
|
|
printf("Cannot find video stream in file.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AVCodecParameters *videoCodecPara =
|
|
|
|
// 获取视频流的解码器参数
|
|
|
|
fmtCtx->streams[videoStreamIndex]->codecpar;
|
|
|
|
videoCodecPara = inputFormatCtx->streams[videoStreamIndex]->codecpar;
|
|
|
|
|
|
|
|
|
|
|
|
if (!(videoCodec = avcodec_find_decoder(videoCodecPara->codec_id))) {
|
|
|
|
decoder = avcodec_find_decoder(videoCodecPara->codec_id);
|
|
|
|
|
|
|
|
if (!decoder) {
|
|
|
|
printf("Cannot find valid decode codec.\n");
|
|
|
|
printf("Cannot find valid decode codec.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 为解码器上下文分配空间
|
|
|
|
if (!(videoCodecCtx = avcodec_alloc_context3(videoCodec))) {
|
|
|
|
decoderCtx = avcodec_alloc_context3(decoder);
|
|
|
|
|
|
|
|
if (!decoderCtx) {
|
|
|
|
printf("Cannot find valid decode codec context.\n");
|
|
|
|
printf("Cannot find valid decode codec context.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 初始化解码器上下文
|
|
|
|
if (avcodec_parameters_to_context(videoCodecCtx, videoCodecPara) < 0) {
|
|
|
|
if (avcodec_parameters_to_context(decoderCtx, videoCodecPara) < 0) {
|
|
|
|
printf("Cannot initialize parameters.\n");
|
|
|
|
printf("Cannot initialize parameters.\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avcodec_open2(videoCodecCtx, videoCodec, NULL) < 0) {
|
|
|
|
// 打开解码器
|
|
|
|
|
|
|
|
if (avcodec_open2(decoderCtx, decoder, NULL) < 0) {
|
|
|
|
printf("Cannot open codec.\n");
|
|
|
|
printf("Cannot open codec.\n");
|
|
|
|
return 0;
|
|
|
|
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);
|
|
|
|
// 1、输出文件设置
|
|
|
|
|
|
|
|
if (avformat_alloc_output_context2(&outputFormatCtx, NULL, NULL, "output_video.mp4") < 0) {
|
|
|
|
|
|
|
|
qDebug() << "Could not create output context.\n";
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 从输入流中找到第一个视频流
|
|
|
|
|
|
|
|
for (int i = 0; i < inputFormatCtx->nb_streams; i++) {
|
|
|
|
|
|
|
|
if (inputFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
|
|
|
|
videoStreamIndexOut = i;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (videoStreamIndexOut == -1) {
|
|
|
|
|
|
|
|
printf("Cannot find video stream in file.\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取视频流的解码器参数
|
|
|
|
|
|
|
|
videoCodecPara2 = inputFormatCtx->streams[videoStreamIndexOut]->codecpar;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3、创建输出视频流
|
|
|
|
|
|
|
|
outStream = avformat_new_stream(outputFormatCtx, NULL);
|
|
|
|
|
|
|
|
if (!outStream) {
|
|
|
|
|
|
|
|
qDebug() << "Failed allocating output stream.\n";
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//4、查找编码器
|
|
|
|
|
|
|
|
encoder = avcodec_find_encoder(videoCodecPara2->codec_id);
|
|
|
|
|
|
|
|
if(!encoder){
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//5、分配解码器上下文
|
|
|
|
|
|
|
|
encoderCtx = avcodec_alloc_context3(encoder);
|
|
|
|
|
|
|
|
if (!encoderCtx) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//初始化视频AVCodecContext
|
|
|
|
|
|
|
|
encoderCtx->height = videoCodecPara2->height;
|
|
|
|
|
|
|
|
encoderCtx->width = videoCodecPara2->width;
|
|
|
|
|
|
|
|
videoCodecPara2->framerate = av_guess_frame_rate(inputFormatCtx,inputFormatCtx->streams[videoStreamIndexOut],NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//视频流的时间基是1 / 帧率
|
|
|
|
|
|
|
|
encoderCtx->time_base = av_inv_q(inputFormatCtx->streams[videoStreamIndexOut]->codecpar->framerate);
|
|
|
|
|
|
|
|
encoderCtx->sample_aspect_ratio = inputFormatCtx->streams[videoStreamIndexOut]->codecpar->sample_aspect_ratio;
|
|
|
|
|
|
|
|
if (encoder->pix_fmts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
encoderCtx->pix_fmt = encoder->pix_fmts[0];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
encoderCtx->codec_type = AVMEDIA_TYPE_VIDEO;
|
|
|
|
|
|
|
|
encoderCtx->codec_id = AV_CODEC_ID_H264;
|
|
|
|
|
|
|
|
encoderCtx->bit_rate = 2000000;
|
|
|
|
|
|
|
|
encoderCtx->time_base.num = 1;
|
|
|
|
|
|
|
|
encoderCtx->time_base.den = 20;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//全局头
|
|
|
|
|
|
|
|
if (outputFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
encoderCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //设置选项
|
|
|
|
|
|
|
|
// AVDictionary *param = 0;
|
|
|
|
|
|
|
|
// //H.264
|
|
|
|
|
|
|
|
// if(videoCodecPara->codec_id == AV_CODEC_ID_H264) {
|
|
|
|
|
|
|
|
// av_dict_set(¶m, "preset", "slow", 0);
|
|
|
|
|
|
|
|
// av_dict_set(¶m, "tune", "zerolatency", 0);
|
|
|
|
|
|
|
|
// av_dict_set(¶m, "profile", "main", 0);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// //H.265
|
|
|
|
|
|
|
|
// if(videoCodecPara->codec_id == AV_CODEC_ID_H265){
|
|
|
|
|
|
|
|
// av_dict_set(¶m, "preset", "ultrafast", 0);
|
|
|
|
|
|
|
|
// av_dict_set(¶m, "tune", "zero-latency", 0);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//6、打开编码器
|
|
|
|
|
|
|
|
if (avcodec_open2(encoderCtx, encoder, NULL) < 0) {
|
|
|
|
|
|
|
|
qDebug() << "Error occurred when opening encoder.\n";
|
|
|
|
|
|
|
|
//return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
avcodec_parameters_from_context(outputFormatCtx->streams[0]->codecpar, encoderCtx);
|
|
|
|
|
|
|
|
//avcodec_parameters_to_context(encoderCtx,outStream->codecpar);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 打开输出文件
|
|
|
|
|
|
|
|
if (!(outputFormatCtx->oformat->flags & AVFMT_NOFILE)) {
|
|
|
|
|
|
|
|
if (avio_open(&outputFormatCtx->pb,
|
|
|
|
|
|
|
|
outputFormatCtx->url /* "output_video.mp4"*/,
|
|
|
|
|
|
|
|
AVIO_FLAG_WRITE) < 0) {
|
|
|
|
|
|
|
|
printf("Could not open output file.\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//写入输出文件的头信息
|
|
|
|
|
|
|
|
if (avformat_write_header(outputFormatCtx, NULL) < 0) {
|
|
|
|
|
|
|
|
qDebug() << "Error occurred when opening output file.\n";
|
|
|
|
|
|
|
|
//return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//格式化输出输出文件信息
|
|
|
|
|
|
|
|
av_dump_format(outputFormatCtx,0,outputFormatCtx->url,1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化图像转换器
|
|
|
|
|
|
|
|
swsCtx = sws_getContext(decoderCtx->width, //
|
|
|
|
|
|
|
|
decoderCtx->height, //
|
|
|
|
|
|
|
|
decoderCtx->pix_fmt, //
|
|
|
|
|
|
|
|
decoderCtx->width, //
|
|
|
|
|
|
|
|
decoderCtx->height, //
|
|
|
|
|
|
|
|
AV_PIX_FMT_RGB32, //
|
|
|
|
|
|
|
|
SWS_BICUBIC, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, //
|
|
|
|
|
|
|
|
decoderCtx->width, //
|
|
|
|
|
|
|
|
decoderCtx->height, //
|
|
|
|
|
|
|
|
1);
|
|
|
|
out_buffer = (unsigned char *)av_malloc(numBytes * sizeof(unsigned char));
|
|
|
|
out_buffer = (unsigned char *)av_malloc(numBytes * sizeof(unsigned char));
|
|
|
|
|
|
|
|
|
|
|
|
int res = av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, out_buffer,
|
|
|
|
int res = av_image_fill_arrays(rgbFrame->data, //
|
|
|
|
AV_PIX_FMT_RGB32, videoCodecCtx->width,
|
|
|
|
rgbFrame->linesize, //
|
|
|
|
videoCodecCtx->height, 1);
|
|
|
|
out_buffer, //
|
|
|
|
|
|
|
|
AV_PIX_FMT_RGB32, //
|
|
|
|
|
|
|
|
decoderCtx->width, //
|
|
|
|
|
|
|
|
decoderCtx->height, 1);
|
|
|
|
if (res < 0) {
|
|
|
|
if (res < 0) {
|
|
|
|
qDebug() << "Fill arrays failed.";
|
|
|
|
qDebug() << "Fill arrays failed.\n";
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -113,52 +244,83 @@ void Cffmpeg_decode::run() {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (av_read_frame(fmtCtx, pkt) >= 0) {
|
|
|
|
// 读取数据包
|
|
|
|
if (pkt->stream_index == videoStreamIndex) {
|
|
|
|
while (av_read_frame(inputFormatCtx, inputPacket) >= 0) {
|
|
|
|
if (avcodec_send_packet(videoCodecCtx, pkt) >= 0) {
|
|
|
|
if (IsstopPlay) {
|
|
|
|
|
|
|
|
qDebug() << "video play stop";
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (inputPacket->stream_index == videoStreamIndex) {
|
|
|
|
|
|
|
|
// 解码数据包
|
|
|
|
|
|
|
|
if (avcodec_send_packet(decoderCtx, inputPacket) >= 0) {
|
|
|
|
int ret;
|
|
|
|
int ret;
|
|
|
|
while ((ret = avcodec_receive_frame(videoCodecCtx, yuvFrame)) >= 0) {
|
|
|
|
while ((ret = avcodec_receive_frame(decoderCtx, yuvFrame)) >= 0) {
|
|
|
|
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
|
|
|
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
else if (ret < 0) {
|
|
|
|
} else if (ret < 0) {
|
|
|
|
fprintf(stderr, "Error during decoding\n");
|
|
|
|
fprintf(stderr, "Error during decoding\n");
|
|
|
|
exit(1);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sws_scale(img_ctx, yuvFrame->data, yuvFrame->linesize, 0,
|
|
|
|
sws_scale(swsCtx, //
|
|
|
|
videoCodecCtx->height, rgbFrame->data, rgbFrame->linesize);
|
|
|
|
yuvFrame->data, //
|
|
|
|
|
|
|
|
yuvFrame->linesize, //
|
|
|
|
|
|
|
|
0, //
|
|
|
|
|
|
|
|
decoderCtx->height, //
|
|
|
|
|
|
|
|
rgbFrame->data, //
|
|
|
|
|
|
|
|
rgbFrame->linesize);
|
|
|
|
|
|
|
|
|
|
|
|
QImage img(out_buffer, videoCodecCtx->width, videoCodecCtx->height,
|
|
|
|
QImage img(out_buffer, //
|
|
|
|
|
|
|
|
decoderCtx->width, //
|
|
|
|
|
|
|
|
decoderCtx->height, //
|
|
|
|
QImage::Format_RGB32);
|
|
|
|
QImage::Format_RGB32);
|
|
|
|
emit sendQImage(img);
|
|
|
|
emit sendQImage(img);
|
|
|
|
|
|
|
|
|
|
|
|
// int m_timeframe= ((double)videoCodecCtx->framerate.den /
|
|
|
|
|
|
|
|
// videoCodecCtx->framerate.num)*1000;
|
|
|
|
|
|
|
|
QThread::msleep(28);
|
|
|
|
QThread::msleep(28);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//将解码后的帧写入输出文件
|
|
|
|
|
|
|
|
if (av_write_frame(outputFormatCtx, inputPacket) < 0) {
|
|
|
|
|
|
|
|
//qDebug() << "Error muxing packet.\n";
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
av_packet_unref(pkt);
|
|
|
|
av_packet_unref(inputPacket);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsstopPlay) {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//花屏
|
|
|
|
|
|
|
|
// if (av_read_frame(inputFormatCtx, inputPacket) < 0) {
|
|
|
|
|
|
|
|
// break; // 达到文件末尾
|
|
|
|
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qDebug() << "All video play done";
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 退出
|
|
|
|
// 退出
|
|
|
|
void Cffmpeg_decode::stop() {
|
|
|
|
void Cffmpeg_decode::stop() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 写入输出文件的尾信息
|
|
|
|
|
|
|
|
// av_write_trailer(outputFormatCtx);
|
|
|
|
IsstopPlay = true;
|
|
|
|
IsstopPlay = true;
|
|
|
|
if (!pkt)
|
|
|
|
if (!inputPacket)
|
|
|
|
av_packet_free(&pkt);
|
|
|
|
av_packet_free(&inputPacket);
|
|
|
|
|
|
|
|
if (!outputPacket)
|
|
|
|
|
|
|
|
av_packet_free(&outputPacket);
|
|
|
|
if (!yuvFrame)
|
|
|
|
if (!yuvFrame)
|
|
|
|
av_frame_free(&yuvFrame);
|
|
|
|
av_frame_free(&yuvFrame);
|
|
|
|
if (!rgbFrame)
|
|
|
|
if (!rgbFrame)
|
|
|
|
av_frame_free(&rgbFrame);
|
|
|
|
av_frame_free(&rgbFrame);
|
|
|
|
if (!videoCodecCtx)
|
|
|
|
if (!encoderCtx)
|
|
|
|
avcodec_free_context(&videoCodecCtx);
|
|
|
|
avcodec_free_context(&encoderCtx);
|
|
|
|
if (!videoCodecCtx)
|
|
|
|
if (!encoderCtx)
|
|
|
|
avcodec_close(videoCodecCtx);
|
|
|
|
avcodec_close(encoderCtx);
|
|
|
|
if (!fmtCtx)
|
|
|
|
if (!decoderCtx)
|
|
|
|
avformat_close_input(&fmtCtx);
|
|
|
|
avcodec_free_context(&decoderCtx);
|
|
|
|
|
|
|
|
if (!decoderCtx)
|
|
|
|
|
|
|
|
avcodec_close(decoderCtx);
|
|
|
|
|
|
|
|
if (!inputFormatCtx)
|
|
|
|
|
|
|
|
avformat_close_input(&inputFormatCtx);
|
|
|
|
|
|
|
|
if (!outputFormatCtx)
|
|
|
|
|
|
|
|
avformat_close_input(&outputFormatCtx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|