3

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

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

テスト アプリには UI コントロールがあり、ほぼすべてのグラフィックを担当します。C++ ライブラリは、フレームを OpenGL 経由で UIView にレンダリングします。

私と一緒にいますか?良い


さて、まず、ユーザーは私のライブラリを呼び出す 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 がブロックされているようです。

次に、同じことを試しましたが、Grand Central Dispatch を使用しました。

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

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

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

これは理にかなっていますか?

4

2 に答える 2

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];
}
于 2011-12-23T00:35:09.157 に答える
0

このサンプル コードは、GCD Serial Queue で AVCaptureVideoDataOutput -setSampleBufferDelegate:queue: のみを使用します。AVCaptureSession は RunLoop で使用する必要があるようです。スレッドで独自の RunLoop を実行するか、このサンプル コードのように C++ ライブラリを変更してみてください。

于 2011-03-02T00:34:29.693 に答える