FFMPEG mp4封装实现

这篇具有很好参考价值的文章主要介绍了FFMPEG mp4封装实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FFMPEG mp4录像

author:lyn
date:2022.09.28
version: ffmpeg4.1.3

1.mp4数据结构

2.ffmpeg mp4封装实现

3.mp4函数调用关系

4.参考资料


1.mp4数据结构
1.1mp4简介

MP4或称MPEG-4第14部分(英语:MPEG-4 Part 14)是一种标准的数字多媒体容器格式。MPEG-4第14部分的扩展名为.mp4,以存储数字音频及数字视频为主,但也可以存储字幕和静止图像。因其可容纳支持比特流的视频流(如高级视频编码),为流媒体。

扩展名为.flv.f4v并同样基于ISO基础媒体文件格式(MPEG-4第12部分)的Flash视频格式与MPEG-4第14部分极为相似,多数情况下直接变更扩展名为.mp4也能够正常播放

1.2mp4名词和文件结构

mp4采用box的方式封装,可以理解为俄罗斯套娃一样一层嵌套一层的结构,但是mp4 box的顺序和结构并不是固定的,除了部分的box是固定的,有些box的位置和顺序是可以更改的,mp4读的过程是根据box的type区分不同box处理;

mp4box的类型有很多,具体可以查看标准文件,这里只说一些常用的box

  • ftyp
    File Type Box 一般在文件的开头,用来指示该mp4文件使用的标准规范。为了早期规范版本兼容,允许不包含ftyp box

  • moov
    Movie Box包含了文件媒体的metadata信息,可以包含mvhdtrakmvexbox

  • mvhd

    Movie Header Box 包含创建时间,推荐播放速度,推荐播放音量等参数;

  • trak

    Track Box 一个mp4文件可以包含多个track,且至少有一个tracktrack之间是独立,有自己的时间和空间信息。trak必须包含一个tkhd和一个mdia

  • tkhd

    Track Header Box 包含宽高,音量等信息

  • mdia

    Media Box 一个track 只有一个,mdia定义了track媒体类型以及sample数据,描述sample信息,包含mdhd hdlr minf和user data

  • mdhd

    Media Header Box mdhd tkhd,内容大致都是一样的。不过tkhd 通常是对指定的 track 设定相关属性和内容。而 mdhd 是针对于独立的 media 来设置的。不过两者一般都是一样的

  • hdlr

    Handler Reference Box hdlr解释了媒体的播放过程信息,该box也可以被包含在meta box(meta)

  • minf

    Media Information Box 重要的容器 box,minf存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。minf是一个container box,其实际内容由子box说明

  • (vmhd、smhd、hmhd、nmhd)

    Media Information Header Box vmhd、smhd这两个box在解析时,非不可或缺的(有时候得看播放器),缺了的话,有可能会被认为格式不正确。

  • dinf

    Data Information Box dinf解释如何定位媒体信息dinf一般包含一个dref(data reference box)。dref下会包含若干个urlurn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据urlurn指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,urlurn中的定位字符串是空的

  • stbl

    Sample Table Box 包含track中的媒体样本中所有的时间和数据索引,使用采样表可以及时定位样本,确定类型(比如是否为I帧)还有确定大小,位置偏移等

  • mvex

    Movie Extends Box 这个box告知读取设备文件里面可能存在片段的媒体数据,必须要查找和扫描完这些片段的媒体数据;

  • moof

    Movie Fragment Box 是分段形式解析,如同hls中的ts分片一样。moof如同moov一样,但moov一定要有,但moof可能没有。每个moof后边都会接一个mdat数据段

  • mfhd

    Movie Fragment Header Box ,被moof包含,包含序列号,从1开始,每个片段递增

  • mdat

    Media Data Box 实际的媒体数据,在视频track里,包含的是视频帧,可以是0个或多个;

  • sidx

    Segment Index Box 0个或多个,提供媒体流的索引,它的设计不仅可以用于mp4的规范,也可用于其他的媒体格式上;

普通格式mp4、分段mp4文件、前移moov mp4文件格式如下所示
FFMPEG mp4封装实现FFMPEG mp4封装实现FFMPEG mp4封装实现


2.ffmpeg mp4封装实现

视频和音频封装为avi格式调用接口顺序如上所示,avio_open avio_close接口取代旧的 url_fopenurl_fclose 然后直接调用mov_write_header写入mp4文件的头部,数据包通过mov_write_packet一帧一帧的将数据写入,不断调用这个接口,最后调用mov_write_trailer将文件尾部写入;这样就将编码数据封装为mov格式的文件;
FFMPEG mp4封装实现

fragment mp4二进制文件如上所示,mp4文件是由不同的box构成;


3.mp4函数调用关系

函数调用关系分析了常用和比较重要的一些函数调用关系,指出整个调用的流程,具体的可以查看相关源码;

	avio_open
	{
		avio_open2
        {
            ffurl_open_whitelist //初始化URLContext
            {
                ffurl_alloc
                {
                    url_find_protocol  //查找合适的URLProtocol,并创建,file也是一种协议
                    url_alloc_for_protocol
                }
                ffurl_connect //打开获得的URLProtocol
            }    
            ffio_fdopen //URLContext初始化AVIOContext
            {
                avio_alloc_context
                {
                	ffio_init_context
                }
            }
        }
	}

具体的avio函数分析可以参考雷神博客;链接详见参考资料;

	mov_write_header
    {
        mov_write_identification
        {
            mov_write_ftyp_tag //写ftyp box
            mov_write_mdat_tag(pb, mov); //如果不是片段的mp4就直接开始写入mdat
            ff_parse_creation_time_metadata //解析创建时间

            mov_write_isml_manifest //ism1流媒体方式
            mov_write_moov_tag	// 片段的mp4写moov box
            {
            	mov_write_mvhd_tag	//写moov容器内的一系列box
            	mov_write_iods_tag
            	mov_write_trak_tag
            	mov_write_mvex_tag
            	mov_write_udta_tag
            	update_size
            }
        }
    }
	mov_write_packet
	{
		mov_flush_fragment
		{
			/* 如果moov没写就将其写入,否则就跳过写入moov过程 */
			get_moov_size
			mov_write_identification // FF_MOV_FLAG_DELAY_MOOV 写ftye等信息
			mov_write_moov_tag // 如果moov没写则写入
            avio_wb32(s->pb, buf_size + 8);
            ffio_wfourcc(s->pb, "mdat");
            avio_write(s->pb, buf, buf_size); // 写入媒体数据
            av_free(buf);
            
            
            mov_write_moof_tag //片段类型mp4写moof
            {
                mov_write_moof_tag_internal
                {
                    ffio_wfourcc(pb, "moof");   // 写 moof
                    mov_write_mfhd_tag;			// 写 mfhd
                    {
                        ffio_wfourcc(pb, "mfhd");
                    }
                    mov_write_traf_tag			// 写traf
                    {
                        mov_write_tfhd_tag
                        mov_write_tfdt_tag
                        mov_write_trun_tag
                    }
                }
                mov_write_sidx_tags	//写索引
                {
                    mov_write_sidx_tag
                    {
                        ffio_wfourcc(pb, "sidx");
                    }
                }
                mov_write_moof_tag_internal
            }
            ffio_wfourcc(s->pb, "mdat");
            avio_write(s->pb, buf, buf_size);	// 写入媒体数据
            av_free(buf);             
		}
		/* 一般情况下会直接来到这里写包 */
		mov_write_single_packet
		{
			check_pkt // 检查数据包
			mov_auto_flush_fragment // 有关键的帧会调用这个接口,fragment mp4写入sidx sidx moof
			{
				mov_flush_fragment // 写入一个包
			}
			ff_mov_write_packet
			{
				check_pkt	// 检查数据包
				mov_flush_fragment_interleaving//写入一帧的数据
				{
                    offset = avio_tell(mov->mdat_buf);
                    avio_write(mov->mdat_buf, buf, buf_size);
                    av_free(buf);
				}
			}
		}
	}
	mov_write_trailer
	{
		mov_write_subtitle_end_packet
		mov_write_moov_tag // 普通mp4在尾部写入moov,fragment mp4会跳过这个阶段
		mov_auto_flush_fragment
		mov_write_mfra_tag
	}
    avio_close							// 释放资源
    {
        avio_flush
        av_opt_free
        avio_context_free
        ffurl_close
    }

4.参考资料

mp4简介

mp4结构

avio函数分析文章来源地址https://www.toymoban.com/news/detail-404073.html


到了这里,关于FFMPEG mp4封装实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt+FFmpeg简单实现录屏并保存为MP4视频

            最近需要实现一个录屏功能,网上查了好多资料,最可靠的方案当然还是用FFmpeg实现,但是也踩了很多坑,包括FFmpeg版本问题,vs2019里相关编译问题,FFmpeg也不太熟悉,很多代码不太容易看懂,想要按自己熟悉的方式实现录屏功能,花了一番功夫。         如果你进

    2024年02月15日
    浏览(41)
  • 手机录像内存不足变为tmp格式修复为MP4步骤

    用手机录像1个多小时后,手机提示内存不足,APP出错,导致视频变成TMP格式,没有正常保存为MP4,TMP并不是常见的视频格式,这通常是因为文件未成功写入而处于临时状态。尝试使用各种播放器打开这个文件,但无一例外,都无法正常播放。想修复正常播放,而且是音画同步

    2024年03月13日
    浏览(40)
  • Node.js脚本项目合集(一):Node.js+FFmpeg实现批量从B站导出离线缓存视频到mp4格式,mp4转mp3,实现听歌自由

    最近被一首JISOO的FLOWER歌洗脑,但碍于版权原因,只能在B站上看mv视频,盯着尬舞听歌着实有些尴尬,突发奇想,如果能将视频中的音频和视频分开不就能只听音乐,不用看尴尬的舞蹈吗?刚好手机上有不少B站本地的学习视频想导入到电脑上看,可是B站下载的格式.m4s文件,

    2024年02月07日
    浏览(39)
  • Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/aac/pcm等

    用ffmpeg做音视频保存到mp4文件,都会遇到一个问题,尤其是在视频监控行业,就是监控摄像头设置的音频是PCM/G711A/G711U,解码后对应的格式是pcm_s16be/pcm_alaw/pcm_mulaw,将这个原始的音频流保存到mp4文件是会报错的,在调用avformat_write_header写文件头的时候提示(-22) Invalid argument,

    2024年04月11日
    浏览(39)
  • MP4封装解析

    MP4封装格式比较常见,但是有些会有问题,下面解析一下具体信息 工具 比较好的是mp4在线工具 MP4主要结构 MP4主要结构类似于树状图。每个节点开头都有8位,前四位记录大小,后四位标记节点类型。根节点一般包含四个字节点(ftyp,free,mdat,moov)。 ftyp(File Type Box)一般

    2024年01月18日
    浏览(20)
  • ffmpeg操作MP4视频封面

    提取视频封面 视频流中提取帧图 3.重新设置视频封面 更多参考: https://blog.csdn.net/m0_37624402/article/details/125123818

    2024年02月04日
    浏览(31)
  • 20231005使用ffmpeg旋转MP4视频

    20231005使用ffmpeg旋转MP4视频 2023/10/5 12:21 百度搜搜:ffmpeg 旋转90度 https://zhuanlan.zhihu.com/p/637790915 【FFmpeg实战】FFMPEG常用命令行 https://blog.csdn.net/weixin_37515325/article/details/127817057 FFMPEG常用命令行 5.视频旋转 顺时针旋转90度:ffmpeg -i test.mp4 -vf \\\"transpose=1\\\" out.mp4//顺时针旋转90° 逆时针

    2024年02月07日
    浏览(31)
  • ffmpeg ts列表合并为mp4

    操作系统:ubuntu 注意事项: 1.ts文件顺序必须正确,也就是下一帧的dst和pst要比上一帧的大,否则会报错 2.codecpar-codec_tag要设置为0,否则报错Tag [27][0][0][0] incompatible with output codec id ‘27’ (avc1) 3.设置output的max_streams数目,默认是1000,超过此数目就会报错

    2024年02月13日
    浏览(43)
  • ffmpeg将rtsp流转成mp4

    中间的rtsp网址一定要加上双引号,避免出现url有特殊字符的问题 如果不支持tcp协议,去掉下面两个参数即可,加上这两个参数是因为ffmpeg默认使用udp协议,会导致丢包 -rtsp_transport、-tcp

    2024年02月11日
    浏览(31)
  • ffmpeg批量转换mpg为mp4

    1、新建一个txt文件,并复制如下代码进入,然后保存。 2、把文件后缀修改为bat 。 3、把后缀为bat的文件放到要批量处理的视频文件夹里面。 4、在确保安装了ffmpeg的情况下,双击bat文件执行即可。 5、参数说明: -i          输入文件,这里指的就是视频文件。 -y       

    2024年02月13日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包