iphone - GPUImageMovieWriter 帧 presentationTime

标签 iphone objective-c ios opengl-es gpuimage

我有一个 GPUImageColorDodgeBlend连接两个输入的过滤器:

  1. A GPUImageVideoCamera它正在从 iPhone 摄像机获取帧。
  2. A GPUImageMovie这是一个 (MP4) 视频文件,我想将其放在实时摄像头画面上。

GPUImageColorDodgeBlend然后连接到两个输出:

  1. A GPUImageImageView提供混合操作的实时预览。
  2. A GPUImageMovieWriter按下录制按钮后将电影写入存储。

现在,在开始录制视频之前,一切正常 100%。 GPUImageVideo很好地混合了实时摄像机视频,没有报告任何问题或警告。

但是,当 GPUImageMovieWriter开始录音,事情开始随机出错。大约 80-90% 的时间,GPUImageMovieWriter完美运行,没有错误或警告,输出视频写入正确。

然而,大约 10-20% 的时间(据我所知,这是相当随机的),在录制过程中似乎出现了问题(尽管屏幕预览继续正常工作)。

具体来说,我开始收到成百上千的 Program appending pixel buffer at time:错误。

此错误源自 - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex GPUImageWriter 中的方法.

此问题是由 frameTime 的问题触发的报告给此方法的值。

据我所知,问题是由于作者有时会收到摄像机编号的帧(这些帧往往具有极高的时间值,如 64616612394291,时间刻度为 1000000000 )。但是,有时作者会得到编号为 GPUImageMovie 的帧。编号要低得多(例如 200200,时间标度为 30000)。

似乎GPUImageWriter只要帧值增加就很高兴,但是一旦帧值减少,它就会停止写入并只发出 Program appending pixel buffer at time:错误。

我似乎在做一些相当普遍的事情,而且这在任何地方都没有作为错误报告,所以我的问题是(对任何或所有这些问题的回答表示赞赏——他们并不都需要必须作为单独的问题依次回答):

  • frameTime 在哪里值来自——为什么 frameTime 看起来如此随意?根据 GPUImageVideoCamera 编号来源或 GPUImageMovie资源?为什么它在每个帧之间交替 - 帧编号方案不应该在所有帧中统一吗?

  • 我认为这个问题是由不增加的 frameTime 引起的吗?是吗?

  • ...如果是这样,为什么 GPUImageView接受并显示 frameTime 100% 的时间在屏幕上都很好,但是 GPUImageMovieWriter需要订购吗?

  • ...如果是这样,我如何确保 frameTime进来的是有效的吗?我尝试添加 if (frameTime.value < previousFrameTime.value) return;跳过任何有效的较少编号的帧 - 大多数时候。不幸的是,当我设置 playsAtActualSpeedGPUImageMovie 上这往往会变得不那么有效,因为在某个点之后所有帧最终都会被跳过。

...或者 也许这是一个错误,在这种情况下,我需要在 GitHub 上报告它——但我很想知道这里是否有我忽略的地方在如何frameTime工作。

最佳答案

我已经找到了这个问题的潜在解决方案,目前我已将其作为 hack 实现,但可以想象可以扩展为适当的解决方案。

我已经将时间的来源追溯到 GPUImageTwoInputFilter它实质上将两个输入源多路复用为单个帧输出。

在方法中- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex , 过滤器一直等到它从第一个源 ( textureInput == 0 ) 和第二个源收集到帧,然后将这些帧转发到它的目标。

问题(我的看法)是该方法仅使用 frameTime无论哪个帧排在第二位(不包括静止图像的情况 CMTIME_IS_INDEFINTE(frameTime) == YES 我现在不考虑因为我不使用静止图像)可能并不总是相同的帧(无论出于何种原因)。

检查两个帧并发送它们进行处理的相关代码如下:

  if ((hasReceivedFirstFrame && hasReceivedSecondFrame) || updatedMovieFrameOppositeStillImage)
    {
        [super newFrameReadyAtTime:frameTime atIndex:0]; // this line has the problem
        hasReceivedFirstFrame = NO;
        hasReceivedSecondFrame = NO;
    }

我所做的是将上面的代码调整为 [super newFrameReadyAtTime:firstFrameTime atIndex:0]这样它总是使用frameTime来自第一个 输入并完全忽略 frameTime从第二个输入。到目前为止,一切都像这样正常工作。 (考虑到 GPUImageMovieWriter 似乎坚持增加 frameTime s,按原样的方法不能保证这一点,有人仍然会让我知道为什么这样写。)

警告:如果你只处理静止图像,这几乎肯定会完全崩溃,在这种情况下你将得到 CMTIME_IS_INDEFINITE(frameTime) == YES对于您的第一个输入 frameTime .

关于iphone - GPUImageMovieWriter 帧 presentationTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14184731/

相关文章:

iphone - NSPredicate 检查数组中的所有项目

iphone - ios didselectrowatindexpath 在编辑模式下不调用

iphone - 如何创建带有字符串文字的 NSArray?

c++ - 在 OSX 上使用 C++ 的蓝牙 LE(扫描)?

c# - 如何创建一个项目来为支持 iOS、Android 和 UWP 的 Xamarin Forms 创建 Nuget 包?

iphone - NSMutableArrays 没有将它们的对象保存在共享实例中

iphone - 弃用的 TransactionReceipt

objective-c - 如何检测是否可以在沙盒应用程序上访问 NSURL?

ios - CCButton 不调用方法

ios - Sprite Kit 中的弹跳标签