MediaCode c аудиодекодер и кодировщик - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь декодировать аудиофайл .wav и закодировать его в аудиофайл .aa c с использованием MediaCode c.

У меня есть несколько вопросов по приведенному ниже коду.

  1. Могу ли я создать экземпляр outputAudioFormat так, как я его создал? Официальные документы говорят: либо сохранить его из методов обратного вызова, либо использовать getOutputFormat() в экземпляре декодера, чтобы получить его.

  2. Это мои логические c мысли.

    а. Я получаю формат ввода декодера из файла.

    b. Я создаю экземпляр вывода MediaFormat для экземпляра кодировщика.

    c. Я получаю вывод декодера MediaFormat экземпляр из пункта 1.

    Теперь мой вопрос:

    1. Нужен ли мне вход кодировщика MediaFormat экземпляр?
    2. Если да, будет ли вывод декодера MediaFormat из 2. c будет таким же, как для входа кодировщика MediaFormat?

      public class AudioUtil {
      
      private static String TAG = AudioUtil.class.getSimpleName();
      
      static final String CODEC_SPECIFIC_DATA_BUFFER_0 = "csd-0";
      static final String CODEC_SPECIFIC_DATA_BUFFER_1 = "csd-1";
      static final String CODEC_SPECIFIC_DATA_BUFFER_2 = "csd-2";
      
      
      public void audioTestMethod(String path) throws IOException {
      
          final MediaExtractor extractor = new MediaExtractor();
          extractor.setDataSource(path);
          int numTracks = extractor.getTrackCount();
      
          int sampleRate = 0;
          int channel = 0;
          MediaFormat inputAudioFormat = null;
      
          for (int i = 0; i < numTracks; ++i) {
              MediaFormat format = extractor.getTrackFormat(i);
              String mime = getMimeTypeFrom(format);
              if (mime.startsWith("audio/"))
              {
                  extractor.selectTrack(i);
                  logCodecSpecificData(format);
                  sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                  channel = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                  inputAudioFormat = format;
                  break;
              }
          }
      
      
          if(inputAudioFormat == null){
              return;
          }
      
          final MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFrom(inputAudioFormat));
          decoder.configure(inputAudioFormat, null, null, 0);
      
          MediaFormat outputAudioFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, sampleRate, channel);
          outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
          //outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_AUDIO_BIT_RATE);
          final MediaCodec encoder = MediaCodec.createEncoderByType(getMimeTypeFrom(outputAudioFormat));
          encoder.configure(outputAudioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
      
          final long TIMEOUT_USEC = 1000;
      
          decoder.setCallback(new MediaCodec.Callback() {
              @Override
              public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int inputBufferId) {
                  if(!extractor.hasCacheReachedEndOfStream()){
                      ByteBuffer inputBuffer = decoder.getInputBuffer(inputBufferId);
                      inputBuffer.clear();
                      int size = extractor.readSampleData(inputBuffer, 0);
                      long presentationTime = extractor.getSampleTime();
                      int flags = extractor.getSampleFlags();
                      decoder.queueInputBuffer(inputBufferId, 0, size, presentationTime, flags);
                  }
                  else{
                      decoder.queueInputBuffer(inputBufferId, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                  }
              }
      
              @Override
              public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
                  boolean render = bufferInfo.size != 0;
                  if((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                      encoder.signalEndOfInputStream();
                      decoder.releaseOutputBuffer(outputBufferId, render);
                  }
                  else if((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0){
                      decoder.releaseOutputBuffer(outputBufferId, false);
                  }
                  else{
                      decoder.releaseOutputBuffer(outputBufferId, render);
                  }
              }
      
              @Override
              public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
      
              }
      
              @Override
              public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec, @NonNull MediaFormat mediaFormat) {
      
              }
          });
      
          encoder.setCallback(new MediaCodec.Callback() {
              @Override
              public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int i) {
      
              }
      
              @Override
              public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int i, @NonNull MediaCodec.BufferInfo bufferInfo) {
      
              }
      
              @Override
              public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
      
              }
      
              @Override
              public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec, @NonNull MediaFormat mediaFormat) {
      
              }
          });
      
          decoder.start();
          encoder.start();
      
          while(!extractor.hasCacheReachedEndOfStream())
          {
          }
      
          decoder.stop();
          decoder.release();
          //decoder = null;
      
          encoder.start();
          encoder.release();
          //encoder = null;
      
          extractor.release();
          //extractor = null;
      
      }
      
      private String getMimeTypeFrom(MediaFormat format) {
          return format.getString(MediaFormat.KEY_MIME);
      }
      
      
      
      private void logCodecSpecificData(MediaFormat format) {
          ByteBuffer codecSpecificDataBuffer = format.getByteBuffer(CODEC_SPECIFIC_DATA_BUFFER_0);
          for (int k = 0; k < codecSpecificDataBuffer.capacity(); ++k) {
              Log.e(TAG, "csd : " + codecSpecificDataBuffer.array()[k]);
          }
      }
      
      }
      
...