2015-10-12 15 views
6

Tôi cần chuyển đổi tệp PCM thành tệp AAC hoặc MP4. Cho đến bây giờ, tôi đã làm điều đó với MediaCodecMediaMuxer, nhưng MediaMuxer được hỗ trợ từ Android 4.3. Có phương pháp nào để thực hiện chuyển đổi mà không cần sử dụng MediaMuxer không?Chuyển đổi tệp PCM thành AAC hoặc MP4 mà không có MediaMuxer

Mã của tôi là thế này:

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

Trình đóng góp: xin lưu ý rằng các công cụ đề xuất câu trả lời không có nghĩa là một câu hỏi đang yêu cầu các công cụ và làm cho nó không có chủ đề. –

Trả lời

4

Như bạn đã chỉ ra, có không có hệ thống API công cộng tương thích với phiên bản cũ của Android cho các loại hình công việc.

Dù sao, bạn có thể theo đuổi một giải pháp tùy chỉnh sử dụng một bộ mã hóa bản địa (như FFMPEG). Tôi có thể đề nghị bạn như sau: timsu/android-aac-enc

Android AAC mã hóa dự án

Khai thác Android Stagefright VO AAC encoder với một Java API tốt đẹp.

Dự án này cung cấp một Java API dễ dàng cho các cơ JNI encoder, và nó phải được sẵn sàng sử dụng từ thư viện có nguồn gốc đã được biên soạn cho generic ARM kiến ​​trúc (xin lưu ý rằng tôi thiên đường' t kiểm tra nó). Toàn bộ thư viện chỉ là 500kb để nó không làm cho APK của bạn bị hỏng.

Đối với một thử nghiệm nhanh, nhập khẩu trong dự án của bạn những phần sau đây:

  1. Java bindings cho AAC mẹ đẻ encorder
  2. Pre-biên soạn AAC encoder .so library
  3. Example của việc sử dụng (mã hóa speech)

Bạn sẽ có thể dễ dàng điều chỉnh ví dụ cho mã của mình.

Các vấn đề liên quan