【问题标题】:How to find the address where width and height are stored inside an mp4 file?如何找到 mp4 文件中存储宽度和高度的地址?
【发布时间】:2014-09-28 13:32:51
【问题描述】:

我需要find the addresses存储宽度和高度,但是标准的IUT version没有给出文件格式的明确定义。

到目前为止我发现了什么......:

  • 这两个值都存储在“a QuickTime float”中。我找不到格式,但它似乎使用两个 16 位整数:一个有符号整数,后跟一个无符号整数。
  • 不像许多文件格式,没有固定的位置,所以它是文件特定的。这取决于 TrackHeaderBox 地址。

我迫切需要的东西:

一个清晰规范的答案,描述了这些信息的位置。 我不希望只引用第三方库的答案 (除非它们是用正确的 JavaScript 编写的)。一些类似 C 的伪结构会有所帮助。

【问题讨论】:

标签: data-structures metadata mp4 h.264 file-structure


【解决方案1】:

没有固定的位置。您需要解析到文件中。请检查此 Java 示例。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;


public class GetHeight {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream(new File(args[0]));

        GetHeight ps = new GetHeight();
        ps.find(fis);
    }

    byte[] lastTkhd;

    private void find(InputStream fis) throws IOException {

        while (fis.available() > 0) {
            byte[] header = new byte[8];
            fis.read(header);

            long size = readUint32(header, 0);
            String type = new String(header, 4, 4, "ISO-8859-1");
            if (containers.contains(type)) {
                find(fis);
            } else {
                if (type.equals("tkhd")) {
                    lastTkhd = new byte[(int) (size - 8)];
                    fis.read(lastTkhd);
                } else {
                    if (type.equals("hdlr")) {
                        byte[] hdlr = new byte[(int) (size - 8)];
                        fis.read(hdlr);
                        if (hdlr[8] == 0x76 && hdlr[9] == 0x69 && hdlr[10] == 0x64 && hdlr[11] == 0x65) {
                            System.out.println("Video Track Header identified");
                            System.out.println("width: " + readFixedPoint1616(lastTkhd, lastTkhd.length - 8));
                            System.out.println("height: " + readFixedPoint1616(lastTkhd, lastTkhd.length - 4));
                            System.exit(1);
                        }
                    } else {
                        fis.skip(size - 8);
                    }
                }
            }
        }
    }

    public static long readUint32(byte[] b, int s) {
        long result = 0;
        result |= ((b[s + 0] << 24) & 0xFF000000);
        result |= ((b[s + 1] << 16) & 0xFF0000);
        result |= ((b[s + 2] << 8) & 0xFF00);
        result |= ((b[s + 3]) & 0xFF);
        return result;
    }

    public static double readFixedPoint1616(byte[] b, int s) {
        return ((double) readUint32(b, s)) / 65536;
    }

    List<String> containers = Arrays.asList(
            "moov",
            "mdia",
            "trak"
    );
}

【讨论】:

  • 谢谢,但不要混淆Java and Javascript
  • 我很清楚两者之间的区别,但由于我是 Java 人,所以我选择了一种不太远的语言,并将翻译留给您。我的印象是你在这里问得太多了。 Stackoverflow 不是关于别人做你有报酬的工作。
  • 是的,我知道 StackOverflow,但这是可以用几行格式化的东西。 JavaScript 的问题是整数的工作方式与 python 中的类似(这就像你总是使用 BigInteger 和通常的运算符)。没有类型的整数,除非你进行位操作:然后整数被转换为有符号的 32 位一(所以对于大多数 java 程序来说应该没问题)。还有一些类型化数组允许使用 16 位和 8 位整数作为数组。 但是没有办法得到 longtype 的等效项:我不知道如何处理这个问题。
  • 只需使用 32 位有符号整数。如果为负,则抛出错误。更大的盒子并不多。或者,您可以查看整数并处理负值的特殊情况:负值加 (2^32 + 1) 是实际的 uint32。然后,您可以分多个步骤跳到这个位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2010-09-20
  • 2019-10-12
  • 1970-01-01
相关资源
最近更新 更多