2016-09-17 9 views
2

私は、Cocoa環境に存在しないプログラムのプラグインを作成しています(C++のコマンドラインプログラムと思われます)。関心があるなら、これはv8ノードアドオンシステムです。私は、画面を記録するには、このプラグインを好きなので、だから、基本的にAVCaptureSessionなどを利用して、のようなものだろう:実際には非ココアアプリからFoundationにコールするとき、NSRunLoopが必要ですか?

void start(/*entry*/) 
{ 
    // No run loop is *necessarily* present. 
    AVCaptureSession * session = ... 
} 

void stop (/*entry*/) 
{ 
    // etc.. 
} 

、私はおそらくそうではこのようなものを行うには、新しいpthreadのを開始しますそれがブロックされていないこと私の質問は、周辺の基盤インフラの整備がどれだけ必要かということです。私は印象を取得しない場合AVCapture中などあらゆるtrickinessが失敗する可能性があること、私はほぼ確実@autoreleasepool {}を必要とするが、私は実際にスレッドで実行するために私自身のデフォルトNSRunLoopを起動する必要があります。

BOOL isStillRecording = YES; 
void start(/*entry*/) 
{ 
    // setup avcapture and what have you. 
    NSRunLoop *theRL = [NSRunLoop new]; 
    while (isStillRecording && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 
} 

void stop(/**entry**/) 
{ 
    // kill avcapture, maybe through async_dispatch to not stop on the start up. 
    isStillRecording = NO; 
} 

答えて

0

更新 実際、私はそれを取り戻します。 AVCaptureFileOutputのようなデリゲートコールバックを取得するには、現在のrunloopを使用する必要があるようです。これは、細かい画面とマイクのQuickTimeムービーを作成します。

#import <AVFoundation/AVFoundation.h> 

@interface Capturer() <AVCaptureFileOutputRecordingDelegate> 

@property(nonatomic) AVCaptureSession *session; 
@property(nonatomic) AVCaptureMovieFileOutput *movieOutput; 
@property(nonatomic, copy) void(^finishBlock)(NSError*); 

@end 

@implementation Capturer 
- (instancetype)init 
{ 
    self = [super init]; 
    if (self) { 
     [self setup]; 
    } 
    return self; 
} 

- (void)setup { 
    self.session = [[AVCaptureSession alloc] init]; 

    // capture the screen 
    CGDirectDisplayID displayId = CGMainDisplayID(); 
    AVCaptureScreenInput *screenInput = [[AVCaptureScreenInput alloc] initWithDisplayID:displayId]; 

    [self.session addInput:screenInput]; 

    // capture microphone input 
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; 
    [self.session addInput:audioInput]; 

    self.movieOutput = [[AVCaptureMovieFileOutput alloc] init]; 

    [self.session addOutput:self.movieOutput]; 
} 

- (void)start { 
    [self.session startRunning]; 
    NSURL *movieURL = [[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] URLByAppendingPathComponent:@"output.mov"]; 
    [[NSFileManager defaultManager] removeItemAtURL:movieURL error:nil]; 
    NSLog(@"recording to %@", movieURL.path); 
    [self.movieOutput startRecordingToOutputFileURL:movieURL recordingDelegate:self]; 
} 

- (void)stop:(void (^)(NSError *))finishBlock { 
    self.finishBlock = finishBlock; 
    [self.movieOutput stopRecording]; 
} 

// MARK: AVCaptureFileOutputRecordingDelegate 
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { 
    NSLog(@"Finished recording to %@ with error %@", outputFileURL.path, error); 
    [self.session stopRunning]; 
    self.finishBlock(error); 
} 

@end 


int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     Capturer *c = [[Capturer alloc] init]; 
     NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 

     [c start]; 

     // record 10s' worth 
     __block BOOL finished = NO; 
     [c performSelector:@selector(stop:) withObject:^(NSError *error) { 
      finished = YES; 
     } afterDelay:10]; 

     // cribbed from https://gist.github.com/syzdek/3220789 
     while(!finished && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:2]]) NSLog(@"waiting"); 

    } 
    return 0; 
} 

以前

私は、コマンドラインのアプリでAVFoundationを使用していると私はNSRunLoopを必要としませんでした。私が作成

  1. に必要な@autoreleasepool(あなたが言うように)AVFoundationとして
  2. は非常に非同期で、処理が終了していた前に私が終了しなかったことを確認するためにセマフォを使用します。
関連する問題