两年前自己的工作记录,没有整理,有些乱了。分两部分来记录下ffmpeg编程中基本的东西。
AVInputFormat
AVOutputFormat
AVOutputFormat
一、初始化及常用函数、结构:
av_register_all(); //注册所有的compiled muxers, demuxers and protocols.
avformat_network_init(); //开启libavformat的网络功能.
辅助函数:
av_iformat_next() / av_oformat_next() 枚举所有系统注册的input/output formats.
avio_enum_protocols() 枚举系统支持的协议,获取其名称.
AVFormatContext:
包括媒体文件的读/写的所有信息:
To create an AVFormatContext, use avformat_alloc_context() (some functions, like avformat_open_input() might do that for you).
AVPacket
"packet" 包含一个编码过的 frame(或多个属于一个流的帧). AVPacket.pts, AVPacket.dts and AVPacket.duration 的时间基准是AVStream.time_base。
AVPacket.buf保存数据
av_read_frame(); //读取一帧
av_dup_packet(); //复制一帧
av_free_packet(); //释放一帧
metadata :
默认是UTF-8编码的Unicode. 但demuxers导出的metadata不见得就是UTF-8
以key/value对存在,key是唯一的;是扁平的,不能分级,没有subtag。
范例: Author-ger=Michael, Author-eng=Mike
二、打开文件解码 流程:
av_read_frame(); //读取一帧
av_dup_packet(); //复制一帧
av_free_packet(); //释放一帧
metadata :
默认是UTF-8编码的Unicode. 但demuxers导出的metadata不见得就是UTF-8
以key/value对存在,key是唯一的;是扁平的,不能分级,没有subtag。
范例: Author-ger=Michael, Author-eng=Mike
二、打开文件解码 流程:
avformat_open_input(); //打开文件,初始化AVFormatContext
avformat_find_stream_info(); //试着读取几帧数据,以获取之前读取head中没有的介质信息.
{
av_read_frame(); //读取一个AVStream的某一帧AVPacket数据(AVPacket.stream_index)
avcodec_decode_video2()/ avcodec_decode_audio4() / avcodec_decode_subtitle2(); //解码一帧
}
avformat_close_input(); //关闭文件,释放相关资源。
特殊情况:
1、打开raw视频文件时,demux无法从文件读取参数就得通这种方式来传入设置:
AVDictionary *options = NULL;
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "pixel_format", "rgb24", 0);
if (avformat_open_input(&s, url, NULL, &options) < 0)
abort();
av_dict_free(&options);
2、初始化时遇到不认识的option时,可以如下读取:
AVDictionaryEntry *e;
if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))
{
fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
abort();
}
三、mux流程
avformat_alloc_context(); //创建muxing context
avformat_find_stream_info(); //试着读取几帧数据,以获取之前读取head中没有的介质信息.
{
av_read_frame(); //读取一个AVStream的某一帧AVPacket数据(AVPacket.stream_index)
avcodec_decode_video2()/ avcodec_decode_audio4() / avcodec_decode_subtitle2(); //解码一帧
}
avformat_close_input(); //关闭文件,释放相关资源。
特殊情况:
1、打开raw视频文件时,demux无法从文件读取参数就得通这种方式来传入设置:
AVDictionary *options = NULL;
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "pixel_format", "rgb24", 0);
if (avformat_open_input(&s, url, NULL, &options) < 0)
abort();
av_dict_free(&options);
2、初始化时遇到不认识的option时,可以如下读取:
AVDictionaryEntry *e;
if (e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))
{
fprintf(stderr, "Option %s not recognized by the demuxer.\n", e->key);
abort();
}
三、mux流程
avformat_alloc_context(); //创建muxing context
...... //设置参数
AVFormatContext.oformat
AVFormatContext.pb //format不是AVFMT_NOFILE时,需初始化AVIOContext:
//从一个打开的IO context, 或者从avio_open2()中,或者自定义一个.
AVStream* = avformat_new_stream(AVFormatContext *s, const AVCodec *c);//format不是AVFMT_NOSTREAMS时:
AVStream.codec
AVCodecContext.codec_type
AVCodecContext.codec_id
AVCodecContext.other parameters (如 width / height, the pixel or sample format,等)
AVCodecContext.time_base
AVFormatContext.metadata //额外参数,视容器格式而定,如AVStream.metadata,AVFormatContext.chapters,
......
avformat_write_header() 初始化muxer内部参数,并且写文件头
av_write_frame() / av_interleaved_write_frame() 写packet数据
av_write_trailer() 清理缓存的Packet,结束文件.
avformat_free_context(); // 清理muxing context
四、codec流程:
avcodec_register_all();
av_dict_set(&opts, "b", "2.5M", 0);
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
exit(1);
context = avcodec_alloc_context3(codec);
if (avcodec_open2(context, codec, opts) < 0)
exit(1);
av_init_packet() //初始化AVPacket
av_free_packet()
int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub);
int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub);
五、成对释放函数
avcodec_encode_video2()
int avformat_alloc_output_context2(AVFormatContext **ctx, ...);
AVFormatContext *avformat_alloc_context(void);
void avformat_free_context(AVFormatContext *s);
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
SwsContext *sws_getContext()
void sws_freeContext( struct SwsContext *swsContext);
void av_init_packet(AVPacket *pkt);
void av_free_packet(AVPacket *pkt);
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
int avcodec_close(AVCodecContext *avctx);
AVIOContext *avio_alloc_context()
av_free();
int avformat_alloc_output_context2(AVFormatContext **ctx, ...);
AVFormatContext *avformat_alloc_context(void);
void avformat_free_context(AVFormatContext *s);
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
SwsContext *sws_getContext()
void sws_freeContext( struct SwsContext *swsContext);
void av_init_packet(AVPacket *pkt);
void av_free_packet(AVPacket *pkt);
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
int avcodec_close(AVCodecContext *avctx);
AVIOContext *avio_alloc_context()
av_free();