FFmpeg 入门学习 07–创建音视频解码管理类

使用 FFmpeg 进行音视频解码,其实是一套标准操作,按照固定的流程进行实现即可。使用 FFmpeg 进行音视频解码的基本流程、及用到的关键 API 接口和 结构体,如下图所示:

FFmpeg 入门学习 07--创建音视频解码管理类

背景

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 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论