当前位置: 首页 > article >正文

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;//音频解码线程
};

http://www.kler.cn/a/5936.html

相关文章:

  • 【AI进化论】 如何让AI帮我们写一个项目系列:将Mysql生成md文档
  • 设计模式学习[15]---适配器模式
  • Windows 11 上配置VSCode 使用 Git 和 SSH 完整步骤
  • 【Ubuntu】 Ubuntu22.04搭建NFS服务
  • QT自定义工具条渐变背景颜色一例
  • 监听器与RBAC权限模型
  • 图片怎么转PDF文件?三种免费转换方法集合!
  • 3、AI的道德性测试
  • linux宝塔面板安装composer的方法[全网详解]
  • @Transactional和synchronized同时使用时的一些问题以及解决
  • YOLO算法改进指南【算法解读篇】:2.如何训练自己的数据集
  • 13、操作系统——posix信号量(无名信号量)
  • python开启局域网传输
  • 【C++笔试强训】第五天
  • 不相交的集合数据结构
  • PerfEnforce Demonstration: Data Analytics with Performance Guarantees
  • 涨点技巧:Yolov5/Yolov7 引入Yolo-Z---ResneXtBottleneckCSP和DenseBlock,提升小目标检测能力
  • PCB模块化设计13——FLASH、DDR和eMMC高速PCB布局布线设计规范
  • QT学习(四)——常用控件
  • 阿里P8高级技术专家自述被裁员,疑似给市长写信,房贷月供3w,压力很大,出门面试找工作很难!...
  • 谷粒商城笔记+踩坑(22)——库存自动解锁。RabbitMQ延迟队列
  • python---数据容器
  • DRF知识点总结
  • 来给大家解释一下赌博为什么会输成穷光蛋。
  • 【C4D】基础快捷键操作,布尔操作——动不了怎么办+选不上怎么办+怎么移动+怎么拉平面或拉平一圈线
  • 算法第二十期——FLoyd算法的入门与应用