ffmpeg源码简析(六)编码-av_write_frame(),av_write_trailer()
来源:互联网 发布:php接口压力测试工具 编辑:程序博客网 时间:2024/05/17 20:26
1.av_write_frame()
av_write_frame()用于输出一帧视音频数据,它的声明位于libavformat\avformat.h,如下所示。
int av_write_frame(AVFormatContext *s, AVPacket *pkt);
简单解释一下它的参数的含义: s:用于输出的AVFormatContext。 pkt:等待输出的AVPacket。函数正常执行后返回值等于0。
av_write_frame()的定义位于libavformat\mux.c,如下所示。
int av_write_frame(AVFormatContext *s, AVPacket *pkt) { int ret; ret = check_packet(s, pkt); if (ret < 0) return ret; //Packet为NULL,Flush Encoder if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { ret = s->oformat->write_packet(s, NULL); if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) avio_flush(s->pb); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; return ret; } return 1; } ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt); if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; //写入 ret = write_packet(s, pkt); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; if (ret >= 0) s->streams[pkt->stream_index]->nb_frames++; return ret; }
从源代码可以看出,av_write_frame()主要完成了以下几步工作:
(1)调用check_packet()做一些简单的检测
(2)调用compute_pkt_fields2()设置AVPacket的一些属性值
(3)调用write_packet()写入数据
下面分别看一下这几个函数功能。
check_packet()
check_packet()定义位于libavformat\mux.c,如下所示。
static int check_packet(AVFormatContext *s, AVPacket *pkt) { if (!pkt) return 0; if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) { av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d\n", pkt->stream_index); return AVERROR(EINVAL); } if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) { av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n"); return AVERROR(EINVAL); } return 0; }
从代码中可以看出,check_packet()的功能比较简单:首先检查一下输入的AVPacket是否为空,如果为空,则是直接返回;然后检查一下AVPacket的stream_index(标记了该AVPacket所属的AVStream)设置是否正常,如果为负数或者大于AVStream的个数,则返回错误信息;
compute_pkt_fields2()
compute_pkt_fields2()主要有两方面的功能:一方面用于计算AVPacket的duration, dts等信息;另一方面用于检查pts、dts这些参数的合理性(例如PTS是否一定大于DTS)
AVOutputFormat->write_packet()
write_packet()函数最关键的地方就是调用了AVOutputFormat中写入数据的方法。如果AVPacket中的flag标记中包含AV_PKT_FLAG_UNCODED_FRAME,就会调用AVOutputFormat的write_uncoded_frame()函数;如果不包含那个标记,就会调用write_packet()函数。write_packet()实际上是一个函数指针,指向特定的AVOutputFormat中的实现函数。
2.av_write_trailer()
av_write_trailer()用于输出文件尾,它的声明位于libavformat\avformat.h,如下所示。
int av_write_trailer(AVFormatContext *s);
它只需要指定一个参数,即用于输出的AVFormatContext。
函数正常执行后返回值等于0。
av_write_trailer()的定义位于libavformat\mux.c,如下所示。
int av_write_trailer(AVFormatContext *s) { int ret, i; for (;; ) { AVPacket pkt; ret = interleave_packet(s, &pkt, NULL, 1); if (ret < 0) goto fail; if (!ret) break; //写入AVPacket ret = write_packet(s, &pkt); if (ret >= 0) s->streams[pkt.stream_index]->nb_frames++; av_free_packet(&pkt); if (ret < 0) goto fail; if(s->pb && s->pb->error) goto fail; } fail: //写文件尾 if (s->oformat->write_trailer) if (ret >= 0) { ret = s->oformat->write_trailer(s); } else { s->oformat->write_trailer(s); } if (s->pb) avio_flush(s->pb); if (ret == 0) ret = s->pb ? s->pb->error : 0; for (i = 0; i < s->nb_streams; i++) { av_freep(&s->streams[i]->priv_data); av_freep(&s->streams[i]->index_entries); } if (s->oformat->priv_class) av_opt_free(s->priv_data); av_freep(&s->priv_data); return ret; }
从源代码可以看出av_write_trailer()主要完成了以下两步工作:
(1)循环调用interleave_packet()以及write_packet(),将还未输出的AVPacket输出出来。
(2)调用AVOutputFormat的write_trailer(),输出文件尾。
AVOutputFormat->write_trailer()
AVOutputFormat的write_trailer()是一个函数指针,指向特定的AVOutputFormat中的实现函数。
- ffmpeg源码简析(六)编码-av_write_frame(),av_write_trailer()
- ffmpeg源码跟踪笔记之av_write_frame 与 av_interleaved_write_frame
- FFmpeg源代码简单分析:av_write_trailer()
- 信源编码(六)h264 jm源码简析
- FFmpeg源代码简单分析:av_write_frame()
- av_write_trailer()
- ffmpeg——av_write_trailer写文件尾
- av_write_frame
- av_write_frame()
- ffmpeg源码简析(五)编码——avformat_alloc_output_context2(),avcodec_encode_video2()
- ffmpeg——av_write_frame/av_interleaved_write_frame写文件包
- ffmpeg学习六:avcodec_open2函数源码分析
- ffmpeg源码简析(十二)FFMPEG中的主要结构体总结
- ffmpeg源码简析(一)结构总览
- ffmpeg源码简析(二)av_register_all(),avcodec_register_all()
- ffmpeg源码简析(四)avcodec_find_encoder(),avcodec_open2(),avcodec_close()
- ffmpeg源码简析(七)解码-avformat_open_input,avformat_find_stream_info()
- ffmpeg源码简析(八)解码 av_read_frame(),avcodec_decode_video2(),avformat_close_input()
- eclipse(springmvc+spring+mybatis)(上)
- [JZOJ5049] 腐女的生日
- POJ 3177 Redundant Paths(边双连通分量+缩点)
- SPP-Net论文学习(2)
- hdu 3033 分组背包,每组最少取一个
- ffmpeg源码简析(六)编码-av_write_frame(),av_write_trailer()
- 构建自己的违例 和 finally
- 容器的内嵌类——迭代器
- PHP 对接招商银行网银接口
- ZOJ Problem Set
- 前端练习——弹窗、判断语句 (星座测试)
- spring、springMVC简单应用FutureTask(线程池)
- Git常用命令
- ¥¥%%%%%Ubuntu下用matplotlib作图时显示中文###重点第5条可以用!!!!%%%%%