1

我在考虑高效解决方案时遇到了一些麻烦。还有我预见了几个问题,第一个是...什么是缓冲MediaProjection的最后X分钟的最有效方法

OOM预防

如果我想在过去的30秒连得5分这是可行的,但如果我想在过去30分钟或整整一个小时,或者一切?保持字节缓冲区意味着将其存储在RAM中。存储超过百兆字节听起来像是虚拟内存自杀。

好的,如果我们在某个tmp文件中存储了以前记录的媒体到磁盘的Y时间量,例如30秒,该怎么办。这可能会工作,我可以使用像mp4解析器库完成时连接它们。然而...

如果我们有30分钟的价值,那就是60个30秒的剪辑。这似乎是一个伟大的方式来烧穿SD卡,即使这不是一个问题,我无法想象需要时间将一百个文件连接成一个。

从我一直在研究什么,我想利用当地的插座做这样的事情的......

MediaRecorder - > setOutputFile(LocalSocket.getFD())

然后在本地套接字...

LocalSocket - > FileOutputStream中 - >写(数据,位置,BUFSIZ) - >刷新()

当后台线程处理文字和位置跟踪和缓冲。

这纯粹是伪代码,我还不够远在还没有测试这一点,我在这个正确的方向前进?从我的想法来看,这只会保留一个被覆盖的文件。由于它每Y秒只写入一次,所以它将IO开销降至最低,并且还减少了它消耗的RAM数量。

视频长度缓冲器大小

我将如何获得规模缓冲器应为请求的视频尺寸。这很奇怪,因为我看到一些很长的视频虽然很小,但视频很短。所以我不知道如何准确地确定这一点。任何人都知道我可以预知,如果我知道视频长度,编码等,这会从媒体录像机设置?

例子

有谁知道任何的例子?我不认为这个想法是完全原创的,但我没有看到它们中的很多,如果它确实是封闭的来源。一个例子很长。

在此先感谢

回答

1

“连续拍摄”活动在Grafika做到这一点,利用MediaCodec而非MediaRecorder。它将最后N秒的视频保存在内存中的循环缓冲区中,并在用户请求时将其写入磁盘。

CircularEncoder constructor估计基于目标位速率的内存需求。以合理的速度(比如4Mbps),你需要1.8GB存储一小时的视频,所以目前的设备不适合RAM。五分钟是150MB,这是推动礼仪的界限。假脱机到磁盘上的文件可能是必要的。

通过套接字传递数据不会为您购买任何您没有从适当的java.util.concurrent数据结构中获得的任何东西。您只需将操作系统置于数据副本中即可。

一种方法是创建一个内存映射文件,并将其与CircularEncoder处理其循环缓冲区的方式相同。在Grafika中,帧数据进入一个单独的大字节缓冲区,元数据(告诉你每个数据包开始和结束的位置等)都位于并行数组中。您可以将帧数据存储在磁盘上,并将元数据保存在内存中。内存映射适用于五分钟的情况,但通常不适用于整个小时的情况,因为获得大的连续虚拟地址范围可能会产生问题。

没有内存映射I/O,这种方法基本上是一样的,但是你必须用文件I/O调用来寻找/读/写。再次,将帧元数据保存在内存中。

如果磁盘I/O暂停,则可能需要额外的缓冲阶段。当通过MediaMuxer编写视频数据时,我看到了周期性的一秒停顿,比MediaCodec缓冲更多,从而导致丢帧。你可以推迟解决,直到你确定你确实有问题。

还有一些额外的细节需要考虑,比如在开始时丢帧以确保视频在同步帧上开始,但您可以看到Grafika如何解决这些问题。

+0

好吧哇,绝对没想到回复如此详细。我现在无法对内容进行明确评论,但我必须感谢您付出的努力。我会稍后阅读并回到您的帖子。 –

+0

只是评论说,我没有忘记这个答案,但是现在我还有其他事情需要首先实施,在我可以开展这个实施之前,我确实有几个基本问​​题:1)我可以吗?大概使用MediaProjection直接与MediaRecorder获得表面?如果是这样,它是一个直接替换? 2)如果我使用JNI/NDK做它,它会产生更好的结果和/或性能吗?我熟悉mmap和C的低级读写,这会有帮助吗?尽管之前我从来没有做过JNI/NDK,但我总是想借口去学习它。 –

+0

(1)MediaCodec和MediaRecorder在询问时提供一个Surface。您将其传递给MediaProjection的'createVirtualDisplay()'调用。对于其中的任何一个,或者SurfaceView都适用。 (2)你在代码中做的计算很少。你的应用只是指挥流量,所以在使用NDK方面没有多大价值。如果Java语言等价物不适合,使用本地I/O可能会有优势,可能允许您避免额外的副本,但我强烈建议在没有NDK的情况下先让它工作。 – fadden

相关问题