Получение звука из ByteArray в Android - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь получить аудио из байтового массива NV21, когда я запускаю код ниже, я получаю сообщение об ошибке в этой строке inputBuffer.put (input); имя ошибки ** "java.nio.BufferOverflowException" ** Как я могу получить аудио из байтового массива?Я думаю, что я получаю ошибку от ByteBuffer, но я не могу ее решить, я должен увеличить inputBuffer, но как я не могу найти.Пожалуйста, помогите мне.

       public void init(){
                //initialize Audio Encoder
             File audio_file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/", "audio_encoded.aac");
                try {
                    outputStream = new BufferedOutputStream(new FileOutputStream(audio_file));
                    Log.e("AudioEncoder", "outputStream initialized");
                } catch (Exception e){
                    e.printStackTrace();
                }

                try {
                    audioCodec = MediaCodec.createEncoderByType(audioType);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                final int kSampleRates[] = { 8000, 11025, 22050, 44100, 48000 };
                final int kBitRates[] = { 64000, 128000 };
                MediaFormat audioFormat  = MediaFormat.createAudioFormat(audioType,kSampleRates[3],2);
                audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
                audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[1]);
                audioCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
                audioCodec.start();
        }
    }

        // called AudioRecord's read
        public synchronized void audioEncoder(byte[] input) {
            Log.e("AudioEncoder", input.length + " is coming");

            try {
                ByteBuffer[] inputBuffers = audioCodec.getInputBuffers();
                ByteBuffer[] outputBuffers = audioCodec.getOutputBuffers();
                int inputBufferIndex = audioCodec.dequeueInputBuffer(-1);
                if (inputBufferIndex >= 0) {
                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                    inputBuffer.clear();

                    inputBuffer.put(input);


                    audioCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
                }

                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = audioCodec.dequeueOutputBuffer(bufferInfo,0);


    //Without ADTS header
                while (outputBufferIndex >= 0) {
                    ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
                    byte[] outData = new byte[bufferInfo.size];
                    outputBuffer.get(outData);
                    outputStream.write(outData, 0, outData.length);
                    Log.e("AudioEncoder", outData.length + " bytes written");

                    audioCodec.releaseOutputBuffer(outputBufferIndex, false);
                    outputBufferIndex = audioCodec.dequeueOutputBuffer(bufferInfo, 0);

                }
            } catch (Throwable t) {
                t.printStackTrace();
            }

        }

        private CameraProxy.CameraDataCallBack callBack = new CameraProxy.CameraDataCallBack() {

            @Override
            public void onDataBack(byte[] data, long length) {
                // TODO Auto-generated method stub
                Log.i(TAG, "length . " + length);

                //audio play
                int min_buffer_size = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormats);

                audioRecord = new AudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormats,min_buffer_size);

                audioRecord.read(data,0,data.length);
                audioEncoder(data);

    }
}

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Аудиокодирование предлагает немного больше гибкости, чем видео, так как легче изменять размер входных данных.

В этом случае я рекомендую проверить размер inputBuffer (inputBuffer.remaining()) и предоставить именно такой объем аудиоданных.Это означает, что если data слишком велико, поместите только в inputBuffer то, что подойдет, и сохраните оставшуюся часть для входного буфера next .А если data слишком мало, временно поместите его в буфер, пока не получите больше аудиоданных (достаточно для заполнения всего inputBuffer).Вот как этот кодек предназначен для использования.

В качестве отступления: у вашего кода, похоже, есть некоторые проблемы с путаницей видеоданных и аудиоданных, жизненным циклом объекта AudioRecord и правильной организацией потоковдля захвата видео и аудио одновременно.Вот некоторые подсказки:

  • NV21 - это формат изображения, а не аудио.
  • onDataBack() дает вам изображение - тогда вы перезаписываете его с небольшим количеством звука
  • В onDataBack(), data будет ОГРОМНЫМ - b / c содержит изображение.И вы пытаетесь читать целиком аудио-данные.В зависимости от того, как настроен AudioRecord, он может считывать только несколько байтов.Вы должны проверить возвращаемое значение.Из документов :

    Данные должны быть считаны с аудиооборудования кусками размеров, меньших общего размера буфера записи.

  • Если выНужен более качественный пример кода, этот проект выглядит довольно прилично.
0 голосов
/ 20 декабря 2018

Вы можете попробовать;

audioFormat.setInteger (MediaFormat.KEY_MAX_INPUT_SIZE, inputSize);

inputSize следует установить в соответствии с размером ввода.Тогда емкости InputBuffers будет достаточно.

...