gpt4 book ai didi

video - 解压缩 MP4 文件中的 time-To-Sample 表 (STTS)

转载 作者:行者123 更新时间:2023-12-04 23:28:09 25 4
gpt4 key购买 nike

我有一个 mp4 视频字节数组,我需要使用它的中间帧为它生成一个缩略图(例如,如果视频长度为 10 秒,那么我需要从第 5 秒开始获取图片)。

我设法解析文件并提取其框(原子)。我还设法从 mvhd 盒子中获取视频长度。我也设法提取
1. stts 框中的 time-To-Sample 表,
2. stcs 框中的 sample-To-Chunk 表,
3. 来自 stco box 的 chunk-Offset 表,
4. stsz box的样本尺寸表,
5. 从 stss 框中同步样本表

我知道所有实际媒体都在 mdat 框中可用,我需要关联上表以找到文件中的确切帧偏移,但我的问题是如何?表数据似乎被压缩(特别是 time-To-Sample 表),但我不知道如何解压缩它们。

任何帮助表示赞赏。

以下是代码示例

将字节转换为十六进制的代码

public static char[] bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;

hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return hexChars;
}

获取框偏移的代码
final static String MOOV                          = "6D6F6F76";
final static String MOOV_MVHD = "6D766864";
final static String MOOV_TRAK = "7472616B";
final static String MOOV_TRAK_MDIA = "6D646961";
final static String MOOV_TRAK_MDIA_MINF = "6D696E66";
final static String MOOV_TRAK_MDIA_MINF_STBL = "7374626C";
final static String MOOV_TRAK_MDIA_MINF_STBL_STSD = "73747364";
final static String MOOV_TRAK_MDIA_MINF_STBL_STTS = "73747473";
final static String MOOV_TRAK_MDIA_MINF_STBL_STSS = "73747373";
final static String MOOV_TRAK_MDIA_MINF_STBL_STSC = "73747363";
final static String MOOV_TRAK_MDIA_MINF_STBL_STCO = "7374636F";
final static String MOOV_TRAK_MDIA_MINF_STBL_STSZ = "7374737A";

static int getBox(char[] s, int offset, String type) {
int typeOffset = -1;
for (int i = offset*2; i<s.length; ) {
String sizeHex = new String(Arrays.copyOfRange(s, i, i + 8));
String typeHex = new String(Arrays.copyOfRange(s, i + 8, i + 16));
int size = Integer.parseInt(sizeHex, 16);

if (typeHex.equals(type)) {
typeOffset = (i/2);
break;
} else if (typeHex.equals(MOOV)
|| typeHex.equals(MOOV_TRAK)
|| typeHex.equals(MOOV_TRAK_MDIA)
|| typeHex.equals(MOOV_TRAK_MDIA_MINF)
|| typeHex.equals(MOOV_TRAK_MDIA_MINF_STBL)) {
int x = (i/2) + 8;
typeOffset = getBox(s, x, type);
if (typeOffset>-1) {
break;
}
}
i+=(size*2);
}

return typeOffset;
}

获取持续时间和时间刻度的代码
static int[] getDuration(char[] s) {
int mvhdOffset = getBox(s, 0, MOOV_MVHD);
int timeScaleStart = (mvhdOffset*2) + (4 + 4 + 1 + 3 + 4 + 4)*2;
int timeScaleEnd = (mvhdOffset*2) + (4 + 4 + 1 + 3 + 4 + 4 + 4)*2;

int durationStart = (mvhdOffset*2) + (4 + 4 + 1 + 3 + 4 + 4 + 4)*2;
int durationEnd = (mvhdOffset*2) + (4 + 4 + 1 + 3 + 4 + 4 + 4 + 4)*2;

String timeScaleHex = new String(Arrays.copyOfRange(s, timeScaleStart, timeScaleEnd));
String durationHex = new String(Arrays.copyOfRange(s, durationStart, durationEnd));

int timeScale = Integer.parseInt(timeScaleHex, 16);
int duration = Integer.parseInt(durationHex, 16);

int[] result = {duration, timeScale};
return result;
}

获取 time-To-Sample 表的代码
static int[][] getTimeToSampleTable(char[] s, int trakOffset) {
int offset = getBox(s, trakOffset, MOOV_TRAK_MDIA_MINF_STBL_STTS);
int sizeStart = offset*2;
int sizeEnd = offset*2 + (4)*2;

int typeStart = offset*2 + (4)*2;
int typeEnd = offset*2 + (4 + 4)*2;

int noOfEntriesStart = offset*2 + (4 + 4 + 1 + 3)*2;
int noOfEntriesEnd = offset*2 + (4 + 4 + 1 + 3 + 4)*2;

String sizeHex = new String(Arrays.copyOfRange(s, sizeStart, sizeEnd));
String typeHex = new String(Arrays.copyOfRange(s, typeStart, typeEnd));
String noOfEntriesHex = new String(Arrays.copyOfRange(s, noOfEntriesStart, noOfEntriesEnd));

int size = Integer.parseInt(sizeHex, 16);
int noOfEntries = Integer.parseInt(noOfEntriesHex, 16);

int[][] timeToSampleTable = new int[noOfEntries][2];

for (int i = 0; i<noOfEntries; i++) {
int sampleCountStart = noOfEntriesEnd + ((i)*((4 + 4)*2));
int sampleCountEnd = noOfEntriesEnd + ((i)*((4 + 4)*2)) + (4)*2;

int sampleDurationStart = noOfEntriesEnd + ((i)*((4 + 4)*2)) + (4)*2;
int sampleDurationEnd = noOfEntriesEnd + ((i)*((4 + 4)*2)) + (4 + 4)*2;

String sampleCountHex = new String(Arrays.copyOfRange(s, sampleCountStart, sampleCountEnd));
String sampleDurationHex = new String(Arrays.copyOfRange(s, sampleDurationStart, sampleDurationEnd));

timeToSampleTable[i][0] = Integer.parseInt(sampleCountHex, 16);
timeToSampleTable[i][1] = Integer.parseInt(sampleDurationHex, 16);
}

return timeToSampleTable;
}

最佳答案

ISO/IEC 14496-12 标准描述了您需要的所有步骤。
附录 7 提供了解码步骤。第 8 节描述了这些表格。

希望这可以帮助。

关于video - 解压缩 MP4 文件中的 time-To-Sample 表 (STTS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34219596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com