设备断电等异常导致MP4文件无法打开的解决方案

在实际项目中,比如DVR设备,视频一般是MP4格式,MP4并非是流媒体格式,如果视频没有正常写完,会导致无法打开和播放这个MP4文件,有没有办法恢复已经保存的MP4文件,就这个文章我们讨论一下可行的方法。

首先我们需要了解MP4文件的组织架构,MP4文件都是以box的形式存储的,box非常的简单,具有如下的格式

长度 4 byte 也就是说一个box长度不超过uint32长度
名称 4 byte 比如 ftyp free mdat moov等
数据 n byte box内的真正数据

具体的MP4格式,我不会过多的介绍,可以参考其他人的博客,这里只要知道MP4结构比较简单就行了,不要产生畏难心理,以下列出一些博客,可供参考
wqyuwss的专栏
超详细MP4格式分析
以上我们就算对MP4格式有一些基础了解了,如果这些博客已经看不到了,或者不想看这些博客,也没什么大问题,针对我们的实际应用,也就是怎么修复未正常写完的MP4文件,我们往下也会分析。

首先我们需要知道为什么MP4文件打不开,没写完MP4肯定是缺少了文件的一些重要部分,一个正常的MP4文件,其结构如下:
MP4文件结构
在一级的box结构里面包含四种box类型:ftyp free mdat 和 moov。打不开的原因就是文件缺少了moov box,这个在文件结束时才能确定里面的数据,才能补充到文件的末尾。也有一些MP4文件为了在网络上快速打开,将moov放到mdat的前面,这是在文件写完时,刻意的将mdat整体向后移动moov长度字节,再将moov写到原来mdat起始位置。
是不是我们将moov补齐就可以播放了?
of course not.

我们之前介绍过,box有个描述自身长度的字段,占四个字节,我们写入视频帧到MP4文件,实际上,我们是将这些帧写入mdat box里面,这时候我们也不会去修改mdat box的长度,只有最后会更新这个长度,所以还要相应的修改mdat box的长度字段。

有了这两个地方的修改和添加,我们的MP4文件就完整了。

理论我们已经有了,实际怎么处理我们介绍两种方法。

实际当中,我们也不会自己写muxer的代码,一般我们使用一些开源的库,比如MP4V2和FFMPEG,我们这里以FFMPEG为例。

FFMPEG中基本的MP4文件写入遵循以下调用:

// 写MP4头
avformat_write_header(avfc, &dict);
// 写MP4视频帧
while(n--) {
    av_interleaved_write_frame(avfc, &video_packet);
}
// 写MP4视频尾,异常情况导致无法调用下面语句,使MP4无法打开
av_write_trailer(avfc);

第一种解决方法要求我们能够修改FFMPEG库,在运行时,将我们需要的数据保存下来,在修复时将moov补充到文件未尾。这需要对FFMPEG库有一定的了解,理论上是非常可行的,我们每隔比如10s,更新一次mdat box的长度字段,并且将此时的moov数据写入一个备用文件,一旦断电,我们检测到这个文件moov没有写入,那就在mdat box向后便宜mdat box 长度字节的位置上,写入我们预存的moov数据。

以上的方法要求我们一直有一个moov备用文件,而且每个10s更新一次。

第二种方法,我们可以只每10s更新一次mdat box的长度字段,甚至不更新这个字段,我们知道moov中有些数据是相对不变的(比如编码器参数,视频的宽高等),有些数据是经常变化的(比如视频时长,帧数等),相对不变的参数我们只需要从一个相似的视频文件中获取(比如DVR前一分钟我们存的视频,与后一分钟视频&

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值