ffmpeg mkv 文件解析

news2024/11/19 6:28:59

一、mkv的文件组织

 1. EBML基本单元

EBML组成mkv文件最基本的单元, 也是解析文件最小的一个粒度。EBML基本元素结构:

  • ID:标志着这个EMBL 是一个什么类型的,类型决定了后面data中存储的是什么类型的数据如是int,string,utf8,str,nest等。ID在mkv标准的文档中都有定义,其后面跟的数据也都是有标准的。是什么类型的元素取决于ID的值。

  • size:ID标志的data 数据的大小。

  • data:ID标志的数据,可以理解成是一个键值对,键是ID,值是data,data可能是另外一个EMBL单元,也有可能是一个int,string等等。

2. ID\size\data读取规则

ID, size, data是怎么从二进制的数据中读出来的?总体的规则是首先读取二进制获取vint的字节数,根据字节数读取存储的信息。具体vint如何解码 参考下面的文章

lucene VInt(变长整数 ) - 简书

这个EBML元素就解析出来了, 这个解码的流程可以不用关注,在ffmpeg中会有标准的解析函数,也可以用embl tree帮忙解析这个层次的数据。

3. LEVEL等级

MKV 整体结构是level0嵌套level1 然后level2 嵌套level3. 这样一级一级下去的。level 0的embl 单元ID 主要有两个EBML Header和Segment。EBML Header由EBMLVersion、DocType等子元素组成,包含了文件的版本、文档类型等相关信息。

Segment部分保存了媒体文件的视频和音频的实际数据,其data部分又可以分为SeekHead、Tracks、Cluster等若干子元素。

具体参考下面的文章

【多媒体封装格式详解】---MKV【1】-mandagod-ChinaUnix博客

4.  解析一个多个level等级嵌套的embl单元 以cue为例

Cueing Data 这部分内容其实是关键帧的index,如果没有关键帧的index的话,在做seek、快进快退的时候是十分困难的。需要逐个包去找。

下面是结构图和对应的embl的id等相关信息。id很重要,只有iD 才能知道这是什么embl。

最外部的是level 0的segment,segment 解析到cue。 cue解析到id, 然后整个cue的size 解析出来, 这个size 包括的是cue中所有数据的大小。

cue的数据解析,cue可能包含多个cuepoint,解析到第一个cuepoint。cuepoint又嵌套cuetime。这样一次次嵌套解析到最后。

二、 ffmpeg 相关的解析

1. ffmpeg 读取流程

通过递归解析到方式进行,首先read_seek的时候才会去解析cue的消息, cue的位置通过之前解析segment的信息可以获取到。通过avio_seek跳到文件对应的位置。

cue是level 1的embl,所有的embl id中嵌套的embl id 都通过结构体已经定义好在代码前面了 现在的任务就是解析文件然后将解析出来的数据填充到一个嵌套的结构体中。

  • 首先从level1_elems 中找到id 为 MATROSKA_ID_CUES,这边存储在cue数据在文件中的位置然后seek到对应位置。
  • 开始解析,传递进去的是segment的结构体数组matroska_segment(这里面存放在的是协议定义的所有可能的segment的类型)、根据之前的规则。解析到ebml的id,从matroska_segment结构体数组中进一步取到cue的结构体matroska_index。通过解析size,知道这个cue数据多大。
  • matroska_index 这个结构定义了id 和 所包含的数据是什么类型。 从结构体知道,下一级是一个nest,也就是它是嵌套的,下一级里面没有具体的数据。
  • 递归的读,然后它的下一级 是一个matroska_index_entry。然后继续看matroska_index_entry 这个结构体。这一一级一级解析。直到后面不是一个nest,而是一个int string等等。

2. ffmpeg level 层级的抽象

typedef const struct EbmlSyntax {

    uint32_t id;

    EbmlType type;

    int list_elem_size;

    int data_offset;

    union {

        int64_t     i;

        uint64_t    u;

        double      f;

        const char *s;

        const struct EbmlSyntax *n;

    } def;

} EbmlSyntax;

重要的结构体, 这个结构体是前面level层级的抽象。 mkv的解析流程就是递归的将这个结构体填充完整。 id就是前面所述的embl的id。 type 包含int sting nest 等等。

list_elem_size:这个就表示当前这个embl中存储的数据需要的空间的大小。

比如matroska_index它的list_elem_size 是sizeof(MatroskaIndex)。

typedef struct MatroskaIndex {

    uint64_t time;

    EbmlList pos;

} MatroskaIndex;

三、 mkv 问题调试分析

1. mkv cue 过多

  • 问题分析:首先文件 有40多G。然后seek的cue point很多大概有接近10万个。 在mkv 的parse 里面, 会需要把解析到所有这些cuepoint保存在EbmlList里面。
  • 问题原因:EBML list是存储在level 1的list里面。解析到一个cuepoint 申请sizeof(MatroskaIndex)*(list->nb_elem + 1)。 因为原始的是realloc,所以每解析到一个cuepoint就会realloc一次 就会realloc 9万多次。
  • 解决方法:使用了fast_realloc, 不会每一次realloc,不够的话 会多申请一些出来。申请的是size + size / 16 + 32。这样realloc会大大减少。解析的时间就少了很多,相当于用空间换时间。同时还需注意 MatroskaIndex的下一级MatroskaIndexPos也会申请内存,申请的大小是 sizeof(MatroskaIndexPos)这个内存是没办法避免。 

2、mkv 缺失cue信息

  • 问题分析:mkv seek没有找到关键帧
  • 问题原因:首先ffmpeg从文件中是如何读到seekcue的位置信息, 首先根据层级的关系,读取0级的ebml, 然后这里面去递归找ebml 1层的数据。找到seekhead 可能就会停止了。 seekhead 里面包含其他ebml元素的位置,通过解析seekhead 的信息 可以seek的track cue等位置。
  • 如果在seekhead 这边解析出错的话,比如embl的type是非标准的,那么可能无法解析到cue。也就是level 1的cue 没有存储起来、在后面进行seek的时候就有I帧的准确位置信息,无法快速的定位到相应的I帧位置。而要seek到对应的位置,ffmpeg 就得从当前位置一个个去解析block,解析到keyframe的时候 然后确认是不是要seek的timestape。

3. mkv 问题分析流程

  • 首先使用mkv 的工具 ebml tree来看mkv 中各个数据是怎么分布。 然后根据这个分布来看ffmpeg 是怎么解析的。 然后根据解析查找问题。 可以在最新的ffmpeg确认是不是有这个问题。

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

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

相关文章

腾讯云备案限制条件说明(必看)

腾讯云网站备案要求首先你有一个需要备案的域名,域名实名认证信息和备案主体相同;在腾讯云有一台符合备案条件的云服务器、轻量应用服务器等云产品;然后根据备案主体所在省份地区,符合当地的通信管理局要求。下面腾讯云百科来详细…

Centos7系统常用命令

一、防火墙firewalld、sestatus 1 查看防火墙状态:systemctl status firewalld 2 关闭运行的防火墙:systemctl stop firewalld.service 开启运行的防火墙:systemctl start firewalld.service 3 禁止防火墙服务器:systemctl di…

如何一行代码实现 OpenAI 可观测,大幅提升使用体验

作者|观测云 徐季秋 现在基于 OpenAI 的 Chat 应用井喷,但给开发者带来了两个难点,一是因为 OpenAI 基于 tokens 的计费机制导致不容易规划消费;另一是 OpenAI 提供的调用本身不稳定,很难分辨是传参错误或是访问失败。…

flume 进阶 Ganglia 部署(十二)

规划安装 hadoop100: web gmetad gmod epel-release hadoop101: gmod epel-release hadoop102: gmod epel-release 安装 三台都安装 sudo yum -y install epel-releasesudo yum -y install ganglia-gmond在hadoop100安装 sudo yum -y install ganglia-gmetadsudo yum -y i…

RT-Thread 2. GD32在 RT-Thread Nano上添加控制台与 FinSH

本篇文档分为两部分: 第一部分是添加 UART 控制台(实现打印):用来向控制台对接的终端输出打印信息;该部分只需要实现两个函数,串口初始化和系统输出函数,即可完成 UART 控制台打印功能。 第二部…

sonarqube上的webAPI如何调用?-暴躁了一天调通了

首先吐槽一句,官方API文档给了个寂寞,调不通啊,然后查各种搞了一天,竟然没有一篇文章能把这件事写清楚,给我暴躁的。 结论竟然是原来是我不会调用接口。。。我今天非要把这篇文章写好。 web接口入口 通过sonarqube下…

QT开发实战-动态壁纸软件

动态壁纸软件开发 项目源代码在下面链接获取: ----------------------------- 开发者:CodeSharkSJ 希望此项目能加强你对Qt的应用 文章目录 项目图与开发环境核心技术原理自定义窗口程序UI布局背景绘制样式表基本实现QWebEngineQMedia使用系统托盘隐藏记忆功能应用程序打包 …

四年巨亏49亿,第四范式四闯IPO

深陷亏损的AI公司第四范式,四闯IPO! 4月24日,决策类AI独角兽北京第四范式智能技术股份有限公司(下称“第四范式”)再次更新招股书,继续向港交所发起上市冲击。 第四范式是一家专注于提供以平台为中心的人…

(9) 线性回归

文章目录 1 多元线性回归LinearRegression1.1 基本原理1.2 linear_model.LinearRegression 2 回归类的模型评估指标2.1 是否预测了正确的数值2.2 是否拟合了足够的信息 3 岭回归与Lasso回归3.1 多重共线性3.2 岭回归3.2.1 linear_model.Ridge3.2.2 选取最佳的正则化参数 α \al…

车载以太网-FlexRay

摘要: 到底什么是FlexRay? 1. FlexRay是什么? 那么到底什么是FlexRay?往简单了说,就是CAN总线加LIN总线混合起来排个课程表、提个速再加个冗余。像LIN一样基于TDMA,提高了协议的复杂度,拥有静态…

【linux】挖矿病毒nanominer伪装成python占用服务器GPU的查杀记录

病毒表现 gpustat -cpu 可以看到root用户将GPU的核心跑满了每个占用都是100%,显存吃了6G多。 nvidia-smi 不能正常显示GPU被哪些进程占用 ![在这里插入图片描述](https://img-blog.csdnimg.cn/780f90080a084a44ac59227e384f985b.png 病毒文件分析 在/tmp/.x/…

win10 vmware虚拟机蓝屏怎么办 win10 vmware虚拟机蓝屏解决方法【详解】

最近有朋友出现win10 vmware虚拟机蓝屏的情况应该怎么办?小伙伴们在使用vmware虚拟机出现了蓝屏现象的小伙伴们不用担心,小编翻阅各种资料后给大家带来两种虚拟机蓝屏的解决方法,想要解决此问题的小伙伴们快跟着小编往下看吧! win…

三分钟看懂JDK、JRE和JVM的区别和联系

节选自JavaGuide(Github 标星 134k star!「Java学习 + 面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识) JVM Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同…

腾讯云轻量应用服务器卡死怎么连接?

腾讯云轻量云服务器卡死怎么解决?使用腾讯云自带的VNC登录连接轻量服务器,或使用腾讯云OrcaTerm一键免密登录轻量实例。如果是确定数据没问题,也可以使用控制台自带的重启实例。 腾讯云轻量应用服务器参考:https://curl.qcloud.co…

5月18号软件资讯更新合集.....

JTopCMS V4 更新:静态发布功能优化 适配版本:V4.6 介绍 : 本次更新对静态发布 HTML 功能进行多个重要优化,支持全站增量模式发布,支持跨站级栏目联动发布,增加定时发布指定栏目范围,增加栏目对…

php对接阿里云API调用企业税号查询的高级实战案例解析(下拉筛选查询、远程调用API、xm-select组件应用)

阿里云API调用企业税号查询 一、功能描述1.请求参数2.GET请求代码3.返回示例4.错误码 二、核心代码1.引入外部JS库2.构建HTML容器3.xmSelect回调 总结 一、功能描述 企业税号查询-公司税号查询-企业公司开票信息查询-企业营业执照信息查询-工商信息查询-企业基本信息查询&…

【ROS】ROS1编程速览

1、简述 很多项目已经转向ROS2,本人作为ROS小白从ROS1开始学起,但是不会深入学习ROS1,只一带而过。 下面只了解一些ROS1中的概念和基本编程接口。 ROS1中有两种通信模式:话题模式和服务模式,区别如下 2、话题模式 …

分享一份适合练手的软件测试实战项目,涵盖金融,电商,银行,商城,家政项目

现如今,越来越多的人涌入到测试行业来了,有自学的,有通过参加培训转行的,不管通过何种方式,他们面临的最主要的问题就是: 1、简历上的项目经验如何去编造? 2、入职的背调、薪资流水、离职证明等…

涨点神器:CVPR2023 InceptionNeXt当Inception遇见ConvNeXt,在Yolov8即插即用,小目标检测涨点明显

论文地址: https://arxiv.org/pdf/2303.16900.pdf 代码: GitHub - sail-sg/inceptionnext: InceptionNeXt: When Inception Meets ConvNeXt 单位:NUS, Sea AI Lab(颜水成等人) 1. InceptionNeXt介绍 摘要:受ViT的 long-range 建模能力的启发,大核卷积来扩大感受野用于…

Nvivo12 mac code comparison编码比较查询:软件操作步骤

编码比较查询步骤 1.合并项目2.编码比较2.1 选择不同的编码人2.1.1 比较单元 2.2-2.4 选择比较项目2.5 显示比较内容 3.结果kappa的解读4.参考资源 1.合并项目 如果两个编码人是在同一个项目文件中编码的(你编一遍,我编一遍),此步…