avformat_open_input  

打开媒体函数先上全部源码。然后逐语句分析。

int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options)
{//第一部分解析AVFormatContext *s = *ps;int i, ret = 0;AVDictionary *tmp = NULL;ID3v2ExtraMeta *id3v2_extra_meta = NULL;//第二部分解析 if (!s && !(s = avformat_alloc_context()))return AVERROR(ENOMEM);if (!s->av_class) {av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");return AVERROR(EINVAL);}//第三部分解析 //如果用户指定了输入格式,直接使用它  if (fmt)s->iformat = fmt;//===================================================================================if (options)av_dict_copy(&tmp, *options, 0);if (s->pb) // must be before any goto fails->flags |= AVFMT_FLAG_CUSTOM_IO;if ((ret = av_opt_set_dict(s, &tmp)) < 0)goto fail;if (!(s->url = av_strdup(filename ? filename : ""))) {ret = AVERROR(ENOMEM);goto fail;}#if FF_API_FORMAT_FILENAME
FF_DISABLE_DEPRECATION_WARNINGSav_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));
FF_ENABLE_DEPRECATION_WARNINGS
#endifif ((ret = init_input(s, filename, &tmp)) < 0)goto fail;s->probe_score = ret;if (!s->protocol_whitelist && s->pb && s->pb->protocol_whitelist) {s->protocol_whitelist = av_strdup(s->pb->protocol_whitelist);if (!s->protocol_whitelist) {ret = AVERROR(ENOMEM);goto fail;}}if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);if (!s->protocol_blacklist) {ret = AVERROR(ENOMEM);goto fail;}}if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);ret = AVERROR(EINVAL);goto fail;}avio_skip(s->pb, s->skip_initial_bytes);/* Check filename in case an image number is expected. */if (s->iformat->flags & AVFMT_NEEDNUMBER) {if (!av_filename_number_test(filename)) {ret = AVERROR(EINVAL);goto fail;}}s->duration = s->start_time = AV_NOPTS_VALUE;/* Allocate private data. */if (s->iformat->priv_data_size > 0) {if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {ret = AVERROR(ENOMEM);goto fail;}if (s->iformat->priv_class) {*(const AVClass **) s->priv_data = s->iformat->priv_class;av_opt_set_defaults(s->priv_data);if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)goto fail;}}/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */if (s->pb)ff_id3v2_read_dict(s->pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)if ((ret = s->iformat->read_header(s)) < 0)goto fail;if (!s->metadata) {s->metadata = s->internal->id3v2_meta;s->internal->id3v2_meta = NULL;} else if (s->internal->id3v2_meta) {av_log(s, AV_LOG_WARNING, "Discarding ID3 tags because more suitable tags were found.\n");av_dict_free(&s->internal->id3v2_meta);}if (id3v2_extra_meta) {if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||!strcmp(s->iformat->name, "tta") || !strcmp(s->iformat->name, "wav")) {if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0)goto close;if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0)goto close;if ((ret = ff_id3v2_parse_priv(s, id3v2_extra_meta)) < 0)goto close;} elseav_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n");}ff_id3v2_free_extra_meta(&id3v2_extra_meta);if ((ret = avformat_queue_attached_pictures(s)) < 0)goto close;if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->internal->data_offset)s->internal->data_offset = avio_tell(s->pb);s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;update_stream_avctx(s);for (i = 0; i < s->nb_streams; i++)s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id;if (options) {av_dict_free(options);*options = tmp;}*ps = s;return 0;close:if (s->iformat->read_close)s->iformat->read_close(s);
fail:ff_id3v2_free_extra_meta(&id3v2_extra_meta);av_dict_free(&tmp);if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))avio_closep(&s->pb);avformat_free_context(s);*ps = NULL;return ret;
}

第一部分:以下是定义了一些必备的变量。

    AVFormatContext *s = *ps;int i, ret = 0;AVDictionary *tmp = NULL;ID3v2ExtraMeta *id3v2_extra_meta = NULL;

第二部分:创建上下文结构,其作用为开辟相关空间并且进行一些初始化赋值。返回上下文结构的指针。

    if (!s && !(s = avformat_alloc_context()))return AVERROR(ENOMEM);

avformat_alloc_context 函数详细解析:

AVFormatContext *avformat_alloc_context(void)
{//定义封装上下文结构体AVFormatContext *ic;AVFormatInternal *internal;//使用sizeof计算结构体大小并且分配空间ic = av_malloc(sizeof(AVFormatContext));if (!ic) return ic;internal = av_mallocz(sizeof(*internal));if (!internal) {av_free(ic);return NULL;}avformat_get_context_defaults(ic);ic->internal = internal;ic->internal->offset = AV_NOPTS_VALUE;ic->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;ic->internal->shortest_end = AV_NOPTS_VALUE;return ic;
}

其中av_malloc封装了c的malloc内存分配函数

void *av_malloc(size_t size)
{void *ptr = NULL;//max_aloc_size 为 2147483647 if (size > max_alloc_size)return NULL;#if HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = memalign(size, ALIGN);
#endif/* Why 64?* Indeed, we should align it:*   on  4 for 386*   on 16 for 486*   on 32 for 586, PPro - K6-III*   on 64 for K7 (maybe for P3 too).* Because L1 and L2 caches are aligned on those values.* But I don't want to code such logic here!*//* Why 32?* For AVX ASM. SSE / NEON needs only 16.* Why not larger? Because I did not see a difference in benchmarks ...*//* benchmarks with P3* memalign(64) + 1          3071, 3051, 3032* memalign(64) + 2          3051, 3032, 3041* memalign(64) + 4          2911, 2896, 2915* memalign(64) + 8          2545, 2554, 2550* memalign(64) + 16         2543, 2572, 2563* memalign(64) + 32         2546, 2545, 2571* memalign(64) + 64         2570, 2533, 2558** BTW, malloc seems to do 8-byte alignment by default here.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}

第三部分:

如果已经事先定义好了AVInputFormat那么就把定义好的直接赋予在这里。具体结构可以参考下面

typedef struct AVInputFormat {const char *name; // 输入格式的短名称const char *long_name; // 格式的长名称(相对于短名称而言,更易于阅读)/*** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,* AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.*/int flags;const char *extensions; // 如果定义了扩展,就不会进行格式探测。但因为该功能目前支持不够,不推荐使用const struct AVCodecTag * const *codec_tag; // 见名知意const AVClass *priv_class; ///< AVClass for the private contextconst char *mime_type; // mime类型,它用于在探测时检查匹配的mime类型。/* 此行下方的任何字段都不是公共API的一部分。 它们不能在libavformat之外使用,可以随意更改和删除。* 应在上方添加新的公共字段。*/struct AVInputFormat *next; // 用于链接下一个AVInputFormatint raw_codec_id; // 原始demuxers将它们的解码器id保存在这里。int priv_data_size; // 私有数据大小,可以用于确定需要分配多大的内存来容纳下这些数据。/*** 判断给定文件是否有可能被解析为此格式。 提供的缓冲区保证为AVPROBE_PADDING_SIZE字节大,因此除非您需      * 要更多,否则无需检查。*/int (*read_probe)(AVProbeData *);/*** 读取格式头,并初始化AVFormatContext结构体* @return 0 表示操作成功*/int (*read_header)(struct AVFormatContext *);/*** 读取一个packet并存入pkt指针中。pts和flags会被同时设置。* @return 0 表示操作成功, < 0 发生异常*         当返回异常时,pkt可定没有allocated或者在函数返回之前被释放了。*/int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);// 关闭流,AVFormatContext和AVStreams并不会被这个函数释放。int (*read_close)(struct AVFormatContext *);/*** 在stream_index的流中,使用一个给定的timestamp,seek到附近帧。* @param stream_index 不能为-1* @param flags 如果没有完全匹配,决定向前还是向后匹配。* @return >= 0 成功*/int (*read_seek)(struct AVFormatContext *,int stream_index, int64_t timestamp, int flags);// 获取stream[stream_index]的下一个时间戳,如果发生异常返回AV_NOPTS_VALUEint64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,int64_t *pos, int64_t pos_limit);// 开始或者恢复播放,只有在播放rtsp格式的网络格式才有意义。int (*read_play)(struct AVFormatContext *);int (*read_pause)(struct AVFormatContext *);// 暂停播放,只有在播放rtsp格式的网络格式才有意义。/*** 快进到指定的时间戳* @param stream_index 需要快进操作的流* @param ts 需要快进到的地方* @param min_ts max_ts seek的区间,ts需要在这个范围中。*/int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);// 返回设备列表和其属性int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);// 初始化设备能力子模块int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);// 释放设备能力子模块int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVInputFormat;

【FFMPEG源码终极解析】 avformat_open_input (一)相关推荐

  1. 【FFMPEG源码终极解析】void av_packet_unref(AVPacket *pkt)

    av_packet_unref 该接口使用了如下调用,该接口主要作用是清理AVPacket中的所有空间数据,清理完毕后进行初始化操作,并且将 data 与 size 置为0,方便下次调用. void ...

  2. 【FFMPEG源码终极解析】 av_packet_alloc 与 av_packet_free

    关于void *av_malloc(size_t size)可以参考av_malloc av_packet_alloc实际是分配AVPacket以后,调用av_init_packet对AVPacket ...

  3. ffmpeg源码阅读之avformat_open_input

    头文件 /*** Open an input stream and read the header. The codecs are not opened.* The stream must be cl ...

  4. 偏向锁、轻量级锁、重量级锁,Synchronized底层源码终极解析!

    synchronized是掌握Java高并发的关键知识点,底层源码更是面试重灾区.本文从源码学习synchronized的原理,讲解对象头.偏向锁.轻量级锁.重量级锁等概念. 扫码关注<Java ...

  5. FFMPEG源码分析:avformat_open_input()(媒体打开函数)

    本文分析了FFMPEG中的媒体打开函数avformat_open_input() //参数ps包含一切媒体相关的上下文结构,有它就有了一切,本函数如果打开媒体成功, //会返回一个AVFormatCo ...

  6. FFmpeg源码分析:avformat_open_input()打开媒体流

    avformat_open_input()用于打开输入媒体流与读取头部信息,包括本地文件.网络流.自定义缓冲区.关键流程:打开avio.探测输入流的封装格式.对应的释放方法为avformat_clos ...

  7. 从头用脚分析FFmpeg源码 --- avformat_open_input

    本文所使用的是FFmpeg n4.4的源码,所有分析均来自博主瞎猜,如果有误,欢迎批评指正. 建议边调试源码,边看对应的源码分析.走上一遍就了解个大概了. avformat_open_input 作用 ...

  8. UOS系统下FFmpeg源码编译安装及注意事项

    条件 当前编译环境:国产UOS系统(基于linux),CPU是ARM架构 需要安装ffmpeg 3.4版本. 通过源码编译进行安装使用 下载源码 在github上将ffmpeg源码下载到本地:下载地址 ...

  9. FFMPEG 源码分析

    FFMPEG基本概念: ffmpeg是一个开源的编解码框架,它提供了一个音视频录制,解码和编码库.FFMPEG是在linux下开发的,但也有windows下的编译版本. ffmpeg项目由以下几部分组 ...

最新文章

  1. 多模态任务新蓝海:视觉语言导航最新进展
  2. java rectangle 类_Java编写的Rectangle类
  3. 题目1200:最大的两个数
  4. 为了实现自己的美好程序人生
  5. 微信小程序开发---页面生命周期
  6. 【Flink】FLink checkpont 界面显示的含义
  7. JDBC 获取 Oracle 数据库连接(使用 Driver)
  8. Spring Cloud Stream
  9. ListView源码(推荐)
  10. 多媒体基础学习笔记:MPEG-7
  11. html去除文章符号,HTML中怎么去除列表项符号
  12. python代码画乌龟_python画乌龟
  13. 动手学pytorch笔记整理12
  14. STM32F10xxx20xxx21xxxL1xxxx Cortex-M3程序设计手册 阅读笔记四(3):嵌套向量中断控制器
  15. 守护网络安全 (三)
  16. 【微服务】Nacos通知客户端服务变更以及重试机制
  17. zabbix监控部署
  18. null、undefined、void、never
  19. Java游戏服务器1
  20. 在WPSOFFICE表格中插入表单域(转)

热门文章

  1. jClarity:在Azure上升级到Java
  2. APIGEE:用于API代理的CI / CD管道
  3. Spring MVC教程
  4. moxy json介绍_MOXy是GlassFish 4中新的默认JSON绑定提供程序
  5. Java Message System简介
  6. java未检查异常_Java中已检查和未检查的异常
  7. 带有Gluon Ignite和Dagger的JavaFX中的依赖注入
  8. jsf集成spring_JSF 2,PrimeFaces 3,Spring 3和Hibernate 4集成项目
  9. 随机JCache内容:多个提供程序和JMX Bean
  10. 使用docker-compose的Spring会话演示