frame-rate
值不会被忽略,但它并不能做到你想要的效果。
frame-rate
和
i-frame-interval
的组合决定了编码输出中I帧(也称为“同步帧”)出现的频率。帧速率值在某些设备上达到
bitrate
目标可能也会发挥作用,但我不确定(例如参见
此帖)。
MediaCodec
编码器不会丢帧。如果您想降低帧率,必须通过向其发送更少的帧来实现。
screenrecord
命令不会以固定的帧速率对屏幕进行“采样”。相反,它从表面合成器(SurfaceFlinger)接收的每一帧都会发送到编码器,并有适当的时间戳。如果screenrecord接收到60帧/秒,则将输出60fps。如果它连续接收10帧,然后5秒钟没有任何内容,然后再来几个,那么输出文件中就会有这样的内容。
您可以修改
screenrecord
以删除帧,但必须小心。如果您尝试将最大帧速率从60fps降低到30fps,通过跳过每个其他帧来实现,那么在“frame0-frame1-long_pause-frame2”序列中,您会跳过frame1,视频将停留在frame0上,显示不完整的动画。因此,您需要缓冲一帧,如果frame N-1和frame N之间的呈现时间差大约为17ms,则编码或删除frame N-1。
棘手的部分是
screenrecord
在其默认操作模式下,直接将帧传输到编码器,所以你只能看到经过编码后的输出。你不能任意丢弃单个帧的编码数据,所以你真正想要的是让编码器在第一时间就不要看到它们。如果使用
screenrecord v1.1源代码,可以利用“overlay”模式(用于
--bugreport
),让帧在传输到编码器之前通过
screenrecord
。
在某些方面,编写一个后处理程序以降低帧率可能会更简单。我不知道通过解码和重新编码视频会失去多少质量。
更新:要进行粗略操作的示例,请将以下内容添加到
processFrame_l()
:
int64_t droppedFrames = 0;
+ {
+ static int flipflop = 0;
+ flipflop = 1 - flipflop;
+ if (flipflop) {
+ printf("dropping frame %lld\n", frameNumber);
+ return;
+ }
+ }
if (mLastFrameNumber > 0) {
请注意,此操作发生在updateTexImage()
之后,该操作获取下一个缓冲区,并跳过对swapBuffers()
的调用,这将提交缓冲区给视频编码器。
Note this comes after
updateTexImage()
, which acquires the next buffer, and skips the call to
swapBuffers()
, which submits the buffer to the video encoder.