Android MediaCodec 似乎忽略了指定的 KEY_BIT_RATE 值

Android MediaCodec seems to be ignoring specified KEY_BIT_RATE value

我需要实现H264编码并配置MediaCodec如下

    MediaCodec codec = MediaCodec.createEncoderByType("video/avc");
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", resolution.getWidth(), resolution.getHeight());

    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1000000);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,30);
    codec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

比特率设置为 1000000,这是网络限制定义的要求。当我在 Samsung Galaxy J7 上进行测试时,我看到了预期的 1000 kbps 输出。但是当我在三星 Galaxy Grand 2 Duos (android 4.4) 或华为 Nexus 6P (android 7.1.2) 等特定设备上测试相同的代码时,我发现编码器产生了多达 5 兆字节每秒输出,这意味着编解码器完全忽略指定值每秒 1000000 位。它出什么问题了?有没有办法强制编码器使用这个指定值?

我也 运行 遇到过这个问题,它只发生在一台设备上(Moto E Plus 在 7 上,虽然 Moto E 在 6 上很好,其他设备在 7 上也是如此)以及更多测试显示它使用指定的比特率作为 Kbps 而不是指定的 bps。
不幸的是,我发现唯一 "solution" 检测 android 实现的错误是观察媒体编解码器的输出并在 bitrate/1000 重置它,如果它看起来输出太多数据.

这种行为的真正原因是我在推入帧时传输到编码器的时间戳。在开发阶段为简单起见,我使用 System.nanoTime() 值作为时间戳。此时间戳以纳秒为单位表示时间,而编码器需要微秒作为时间戳。

大多数编解码器实现可能使用它们自己的计时器来测量实际传入的 fps,因此它们不依赖于实际的时间戳值,只是忽略它们。但是 Nexus 6P 可能有一个聪明的编码器,这个编码器使用时间戳来测量 fps 值。时间戳以纳秒为单位给出,从编解码器的角度来看,时间流慢了 1000 倍,测量的 fps 为每 33 秒 1000/30 ~ 1 帧,因此编解码器试图将所有请求的兆位推入单个输出帧。