使用 FFmpeg 进行音视频解码,其实是一套标准操作,按照固定的流程进行实现即可。使用 FFmpeg 进行音视频解码的基本流程、及用到的关键 API 接口和 结构体,如下图所示:
背景
FFmpeg 解码所需资源
使用 FFmpeg 对视频流解码和音频流解码的基本流程是一样的,因此可以使用同一个基类对相关资源进行管理。
FFmpeg 解码所需资源如下:
- AVFormatContext
封装格式上下文,在使用 FFmpeg 进行解码时 AVFormatContext 是一个贯穿始终的数据结构。 - AVCodecContext
编解码器上下文,用于存储编解码过程中的各种状态信息。 - AVCodec
存储编解码器信息的结构体,每个编解码器对应一个 AVCodec 结构体。 - 流索引
通过索引获取对应流的编解码器的相关参数。 - 缓存队列
- AVPacket 缓存队列
- AVFrame 缓存队列
C++ 惯用法之 CRTP
CRTP 是 一种 C++ 的设计方法,其巧妙的结合了继承和模板编程技术,可以用来给类提供额外的功能。
CRTP 的基本特征表现为:基类是一个模板类;派生类在继承该基类时,将派生类自身作为模板参数传递给基类。
一般使用 CRTP 可以把重复性的代码抽象到基类中,减少代码冗余,示例如下:
template<typename T>
class baseDemo
{
public:
virtual ~baseDemo(){}
void getType()
{
T& t = static_cast<T&>(*this);
cout << typeid(t).name() << endl;
}
};
class derivedDemo1:public baseDemo<derivedDemo1>
{
};
class derivedDemo2 :public baseDemo<derivedDemo2>
{
};
int main()
{
derivedDemo1 d1;
derivedDemo2 d2;
d1.getType();
d2.getType();
return 0;
}
创建解码管理基类
使用 CRTP 惯用法把视频解码、音频解码相同的部分抽象到基类,然后再分别扩展各自不同的部分。
定义模板基类
基类用于对相同部分的资源进行管理,定义如下:
template<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;}
protected:
AVFormatContext* formatContext = nullptr;//封装格式上下文,外部传入
AVCodecContext* codecContext{ nullptr };//解码上下文
const AVCodec* codec{ nullptr };//解码器
Queue<AVPacket>* packetQueue{ nullptr };// packet 队列
Queue<AVFrame>* frameQueue{ nullptr }; //frame 队列
int streamIndex{ -1 };//流索引,外部传入
WaitAndNotify &packetFullWait;// 用于唤醒解封装线程
};
定义视频解码类
视频解码类继承以自身为参数的 Decoder 模板类,代码如下:
class VideoDecoder:public Decoder<VideoDecoder>
{
public:
explicit VideoDecoder(WaitAndNotify &packet_wait) : Decoder<VideoDecoder>(20,3, packet_wait){};
~VideoDecoder() ;
private:
std::thread * decode_thread = nullptr;//视频解码线程
};
定义音频解码类
音频解码类继承以自身为参数的 Decoder 模板类,代码如下:
class AudioDecoder:public Decoder<AudioDecoder>
{
public:
explicit AudioDecoder(WaitAndNotify &packet_wait): Decoder<AudioDecoder>(20,9, packet_wait){};
~AudioDecoder() ;
private:
std::thread * decode_thread = nullptr;//音频解码线程
};
作者:litanyuan | 来源:公众号——编程猿来如此
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。