Search code examples
androidandroid-mediacodecmediaextractor

MediaCodec outputBuffer is always empty


I have a problem with the outputBuffer inside my onOutputBufferAvailable() callback method. Everytime this callback method is called I check the outputBuffer using outputBuffer.hasRemaining method and this is always return false.

        codec.setCallback(new MediaCodec.Callback() {

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {

                ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
                int rounds = extractor.readSampleData(inputBuffer,0);

                if(rounds > 0) {
                    long currentT = extractor.getSampleTime();
                    Log.i("CurrentT", String.valueOf(currentT/(1000*1000)));
                    codec.queueInputBuffer(inputBufferId, 0, rounds, 0, 0);
                     extractor.advance();


                } else {
                    // EOS
                    codec.queueInputBuffer(inputBufferId, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    Log.i("EOS","=-1");


                }


            }

            @Override
            public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
                Log.i("error", "e");
            }
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, MediaCodec.BufferInfo info) {
                ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);

                Log.i("has", String.valueOf(outputBuffer.hasRemaining()));
                if (outputBuffer.hasRemaining()) {

                    b = outputBuffer.get();
                    Log.i("i", String.valueOf(b));
                    BAOS.write(b);
                    outputBuffer.clear();

                } else {

                    array= BAOS.toByteArray();
                    codec.stop();
                    codec.release();

                }
                 codec.releaseOutputBuffer(outputBufferId, false);

            }


            @Override
            public void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
                // Subsequent data will conform to new format.
                // Can ignore if using getOutputFormat(outputBufferId)
               // mOutputFormat = format; // option B
            }
        });

Solution

  • The main reason of the problem was wrong MediaCodec mode; wasMediaCodec.createByCodecName(...), should be codec = MediaCodec.createDecoderByType("audio/mpeg"). After unsuccesfull tries getting byte using get() I finally ended up with get(byte[] dst) method. Working code below.

                @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
                @Override
                public void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, MediaCodec.BufferInfo info) {
                    ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
    
                        byte[] b = new byte[outputBuffer.remaining()];
                        outputBuffer.get(b);
    
                        for(i=0;i< b.length;i++) {
                            BAOS.write(b[i]);
                        }
                        outputBuffer.clear();
    
                    codec.releaseOutputBuffer(outputBufferId, false);
    
                    if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
                        array=BAOS.toByteArray();
                        Log.i("array", String.valueOf(array.length));
                        FileTools fl = new FileTools();
                        fl.WriteFile(array);
                        codec.stop();
                        codec.release();
                    }
                }