从.3gp
文件中提取原始AMR音频帧时遇到一些问题。我按照链接:“http://android.amberfog.com/?p=181”但不是“mdat”框类型我有“moov”。我在某处读到“moov”框和“mdat”框位置因设备而异。有谁知道如何正确跳过.3gp
标题并提取原始AMR数据?以下是代码段:
public AMRFile convert3GPDataToAmr(String rawAmrFilePath) throws IOException {
if (_3gpFile == null) {
return null;
}
System.out.println("3GP file length: "+_3gpFile.getRawFile().length());
//FileInputStream is = new FileInputStream(_3gpFile.getRawFile());
ByteArrayInputStream bis = new ByteArrayInputStream(FileUtils.readFileToByteArray(_3gpFile.getRawFile()));
// read FileTypeHeader
System.out.println("Available1: "+bis.available());
FileTypeBox ftypHeader = new FileTypeBox(bis);
System.out.println("Available2: "+bis.available());
String header = ftypHeader.getHeaderAsString();
if(!FileTypeBox.HEADER_TYPE.equalsIgnoreCase(header)){
throw new IOException("File is not 3GP. ftyp header missing.");
}
// You can check if it is correct here
// read MediaDataHeader
MediaDataBox mdatHeader = new MediaDataBox(bis);
System.out.println("Available3: "+bis.available());
header = mdatHeader.getHeaderAsString();
if(!MediaDataBox.HEADER_TYPE.equalsIgnoreCase(header)){
//here is THE PROBLEM!!!!! - header is "moov" instead of "mdat" !!!!!!!!!!!!!
throw new IOException("File is not 3GP. mdat header missing.");
}
// You can check if it is correct here
int rawAmrDataLength = mdatHeader.getDataLength();
System.out.println("RAW Amr length: "+bis.available());
int fullAmrDataLength = AMR_MAGIC_HEADER.length + rawAmrDataLength;
byte[] amrData = new byte[fullAmrDataLength];
System.arraycopy(AMR_MAGIC_HEADER, 0, amrData, 0, AMR_MAGIC_HEADER.length);
bis.read(amrData, AMR_MAGIC_HEADER.length, rawAmrDataLength);
bis.close();
//create raw amr file
File rawAmrFile = new File(rawAmrFilePath);
FileOutputStream fos = new FileOutputStream(rawAmrFile);
AMRFile amrFile = null;
try {
fos.write(amrData);
} catch (Exception e) {
Log.e(getClass().getName(), e.getMessage(), e);
}
finally{
fos.close();
amrFile = new AMRFile(rawAmrFile);
}
System.out.println("AMR file length: "+amrFile.getRawFile().length());
return amrFile;
}
答案 0 :(得分:1)
我使用了一些HEX Viewer工具查看我的.3gp文件,我看到mdat框不在算法所在的位置,所以我决定从流中读取,直到找到mdat框。现在提取工作正常。我稍微修改了MediaDataBox:
public MediaDataBox(FileInputStream is) throws IOException {
super(is);
//check the mdat header - if not read until mdat if found
long last32Int = 0;
long curr32Int = 0;
long temp;
while (is.available()>=8) {
temp = curr32Int = readUint32(is);
//test like this to avoid low memory issues
if((HEADER_TYPE.charAt(0) == (byte)(temp >>> 24)) &&
(HEADER_TYPE.charAt(1) == (byte)(temp >>> 16)) &&
(HEADER_TYPE.charAt(2) == (byte)(temp >>> 8)) &&
(HEADER_TYPE.charAt(3) == (byte)temp)){
size = last32Int;
type = curr32Int;
boxSize = 8;
break;
}
last32Int = curr32Int;
}
}
和超级班:
public _3GPBox(FileInputStream is) throws IOException{
size = readUint32(is);
boxSize += 4;
type = readUint32(is);
boxSize += 4;
}