1.av_write_frame()

av_write_frame()用于输出一帧视音频数据,它的声明位于libavformat\avformat.h,如下所示。

int av_write_frame(AVFormatContext *s, AVPacket *pkt); 
  • 1
简单解释一下它的参数的含义:s:用于输出的AVFormatContext。pkt:等待输出的AVPacket。函数正常执行后返回值等于0。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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;  }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

从源代码可以看出,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;  }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

从代码中可以看出,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);  
  • 1

它只需要指定一个参数,即用于输出的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;  }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

从源代码可以看出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()相关推荐

  1. ffmpeg源码简析(十二)FFMPEG中的主要结构体总结

    FFMPEG中结构体很多.最关键的结构体可以分成以下几类: a) 解协议(http,rtsp,rtmp,mms) AVIOContext,URLProtocol,URLContext主要存储视音频使用 ...

  2. ffmpeg源码简析(十)libswscale中的SwsContext,sws_scale()

    libswscale是一个主要用于处理图片像素数据的类库.可以完成图片像素格式的转换,图片的拉伸等工作.  libswscale常用的函数数量很少,一般情况下就3个: sws_getContext() ...

  3. ffmpeg源码简析(九)av_log(),AVClass,AVOption

    1.av_log() av_log()是FFmpeg中输出日志的函数.随便打开一个FFmpeg的源代码文件,就会发现其中遍布着av_log()函数.一般情况下FFmpeg类库的源代码中是不允许使用pr ...

  4. ffmpeg实战教程(十三)iJKPlayer源码简析

    要使用封装优化ijk就必须先了解ffmpeg,然后看ijk对ffmpeg的C层封装! 这是我看ijk源码时候的笔记,比较散乱.不喜勿喷~ ijk源码简析: 1.ijkplayer_jni.c 封装的播 ...

  5. 【Android项目】本地FM收音机开发及源码简析

    [Android项目]本地FM收音机开发及源码简析 目录 1.概述 2.收音机的基本原理 3.收音机其他信息 RDS功能 4.Android开发FM收音机源码解析 5.App层如何设计本地FM应用 6 ...

  6. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  7. django源码简析——后台程序入口

    django源码简析--后台程序入口 这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主 ...

  8. (Ajax)axios源码简析(三)——请求与取消请求

    传送门: axios源码简析(一)--axios入口文件 axios源码简析(二)--Axios类与拦截器 axios源码简析(三)--请求与取消请求 请求过程 在Axios.prototype.re ...

  9. java ArrayList 概述 与源码简析

    ArrayList 概述 与源码简析 1 ArrayList 创建 ArrayList<String> list = new ArrayList<>(); //构造一个初始容量 ...

最新文章

  1. PowerDesigner连接Oracle数据库生成数据模型【本地连接方式】
  2. 关于perl中变量内插问题的讨论
  3. tensorflow和keras的版本问题
  4. ubuntu通过xmange连接桌面
  5. zookeeper动物园管理员学习笔记
  6. C++ (public, protected, private继承)
  7. Android之解决底部4个TextView占比例大小不一致问题
  8. 微服务(一) --- 架构与选型
  9. filebeat + logstash 发送日志至kafka 入门
  10. Java 多线程 南北多人过桥
  11. 【BZOJ1057】[ZJOI2007] 棋盘制作(单调栈的运用)
  12. antd vue表单验证_解决antd 表单设置默认值initialValue后验证失效的问题
  13. 「运维有小邓」搜索日志数据以作为网络安全情报
  14. 手机注册服务器异常是什么问题,ohho注册不了网络异常
  15. 购买太平洋保险公司聚宝盆险发现虚假宣传,没有证据,如何向保监会投诉
  16. android 邮件发送
  17. 综合评价理想解法(TOPSIS解法)
  18. opencv学习日志15-统计焊点个数并输出
  19. a and b a or b
  20. c语言计算标准体重的程序,C语言标准体重测试程序,请大家帮我看下,我的代码哪错了?...

热门文章

  1. 关于android上的定位
  2. 第十四章:Qt网络编程
  3. 全网优秀的攻防渗透工具总结
  4. MATLAB传递函数分析总结,Matlab实验分析报告.doc
  5. 导入shp数据到postgis库
  6. eclipse安装包网址
  7. 果实可采摘点论文汇总
  8. 积极废人:只要人生中有捷径,捷径很快就成了唯一的路
  9. 【基础强训】day3
  10. 聊聊WPF中字体的设置