【FFMPEG源码终极解析】 avformat_open_input (一)

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;

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring async_Spring Async和Java的8 CompletableFuture

spring async众所周知&#xff0c;我不是Spring的最大粉丝&#xff0c;但是当时我在一个组织中工作&#xff0c;该组织使用Spring&#xff08;以不同的形式和版本&#xff09;维护了太多的项目。 我仍然对Spring持怀疑态度&#xff0c;当然有一些很好的主意&#xff0c;有一些很…

公里与英里的换算c语言函数_60迈=60码=60公里?这三者天壤之别,可别搞错了

说到行车速度&#xff0c;大家经常用的是这三个单位&#xff1a;码、迈、公里/时&#xff0c;很多人以为这三者是同一个意思&#xff0c;都是每小时多少公里。实际上这三者并不等同&#xff0c;下面小编科普一下这几个词的差异。码1码不等于1公里&#xff0c;而是等于0.9144米&…

php3.2.3分组查询,ThinkPHP3.2.3版本如何设置应用分组

鑫强已经解决了我的解决方法是创建两个入口文件实际上我的目的就是想要达到两个模块共用一个配置文件和公共函数文件我的解决方法是在项目根目录下建立两个入口文件一个是Index.php与Root.php两个入口文件其中是这样写的Index.php{<?php #前台入口文件 header(Conte…

FFmpeg options

libavformat options libavcodec options

通过图书编号查询python,基于Python的ISBN书号查询示例代码-六派数据

示例代码本代码示例是基于Python的六派数据接口进行数据请求API服务请求的代码示例&#xff0c;使用前你需要&#xff1a;以下是完整代码示例&#xff1a;#!/usr/bin/env python# -*- coding: utf-8 -*-# 测试环境: python2.7# 安装requests依赖 > pip install requests/ ea…

归约操作java8_使用Java 8进行分组,转换和归约

归约操作java81.简介 在上一篇文章中 &#xff0c;我写了关于如何使用流和分组对对象集合进行分组的文章。 这很有用&#xff0c;但不涵盖特定的用例。 例如&#xff0c;有时我们不仅需要对事物进行分组&#xff0c;还需要将结果转换为更合适的对象。 在这篇文章中&#xff0c…

C++ 11 深度学习(一)auto、头文件防卫、引用、常量

1.数组初始化 int a[]{ 1,2,3,4,5 }; 2.C11 auto auto可以在声明变量的时候根据变量的初始值的类型自动为此变量先择合适的类型&#xff0c;声明时要赋予初值。 auto自动推导发生在编译期间 auto A 10;//A会被自动推导为int类型 3.头文件防卫式声明 作用:防止头文件重…

flux storm_Apache Storm:如何使用Flux配置KafkaBolt

flux storm微型框架中的助焊剂可以帮助我们定义和部署Storm拓扑。 Flux有各种包装器&#xff0c;可帮助您定义所需的流并初始化Bolts和Spouts&#xff08;使用带有或不带有参数的构造函数&#xff0c;并通过反射自动调用自定义配置方法&#xff09;。 您只需要使用Flux就是将…

android 在什么情况下会主动gc_Python 什么情况下会生成 pyc 文件?

作者&#xff1a;折木奉太郎(经授权转载)来源&#xff1a;https://www.zhihu.com/question/30296617/answer/112564303作为 Python 爱好者&#xff0c;需要了解 .py 脚本的基本运行机制及特性&#xff1a;在很多工作上&#xff0c;Python 的运行流程基本上取决于用户&#xff0…

oracle 查看内存参数配置,Oracle内存参数配置及版本问题

Oracle的内存配置与Oracle性能息息相关。从总体上讲&#xff0c;可以分为两大块&#xff1a;共享部分(主要是SGA)和进程独享部分(主要是PGA)。在 32 位操作系统下 的Oracle版本&#xff0c;不时有项目反馈关于内存的错误(如ORA-04030、04031错误)都是十分令人头疼的问题。查阅资…

【IP协议头分析】

Version 版本号 IHL IP头长度 Type of Service Total Length 总长度 Identification 拆包的唯一标识 Flags 1位保留 &#xff0c; 2位 允许拆包 3位 不允许拆包 Fragment offset 在原包偏移量 Time to Live 时间或路由跳数 Protocol IP中是什么协议类型 Header Check…

乡村野生草药_官方野生蝇群流口水分数

乡村野生草药官方是什么&#xff1f; 标题太小&#xff0c;但有用的贡献。 Wildfly Swarm允许我们创建相当小的自包含应用程序&#xff0c;包括我们从Wildfly Application Server中需要的应用程序。 在这篇文章中&#xff0c;我们将研究与Wildfly Swarm合作使用的Drools分数 。…

obs多推流地址_(无人直播)教程利用OBS推流抖音直播电脑屏幕或PC游戏

目前的火爆程度相信大家都有目共睹&#xff0c;也為部分活躍用戶提供直播功能&#xff0c;開通直播的方法有&#xff1a;①粉絲達到10000粉絲&#xff0c;官方會自動邀請妳開通直播權限。②加入和官方合作的工會&#xff0c;無需粉絲&#xff0c;也可以開通直播權限。開通直播功…

oracle数据库sqlloader,sql loader ---ORACLE SQLLDR

sql loader的基本使用&#xff1a;1. sql loader里有几个概念&#xff1a;控制文件&#xff1a;和数据库的文件不是一回事&#xff0c;个人理解是用于数据加载控制的。数据文件&#xff1a;要加载入库的数据文件&#xff0c;支持文本&#xff0c;csv, 等格式。 数据文件的内容可…

倒数日电脑版_应用日报|iOS 或更名为 iPhoneOS,倒数日 Mac 版上线限时免费

今日推荐倒数日 Days Matter for Desktop免费&#xff0c;macOS 86 MB倒数日 Days Matter 是 iOS 端非常经典的应用&#xff0c;今天它的 Mac 版本上线&#xff0c;限时免费 7 天。它延续了 iOS 端的风格语言&#xff0c;同样能帮你记录生活中重要的日子&#xff1a;例如恋人…

【TPC协议头解析】

Source Port 源端口 Destination Port 目的端口 Sequence Number 数据报编号 (seq)&#xff08;按字节序&#xff09;保证有序 Acknowledgment Number (ACK) 报文应答, 保证可靠性 Data offset 跳到data数据部分 Reserved 保留部分 URG 紧急数据标识 ACK 确认消息…

hibernate查询缓存_在Hibernate中启用实体和查询缓存

hibernate查询缓存1.简介 在我执行过的与性能相关的任务中&#xff0c;这就是其中之一。 令人担心的是&#xff0c;如果对于特定实体每次都调用相同的查询&#xff0c;并且表数据在特定的时隙内不易更改&#xff0c;则我们可以使用Hibernate缓存查询结果。 这意味着&#xff0c…

iphone新旧手机数据传输已取消_如何取消iPhone手机App自动扣费?三种方法让你不再被“偷”...

一直以来苹果手机App这个自动续费真是让大家不胜其烦&#xff0c;钱虽然不多可总是平白无故这里十块&#xff0c;那里二十块的被扣也是不小的浪费&#xff0c;日常生活中为了追追剧、听听音乐、玩玩游戏难免会开通一些App会员而选择自动续费的话每月会费是有不错优惠的&#xf…