为什么从 MediaCodec 获取 KEY_FRAME_RATE 时总是出现 NullPointerException?

Why always got NullPointerException while getting KEY_FRAME_RATE from MediaCodec?

我想从 MediaCodec 中检索 frameRate,但我总是得到 NullPointerException。代码如下:

    public void handleWriteSampleData(MediaCodec encoder, int trackIndex, int bufferIndex, ByteBuffer encodedData, MediaCodec.BufferInfo bufferInfo) {
        super.writeSampleData(encoder, trackIndex, bufferIndex, encodedData, bufferInfo);
        int rc = -1;

        if (((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)) {
            if (VERBOSE) Log.i(TAG, "handling BUFFER_FLAG_CODEC_CONFIG for track " + trackIndex);
            if (trackIndex == VIDEO_TRACK_INDEX) {
                // Capture H.264 SPS + PPS Data
                Log.d(TAG, "Capture SPS + PPS");

                captureH264MetaData(encodedData, bufferInfo);
                mFFmpeg.setVideoCodecExtraData(videoConfig, videoConfig.length);
                fps = encoder.getOutputFormat().getInteger(MediaFormat.KEY_FRAME_RATE);
                Log.i(TAG, "fps:" + fps);
            }
            ....

异常如下:

E/AndroidRuntime( 1419): java.lang.NullPointerException
E/AndroidRuntime( 1419):    at android.media.MediaFormat.getInteger(MediaFormat.java:282)

我已经完成了 source code:

/**
 * Returns the value of an integer key.
 */
public final int getInteger(String name) {
    return ((Integer)mMap.get(name)).intValue();
}

如何从 MediaCodec 获得正确的 fps 值?

如果要从编解码器读取 MediaFormat,则需要等待 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED 标志。

int bufferIndex = mMediaCodec.dequeueOutputBuffer(this.mBufferInfo, QUEUEING_TIMEOUT);
if (bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
    MediaFormat mMediaFormat = mMediaCodec.getOutputFormat();
}

无法从 MediaCodec 获得该信息,因为时间信息不一定存在于 H.264 中(参见 this link)。 KEY_FRAME_RATE 是编码器的参数。

标称帧速率值可能存在于 MediaExtractor 处理的包装器(例如 .mp4)中,但我不知道是否有一致的方法来访问它。

您可以深入了解 SPS,或通过查看一系列帧上的呈现时间戳来计算 fps 值。如果视频使用可变帧速率,例如 "screenrecord" 输出,那么您可能会从中得到不正确的数字......但我认为,对于 VFR 视频,帧速率没有正确的数字,只有最大值和平均值。