【问题标题】:Extracting AMR data from 3GP file从 3GP 文件中提取 AMR 数据
【发布时间】:2013-07-08 09:01:30
【问题描述】:

我在从 .3gp 文件中提取原始 AMR 音频帧时遇到了一些问题。我点击了链接:“http://android.amberfog.com/?p=181”,但不是“mdat”框类型,而是“moov”。我在某处读到“moov”框和“mdat”框位置因设备而异。有谁知道如何正确跳过 .3gp 标头并提取原始 AMR 数据?下面是一段代码sn-p:

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;
    }

【问题讨论】:

  • 这哪里失败了?
  • if(!MediaDataBox.HEADER_TYPE.equalsIgnoreCase(header)){ //这是问题!!!!!! - 标题是“moov”而不是 if(!MediaDataBox.HEADER_TYPE.equalsIgnoreCase(header)){
  • 标头不是 mdat,而是 moov
  • 原始AMR数据不正确(可能是mdat box的位置改变了)
  • 您确定失败不是特定于文件的吗?也许您只是在使用损坏的测试 3gp 文件?我不确定我是否发现算法有问题。如果您解析非 3gp 标头(moov 而不是 mdat),您的解析器需要修复或者您不知道您的测试文件。

标签: java android audio amr 3gp


【解决方案1】:

我使用一些 HEX 查看器工具查看了我的 .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;
    }

【讨论】:

    猜你喜欢
    • 2013-07-03
    • 2011-08-30
    • 2011-03-25
    • 1970-01-01
    • 2012-03-22
    • 2014-05-01
    • 2012-05-03
    • 2012-06-20
    • 2020-12-20
    相关资源
    最近更新 更多