android mediacodec仅在收到下一个I帧后播放I帧(I帧之间的时差为2-3秒)

android mediacodec仅在收到下一个I帧后播放I帧(I帧之间的时差为2-3秒),android,android-mediacodec,Android,Android Mediacodec,我正在尝试使用Android MediaCodec对NAL单元进行解码。问题是视频的播放延迟为2-3秒,因为只有在接收到下一个I帧后才播放第一个I帧,I帧之间的时间差为2-3秒。因此,如果我将同一个I帧连续放置2次,那么它将毫不延迟地播放。但在这种情况下,我不能播放其余的帧 我不明白问题出在哪里。我试着自己解决它,但我做不到 public void play(MediaCodec decoder, PESPacket currentPES){ byte[] data = currentP

我正在尝试使用Android MediaCodec对NAL单元进行解码。问题是视频的播放延迟为2-3秒,因为只有在接收到下一个I帧后才播放第一个I帧,I帧之间的时间差为2-3秒。因此,如果我将同一个I帧连续放置2次,那么它将毫不延迟地播放。但在这种情况下,我不能播放其余的帧

我不明白问题出在哪里。我试着自己解决它,但我做不到

public void play(MediaCodec decoder, PESPacket currentPES){
    byte[] data = currentPES.data.toByteArray();
    pts = currentPES.getPts();

    try {
        if (data[4] == 0x67) {
            Log.d(TAG, "found sps/pps!");
            int ibs = decoder.dequeueInputBuffer(0);
            if (ibs >= 0) {
                ByteBuffer buffer = decoder.getInputBuffers()[ibs];
                buffer.clear();
                buffer.put(data);
                decoder.queueInputBuffer(ibs, 0, data.length, pts, MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
            }
        } else {
            if (data[4] == 0x41) {              // not I-frame
                int ibs = decoder.dequeueInputBuffer(0);
                if (ibs >= 0) {
                    System.out.println("queueInputBuffer little");
                    ByteBuffer buffer = decoder.getInputBuffers()[ibs];
                    buffer.clear();
                    buffer.put(data);
                    decoder.queueInputBuffer(ibs, 0, data.length, pts, 0);
                }
            }
            if (data[4] == 0x65) {              // I-frame
                int ibs = decoder.dequeueInputBuffer(0);
                if (ibs >= 0) {
                    System.out.println("queueInputBuffer");
                    ByteBuffer buffer = decoder.getInputBuffers()[ibs];
                    buffer.clear();
                    buffer.put(data);
                    decoder.queueInputBuffer(ibs, 0, data.length, pts, 0);
                }

            }
        }

        int outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 10000);
        if (outputBufferIndex >= 0) {
            System.out.println("releaseOutputBuffer " + outputBufferIndex);
            decoder.releaseOutputBuffer(outputBufferIndex, true);
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
            System.out.println("INFO_OUTPUT_BUFFERS_CHANGED ");
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            MediaFormat format = decoder.getOutputFormat();
            System.out.println("INFO_OUTPUT_FORMAT_CHANGED " + format);
        }
    } catch (Throwable t) {
        t.printStackTrace();
    }
}    

可能已经太晚了,但我想分享一些信息

如果仅向视频解码器发送IDR帧,则可以在配置解码器时尝试将MediaFormat中的android.\u num-input-buffers和android.\u num-output-buffers设置为1。这将尝试在视频解码器中分配单个缓冲区,从而立即输出缓冲区。然而,该行为不能保证,将取决于解码器的实现

我猜,谷歌的软件H264解码器omx.Google.H264.decoder应该支持这种行为,但我还没有测试过

有关如何设置参数,请参考以下Android source code FrameDecoder.cpp。FrameDecoder.cpp是Android API MetaDataExtractor.getFrameAt的框架层实现


你的共和党有多大?这是正常的,预计解码器中会有一些延迟-你不能输入一个缓冲区,然后等待它从另一端弹出-但它通常在4帧左右。GOP大小是15。我只有在收到第十五帧后才有输出缓冲区。。。这是MediaCodec的正常行为吗?我不认为有正常行为。MediaCodec是供应商提供的使用OMX接口的编解码器驱动程序的包装器。缓冲量取决于编解码器实现和流的性质。在基于qcom的设备上解码AVC时,我看到了初始启动时的大约4帧。谢谢。那么,你能告诉我问题出在哪里吗?我正在测试Nexus5。你解决过这个问题吗?
451    // For the thumbnail extraction case, try to allocate single buffer in both
452    // input and output ports, if seeking to a sync frame. NOTE: This request may
453    // fail if component requires more than that for decoding.
454    bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
455            || (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
456    if (!isSeekingClosest) {
457        videoFormat->setInt32("android._num-input-buffers", 1);
458        videoFormat->setInt32("android._num-output-buffers", 1);
459    }