• FFMPEG C++封装(三)


    4 详细设计

    这章是FFMPEG C++封装库的详细设计。

    4.3 Packet

    该模块是编码后数据包类型。

    4.3.1 Packet定义

    namespace media
    {
    namespace sdk
    {
    typedef int PacketType;
    
    PacketType const PacketType_Audio    = 0;
    PacketType const PacketType_Video    = 1;
    PacketType const PacketType_Subtitle = 2;
    PacketType const PacketType_Data     = 3;
    PacketType const PacketType_None     = 4;
    
    struct MEDIASDK_EXPORT Rational
    {
        Rational() : num(1), den(1){}
        Rational(int n, int d) : num(n) , den(d) {}
        bool operator ==(Rational const& r) const
        {
            return num == r.num && den == r.den;
        }
        bool operator !=(Rational const& r) const
        {
            return !(*this == r);
        }
        int num;
        int den;
    };
    
    typedef struct PacketHandle* PacketHandlePtr;
    struct MEDIASDK_EXPORT Packet
    {
        Packet();
        Packet(Packet const&) = delete;
    
        ~Packet();
    
        Packet& operator = (Packet const&) = delete;
    
        static int64_t ToTime(int64_t const& pts, Rational const& timebase);
    
        typedef std::shared_ptr<Packet> Ptr;
        PacketType type() const;
        
        bool is_empty() const;
        bool is_keyframe() const;
        bool is_badframe() const;
        
        int64_t pts() const;
        int64_t dts() const;
        int64_t original_pts() const;
        int64_t original_dts() const;
        int64_t pos() const;
    
        int64_t duration() const;
        int64_t next_dts() const;
    
        void offset_time(int64_t const& offset);
        void modify_time(Rational const& timebase1, Rational const& timebase2);
    
        const uint8_t *data() const;
        int size() const;
    
        int stream_index() const;
        void reset();
    private:
        PacketHandlePtr handle();
        void type(PacketType type);
        friend struct IStream;
        friend struct OStream;
        friend struct VideoDecoder;
        friend struct AudioDecoder;
        friend struct VideoEncoder;
        friend struct AudioEncoder;
    
        // noncopyable:
        Packet( Packet& );
        void operator = ( Packet& );
    
        PacketHandlePtr handle_;
    };
    typedef Packet::Ptr PacketPtr;
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    类型说明:

    • PacketType Packet类型。
      • PacketType_Audio 音频类型
      • PacketType_Video 视频类型
      • PacketType_Subtitle 字幕类型
      • PacketType_Data 数据类型
      • PacketType_None 无效类型,用作初始值
    • Rational 一个分数类型,这里主要用来描述时间单位。
    • Packet 编码数据包类型,对AVPacket数据类型封装。
      • ToTime 将显示时间戳转换为以timebase为单位的时间。
      • type 返回Packet类型
      • is_empty 判断Packet是否为空。
      • is_keyframe 判断Packet是否为关键帧。
      • is_badframe 判断Packet是否为损坏帧。
      • pts 返回显示时间戳
      • dts 返回解码时间戳
      • original_pts 返回原始显示时间戳
      • original_dts 返回原始解码时间戳
      • pos 返回Packet在视频文件中位置(从文件头到Packet开始的字节位置)
      • duration Packet包的时长。
      • next_dts 下一个解码时间戳
      • offset_time 偏移时间
      • modify_time 修改时间单位。
      • data 返回Packet包数据。
      • size 返回Pakcet数据大小
      • stream_index Packet包在视频文件中流索引。
      • reset 复位Packet包到刚创建时。

    4.3.2 PacketHandle定义

    extern "C"
    {
    #include 
    }
    namespace media
    {
    namespace sdk
    {
    struct PacketHandle
    {
        PacketHandle()
            : packet(new AVPacket())
            , type(PacketType_None)
        {
           av_init_packet(packet);
           packet->data = 0;
           packet->size = 0;
           original_pts = packet->pts;
           original_dts = packet->dts;
        }
    
        ~PacketHandle()
        {
            av_packet_unref(packet);
        }
    
        AVPacket* packet;
        PacketType  type;
        int64_t original_pts;
        int64_t original_dts;
    };
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    函数说明:

    • 构造函数 创建AVPacket对象并初始化
    • 析构函数 删除AVPacket对象

    4.3.3 Packet实现

    namespace media
    {
    namespace sdk
    {
    Packet::Packet()
        : handle_(new PacketHandle())
    {
    }
    
    Packet::~Packet()
    {
        delete handle_;
    }
    
    int64_t Packet::ToTime(int64_t const& pts, Rational const& timebase)
    {
        AVRational tb1 = {timebase.num, timebase.den};
        AVRational tb2 = {1, AV_TIME_BASE};
        return av_rescale_q(pts, tb1, tb2);
    }
    
    void Packet::reset()
    {
        av_packet_unref(handle_->packet);
        av_init_packet(handle_->packet);
    }
    
    PacketType Packet::type() const
    {
        return handle_->type;
    }
    
    bool Packet::is_empty() const
    {
        return (handle_->packet->data == 0) ? true : false;
    }
    
    bool Packet::is_keyframe() const
    {
        if(handle_->packet->flags & AV_PKT_FLAG_KEY)
            return true;
        return false;
    }
    
    bool Packet::is_badframe() const
    {
        if(handle_->packet->flags & AV_PKT_FLAG_CORRUPT)
            return true;
        return false;
    }
    
    int64_t Packet::pts() const
    {
        return handle_->packet->pts;
    }
    
    int64_t Packet::dts() const
    {
        return handle_->packet->dts;
    }
    
    int64_t Packet::original_pts() const
    {
        return handle_->original_pts;
    }
    
    int64_t Packet::original_dts() const
    {
        return handle_->original_dts;
    }
    
    int64_t Packet::duration() const
    {
        return handle_->packet->duration;
    }
    
    int64_t Packet::next_dts() const
    {
        return handle_->packet->dts + handle_->packet->duration;
    }
    
    void Packet::offset_time(int64_t const& offset)
    {
        if(handle_->packet)
        {
            handle_->packet->dts += offset;
            handle_->packet->pts += offset;
        }
    }
    
    void Packet::modify_time(Rational const& timebase1, Rational const& timebase2)
    {
        if(timebase1 == timebase2)
            return;
    
        AVRational tb1 = {timebase1.num, timebase1.den};
        AVRational tb2 = {timebase2.num, timebase2.den};
        handle_->packet->dts = av_rescale_q(handle_->packet->dts, tb1, tb2);
        handle_->packet->pts = av_rescale_q(handle_->packet->pts, tb1, tb2);
        handle_->packet->duration = av_rescale_q(handle_->packet->duration, tb1, tb2);
    }
    
    int64_t Packet::pos() const
    {
        return handle_->packet->pos;
    }
    
    const uint8_t *Packet::data() const
    {
        return handle_->packet->data;
    }
    
    int Packet::size() const
    {
        return handle_->packet->size;
    }
    
    int Packet::stream_index() const
    {
        return handle_->packet->stream_index;
    }
    
    void Packet::type(PacketType t)
    {
        handle_->type = t;
    }
    
    PacketHandlePtr Packet::handle()
    {
        return handle_;
    }
    
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134

    说明:

    • Packet类实现比较简单,不再详述。

    未完待续…

  • 相关阅读:
    5G通信与蜂窝模组之间的关系
    [SQL]数据查询(一)
    绘制函数堆栈
    实习生跑路留了一个大坑,搞出2个线上问题,我被坑惨了
    [HTML/CSS基础]知识点汇总
    MyBatisPlus使用自定义JsonTypeHandler实现自动转化JSON
    关于丢失msvcp71.dll的5个解决办法,msvcp71.dll丢失原因分析
    LeetCode 98. 验证二叉搜索树(C++)
    Java项目:智能点餐推荐系统(java+SSM+JSP+BootStrap+Mysql)
    ros2 服务节点源代码
  • 原文地址:https://blog.csdn.net/flysnow010/article/details/137844383