5

2つの入力が接続されたGPUImageColorDodgeBlendフィルターがあります。

  1. GPUImageVideoCameraiPhoneビデオカメラからフレームを取得しているA。
  2. GPUImageMovieライブカメラフィードに重ねたい(MP4)ビデオファイルです。

次に、GPUImageColorDodgeBlendは2つの出力に接続されます。

  1. GPUImageImageView動作中のブレンドのライブプレビューを提供するためのA。
  2. GPUImageMovieWriter録画ボタンが押されたときにムービーをストレージに書き込むためのA。

これで、ビデオの録画が開始される前に、すべてが100%正常に機能します。はGPUImageVideoライブカメラビデオにうまくブレンドされており、問題や警告は報告されていません。

ただし、GPUImageMovieWriter録音を開始すると、ランダムに問題が発生し始めます。約80〜90%の時間、GPUImageMovieWriter完全に機能し、エラーや警告はなく、出力ビデオは正しく書き込まれます。

ただし、約10〜20%の時間(そして私が見る限り、これはかなりランダムです)、記録プロセス中に問題が発生しているように見えます(画面上のプレビューは引き続き正常に機能します)。

具体的には、何百ものProgram appending pixel buffer at time:エラーが発生し始めます。

このエラーは、の- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndexメソッドが原因で発生しGPUImageWriterます。

frameTimeこの問題は、このメソッドに報告される値の問題によって引き起こされます。

私が見ることができることから、問題は、ビデオカメラによって番号が付けられたフレームをライターが時々受信することによって引き起こされます( 1000000000のタイムスケールで64616612394291のような非常に高い時間値を持つ傾向があります)。ただし、ライターは、によって番号が付けられたフレームを取得することがあります。フレームの番号ははるかに低くなります(タイムスケールが30000の200200など)。GPUImageMovie

GPUImageWriterフレーム値が増加している限りは問題ないようですが、フレーム値が減少すると、書き込みが停止し、Program appending pixel buffer at time:エラーが発生します。

私はかなり一般的なことをしているようですが、これはバグとしてどこにも報告されていないので、私の質問は次のとおりです(これらのいずれかまたはすべてへの回答はありがたいです-必ずしもすべてが別々に順番に回答される必要はありません質問):

  • 値はどこから来るのですか?ソースまたはソースに従って番号が付けられているframeTimeかどうかが、なぜそれほど恣意的に見えるのですか?なぜそれがそれぞれの間で交互になるのですか?フレーム番号付けスキームはすべてのフレームにわたって均一であるべきではありませんか?frameTimeGPUImageVideoCameraGPUImageMovie

  • この問題はsが増加しないことが原因であると考えるのは正しいframeTimeですか?

  • ...もしそうなら、なぜ100%の時間、画面上で問題なくsGPUImageViewを受け入れて表示するのに、注文する必要があるのでしょうか。frameTimeGPUImageMovieWriter

  • ...もしそうなら、どうすればframeTime入ってくるが有効であることを確認できますか?if (frameTime.value < previousFrameTime.value) return;ほとんどの場合、機能する数の少ないフレームをスキップするように追加してみました。残念ながら、これを設定すると、特定のポイントの後にすべてのフレームがスキップされるためplaysAtActualSpeedGPUImageMovieこれははるかに効果が低くなる傾向があります。

...またはおそらくこれはバグです。その場合はGitHubで報告する必要がありますが、ここで見落としていることがあるかどうかを知りたいと思いますframeTime

4

1 に答える 1

3

私はこの問題の潜在的な解決策を見つけました。これは今のところハックとして実装していますが、おそらく適切な解決策に拡張することができます。

GPUImageTwoInputFilter2つの入力ソースをフレームの単一の出力に本質的に多重化するタイミングのソースをトレースしました。

この方法- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndexでは、フィルターは最初のソース()と2番目のソースからフレームを収集するまで待機してから、textureInput == 0これらのフレームをターゲットに転送します。

問題(私が見ているように)は、この方法では、2番目に来るフレームのいずれかを単純に使用することです(静止画像を使用していないため、今は検討していない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入力からのを使用し、2番目の入力からのを完全に無視するようにします。これまでのところ、すべてこのように正常に機能しています。(これがこのように書かれている理由を誰かが私に知らせてくれることにまだ興味があります。それはsを増やすことを主張しているようですが、この方法はそのままでは保証されません。)frameTimeGPUImageMovieWriterframeTime

警告:静止画像のみを操作する場合、これはほぼ確実に完全に機能しなくなります。その場合CMTIME_IS_INDEFINITE(frameTime) == YES、最初の入力はになりますframeTime

于 2013-01-06T21:11:55.477 に答える