java .lang.IllegalArgumentException в обратном вызове MediaCode c onInputBufferAvailable - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь создать асинхронный декодер, который считывает кадры из очереди, которая записывается экстрактором мультимедиа, который заполняет ее пакетами, считанными из файла MP4.

public class AsynchronousDecoder {
    private static String TAG = "AsynchronousDecoder";
    public final int MAX_FRAMES = 30;
    final Queue<Frame> inputFrames = new LinkedList<>();
    private MediaFormat mediaFormat;
    private String mime;
    private MediaFormat mOutputFormat;
    MediaCodec codec;
    MediaCodec.BufferInfo info;
    void setFormat(MediaFormat mediaFormat) {
        this.mediaFormat = mediaFormat;
    }

    void setMime(String mime) {
        this.mime = mime;
    }
    void begin() throws IOException {
        MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
        String name = mediaCodecList.findDecoderForFormat(this.mediaFormat);
        codec = MediaCodec.createByCodecName(name);
        info = new MediaCodec.BufferInfo();

        codec.setCallback(new MediaCodec.Callback() {
            @Override
            public void onInputBufferAvailable(MediaCodec mediaCodec, int inputBufferId) {
                ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferId);
                // fill inputBuffer with valid data
                Frame frame = null;
                synchronized (inputFrames) {
                    if (inputFrames.size()>0) {
                        frame = inputFrames.element();
                    }
                }
                if (frame != null) {
                    assert inputBuffer != null;
                    int offset = 0;
                    int flags = BUFFER_FLAG_KEY_FRAME;
                    try {
                        inputBuffer.clear();
                        inputBuffer.put(frame.byteBuffer);
                        Log.d(TAG, "gonna queue frame of capacity " + frame.byteBuffer.capacity());
                        Log.d(TAG, "inputBuffer has capacity " + inputBuffer.capacity());
                        Log.d(TAG, "gonna queue input buffer of id " + inputBufferId);
                        codec.queueInputBuffer(inputBufferId,
                                offset,
                                frame.byteBuffer.capacity(),
                                frame.presentationTimeUs,
                                flags);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onOutputBufferAvailable(MediaCodec mediaCodec, int outputBufferId, MediaCodec.BufferInfo info) {
                ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
                MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
                // bufferFormat is equivalent to mOutputFormat
                // outputBuffer is ready to be processed or rendered.

                Log.d(TAG, "onOutputBufferAvailable!, bufferFormat: " + bufferFormat);
                //false means do not send to surface
                codec.releaseOutputBuffer(outputBufferId, false);
            }

            @Override
            public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) {
                // Subsequent data will conform to new format.
                // Can ignore if using getOutputFormat(outputBufferId)
                Log.d(TAG, "onOutputFormatChanged: " + mediaFormat);
                mOutputFormat = mediaFormat; // option B
            }

            @Override
            public void onError(MediaCodec mc, MediaCodec.CodecException codecException) {
                Log.d(TAG, codecException.toString());
            }
        });
        if (mediaFormat!=null) {
            Log.d(TAG, "configuring with mediaFormat " + mediaFormat.toString());
            codec.configure(mediaFormat, null, null, 0);

        } else {
            Log.d(TAG, "EXCEPTION: mediaFormat is null");
            //throw Exception("")
        }
        mOutputFormat = codec.getOutputFormat(); // option B
        codec.start();
        Log.d(TAG, "codec started");
        // wait for processing to complete
        try
        {
            //TODO: make it wait for EOF
            Thread.sleep(1000000);
        }
        catch(InterruptedException ex)
        {
            Thread.currentThread().interrupt();
        }
        codec.stop();
        codec.release();
    }
}

Вот что я получение:

2020-07-10 22:18:00.878 28876-28876/com.something.mediacodecdecoderexample D/AsynchronousDecoder: gonna queue frame of capacity 100000
2020-07-10 22:18:00.878 28876-28876/com.something.mediacodecdecoderexample D/AsynchronousDecoder: inputBuffer has capacity 8192
2020-07-10 22:18:00.878 28876-28876/com.something.mediacodecdecoderexample D/AsynchronousDecoder: gonna queue input buffer of id 3
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err: java.lang.IllegalArgumentException
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.media.MediaCodec.native_queueInputBuffer(Native Method)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.media.MediaCodec.queueInputBuffer(MediaCodec.java:2342)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at com.something.mediacodecdecoderexample.AsynchronousDecoder$1.onInputBufferAvailable(AsynchronousDecoder.java:62)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.media.MediaCodec$EventHandler.handleCallback(MediaCodec.java:1668)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.media.MediaCodec$EventHandler.handleMessage(MediaCodec.java:1626)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:105)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.os.Looper.loop(Looper.java:164)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6617)
2020-07-10 22:18:00.879 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2020-07-10 22:18:00.880 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
2020-07-10 22:18:00.880 28876-28876/com.something.mediacodecdecoderexample W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)

Я не понимаю, что делаю не так. Я думал, что это связано с тем, что я использовал codec вместо mediaCodec, переданного в обратный вызов, но я просто звоню, как Google показывает в документации MediaCode c. Я изменился, и это не помогло.

...