Video 在MP4文件中解压缩采样时间表(STTS)
我有一个mp4视频字节数组,我需要使用它的中间帧为它生成一个缩略图(例如,如果视频长度为10秒,那么我需要从第5秒开始获取图片) 我设法解析了文件并提取了它的框(atom)。我还设法从mvhd盒中获取视频长度。我还设法提取了 1.从stts框采样表的时间, 2.stcs框中的样本到区块表, 3.stco框中的块偏移表, 4.stsz盒中的样本量表, 5.从stss框同步示例表 我知道所有实际的介质都在mdat框中,我需要关联上表以找到文件中的精确帧偏移量,但我的问题是如何关联?表的数据似乎被压缩了(特别是采样表的时间),但我不知道如何解压缩它们 感谢您的帮助 下面是代码示例 将字节转换为十六进制的代码Video 在MP4文件中解压缩采样时间表(STTS),video,ffmpeg,hex,mp4,compression,Video,Ffmpeg,Hex,Mp4,Compression,我有一个mp4视频字节数组,我需要使用它的中间帧为它生成一个缩略图(例如,如果视频长度为10秒,那么我需要从第5秒开始获取图片) 我设法解析了文件并提取了它的框(atom)。我还设法从mvhd盒中获取视频长度。我还设法提取了 1.从stts框采样表的时间, 2.stcs框中的样本到区块表, 3.stco框中的块偏移表, 4.stsz盒中的样本量表, 5.从stss框同步示例表 我知道所有实际的介质都在mdat框中,我需要关联上表以找到文件中的精确帧偏移量,但我的问题是如何关联?表的数据似乎被压缩
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;
}
获取样本表时间的代码
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;
}
static int[][]getTimeToSampleTable(char[]s,int-trakOffset){
int offset=getBox(s,trakOffset,MOOV_TRAK_MDIA_MINF_STBL_STTS);
int sizeStart=偏移量*2;
int SIZEND=偏移量*2+(4)*2;
int typeStart=偏移量*2+(4)*2;
int typeEnd=偏移量*2+(4+4)*2;
int noofentriessstart=偏移量*2+(4+4+1+3)*2;
int noOfEntriesEnd=偏移量*2+(4+4+1+3+4)*2;
String sizeHex=新字符串(Arrays.copyOfRange(s、sizeStart、sizend));
String typeHex=新字符串(Arrays.copyOfRange(s,typeStart,typeEnd));
String noOfEntriesHex=新字符串(Arrays.copyOfRange(s,noOfEntriesStart,noOfEntriesEnd));
int size=Integer.parseInt(sizeHex,16);
int noOfEntries=Integer.parseInt(noOfEntriesHex,16);
int[][]timeToSampleTable=新int[noOfEntries][2];
对于(int i=0;iISO/IEC 14496-12标准描述了您需要的所有步骤。
附录7提供了解码步骤。第8节描述了这些表
希望这能有所帮助。嗨,你找到解决办法了吗?还不是很不幸
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;
}
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;
}