mp4 seek

Seeking主要是利用sample table box里面包含的子box来实现的,还需要考虑edit list的影响。

可以按照以下步骤seek某一个track到某个时间T,注意这个T是以movie header box里定义的time scale为单位的:

  1. 如果track有一个edit list,遍历所有的edit,找到T落在哪个edit里面。将Edit的开始时间变换为以movie time scale为单位,得到EST,T减去EST,得到T',就是在这个edit里面的duration,注意此时T'是以movie的time scale为单位的。然后将T'转化成track媒体的time scale,得到T''。T''与Edit的开始时间相加得到以track媒体的time scale为单位的时间点T'''。
  2. 这个track的time-to-sample表说明了该track中每个sample对应的时间信息,利用这个表就可以得到T'''对应的sample NT
  3. sample NT可能不是一个random access point,这样就需要其他表的帮助来找到最近的random access point。一个表是sync sample表,定义哪些sample是random access point。使用这个表就可以找到指定时间点最近的sync sample。如果没有这个表,就说明所有的sample都是synchronization points,问题就变得更容易了。另一个shadow sync box可以帮助内容作者定义一些特殊的samples,它们不用在网络中传输,但是可以作为额外的random access point。这就改进了random access,同时不会影响正常的传输比特率。这个表指出了非random access point和random access point之间的关系。如果要寻找指定sample之前最近的shadow sync sample,就需要查询这个表。总之,利用sync sample和shadow sync表,就可以seek到NT之前的最近的access point sample Nap
  4. 找到用于access point的sample Nap之后,利用sample-to-chunk表来确定sample位于哪个chunk内。
  5. 找到chunk后,使用chunk offset找到这个chunk的开始位置。
  6. 使用sample-to-chunk表和sample size表中的数据,找到Nap在此chunk内的位置,再加上此chunk的开始位置,就找到了Nap在文件中的位置。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java实现MP4文件分割的方法和普通文件分割类似,只需要注意一下MP4文件的特殊格式即可。MP4文件是一种流媒体文件格式,它包含一个或多个“框”(box),每个框都有自己的类型(type),长度(size)和内容(data)。 在进行MP4文件分割时,需要根据MP4文件格式的规范,按照一定的方式进行文件分割。具体步骤如下: 1. 创建一个RandomAccessFile对象,指定要分割的MP4文件和读写模式。 2. 找到主要的moov和mdat框,这两个框是MP4文件的核心部分。moov框包含了文件的元数据信息,mdat框包含了实际的媒体数据。 3. 将moov框和mdat框之间的数据读取出来,写入一个新文件,并在新文件中添加必要的头信息。 4. 关闭所有文件流。 下面是一个简单的Java MP4文件分割示例代码: ```java import java.io.*; public class Mp4Splitter { public static void main(String[] args) { String sourceFile = "D:/sample.mp4"; // 原文件名 String targetFolder = "D:/split/"; // 分割文件存放目录 int fileSize = 1024 * 1024; // 分割文件大小,这里为1MB try { // 创建RandomAccessFile对象 RandomAccessFile raf = new RandomAccessFile(sourceFile, "r"); // 查找moov和mdat框 long moovOffset = findBox(raf, "moov"); long mdatOffset = findBox(raf, "mdat"); // 计算moov和mdat框之间的数据长度 long dataLength = mdatOffset - moovOffset - 8; // 计算分割文件数 int fileCount = (int) Math.ceil((double) dataLength / fileSize); // 读取moov和mdat框之间的数据,并写入分割文件 byte[] buffer = new byte[fileSize]; int len; for (int i = 0; i < fileCount; i++) { // 创建分割文件 File targetFile = new File(targetFolder + "part" + i + ".mp4"); RandomAccessFile targetRaf = new RandomAccessFile(targetFile, "rw"); // 写入MP4文件头信息 if (i == 0) { byte[] header = new byte[(int) moovOffset]; raf.seek(0); raf.read(header); targetRaf.write(header); } // 读取并写入分割文件 raf.seek(moovOffset + 8 + i * fileSize); while ((len = raf.read(buffer)) != -1) { targetRaf.write(buffer, 0, len); if (targetRaf.length() >= fileSize) { break; } } // 关闭分割文件流 targetRaf.close(); } // 关闭原文件流 raf.close(); } catch (IOException e) { e.printStackTrace(); } } private static long findBox(RandomAccessFile raf, String boxType) throws IOException { byte[] typeBytes = boxType.getBytes(); byte[] buffer = new byte[8]; int len; while ((len = raf.read(buffer)) != -1) { int size = readInt(buffer, 0); byte[] type = new byte[4]; System.arraycopy(buffer, 4, type, 0, 4); if (size == 1) { raf.read(buffer); size = readLong(buffer, 0); } if (new String(type).equals(boxType)) { return raf.getFilePointer() - len; } raf.seek(raf.getFilePointer() + size - len); } return -1; } private static int readInt(byte[] bytes, int offset) { return ((bytes[offset] & 0xff) << 24) | ((bytes[offset + 1] & 0xff) << 16) | ((bytes[offset + 2] & 0xff) << 8) | (bytes[offset + 3] & 0xff); } private static long readLong(byte[] bytes, int offset) { return ((long) readInt(bytes, offset) << 32) | (readInt(bytes, offset + 4) & 0xffffffffL); } } ``` 以上代码将一个名为sample.mp4文件分割成1MB大小的多个文件,并存放在D:/split目录下。注意,这里只是一个简单的示例代码,对于一些特殊的MP4文件格式可能需要进行一些额外的处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值