2016-09-17 1 views
2

Ich schreibe ein Programm ein Plugin für ein Programm, das nicht in der Cocoa-Umgebung existiert (denke C++ - Kommandozeilenprogramm sagen wir mal). Wenn es von Interesse ist, ist dies das v8-Knoten-Add-On-System. Ich würde dieses Plugin wie den Bildschirm zu erfassen und somit den Einsatz von AVCaptureSession zu machen, etc. Also im Wesentlichen, so etwas wie:Wenn ich von einer Nicht-Cocoa-App aus in die Foundation eintrete, benötige ich NSRunLoop?

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

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

In Wirklichkeit werde ich wahrscheinlich eine neue pthread beginnen, dieses Zeug zu tun in so dass nichts davon blockiert. Meine Frage ist, wie viel von der umliegenden Foundation-Infrastruktur ich einrichten muss. Ich brauche an Sicherheit grenzender Wahrscheinlichkeit eine @autoreleasepool {}, aber sollte ich meine eigenen Standard NSRunLoop im Thread ausgeführt werden, tatsächlich beginnen, nach oben, wenn ich nicht den Eindruck, dass jede Verschlagenheit in AVCapture usw. fehlschlagen:

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; 
} 

Antwort

0

UPDATE Eigentlich nehme ich es zurück. Es sieht so aus, als müssten Sie den aktuellen Runloop verwenden, um einige Delegat-Callbacks wie AVCaptureFileOutput zu erhalten. Dies erzeugt einen Quicktime-Film auf dem Bildschirm und Mikrofon fein:

#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; 
} 

zuvor

I AVFoundation in der Befehlszeile apps verwendet habe, und ich habe nicht NSRunLoop brauchen. Ich musste

  1. erstellen ein @autoreleasepool (wie Sie sagen)
  2. als AVFoundation ist ziemlich asynchron, eine Semaphore verwenden, um sicherzustellen, dass ich nicht Ausfahrt vor der Verarbeitung beendet hatte.
Verwandte Themen