Android实现MP4边下边播(边缓存边播放、在线播放)原理与代码

推荐一款全平台广告聚合SDK【ADEasy】:https://blog.csdn.net/u013640004/article/details/105416193

对于这套方法我已经封装成库,可以直接下载使用。
MP4Info1.0.2.jar下载
配套的视频播放器终于出来了,UI可自定义。
VideoPlayOL
另外写了一个查看MP4结构的软件,安卓版的
(下载安卓版MP4Info查看MP4结构)
码云项目
MP4Info-码云开源

QQ群交流:425219113(计算机语言交流)

播放器Demo预览图


边下边播方法初试

**刚开始实现这个的时候,我第一下想到的是:**先将MP4文件单纯的从字节的层次分为若干个文件,然后播放的时候,不断从服务器一边下载,一边追加到一个源文件里面,最后直接播放这个源文件就可以了。如图:
这里写图片描述
这个方法到底可不可行呢?能否播放?如果遇到播放快于下载的情况,会不会出错呢?
这个方法在一定的情况下是可行的,如果遇到播放错误,也只需要给VideoView设置错误监听器setOnErrorListener()就行。如果监听到错误,就显示加载框,然后继续下载,下载完了再尝试播放。
但后来我发现,并不是所有的MP4都支持这种做法,有的MP4这样做依然是要等到全部下载完了才能播放的。


MP4结构分析 -怎么才能边下边播##

先了解一下MP4的基本结构。(可以用百度手机助手下载MP4Info查看MP4结构)
这里写图片描述
简要地说,MP4文件主要由ftyp,mdat,moov这三部分组成。

  • ftyp 记录了mp4格式,编码格式之类的一些基本信息
  • mdat记录了视频媒体信息(mdat的体积往往非常的大,几乎等于MP4总大小)
  • moov是如同检索表一样的存在,里面记录了每一帧对应的数据在哪里等等

MP4播放流程大概是

  1. 读取ftype部分决定解码方式。
  2. 寻找并读取moov部分,获取视频总时长等信息。
  3. 根据moov的检索信息到mdat里面读取相应的媒体信息,进而播放。

所以,想要播放MP4,一定要让播放器先读取到ftyp与moov才行的。但根据我最开始的做法,如果MP4的moov在mdat的前面的话,正常分割,追加,自然可以做到边下边播。但是,如果moov在mdat后面的话,就需要等下载完ftyp-mdat-moov(等于下载整个MP4)才能正常播放了。

重要的是,有的甚至是大部分MP4是如上图的结构的,moov在mdat的后面。


边下边播方法再试

那面对moov在mdat后面的MP4,我们应该如何处理呢?怎么才能让播放器先读取到ftyp与moov呢

然后,我想着单纯在字节层次,将moov整个搬到mdat的前面,ftyp的后面。但失败了,大概是因为moov里面已经写死了对应mdat的地址检索表,所以我们这样移动定然改变了mdat的原本位置,而导致无法检索数据。如下图:
这里写图片描述

这里注意,播放器播放视频的时候,大概是不在乎mdat的数据是否正确的,而是哪里正确则播放到哪里,直到错误报错。


边下边播方法成功

所以我后来受到网上的启示。先不管mdat这一部分,只下载ftyp与moov部分,并按照其原本的位置放置,而将mdat这一部分架空。最后和方法一同样,不断下载mdat的分段文件并追加到指定位置。(注意,可能有这三者以外的其他数据,所以我将视频重新分为三部分:head,mDat,foot,head是mDat的前面部分,foot是mDat的后面部分)
分割上传视频

下载播放视频


边下边播方法改良

上面已经是很久之前的做法了,从数据结构上来说,分的并不是很合理。现在我改变了一下这里的逻辑:将head、foot、自定义数据、mDat大小这些信息在切割的时候就包含子自定义文件tjbb里面,然后在下载回来的时候,先下载tjbb文件就可以了解析所有必要信息了
这里写图片描述


到了这里,就能实现边下载边播放了。但要怎么样才能知道ftyp,mdat,moov的位置呢。
这里就要再了解一下mp4结构了。

MP4由多个Box组成,Box可以理解为一种结构规范,另外Box可以层层嵌套,如Moov里面又有很多个Box。

下面所讨论的Box都具备以下特性:以8个字节开头,接着就是Box的数据。该8个字节,前四个字节包含了整一个Box的大小信息,后四个字节包含了该Box的类型(也可以说是名字)。有一种叫footBox不太一样。

这里写图片描述

我们可以通过将字节转化为字符串的形式,获取mdat字符的位置,然后减去4个字节(存储大小信息的部分),就能得到mdat这个box的起始位置了,然后再读取其大小信息,获取mdat的总大小,就能获取到mdat的结束位置。

特别注意,这里我们不是讲mp4分为type,mdat与moov了,而是分为head,mdat,foot,因为其中间可能还有一些别的Box,而这种分法,还有可能moov在mdat前面的,而导致没有foot,这也是需要注意的。

另外,查找mdat位置的时候,不要一次性将mp4读取到手机内存啊,会崩溃的,需要用到缓冲池,我倒是写了不少算法,不过也不是很齐全,日后再发了。

到此,这就是我实现mp4边下边播的方法了,挺有意思的不是。如果有问题可以评论留言。

  • 24
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
Android项目异步加载图像小结 (含线程池,缓存方法) 本资源为一份关于Android项目中异步加载图像的详细文档,包含了线程池和缓存方法的应用。文档旨在帮助开发者解决在Android应用中高效加载大量图像的问题,提高应用的性能和用户体验。 主要内容包括: 1. 异步加载图像的重要性:阐述了为何需要在Android应用中采用异步加载图像的方式,以及异步加载图像对应用性能的提升效果。 2. 线程池技术:介绍了线程池的基本概念、工作原理以及在Android项目中的应用场景。通过使用线程池,可以实现对线程的有效管理,避免因创建过多线程而导致的性能问题。 3. 缓存方法:详细讲解了在Android项目中实现图像缓存的几种常用方法,包括内存缓存、磁盘缓存和第三方库缓存。这些缓存方法可以有效减少网络请求次数,降低服务器压力,提高图像加载速度。 4. 实践案例分析:通过一个实际案例,展示了如何在Android项目中结合线程池和缓存方法实现高效的异步图像加载功能。案例代码具有很好的可扩展性和可定制性,开发者可以根据自己的需求进行修改和优化。 本资源适合对Android开发有一定基础的读者,可以帮助他们更好地理解和掌握异步加载图像的技术和方法。通过学习和实践,开发者可以提高自己项目的性能和用户体验,从而打造出更加优秀的Android应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值