问题描述
我想在Android 4.4系统修改源screenrecord,降低拍摄帧速率,但无论我把什么值:
I am trying to modify the source for screenrecord in android 4.4 and lower the captured frame rate, but no matter what value I put in:
format->setFloat("frame-rate", 5);
的结果总是相同的(一个非常高的帧速率)
the result is always the same ( a very high frame rate )
时的EN codeR忽略这个属性?我怎么能控制帧速率?
Is the encoder ignoring this property ?how can I control the frame rate ?
推荐答案
在帧速率
价值也是不能忽视的,但它不会做你想要的。
The frame-rate
value is not ignored, but it doesn't do what you want.
的组合帧速率
和 I帧间隔
决定了我经常帧(也称为同步帧)出现在连接codeD输出。帧速率值也可能在满足码率
目标在某些设备上起到一定的作用,但我不知道这一点(如见<一href="http://stackoverflow.com/questions/20661391/inconsistent-video-quality-when-encoding-camera-$p$pview-frames-with-media$c$cc-o">this帖子)。
The combination of frame-rate
and i-frame-interval
determines how often I-frames (also called "sync frames") appear in the encoded output. The frame rate value might also play a role in meeting the bitrate
target on some devices, but I'm not sure about that (see e.g. this post).
在媒体codeC
连接coder不丢帧。如果你想减少帧速率,则必须通过发送更少的帧来它这样做。
The MediaCodec
encoder does not drop frames. If you want to reduce the frame rate, you have to do so by sending fewer frames to it.
在 screenrecord
命令没有样本屏幕以固定帧速率。相反,每次它接收从表面合成器帧(SurfaceFlinger)被发送到连接codeR,用适当的时间标记。如果screenrecord接收每秒60帧,你就会有60fps的输出。如果它收到临门,后面什么都没有5秒10帧,然后是一对夫妇多了,你就会有确切的输出文件。
The screenrecord
command doesn't "sample" the screen at a fixed frame rate. Instead, every frame it receives from the surface compositor (SurfaceFlinger) is sent to the encoder, with an appropriate time stamp. If screenrecord receives 60 frames per seconds, you'll have 60fps output. If it receives 10 frames in quick succession, followed by nothing for 5 seconds, followed by a couple more, you'll have exactly that in the output file.
您可以修改 screenrecord
丢帧,但你必须要小心一点。如果您尝试通过删除每隔一个框架,以降低最大帧速率自60fps 30fps的,你跑,在一个风险frame0 - 帧1 - long_pause - 帧2的序列,你会下降帧1,视频将举行frame0相反,呈现出没有非常完整的动画。所以,你需要缓冲了一个框架,然后连接code或丢弃帧N-1,如果在与帧N之间presentation倍的差别是〜17MS。
You can modify screenrecord
to drop frames, but you have to be a bit careful. If you try to reduce the maximum frame rate from 60fps to 30fps by dropping every-other frame, you run the risk that in a "frame0 - frame1 - long_pause - frame2" sequence you'll drop frame1, and the video will hold on frame0 instead, showing a not-quite-complete animation. So you need to buffer up a frame, and then encode or drop frame N-1 if the difference in presentation times between that and frame N is ~17ms.
最棘手的部分是, screenrecord
在其默认的工作模式,引导帧的EN codeR而不触及,所以你看到的是EN codeD输出。你不能随意丢弃的单个帧恩codeD数据,让您真正看到他们首先要prevent的EN codeR。如果您使用 screenrecord V1.1 来源,您可以挖掘到叠加模式,用于 - 错误报告
,有框架的道路上的EN codeR
The tricky part is that screenrecord
, in its default operating mode, directs the frames to the encoder without touching them, so all you see is the encoded output. You can't arbitrarily drop individual frames of encoded data, so you really want to prevent the encoder from seeing them in the first place. If you use the screenrecord v1.1 sources you can tap into "overlay" mode, used for --bugreport
, to have the frames pass through screenrecord
on their way to the encoder.
在某些方面可能是更简单的写一个后处理程序,将降低帧速率。我不知道有多少的质量将通过解码和再编码的视频丢失。
In some respects it might be simpler to write a post-processor that reduces the frame rate. I don't know how much quality would be lost by decoding and re-encoding the video.
更新:对于如何粗暴地做到这一点的一个例子,它添加到 processFrame_l()
:
Update: for an example of how to do it crudely, add this to 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()
,它提交了缓冲的视频连接codeR。
Note this comes after updateTexImage()
, which acquires the next buffer, and skips the call to swapBuffers()
, which submits the buffer to the video encoder.
这篇关于媒体codeC KEY_FRAME_RATE似乎被忽略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!