FFmpeg 入门学习 07--创建音视频解码管理类
前言
使用 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;//音频解码线程
};