我有一个 GPUImageColorDodgeBlend
连接两个输入的过滤器:
- A
GPUImageVideoCamera
它正在从 iPhone 摄像机获取帧。 - A
GPUImageMovie
这是一个 (MP4) 视频文件,我想将其放在实时摄像头画面上。
GPUImageColorDodgeBlend
然后连接到两个输出:
- A
GPUImageImageView
提供混合操作的实时预览。 - 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;
跳过任何有效的较少编号的帧 - 大多数时候。不幸的是,当我设置playsAtActualSpeed
在GPUImageMovie
上这往往会变得不那么有效,因为在某个点之后所有帧最终都会被跳过。
...或者 也许这是一个错误,在这种情况下,我需要在 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/