简体   繁体   English

如何在Android MediaCodec中设置演示文稿时间戳?

[英]How to set presentation timestamp in Android MediaCodec?

I am rendering an h.264 video on Android using the MediaCodec (and SurfaceView). 我使用MediaCodec(和SurfaceView)在Android上渲染h.264视频。 Here are some of my codes. 这是我的一些代码。

@Override
public void surfaceCreated(SurfaceHolder holder) {

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (videoPlayer == null) {
        videoPlayer = new PlayerThread(holder.getSurface());
        videoPlayer.start();
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (videoPlayer != null) {
        videoPlayer.interrupt();
        videoPlayer.isEOS = true;
        videoPlayer = null;
    }
}

private class PlayerThread extends Thread {
    private MediaCodec decoder;
    private Surface surface;
    private final static String mimeType = "video/avc";
    public boolean isEOS = false;

    public PlayerThread(Surface surface) {
        this.surface = surface;
    }

    @Override
    public void run() {
        MediaFormat format = MediaFormat.createVideoFormat(mimeType, frame.width, frame.height);
        decoder = MediaCodec.createDecoderByType(mimeType);
        decoder.configure(format, surface, null, 0);
        decoder.start();

        ByteBuffer[] inputBuffers = decoder.getInputBuffers();
        ByteBuffer[] outputBuffers = decoder.getOutputBuffers();

        int startPTS = 0;
        while (!Thread.interrupted() && !isEOS) {
            frame = frameReader.nextFrame();
            if (startPTS == 0) {
                startPTS = frame.pts;
            }
            int relativePTS = frame.pts - startPTS;
            int inIndex = decoder.dequeueInputBuffer(-1);
            if (inIndex >= 0)
            {
                ByteBuffer inputBuffer = inputBuffers[inIndex];
                inputBuffer.clear();
                inputBuffer.put(frame.buf, 0, frame.size);

                decoder.queueInputBuffer(inIndex, 0, frame.size, relativePTS*1000, 0);
            }

            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();

            int outIndex = decoder.dequeueOutputBuffer(info, -1);

            switch (outIndex) {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
                    outputBuffers = decoder.getOutputBuffers();
                    break;
                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
                    break;
                case MediaCodec.INFO_TRY_AGAIN_LATER:
                    Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
                    break;
                default:
                    ByteBuffer outputBuffer = outputBuffers[outIndex];
                    Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + outputBuffer);

                    decoder.releaseOutputBuffer(outIndex, true);
            }
        }

        /* clean */
        decoder.stop();
        decoder.release();
        decoder = null;
    }
}

I set the PTS, but it's not working. 我设置了PTS,但它不起作用。 The video playback very fast. 视频播放速度非常快。

Anyone know how to set the correct presentation timestamp in this situation? 在这种情况下,任何人都知道如何设置正确的演示文稿时间戳? Any help would be greatly appreciated. 任何帮助将不胜感激。

When decoding video with MediaCodec, you are not the one setting the PTS, you are the one receiving the PTS. 使用MediaCodec解码视频时,您不是设置 PTS的人,而是接收 PTS的人。 When you call releaseOutputBuffer() with the "render" flag set, you are telling the system to render the frame as soon as possible. 当你设置“render”标志调用releaseOutputBuffer()时,你告诉系统尽快渲染帧。 It's your responsibility to pace the frames. 你有责任控制框架。

For an example of a MediaCodec-based video player that controls the playback rate, see Grafika , in particular the use of the SpeedControlCallback class. 有关控制播放速率的基于MediaCodec的视频播放器的示例,请参阅Grafika ,特别是使用SpeedControlCallback类。

In your example, you should consider employing info.mPresentationTimeUs which is received as part of decoder.dequeueOutputBuffer(info, -1); 在您的示例中,您应该考虑使用info.mPresentationTimeUs作为decoder.dequeueOutputBuffer(info, -1);一部分接收decoder.dequeueOutputBuffer(info, -1); . Once the output frame is received, you should perform the AV Sync with a reference clock which could be audio clock or system clock. 收到输出帧后,您应该使用参考时钟执行AV Sync ,参考时钟可以是audio时钟或system时钟。

Please refer to this link for a good reference as an example. 请参考此链接以获取一个很好的参考作为示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM