我有一个mp4视频字节数组,我需要使用它的中间帧为它生成一个缩略图(例如,如果视频长度是10秒,那么我需要从5秒开始获取图片)。
我设法解析了文件并提取了它的盒子(atom)。我还设法从mvhd盒子里拿到了视频长度。我还设法从stts box中提取了1.采样时间表,2. stcs box中的sample- to -Chunk表,3. stco box中的块偏移表,4. stsz box中的样本大小表,5. stss box中的同步样本表。
我知道所有实际的媒体都在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;
}获取盒子偏移量的代码
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;
} 发布于 2016-05-30 20:34:03
ISO/IEC 14496-12标准描述了您需要的所有步骤。附录7提供了解码步骤。第8节介绍了这些表。
希望这能有所帮助。
https://stackoverflow.com/questions/34219596
复制相似问题