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类实现比较简单,不再详述。

未完待续...

相关推荐
七七&5561 小时前
2024年08月13日 Go生态洞察:Go 1.23 发布与全面深度解读
开发语言·网络·golang
java坤坤1 小时前
GoLand 项目从 0 到 1:第八天 ——GORM 命名策略陷阱与 Go 项目启动慢问题攻坚
开发语言·后端·golang
元清加油1 小时前
【Golang】:函数和包
服务器·开发语言·网络·后端·网络协议·golang
健康平安的活着2 小时前
java之 junit4单元测试Mockito的使用
java·开发语言·单元测试
No0d1es2 小时前
电子学会青少年软件编程(C/C++)5级等级考试真题试卷(2024年6月)
c语言·c++·算法·青少年编程·电子学会·五级
DjangoJason3 小时前
C++ 仿RabbitMQ实现消息队列项目
开发语言·c++·rabbitmq
m0_480502644 小时前
Rust 入门 KV存储HashMap (十七)
java·开发语言·rust
大阳1234 小时前
线程(基本概念和相关命令)
开发语言·数据结构·经验分享·算法·线程·学习经验
YA3334 小时前
java基础(九)sql基础及索引
java·开发语言·sql
奇树谦5 小时前
QT|windwos桌面端应用程序开发,当连接多个显示器的时候,如何获取屏幕编号?
开发语言·qt