【问题标题】:Out of order BufferInfo.presentationTimeUs timestamps in mediacodec decodermediacodec解码器中的无序BufferInfo.presentationTimeUs时间戳
【发布时间】:2021-12-21 19:47:10
【问题描述】:

我得到了不规则的 newBufferInfo.presentationTimeUs,因为如果我把 Thread.sleep 放慢播放速度,就会丢掉很多帧。

实际上,使用 Surface 时,帧时间戳会自动与系统时间戳同步,无需休眠,但它不适用于向 OpenGLES 提供输出。 https://developer.android.com/reference/android/media/MediaCodec#releaseOutputBuffer(int,%20long)

我认为mExtractor.getSampleTime() 是问题,但即使删除它,问题仍然存在。

package com.example.app;

import android.graphics.PixelFormat;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;

import java.io.IOException;
import java.nio.ByteBuffer;


public final class MediaCodecDecoder {

    private static final String VIDEO = "video/";
    private static final String TAG = "MediaCodecDecoder";
    private final Surface mSurface;
    private final String mClipPath;
    private SurfaceHolder mSurfaceHolder = null;
    private MediaCodec mVideoDecoder;
    private MediaExtractor mExtractor;
    private Boolean mVideoDecoderRunning = false;
    private Thread mVideoDecoderThread;
    private int mDropCount;
    private int mRenderCount;
    private int mFramerate = 30;

    public MediaCodecDecoder(SurfaceHolder surfaceHolder, Surface surface, String clipPath) {
        this.mClipPath = clipPath;
        this.mSurface = surface;
        this.mSurfaceHolder = surfaceHolder;
    }

    public void start() {
        mDropCount = 0;
        mRenderCount = 0;
        mExtractor = new MediaExtractor();
        try {
            mExtractor.setDataSource(mClipPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int index = 0; index <= mExtractor.getTrackCount(); index++) {
            MediaFormat format = mExtractor.getTrackFormat(index);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime != null && mime.startsWith(VIDEO)) {
                mExtractor.selectTrack(index);
                try {
                    mVideoDecoder = MediaCodec.createDecoderByType(mime);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    Log.i(TAG, "format : " + format);
                    format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 65536);
                    mFramerate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
                    mVideoDecoder.configure(format, mSurface, null, 0 /* Decode */);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        mVideoDecoder.start();
        mVideoDecoderThread = new videoDecoderHandler(false);
        mVideoDecoderThread.start();
    }


    public void stop() {
        mVideoDecoderRunning = false;
        try {
            mVideoDecoderThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Clear the surface
        if (mSurfaceHolder != null) {
            mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
            mSurfaceHolder.setFormat(PixelFormat.OPAQUE);
        }

        Log.v("Extended Stats", "drop Count: " + mDropCount);
        Log.v("Extended Stats", "rendered Count: " + mRenderCount);
        Log.v("Extended Stats", "Total Frames Decoded: " + (mRenderCount + mDropCount));
    }


    class videoDecoderHandler extends Thread {
        boolean endOfStream;

        public videoDecoderHandler(boolean endOfStream) {
            this.endOfStream = endOfStream;
        }

        //method where the thread execution will start
        public void run() {
            //logic to execute in a thread
            mVideoDecoderRunning = true;
            MediaCodec.BufferInfo newBufferInfo = new MediaCodec.BufferInfo();
            ByteBuffer[] inputBuffers = mVideoDecoder.getInputBuffers();
            ByteBuffer[] outputBuffers = mVideoDecoder.getOutputBuffers();
            long startNs = System.nanoTime();
            int generateIndex = 0;

            while (mVideoDecoderRunning) {
                int index = mVideoDecoder.dequeueInputBuffer(1000);
                if (index >= 0) {
                    // fill inputBuffers[inputBufferIndex] with valid data
                    ByteBuffer inputBuffer = inputBuffers[index];
                    int sampleSize = mExtractor.readSampleData(inputBuffer, 0);

                    if (mExtractor.advance() && sampleSize > 0) {
                        Log.d(TAG, "index " + index + " mFramerate " + mFramerate + " mExtractor.getSampleTime() " +
                                mExtractor.getSampleTime() + " PresentationTime " +
                                (startNs / 1000 + computePresentationTime(generateIndex, mFramerate)));
                        // mVideoDecoder.queueInputBuffer(index, 0, sampleSize, startNs / 1000 + mExtractor.getSampleTime(), 0);
                        mVideoDecoder.queueInputBuffer(index, 0, sampleSize, startNs / 1000 +
                                computePresentationTime(generateIndex, 30), 0);
                        generateIndex++;
                    } else {
                        Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                        mVideoDecoder.queueInputBuffer(
                                index,
                                0,
                                0,
                                0,
                                MediaCodec.BUFFER_FLAG_END_OF_STREAM
                        );
                    }
                }
                int outIndex = mVideoDecoder.dequeueOutputBuffer(newBufferInfo, 1000);

                switch (outIndex) {
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                        Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
                        outputBuffers = mVideoDecoder.getOutputBuffers();
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " +
                                mVideoDecoder.getOutputFormat());
                        break;
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                        Log.d(TAG, "INFO_TRY_AGAIN_LATER");
                        break;
                    default:
                        Log.d(TAG, "outIndex " + outIndex + " newBufferInfo.presentationTimeUs " +
                                newBufferInfo.presentationTimeUs);
                        boolean render = newBufferInfo.size != 0;
                        long currentNs = System.nanoTime();
                        if (!render) {
                            mVideoDecoder.releaseOutputBuffer(outIndex, false);
                        } else if (currentNs / 1000 - newBufferInfo.presentationTimeUs > 30000) {
                            mVideoDecoder.releaseOutputBuffer(outIndex, false);
                            mDropCount++; // drop if more than 30ms late
                        } else {
                            try {
                                if ((newBufferInfo.presentationTimeUs - currentNs / 1000) / 1000 > 0) {
                                    Thread.sleep((newBufferInfo.presentationTimeUs - currentNs / 1000) / 1000);
                                }
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            mVideoDecoder.releaseOutputBuffer(outIndex, true);
                            mRenderCount++;
                        }
                }

                // All decoded frames have been rendered, we can stop playing now
                if ((newBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                    break;
                }

                if (endOfStream) {
                    break;
                }
            }
            mVideoDecoder.stop();
            mVideoDecoder.release();
            mExtractor.release();
        }
    }


    /**
     * Generates the presentation time for frame N, in microseconds.
     */
    private static long computePresentationTime(int frameIndex, int FRAME_RATE) {
        return (132 + Long.valueOf(frameIndex) * 1000000
                / Long.valueOf(FRAME_RATE));
    }

}

该类获取mp4视频clipPath,并具有startstop函数,用于开始和停止将mp4视频解码为传递的surface

这是日志

04-21 20:49:35.875 3595 3971 D MediaCodecDecoder: index 0 mFramerate 30 mExtractor.getSampleTime() 9666666 PresentationTime 362231984
04-21 20:49:35.879 3595 3971 D MediaCodecDecoder: outIndex 14 newBufferInfo.presentationTimeUs 361965317
04-21 20:49:35.884 3595 3971 D MediaCodecDecoder: index 1 mFramerate 30 mExtractor.getSampleTime() 9800000 PresentationTime 362265317
04-21 20:49:35.888 3595 3971 D MediaCodecDecoder: outIndex 2 newBufferInfo.presentationTimeUs 362131984
04-21 20:49:35.894 1124 3960 E OMX-VDEC-1080P: Unable to convey fps info to driver, performance might be affected
04-21 20:49:35.962 3595 3971 D MediaCodecDecoder: index 2 mFramerate 30 mExtractor.getSampleTime() 9766666 PresentationTime 362298650
04-21 20:49:35.969 3595 3971 D MediaCodecDecoder: outIndex 6 newBufferInfo.presentationTimeUs 362098650
04-21 20:49:35.973 3595 3971 D MediaCodecDecoder: index 3 mFramerate 30 mExtractor.getSampleTime() 9900000 PresentationTime 362331984
04-21 20:49:35.988 1124 3960 E OMX-VDEC-1080P: Unable to convey fps info to driver, performance might be affected
04-21 20:49:35.990 3595 3971 D MediaCodecDecoder: outIndex 13 newBufferInfo.presentationTimeUs 362165317
04-21 20:49:35.993 1124 3960 E OMX-VDEC-1080P: Unable to convey fps info to driver, performance might be affected
04-21 20:49:36.000 3595 3971 D MediaCodecDecoder: index 0 mFramerate 30 mExtractor.getSampleTime() 9866666 PresentationTime 362365317
04-21 20:49:36.003 3595 3971 D MediaCodecDecoder: outIndex 5 newBufferInfo.presentationTimeUs 362065317
04-21 20:49:36.005 3595 3971 D MediaCodecDecoder: index 1 mFramerate 30 mExtractor.getSampleTime() 9833333 PresentationTime 362398650
04-21 20:49:36.007 3595 3971 D MediaCodecDecoder: outIndex 3 newBufferInfo.presentationTimeUs 362265317
04-21 20:49:36.013 1124 3960 E OMX-VDEC-1080P: Unable to convey fps info to driver, performance might be affected
04-21 20:49:36.096 3595 3971 D MediaCodecDecoder: index 2 mFramerate 30 mExtractor.getSampleTime() 10033333 PresentationTime 362431984
04-21 20:49:36.102 3595 3971 D MediaCodecDecoder: outIndex 4 newBufferInfo.presentationTimeUs 362231984
04-21 20:49:36.108 3595 3971 D MediaCodecDecoder: index 3 mFramerate 30 mExtractor.getSampleTime() 9966666 PresentationTime 362465317
04-21 20:49:36.111 3595 3971 D MediaCodecDecoder: outIndex 15 newBufferInfo.presentationTimeUs 362198650



04-21 20:49:40.614 3595 3595 V Extended Stats: drop Count: 232
04-21 20:49:40.614 3595 3595 V Extended Stats: rendered Count: 192
04-21 20:49:40.615 3595 3595 V Extended Stats: Total Frames Decoded: 424

这里是日志

                         mVideoDecoder.queueInputBuffer(index, 0, sampleSize, startNs / 1000 + mExtractor.getSampleTime(), 0);
//                        mVideoDecoder.queueInputBuffer(index, 0, sampleSize, startNs / 1000 +
//                                computePresentationTime(generateIndex, 30), 0);
2021-11-09 15:36:33.898 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 0 mFramerate 30 mExtractor.getSampleTime() 64798066 PresentationTime 907904455
2021-11-09 15:36:33.899 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 14 newBufferInfo.presentationTimeUs 907735489
2021-11-09 15:36:33.910 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 1 mFramerate 30 mExtractor.getSampleTime() 64898166 PresentationTime 907937788
2021-11-09 15:36:33.912 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 15 newBufferInfo.presentationTimeUs 907902323
2021-11-09 15:36:33.969 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 2 mFramerate 30 mExtractor.getSampleTime() 64864800 PresentationTime 907971122
2021-11-09 15:36:33.970 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 8 newBufferInfo.presentationTimeUs 907802223
2021-11-09 15:36:33.973 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 3 mFramerate 30 mExtractor.getSampleTime() 64964900 PresentationTime 908004455
2021-11-09 15:36:33.975 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 9 newBufferInfo.presentationTimeUs 907935690
2021-11-09 15:36:33.999 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 4 mFramerate 30 mExtractor.getSampleTime() 64931533 PresentationTime 908037788
2021-11-09 15:36:34.002 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 11 newBufferInfo.presentationTimeUs 907868956
2021-11-09 15:36:34.004 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 5 mFramerate 30 mExtractor.getSampleTime() 65031633 PresentationTime 908071122
2021-11-09 15:36:34.005 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 6 newBufferInfo.presentationTimeUs 908002423
2021-11-09 15:36:34.065 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 6 mFramerate 30 mExtractor.getSampleTime() 64998266 PresentationTime 908104455
2021-11-09 15:36:34.068 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 4 newBufferInfo.presentationTimeUs 908069156
2021-11-09 15:36:34.131 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 7 mFramerate 30 mExtractor.getSampleTime() 65098366 PresentationTime 908137788
2021-11-09 15:36:34.132 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 3 newBufferInfo.presentationTimeUs 907969056
2021-11-09 15:36:34.133 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 8 mFramerate 30 mExtractor.getSampleTime() 65065000 PresentationTime 908171122
2021-11-09 15:36:34.134 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 7 newBufferInfo.presentationTimeUs 908135890
2021-11-09 15:36:34.209 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 9 mFramerate 30 mExtractor.getSampleTime() 65165099 PresentationTime 908204455
2021-11-09 15:36:34.211 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 13 newBufferInfo.presentationTimeUs 908035790
2021-11-09 15:36:34.213 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 10 mFramerate 30 mExtractor.getSampleTime() 65131733 PresentationTime 908237788
2021-11-09 15:36:34.215 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 5 newBufferInfo.presentationTimeUs 908202623
2021-11-09 15:36:34.270 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 11 mFramerate 30 mExtractor.getSampleTime() 65231833 PresentationTime 908271122
2021-11-09 15:36:34.273 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 16 newBufferInfo.presentationTimeUs 908102523
2021-11-09 15:36:34.275 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 0 mFramerate 30 mExtractor.getSampleTime() 65198466 PresentationTime 908304455
2021-11-09 15:36:34.277 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 12 newBufferInfo.presentationTimeUs 908269356
2021-11-09 15:36:34.331 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 1 mFramerate 30 mExtractor.getSampleTime() 65265199 PresentationTime 908337788
2021-11-09 15:36:34.333 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 14 newBufferInfo.presentationTimeUs 908169256
2021-11-09 15:36:34.334 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 2 mFramerate 30 mExtractor.getSampleTime() 65331933 PresentationTime 908371122
2021-11-09 15:36:34.335 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 10 newBufferInfo.presentationTimeUs 908336089
2021-11-09 15:36:34.398 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 3 mFramerate 30 mExtractor.getSampleTime() 65298566 PresentationTime 908404455
2021-11-09 15:36:34.401 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 8 newBufferInfo.presentationTimeUs 908235990
2021-11-09 15:36:34.402 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: index 4 mFramerate 30 mExtractor.getSampleTime() 65398666 PresentationTime 908437788
2021-11-09 15:36:34.403 6051-6106/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 15 newBufferInfo.presentationTimeUs 908402823
2021-11-09 15:36:34.544 6051-6098/org.codeaurora.qmedia2 D/SurfaceUtils: disconnecting from surface 0x733202f010, reason disconnectFromSurface

2021-11-09 15:36:34.581 6051-6051/org.codeaurora.qmedia2 V/Extended Stats: drop Count: 909
2021-11-09 15:36:34.581 6051-6051/org.codeaurora.qmedia2 V/Extended Stats: rendered Count: 1044
2021-11-09 15:36:34.581 6051-6051/org.codeaurora.qmedia2 V/Extended Stats: Total Frames Decoded: 1953

这里是日志


mVideoDecoder.queueInputBuffer(index, 0, sampleSize, mExtractor.getSampleTime(), 0);
2021-02-23 02:36:10.112 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 0 newBufferInfo.presentationTimeUs 15515500
2021-02-23 02:36:10.119 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 10 newBufferInfo.presentationTimeUs 15415400
2021-02-23 02:36:10.178 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 4 newBufferInfo.presentationTimeUs 15582233
2021-02-23 02:36:10.183 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 8 newBufferInfo.presentationTimeUs 15482133
2021-02-23 02:36:10.245 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 14 newBufferInfo.presentationTimeUs 15648966
2021-02-23 02:36:10.252 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 6 newBufferInfo.presentationTimeUs 15548866
2021-02-23 02:36:10.278 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 12 newBufferInfo.presentationTimeUs 15682333
2021-02-23 02:36:10.283 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 3 newBufferInfo.presentationTimeUs 15615600
2021-02-23 02:36:10.345 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 1 newBufferInfo.presentationTimeUs 15749066
2021-02-23 02:36:10.412 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 9 newBufferInfo.presentationTimeUs 15815800
2021-02-23 02:36:10.430 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 2 newBufferInfo.presentationTimeUs 15715700
2021-02-23 02:36:10.478 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 7 newBufferInfo.presentationTimeUs 15882533
2021-02-23 02:36:10.482 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 15 newBufferInfo.presentationTimeUs 15782433
2021-02-23 02:36:10.545 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 5 newBufferInfo.presentationTimeUs 15949266
2021-02-23 02:36:10.550 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 13 newBufferInfo.presentationTimeUs 15849166
2021-02-23 02:36:10.612 5149-5331/org.codeaurora.qmedia2 D/MediaCodecDecoder: outIndex 0 newBufferInfo.presentationTimeUs 16015999

默认情况下,int outIndex = mVideoDecoder.dequeueOutputBuffer(newBufferInfo, 1000); 应该按照我在文档中检查的显示顺序(即时间戳顺序)输出帧,但时间戳不正确。

出于某种原因,即使时间戳乱序,视频播放似乎也很流畅,我完全糊涂了。

【问题讨论】:

  • 如果我做得对,有人可以发表评论吗?
  • 也许你应该从你想要完成的事情开始,我很难理解你正在解决什么问题,什么不起作用。
  • 在通常的解码过程中,播放速度非常快。我想通过使用睡眠来限制它。但是,帧时间戳出现乱序,导致大量帧延迟过多并被丢弃。
  • 我只想限制帧率。
  • OpenGLES 正在使用SurfaceTexture.OnFrameAvailableListener 来检查帧。

标签: java android android-mediacodec


【解决方案1】:

我发现了这个问题。它在dequeueInputBuffer 部分。 我在 if 语句中事先做了mExtractor.advance()

正确的实现如下

int index = mVideoDecoder.dequeueInputBuffer(1000);
if (index >= 0) {
    // fill inputBuffers[inputBufferIndex] with valid data
    ByteBuffer inputBuffer = inputBuffers[index];
    int sampleSize = mExtractor.readSampleData(inputBuffer, 0);

    if (sampleSize >= 0) {
        mVideoDecoder.queueInputBuffer(index, 0, sampleSize,
                mExtractor.getSampleTime(), 0);
    } else {
        Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
        mVideoDecoder.queueInputBuffer(index, 0, 0,
                0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
    }
    mExtractor.advance();
}

【讨论】:

    【解决方案2】:

    我注意到您的代码存在一些问题。

    首先,您不应该自己计算演示时间,因为如果视频有 B 帧,则帧的演示时间可能并不总是按递增顺序排列。导致帧时间戳似乎乱序。

    https://ottverse.com/i-p-b-frames-idr-keyframes-differences-usecases/

    其次,您不应根据将帧传递到解码器的时间来丢弃帧。解码器在输出新帧之前需要经过多个帧,因此解码器可能需要一些时间来解码特定帧。 相反,您应该根据渲染的第一帧来计算它。

    // when passing frame to decoder
    sampleTime = mExtractor.getSampleTime()
    if (firstFrame) {
       firstSampleTime = sampleTime
    }
    mVideoDecoder.queueInputBuffer(index, 0, sampleSize, sampleTime,0);
    
    
    
    
    // when receiving the frame from decoder
    currrent = System.nanoTime()/ 1000
    if (firstFrame) {
       firstFrameReceived = current
    }
    
    receivedDelta =  current - firstFrame
    presentationTimeDelta = mBufferInfo.presentationTimeUs - firstSampleTime
    
    if (receivedDelta - presentatinTimeDelta > 30ms) {
        // Drop frame
    }
    
    

    【讨论】:

    • 至于您的第二个建议,实际效果只是在(receivedDelta - presentatinTimeDelta &gt; 30ms) 中将一些毫秒添加到 30。它可能会减少一些帧的丢失,但不能解决我的乱序问题。
    • 对于您的第一条评论,我已经尝试过mExtractor.getSampleTime()。请检查问题中添加的更多详细信息。
    • 我认为这并不重要,但是,您可以尝试在不添加 startTimeNs/1000 的情况下按原样传递提取器时间,并检查输出时间戳是否正确。据了解,cts 保证它是有序的。 android.googlesource.com/platform/cts/+/5780add/tests/tests/…。 ,顺便说一句,你能告诉我你使用的是什么设备吗?
    • 我做到了。检查更新的问题。你给的cts测试很有趣,我会进一步检查。我可以告诉你,我的设备运行的是 Android 10。
    猜你喜欢
    • 2016-08-31
    • 2016-01-04
    • 2020-05-27
    • 2020-09-23
    • 1970-01-01
    • 2021-11-23
    • 2016-09-06
    • 1970-01-01
    • 2018-10-11
    相关资源
    最近更新 更多