使用 FFmpeg 进行音视频解码,其实是一套标准操作,按照固定的流程进行实现即可。
使用 FFmpeg 进行音视频解码的基本流程、及用到的关键 API 接口和 结构体,如下图所示:
音视频解码管理基类
概述
使用 FFmpeg 对视频流解码和音频流解码的基本流程是一样的,因此可以使用同一个基类对相关资源进行管理。
解码器初始化
在使用 FFmpeg 对视频流解码和音频流解码之前,需要根据封装格式查找并打开对应的音视频解码器
打开音视频解码器
本文以软解(CPU 解码)为例进行实现。
代码示例
在 Decoder 类中增加 avCodecIni 接口,用于初始化解码器:
emplate<typename T>
class Decoder
{
public:
Decoder(int packetSize,int frameSize, WaitAndNotify &packet_wait):packetQueue( new Queue<AVPacket>(packetSize)),frameQueue( new Queue<AVFrame>(frameSize)), packetFullWait(packet_wait){};
~Decoder() ;
public:
void setAVFormatContext(AVFormatContext* format){ formatContext = format;}
void setStreamIndex(int m_index){ streamIndex = m_index;}
int getStreamIndex() const { return streamIndex;}
int avCodecIni();//解码器初始化
protected:
AVFormatContext* formatContext = nullptr;//封装格式上下文,外部传入
AVCodecContext* codecContext{ nullptr };//解码上下文
const AVCodec* codec{ nullptr };//解码器
AVFrame* currentFrame{ nullptr };//解码临时帧
Queue<AVPacket>* packetQueue{ nullptr };// packet 队列
Queue<AVFrame>* frameQueue{ nullptr }; //frame 队列
int streamIndex{ -1 };//流索引,外部传入
WaitAndNotify &packetFullWait;// 用于唤醒解封装线程
};
avCodecIni 方法实现如下:
template<typename T>
int Decoder<T>::avCodecIni() {
//创建解码上下文
codecContext = avcodec_alloc_context3(nullptr);
AVDictionary* opts = nullptr;
std::shared_ptr<AVDictionary*> optsCloser(&opts, av_dict_free);//用于自动关闭 opts
if (codecContext == nullptr) return -1;
//获取解码器
if (avcodec_parameters_to_context(codecContext, formatContext->streams[streamIndex]->codecpar) < 0)
{
return -1;
}
codecContext->pkt_timebase = formatContext->streams[streamIndex]->time_base;
codec = avcodec_find_decoder(codecContext->codec_id);
if (codec == nullptr)
{
return -1;
}
if( codec->type == AVMEDIA_TYPE_AUDIO)
{
static_cast<T *>(this)->paramsIni(codecContext);
}
//打开解码器
if (avcodec_open2(codecContext, codec, &opts) < 0)
{
return -1;
}
formatContext->streams[streamIndex]->discard = AVDISCARD_DEFAULT;//丢弃无用的数据包
currentFrame = av_frame_alloc();
return 0;
}
作者:litanyuan | 来源:公众号——编程猿来如此
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。