You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
7.4 KiB
271 lines
7.4 KiB
#ifndef AVFORMAT_H
|
|
#define AVFORMAT_H
|
|
|
|
/*************************************************
|
|
** 定义识别文件格式和媒体类型库使用的宏、数据结构和函数,
|
|
**通常这些宏、数据结构和函数在此模块内相对全局有效
|
|
*************************************************/
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
/* 版本号相关 */
|
|
#define LIBAVFORMAT_VERSION_INT ((50<<16)+(4<<8)+0)
|
|
#define LIBAVFORMAT_VERSION 50.4.0
|
|
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
|
|
|
|
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
|
|
|
|
/* 编解码头文件 */
|
|
#include "../libavcodec/avcodec.h"
|
|
|
|
/* io操作头文件 */
|
|
#include "avio.h"
|
|
|
|
/* 错误码定义 */
|
|
#define AVERROR_UNKNOWN (-1) // unknown error
|
|
#define AVERROR_IO (-2) // i/o error
|
|
#define AVERROR_NUMEXPECTED (-3) // number syntax expected in filename
|
|
#define AVERROR_INVALIDDATA (-4) // invalid data found
|
|
#define AVERROR_NOMEM (-5) // not enough memory
|
|
#define AVERROR_NOFMT (-6) // unknown format
|
|
#define AVERROR_NOTSUPP (-7) // operation not supported
|
|
|
|
/* 在文件中跳转 */
|
|
#define AVSEEK_FLAG_BACKWARD 1 // seek backward
|
|
#define AVSEEK_FLAG_BYTE 2 // seeking based on position in bytes
|
|
#define AVSEEK_FLAG_ANY 4 // seek to any frame, even non keyframes
|
|
|
|
#define AVFMT_NOFILE 0x0001 // no file should be opened
|
|
|
|
#define PKT_FLAG_KEY 0x0001
|
|
|
|
#define AVINDEX_KEYFRAME 0x0001
|
|
|
|
#define AVPROBE_SCORE_MAX 100
|
|
|
|
#define MAX_STREAMS 20
|
|
|
|
/*
|
|
** 数据包(视频包或者音频包,一般一个数据包包含一帧数据)
|
|
** 它包含了未解码的帧数据
|
|
*/
|
|
typedef struct AVPacket
|
|
{
|
|
int64_t pts; // presentation time stamp in time_base units 表示时间,对视频是显示时间
|
|
int64_t dts; // decompression time stamp in time_base units 解码时间,这个不是很重要
|
|
int64_t pos; // byte position in stream, -1 if unknown
|
|
uint8_t *data; // 实际保存音视频数据缓存的首地址
|
|
int size; // 实际保存音视频数据缓存的大小
|
|
int stream_index; // 当前音视频数据包对应的流索引,在本例中用于区别音频还是视频
|
|
int flags; //数据包的一些标记,比如是否是关键帧等。
|
|
void(*destruct)(struct AVPacket*); // 销毁函数
|
|
} AVPacket;
|
|
|
|
/* 视频包列表 */
|
|
typedef struct AVPacketList
|
|
{
|
|
AVPacket pkt;
|
|
struct AVPacketList *next;
|
|
} AVPacketList;
|
|
|
|
/* 释放数据包内的数据 */
|
|
static inline void av_destruct_packet(AVPacket *pkt)
|
|
{
|
|
av_free(pkt->data);
|
|
pkt->data = NULL;
|
|
pkt->size = 0;
|
|
}
|
|
|
|
/* 释放一个视频包 */
|
|
static inline void av_free_packet(AVPacket *pkt)
|
|
{
|
|
if (pkt && pkt->destruct)
|
|
pkt->destruct(pkt);
|
|
}
|
|
|
|
/*
|
|
** 获取一个完整的视频包
|
|
** 读文件往数据包中填数据,
|
|
** 注意程序跑到这里时,文件偏移量已确定,要读数据的大小也确定
|
|
** 但是数据包的缓存没有分配。分配好内存后,要初始化包的一些变量
|
|
*/
|
|
static inline int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
|
|
{
|
|
int ret;
|
|
unsigned char *data;
|
|
if ((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
|
|
return AVERROR_NOMEM;
|
|
|
|
// 内存分配
|
|
data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
|
|
if (!data)
|
|
return AVERROR_NOMEM;
|
|
|
|
memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
pkt->pts = AV_NOPTS_VALUE;
|
|
pkt->dts = AV_NOPTS_VALUE;
|
|
pkt->pos = - 1;
|
|
pkt->flags = 0;
|
|
pkt->stream_index = 0;
|
|
pkt->data = data;
|
|
pkt->size = size;
|
|
pkt->destruct = av_destruct_packet;
|
|
|
|
pkt->pos = url_ftell(s);
|
|
|
|
// 读取实际的数据
|
|
ret = url_fread(s, pkt->data, size);
|
|
if (ret <= 0)
|
|
av_free_packet(pkt);
|
|
else
|
|
pkt->size = ret;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
** 探测的数据
|
|
** 为识别文件格式,要读一部分文件头数据来分析匹配 ffplay 支持的文件格式文件特征
|
|
** 该结构定义了文件名,首地址和大小。此处的读独立于其他文件操作
|
|
*/
|
|
typedef struct AVProbeData
|
|
{
|
|
// 文件名
|
|
const char *filename;
|
|
// 探测到的数据
|
|
unsigned char *buf;
|
|
// 数据长度
|
|
int buf_size;
|
|
} AVProbeData;
|
|
|
|
/*
|
|
** 文件索引结构,flags 和 size 位定义是为了节省内存
|
|
*/
|
|
typedef struct AVIndexEntry
|
|
{
|
|
int64_t pos;
|
|
int64_t timestamp;
|
|
int flags: 2;
|
|
int size: 30; //yeah trying to keep the size of this small to reduce memory requirements (its 24 vs 32 byte due to possible 8byte align)
|
|
} AVIndexEntry;
|
|
|
|
/*
|
|
** 流:视频流、音频流
|
|
** AVStream 抽象的表示一个媒体流,定义了所有媒体一些通用的属性
|
|
** 具体可以再细分为视频流和音频流,视频流又可以分成AVI流和,mp4流等
|
|
*/
|
|
typedef struct AVStream
|
|
{
|
|
// 解码器上下文
|
|
AVCodecContext *actx; // codec context, change from AVCodecContext *codec;
|
|
|
|
// 具体的流
|
|
void *priv_data; // AVIStream 在本例中,关联到 AVIStream
|
|
|
|
// 时间基准
|
|
AVRational time_base; // 由 av_set_pts_info()函数初始化
|
|
|
|
// 索引对象,假如不支持随机的查找的时候使用
|
|
AVIndexEntry *index_entries; // only used if the format does not support seeking natively
|
|
int nb_index_entries;
|
|
int index_entries_allocated_size;
|
|
|
|
double frame_last_delay; // 帧最后延迟
|
|
} AVStream;
|
|
|
|
/* 格式参数 */
|
|
typedef struct AVFormatParameters
|
|
{
|
|
int dbg; //only for debug 只保留了一个调试标志
|
|
} AVFormatParameters;
|
|
|
|
/*
|
|
** 的输入格式(读文件的结构和指针)
|
|
** AVInputFormat 定义输入文件容器格式(注意不是AVI,而是AV Input),着重于功能函数
|
|
** 在程序运行时有多个实例
|
|
*/
|
|
typedef struct AVInputFormat
|
|
{
|
|
// 文件名
|
|
const char *name;
|
|
|
|
int priv_data_size;
|
|
|
|
// 探测函数
|
|
int(*read_probe)(AVProbeData*);
|
|
|
|
// 读取头部
|
|
int(*read_header)(struct AVFormatContext *, AVFormatParameters *ap);
|
|
|
|
// 读取一帧数据(一个数据包)
|
|
int(*read_packet)(struct AVFormatContext *, AVPacket *pkt);
|
|
|
|
// 关闭文件
|
|
int(*read_close)(struct AVFormatContext*);
|
|
|
|
const char *extensions; // 文件扩展名
|
|
|
|
// 下一个输入文件的格式
|
|
struct AVInputFormat *next;
|
|
|
|
} AVInputFormat;
|
|
|
|
/*
|
|
** AVFormatContext 结构表示程序运行的当前文件容器格式使用的上下文,
|
|
** 着重于所有文件容器共有的属性,程序运行后仅一个实例
|
|
*/
|
|
typedef struct AVFormatContext // format I/O context
|
|
{
|
|
// 输入文件的格式,AVFormatContext是一个抽象的概念,而AVInputFormat则是一个具体的概念
|
|
struct AVInputFormat *iformat;
|
|
|
|
void *priv_data;
|
|
|
|
// 广义的输入文件
|
|
ByteIOContext pb;
|
|
|
|
// 流的数量
|
|
int nb_streams;
|
|
|
|
// 流(音频流、视频流)
|
|
AVStream *streams[MAX_STREAMS];
|
|
|
|
} AVFormatContext;
|
|
|
|
int avidec_init(void);
|
|
|
|
void av_register_input_format(AVInputFormat *format);
|
|
|
|
void av_register_all(void);
|
|
|
|
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
|
|
int match_ext(const char *filename, const char *extensions);
|
|
|
|
int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename,
|
|
AVInputFormat *fmt, AVFormatParameters *ap);
|
|
|
|
int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, AVInputFormat *fmt,
|
|
int buf_size, AVFormatParameters *ap);
|
|
|
|
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
|
|
int av_read_packet(AVFormatContext *s, AVPacket *pkt);
|
|
void av_close_input_file(AVFormatContext *s);
|
|
AVStream *av_new_stream(AVFormatContext *s, int id);
|
|
void av_set_pts_info(AVStream *s, int pts_wrap_bits, int pts_num, int pts_den);
|
|
|
|
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
|
|
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags);
|
|
|
|
int strstart(const char *str, const char *val, const char **ptr);
|
|
void pstrcpy(char *buf, int buf_size, const char *str);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|