Movie Box (moov) 该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层。一般情况下,“moov”会紧随“ftyp”出现。
以下是读取下一个bax的大小和类型的代码:
1 2 3 4 5 6 7 it.read(buf) val moovBoxSize = buf.toInt()Log.e("JIN" , "size = $moovBoxSize " ) it.read(buf) Log.e("JIN" , "type = ${buf.toCharString()} " )
然而类型却不是 moov 而是 free, 上面说了,一般情况下 ftype 后面是 moov。
那就跳过当前的box读取下一个box吧。
我又读取了下一个box, 这个 box 是 mdat, 看来,我要读取完整个文件来看看到底这个 mp4 文件有没有 moov 的 box 了。
重构了代码:
1 2 3 4 5 6 7 f.inputStream().also { while (it.available() > 0 ) { val box = Box(it, buf) Log.e("JIN" , box.toString()) } }
Box 对象的代码:
1 2 3 4 5 6 7 8 9 10 11 12 class Box (val size: Int , val type: String) { constructor (inStream: InputStream, byterArray: ByteArray) : this (inStream.read(byterArray).let { byterArray.toInt() }, inStream.read(byterArray).let { byterArray.toCharString() }) { inStream.skip(size - 8L ) } override fun toString () : String { return "$type : $size " } }
这里, 只读取了 size 和 type, 然后跳过了其他数据。
按照大端的方式转化4个字节为 Int 的方法:
1 2 3 4 5 6 7 fun ByteArray.toInt () : Int { val a = this [0 ].toUByte().toInt() * Math.pow(2.0 , 8.0 * 3 ) val b = this [1 ].toUByte().toInt() * Math.pow(2.0 , 8.0 * 2 ) val c = this [2 ].toUByte().toInt() * Math.pow(2.0 , 8.0 ) return (this [3 ].toUByte().toInt() + a + b + c).toInt() }
这里, 除了点问题, 每个字节,要转化成无符号数,再转成 Int, 之前没有转, 因为数小没出问题。
这样打印出了这个 mp4 的所有文件级别的 box:
ftyp: 32
free: 8
mdat: 11703979
moov: 16281
这就有意思了,下一步该绘制 UI 了
明天: 每天一点点_音视频_MP4_视频数据BOX1