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 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学2 小时前
QT-简单视觉框架代码
开发语言·qt
威桑2 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服2 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生2 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生2 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans2 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
Chinese Red Guest3 小时前
python
开发语言·python·pygame
一棵星3 小时前
Java模拟Mqtt客户端连接Mqtt Broker
java·开发语言