我有一个GPUImageColorDodgeBlend
过滤器,连接了两个输入:
GPUImageVideoCamera
。GPUImageMovie
,这是一个(MP4)视频文件,我想放在实时相机Feed上。然后GPUImageColorDodgeBlend
连接到两个输出:
GPUImageImageView
,用于提供正在进行的混合的实时预览。GPUImageMovieWriter
将电影写入存储空间。现在,在视频开始录制之前,所有内容都可以正常运行。 GPUImageVideo
在实时摄像机视频中混合使用,并且不会报告任何问题或警告。
然而,当GPUImageMovieWriter
开始录制时,事情随机开始出错。大约80-90%的时间,GPUImageMovieWriter
完美运行,没有错误或警告,输出视频写得正确。
然而,大约10-20%的时间(从我可以看到,这是相当随机的),在录制过程中似乎出现了问题(虽然屏幕预览继续正常工作)。 / p>
具体来说,我开始得到数百&数百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
在100%的时间内接受并在屏幕上显示frameTime
就好了,但GPUImageMovieWriter
要求它们是有序?
......如果是这样,我怎样才能确保进来的frameTime
有效?我尝试添加if (frameTime.value < previousFrameTime.value) return;
以跳过任何较少编号的帧 - 大部分时间都可以。不幸的是,当我在playsAtActualSpeed
上设置GPUImageMovie
时,这种情况的效果远远低于所有,这些帧最终会在某个点之后被跳过。
... 或也许这是一个错误,在这种情况下我需要在GitHub上报告 - 但我有兴趣知道这里是否有我忽略的东西在frameTime
的工作方式。
答案 0 :(得分:3)
我找到了这个问题的潜在解决方案,我现在已经将其作为黑客实施,但可以想象可以扩展到正确的解决方案。
我已经将时序源追溯到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,而方法原样并不能保证。)< / p>
警告:如果您只使用静止图像,这几乎肯定会完全破坏,在这种情况下,您的第一个输入CMTIME_IS_INDEFINITE(frameTime) == YES
会有frameTime
。