FFMPEG C++封装(三)

4 详细设计

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

4.3 Packet

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

4.3.1 Packet定义

cpp 复制代码
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;
}
}

类型说明:

  • 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定义

cpp 复制代码
extern "C"
{
#include <libavcodec/avcodec.h>
}
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;
};
}
}

函数说明:

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

4.3.3 Packet实现

cpp 复制代码
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_;
}

}
}

说明:

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

未完待续...

相关推荐
神仙别闹1 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE2 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
我们的五年12 分钟前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
zwjapple19 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five20 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
前端每日三省22 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱35 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
做人不要太理性38 分钟前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.1 小时前
2、桥接模式
c++·桥接模式
chnming19871 小时前
STL关联式容器之map
开发语言·c++