2015-10-12 11 views
6

PCMファイルをAACまたはMP4ファイルに変換する必要があります。これまではMediaCodecMediaMuxerで行っていましたが、MediaMuxerはAndroid 4.3からサポートされています。 MediaMuxerを使用せずに変換を行う方法はありますか?PCMをMediaMuxerなしのAACまたはMP4ファイルに変換する

私のコードはこれです:あなたはすでに指摘したように

MediaMuxer mux = null; 
try { 
    File inputFile = new File(filePath + ".pcm"); 
    FileInputStream fis = new FileInputStream(inputFile); 
    mux = new MediaMuxer(filePath + ".mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 

    MediaFormat outputFormat = MediaFormat.createAudioFormat(COMPRESSED_AUDIO_FILE_MIME_TYPE, 
      SAMPLING_RATE, 1); 
    outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); 
    outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, COMPRESSED_AUDIO_FILE_BIT_RATE); 

    MediaCodec codec = MediaCodec.createEncoderByType(COMPRESSED_AUDIO_FILE_MIME_TYPE); 
    codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
    codec.start(); 

    ByteBuffer[] codecInputBuffers = codec.getInputBuffers(); 
    ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers(); 

    MediaCodec.BufferInfo outBuffInfo = new MediaCodec.BufferInfo(); 

    byte[] tempBuffer = new byte[BUFFER_SIZE]; 
    boolean hasMoreData = true; 
    double presentationTimeUs = 0; 
    int audioTrackIdx = 0; 
    int totalBytesRead = 0; 
    int percentComplete; 

    do { 

     int inputBufIndex = 0; 
     while (inputBufIndex != -1 && hasMoreData) { 
      inputBufIndex = codec.dequeueInputBuffer(CODEC_TIMEOUT_IN_MS); 

      if (inputBufIndex >= 0) { 
       ByteBuffer dstBuf = codecInputBuffers[inputBufIndex]; 
       dstBuf.clear(); 

       int bytesRead = fis.read(tempBuffer, 0, dstBuf.limit()); 
       if (bytesRead == -1) { // -1 implies EOS 
        hasMoreData = false; 
        codec.queueInputBuffer(inputBufIndex, 0, 0, (long) presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
       } else { 
        totalBytesRead += bytesRead; 
        dstBuf.put(tempBuffer, 0, bytesRead); 
        codec.queueInputBuffer(inputBufIndex, 0, bytesRead, (long) presentationTimeUs, 0); 
        presentationTimeUs = 1000000l * (totalBytesRead/2)/SAMPLING_RATE; 
       } 
      } 
     } 

     // Drain audio 
     int outputBufIndex = 0; 
     while (outputBufIndex != MediaCodec.INFO_TRY_AGAIN_LATER) { 

      outputBufIndex = codec.dequeueOutputBuffer(outBuffInfo, CODEC_TIMEOUT_IN_MS); 
      if (outputBufIndex >= 0) { 
       ByteBuffer encodedData = codecOutputBuffers[outputBufIndex]; 
       encodedData.position(outBuffInfo.offset); 
       encodedData.limit(outBuffInfo.offset + outBuffInfo.size); 

       if ((outBuffInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 && outBuffInfo.size != 0) { 
        codec.releaseOutputBuffer(outputBufIndex, false); 
       } else { 

        mux.writeSampleData(audioTrackIdx, codecOutputBuffers[outputBufIndex], outBuffInfo); 
        codec.releaseOutputBuffer(outputBufIndex, false); 
       } 
      } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
       outputFormat = codec.getOutputFormat(); 
       Log.v("AUDIO", "Output format changed - " + outputFormat); 
       audioTrackIdx = mux.addTrack(outputFormat); 
       mux.start(); 
      } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 
       Log.e("AUDIO", "Output buffers changed during encode!"); 
      } else if (outputBufIndex != MediaCodec.INFO_TRY_AGAIN_LATER){ 
       Log.e("AUDIO", "Unknown return code from dequeueOutputBuffer - " + outputBufIndex); 
      } 
     } 
     percentComplete = (int) Math.round(((float) totalBytesRead/(float) inputFile.length()) * 100.0); 
     Log.v("AUDIO", "Conversion % - " + percentComplete); 
    } while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM); 

    fis.close(); 
    mux.stop(); 
    mux.release(); 
+1

Closevoter:ツールの推奨回答は、質問がツールを求めてトピックを外しているという意味ではありません。 –

答えて

4

仕事のこの種のためのAndroidの旧バージョンとの互換性がない公共システムAPIがあります。

とにかく、あなたはネイティブエンコーダ(のようなFFMPEG)を使用して、カスタムソリューションを追求することができます。私はあなたに次のことを提案することができますtimsu/android-aac-enc

AndroidのAACエンコーダプロジェクト

素敵なのJava APIとAndroidのStagefright VOのAACエンコーダの抽出。

このプロジェクトは、基礎となるJNIエンコーダため簡単なJava APIを提供し、ネイティブライブラリがすでにジェネリックARMアーキテクチャ用にコンパイルされるので、それを使用する準備ができているはずです(「はIの避難所に注意してくださいそれをテストしました)。ライブラリ全体は500kbなので、APKをそれほど大きくすることはありません。簡単なテストのために

、プロジェクト内のインポート以下の部分:使用状況(音声符号化)の式エンコーダ

  • プリコンパイルAAC encoder .so library
  • ExampleネイティブAACため

    1. Java bindings

    例をコードに簡単に適用できるはずです。

  • 関連する問題