我正在尝试修改android 4.4中的screenrecord源代码,并降低捕获的帧速率,但不管我输入了什么值:

format->setFloat("frame-rate", 5);

结果总是一样的(非常高的帧速率)
编码器是否忽略此属性?
如何控制帧速率?

最佳答案

frame-rate值不会被忽略,但它不会做您想要的事情。
frame-ratei-frame-interval的组合确定i帧(也称为“同步帧”)在编码输出中出现的频率。在某些设备上,帧速率值也可能在满足bitrate目标方面发挥作用,但我对此不确定(请参见this post)。
编码器不丢弃帧。如果要降低帧速率,必须通过向其发送较少的帧来实现。
MediaCodec命令不会以固定帧速率“采样”屏幕。相反,它从曲面合成器(surfaceflinger)接收到的每一帧都被发送到编码器,并带有适当的时间戳。如果ScreenRecord每秒接收60帧,则输出每秒60帧。如果它连续快速地接收10帧,然后5秒钟内不接收任何内容,然后再接收几帧,那么您将在输出文件中得到确切的结果。
您可以修改screenrecord以删除帧,但必须小心一点。如果尝试通过每隔一帧删除一次将最大帧速率从60fps降低到30fps,则可能会在“frame0-frame1-long_pause-frame2”序列中删除frame1,而视频将保留frame0,从而显示不完全的动画。所以你需要缓冲一个帧,然后编码或删除帧n-1,如果它和帧n之间的呈现时间差是~17ms。
棘手的是,在默认的操作模式下,screenrecord将帧定向到编码器而不接触它们,所以您所看到的只是编码输出。您不能随意丢弃编码数据的各个帧,因此您确实希望防止编码器首先看到它们。如果使用screenrecord v1.1源,您可以进入用于screenrecord的“覆盖”模式,使帧在到达编码器的路上通过--bugreport
在某些方面,编写降低帧速率的后处理器可能更简单。我不知道解码和重新编码视频会损失多少质量。
更新:对于如何粗略地执行此操作的示例,请将其添加到screenrecord

     int64_t droppedFrames = 0;
+    {
+        static int flipflop = 0;
+        flipflop = 1 - flipflop;
+        if (flipflop) {
+            printf("dropping frame %lld\n", frameNumber);
+            return;
+        }
+    }

     if (mLastFrameNumber > 0) {

注意,这是在获取下一个缓冲区的processFrame_l()之后发生的,并跳过对updateTexImage()的调用,后者将缓冲区提交给视频编码器。

07-27 14:40