#include "FfmpegDecodeOld.h" ConstBuffer* FfmpegDecodeOld::m_pConstBuffer = new ConstBuffer(VideoBufferLength, false, false, VideoPacketLength); FfmpegDecodeOld::FfmpegDecodeOld(QObject* parent) : QThread(parent) , m_bNeedWork(false) , m_sBufferSize(VideoPacketLength) , m_pBuffer(nullptr) , m_pAVIOContext(nullptr) , m_pAVInputFormat(nullptr) , m_pAVFormatContext(nullptr) , m_iId(-1) , m_pAVPacket(nullptr) , m_pAVCodec(nullptr) , m_pAVCodecContext(nullptr) , m_pAVFrameSrc(nullptr) , m_pAVFrameDes(nullptr) , m_pAVCodecParameters(nullptr) , m_pSwsContext(nullptr) {} FfmpegDecodeOld::~FfmpegDecodeOld() {} int FfmpegDecodeOld::read_data(void* opaque, uint8_t* buf, int buf_size) { FfmpegDecodeOld* pFfmpegDecodeOld = (FfmpegDecodeOld*)opaque; unsigned short usRecvSize = pFfmpegDecodeOld->getConstBuffer()->read(buf, buf_size); return usRecvSize; } void FfmpegDecodeOld::init() { // (1)注册所有编解码器(codecs)、解析器(parsers)以及码流过滤器(bitstream filters) avcodec_register_all(); // (2)申请内存 m_pBuffer = (uint8_t*)av_malloc(sizeof(uint8_t) * m_sBufferSize); // (3)申请一个AVIOContext m_pAVIOContext = avio_alloc_context(m_pBuffer, m_sBufferSize, 0, NULL, read_data, NULL, NULL); // (4)探测网络流格式 if (av_probe_input_buffer(m_pAVIOContext, &m_pAVInputFormat, "", NULL, 0, 0) < 0) { return; } // (5)申请一个AVFormatContext m_pAVFormatContext = avformat_alloc_context(); // (6)将申请到的AVIOContext句柄挂载至之前申请的m_pAVFormatContext中 m_pAVFormatContext->pb = m_pAVIOContext; // (7)打开输入的AVFormatContext if (avformat_open_input(&m_pAVFormatContext, "", m_pAVInputFormat, NULL) < 0) { return; } // (8)检索流信息 if (avformat_find_stream_info(m_pAVFormatContext, NULL) < 0) { return; } // (9)打印格式信息 av_dump_format(m_pAVFormatContext, 0, "", 0); // (10)判断是否有视频编码解码器 for (int i = 0; i < m_pAVFormatContext->nb_streams; ++i) { if (m_pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { m_iId = i; break; } } if (m_iId == -1) { avformat_close_input(&m_pAVFormatContext); // 关闭流信息 return; } // (11)找到流的解码器 m_pAVCodec = avcodec_find_decoder(m_pAVFormatContext->streams[m_iId]->codecpar->codec_id); if (!m_pAVCodec) { return; // 未找到解码器 } // (12)分配视频编解码器上下文 m_pAVCodecContext = avcodec_alloc_context3(m_pAVCodec); if (!m_pAVCodecContext) { // 无法分配视频编解码器上下文 return; } // (13)将编解码器参数从输入流复制到输出编解码器上下文 m_pAVCodecParameters = m_pAVFormatContext->streams[m_iId]->codecpar; if (avcodec_parameters_to_context(m_pAVCodecContext, m_pAVFormatContext->streams[m_iId]->codecpar) < 0) { return; } // (14)打开解码器 if (avcodec_open2(m_pAVCodecContext, m_pAVCodec, NULL) < 0) { return; } // (15)申请视频帧存储空间 m_pAVFrameSrc = av_frame_alloc(); if (!m_pAVFrameSrc) { // 申请视频帧存储空间失败 return; } // (16)申请分配压缩数据包空间 av_init_packet(m_pAVPacket); if (!m_pAVPacket) { // 申请分配压缩数据包空间失败 return; } // (19)初始化图像数据存储空间 m_pAVFrameDes = av_frame_alloc(); if (!m_pAVFrameDes) { return; } av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, m_pAVCodecParameters->width, m_pAVCodecParameters->height, AV_PIX_FMT_RGB24, 1); // (20)初始化图像格式转换 m_pSwsContext = sws_getContext(m_pAVCodecParameters->width, m_pAVCodecParameters->height, (AVPixelFormat)m_pAVCodecParameters->format, m_pAVCodecParameters->width, m_pAVCodecParameters->height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); } void FfmpegDecodeOld::run() { int get_pict = 0; int ret = -1; // (17)获取一个AVPacket数据 while (0 <= av_read_frame(m_pAVFormatContext, m_pAVPacket)) { if (m_pAVPacket->stream_index == m_iId) { // (18)对AVPacket数据解码并将数据保存到m_pAVFrame中 if (0 <= avcodec_decode_video2(m_pAVCodecContext, m_pAVFrameSrc, &get_pict, m_pAVPacket)) { if (get_pict) { // (21)进行图像格式转换 sws_scale(m_pSwsContext, m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, 0, m_pAVFrameSrc->height, m_pAVFrameDes->data, m_pAVFrameDes->linesize); // (22)对转换后的数据进行处理 } } } } }