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