3

私は、captureOutputコールバックを介して配信されるビデオフレームをキャプチャするためにAVCaptureSessionを使用するiOS用のC++ライブラリを作成しています(残念ながら、残念ながらC++でなければなりません)。 C++ライブラリは私の成果物です。私はそれをテスト/デモするためのココアタッチアプリケーションがあります。だから、それは次のようになります。NSRunLoopとGCDのキュー

(テスト用アプリ)< ----->(C++のlib(AVFoundationのコールバック))

テストアプリはUIコントロールを持っており、ほとんどすべてのグラフィックを担当しています。 C++ライブラリは、OpenGLを使用してフレームをUIViewにレンダリングします。

あなたは私と一緒にいますか? Good


まず、ユーザーがUIButtonを押して自分のライブラリを呼び出します。この呼び出しには10秒以上かかります。したがって、ボタンをクリックした直後に呼び出しを行うと、ライブラリ関数が返されるまでUIはブロックされます。

-(IBAction)hBut:(id)sender{ 
    [myLib foo]; // takes 10+ seconds to return 
} 

これは良くありません。私が試した次のことは、LIBを呼び出すスレッド産卵しました:

-(void)callIntoLib{ 
    [myLib foo]; 
} 

-(IBAction)hBut:(id)sender{ 
    [NSThread detach..:myLib selector:foo object:nil]; 
} 

これはもはやブロックUIを、今のビデオフレームのコールバック関数は、(AVCaptureSessionのcaptureOutput)を発射することはありません。メインのNSRunLoopがブロックされているようです。

次の私は、しかし、グランドセントラル派遣して、同じことを試してみました:

-(IBAction)hBut:(id)sender{ 
    _myQueue = dispatch_queue_create("com.domain.me", NULL); // member variable 
    dispatch_async(_myQueue, 
    ^{ 
      [myLib foo]; 
    }); 
} 

これは、同じ動作を持っています。つまり、ビデオフレームのコールバックは発生しません。ラメ

2番目と3番目のケースでメインのNSRunLoopがブロックされるのはなぜですか?キューをキューに関連付ける方法はありますか?

これは意味がありますか?

答えて

0

このサンプルコードはのみAV​​CaptureVideoDataOutput -setSampleBufferDelegate使用しています:キュー:GCDシリアルキューに。 AVCaptureSessionはRunLoopで使用する必要があります。スレッド上で独自のRunLoopを実行するか、このサンプルコードとしてC++ライブラリを修正する必要があります。

+1

このli kは現在壊れています(アップルの悪賢いウェブマスターがURLを破棄しています)。新しいバージョンはhttps://developer.apple.com/library/ios/qa/qa1702/_index.html – Adam

+0

スレッドが独自のrunloopを持っていても、 'AVCaptureSession'はメインrunloop(' CFRunLoopGetMain')。私は[NSThreadを生成する](https://github.com/dashesy/pyavfcam/blob/develop/src/modules/avf_impl.m)を実行し、その中のすべてを実行しますが、コールバックはメインrunloopからのみ取得され、メインrunloopがブロックしている場合は、コールバックは受信されません。メインループですべてをやっても問題ないですが、新しいスレッドが好きではありません。私はOSXではなくOSXについて話しています。 – dashesy

2

メインスレッドはrunLoopを単独で実行するため、カメラのイベントは最初のケースでライブラリに配信されました。カスタムスレッドはrunLoopを実行しないので、自分で実行する必要があります。

-(void)callIntoLib { 
    [myLib foo]; 
    self.callIntoLibExecuted = YES; 
} 


-(void)threadBody { 
    @autoreleasepool { 
     self.callIntoLibExecuted = NO; 

     [self performSelector:@selector(callIntoLib) 
       onThread:[NSThread currentThread] 
       withObject:nil 
       waitUntilDone:NO]; 

     while (!self.callIntoLibExecuted) 
     { 
      @autoreleasepool { 
       [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
         beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 
      } 
     } 
    } 
} 

-(IBAction)hBut:(id)sender { 
    [NSThread detachNewThreadSelector:@selector(threadBody) 
       toTarget:self withObject:nil]; 
} 
+0

これは試しましたか?私はカスタムスレッドを持っています(https://github.com/dashesy/pyavfcam/blob/develop/src/modules/avf_impl。m)、それでもAVFoundationはメイン実行ループを通って来る。メイン実行ループがブロックされている場合、OSXはiOSではないと言います。 – dashesy

+0

私はAVFoundationがiOSからOSX上で異なって動作すると考えていますが、この回答はiOSの質問に提供されました。 AVCaptureMovieFileOutputの代わりにAVCaptureVideoDataOutputを使用する場合は、指定したディスパッチキューのコールバックをキャッチできます。それを試してください。多分あなたのメインスレッドはキャプチャ中に使用されません。 – DisableR