5

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

  1. AGPUImageVideoCamera从 iPhone 摄像机获取帧。
  2. AGPUImageMovie这是一个 (MP4) 视频文件,我想放在实时摄像机源上。

然后将GPUImageColorDodgeBlend其连接到两个输出:

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

现在,在视频开始录制之前,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似乎如此随意?为什么它在每个之间交替 - 帧编号方案不应该在所有帧之间保持一致?frameTimeGPUImageVideoCameraGPUImageMovie

  • 我认为这个问题是由不增加frameTime的 s 引起的是否正确?

  • ...如果是这样,为什么100% 的时间在屏幕上GPUImageView接受和显示frameTimes 就好了,但GPUImageMovieWriter需要订购它们?

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

...或者这可能是一个错误,在这种情况下,我需要在 GitHub 上报告它——但我很想知道在frameTimes 的工作方式中是否有一些我在这里忽略的东西。

4

1 回答 1

3

我已经找到了一个解决这个问题的潜在解决方案,我现在已经将它作为一个 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似乎坚持增加frameTimes,而方法原样不能保证。)

警告:如果您只使用静止图像,这几乎肯定会完全中断,在这种情况下,您将有CMTIME_IS_INDEFINITE(frameTime) == YES第一次输入的frameTime.

于 2013-01-06T21:11:55.477 回答