nuclear_kote
@nuclear_kote

Почему не воспроизводится звук?

public class VoicePlayer extends Plugin {

    private AudioTrack track;
    private final BlockingDeque<byte[]> queue = new LinkedBlockingDeque<>();

    MediaCodec decoder = null;

    @PluginMethod
    public void init(PluginCall call) {
        Context context = getContext();

        int bufferLength = call.getInt("bufferLength", 16384);
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.STREAM_MUSIC);

        AudioFormat.Builder audioFormatBuilder = new AudioFormat.Builder();
        audioFormatBuilder.setSampleRate(Parameters.SAMPLE_RATE);
        audioFormatBuilder.setChannelMask(AudioFormat.CHANNEL_OUT_DEFAULT);
        audioFormatBuilder.setEncoding(AudioFormat.ENCODING_PCM_16BIT);

        AudioAttributes.Builder aBuilder = new AudioAttributes.Builder();
        aBuilder.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH);
        track =
                new AudioTrack(aBuilder.build(), audioFormatBuilder.build(),
                        bufferLength*10, AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);

        track.play();
        try {
            decoder = makeDecoder();
            decoder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @PluginMethod
    public void destroy(PluginCall call) {
        if (track != null) {
            track.stop();
            track.release();
        }
    }

    @PluginMethod()
    public void play(PluginCall call) {
        try {

            byte[] base64s = readBase64AsByteArray(call.getString("base64"));
            queue.add(base64s);
            call.resolve(ResponseGenerator.successResponse());
        } catch (Exception e) {
            call.reject("PLAY_ERROR", e);
        } finally {
           // if (decoder != null) {
             //   decoder.stop();
              //  decoder.release();
            //}
        }

    }


    private MediaCodec makeDecoder() throws IOException {
        MediaCodec decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
        MediaFormat format = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, Parameters.CHANNELS);
        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, Parameters.SAMPLE_RATE);
        format.setInteger(MediaFormat.KEY_BIT_RATE, Parameters.BIT_RATE);
        //AAC-HE 64kbps
        format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
        decoder.configure(format, null, null, 0);
        decoder.setCallback(new MediaCodec.Callback() {
            @Override
            public void onInputBufferAvailable(MediaCodec mediaCodec, int i) {
                //One InputBuffer is available to decode
                try {
//                    while (true) {
                        byte[] data = queue.takeFirst();
                        ByteBuffer buffer = mediaCodec.getInputBuffer(i);
                        buffer.put(data, 0, data.length);
                        mediaCodec.queueInputBuffer(i, 0, data.length, 0, 0);
//                        break;
//                    }
                } catch (Exception ignored) {
                    ignored.printStackTrace();
                }
            }

            @Override
            public void onOutputBufferAvailable(MediaCodec mediaCodec, int i, MediaCodec.BufferInfo info) {
                //DECODING PACKET ENDED
                ByteBuffer outBuffer = mediaCodec.getOutputBuffer(i);
                byte[] chunk = new byte[info.size];
                outBuffer.get(chunk); // Read the buffer all at once
                outBuffer.clear();
                track.write(chunk, info.offset, info.offset + info.size); // AudioTrack write data
                mediaCodec.releaseOutputBuffer(i, false);
            }

            @Override
            public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
                notifyListeners("playError", ResponseGenerator.failResponse(e));
            }

            @Override
            public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) {
            }
        });

        return decoder;
    }


    private byte[] readBase64AsByteArray(String base64) {
        return Base64.decode(base64, Base64.DEFAULT);
    }

}


Вообщем делаю плагин для ионика (капацитор), в play прилетает base64 строка содержащая aac, после чего она декодируется в pcm и проигрывается, через AudioTrack. Проблема в том что MediaCodec.Callback()::onInputBufferAvailable не вызывается, точнее вызывается изредка, непонятно при каких условиях и кидает IllegalStateException, если вызвался,
onOutputBufferAvailable не вызывается никогда
  • Вопрос задан
  • 17 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы