2016-08-09 22 views
1

Mein Ziel ist es, den Bildschirm eines iDevice zu OSX so verzögerungsfrei wie möglich zu spiegeln.Kann VideoToolbox H264 Anhang B nativ dekodieren? Fehlercode -8969 BadData

Meines Wissens gibt es zwei Möglichkeiten, um dies:

  1. Airplay Mirroring (zB Reflektor)
  2. CoreMediaIO über Lightning (zB Quicktime Recording)

Ich habe gewählt, um das zweite Verfahren zu verfolgen , weil (nach meinem Wissen) angeschlossene iDevices nach einmaliger Einrichtung automatisch als DAL-Geräte erkannt werden können.

Die wichtigste Ressource, wie dies zu tun, ist dieser Blog: https://nadavrub.wordpress.com/2015/07/06/macos-media-capture-using-coremediaio/

Das Blog sehr tief in geht, wie CoreMediaIO zu verwenden, jedoch scheint es, wie Sie mit AVFoundation arbeiten können, wenn Sie das angeschlossene iDevice als erkannt haben AVCaptureDevice.

Diese Frage: How to mirror iOS screen via USB? hat eine Lösung zur Verfügung gestellt, wie man jeden Rahmen des H264 (Anhang B) muxxed Datenstroms, der vom iDevice geliefert wird, ergreift.

Mein Problem ist jedoch, dass VideoToolbox wird nicht korrekt dekodieren (Fehlercode -8969, BadData), obwohl es keinen Unterschied im Code sein sollte.

vtDecompressionDuctDecodeSingleFrame signalisiert err = -8.969 (err) (VTVideoDecoderDecodeFrame Fehler zurückgegeben) bei /SourceCache/CoreMedia_frameworks/CoreMedia-1562.240/Sources/VideoToolbox/VTDecompressionSession.c Linie 3241

komplette Code:

#import "ViewController.h" 

@import CoreMediaIO; 
@import AVFoundation; 
@import AppKit; 

@implementation ViewController 

AVCaptureSession *session; 
AVCaptureDeviceInput *newVideoDeviceInput; 
AVCaptureVideoDataOutput *videoDataOutput; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
} 

- (instancetype)initWithCoder:(NSCoder *)coder 
{ 
    self = [super initWithCoder:coder]; 
    if (self) { 
     // Allow iOS Devices Discovery 
     CMIOObjectPropertyAddress prop = 
     { kCMIOHardwarePropertyAllowScreenCaptureDevices, 
      kCMIOObjectPropertyScopeGlobal, 
      kCMIOObjectPropertyElementMaster }; 
     UInt32 allow = 1; 
     CMIOObjectSetPropertyData(kCMIOObjectSystemObject, 
            &prop, 0, NULL, 
            sizeof(allow), &allow); 

     // Get devices 
     NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeMuxed]; 
     BOOL deviceAttahced = false; 
     for (int i = 0; i < [devices count]; i++) { 
      AVCaptureDevice *device = devices[i]; 
      if ([[device uniqueID] isEqualToString:@"b48defcadf92f300baf5821923f7b3e2e9fb3947"]) { 
       deviceAttahced = true; 
       [self startSession:device]; 
       break; 
      } 
     } 

    } 
    return self; 
} 

- (void) deviceConnected:(AVCaptureDevice *)device { 
    if ([[device uniqueID] isEqualToString:@"b48defcadf92f300baf5821923f7b3e2e9fb3947"]) { 
     [self startSession:device]; 
    } 
} 

- (void) startSession:(AVCaptureDevice *)device { 

    // Init capturing session 
    session = [[AVCaptureSession alloc] init]; 

    // Star session configuration 
    [session beginConfiguration]; 

    // Add session input 
    NSError *error; 
    newVideoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; 
     if (newVideoDeviceInput == nil) { 
     dispatch_async(dispatch_get_main_queue(), ^(void) { 
      NSLog(@"%@", error); 
     }); 
    } else { 
     [session addInput:newVideoDeviceInput]; 
    } 

    // Add session output 
    videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    videoDataOutput.videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey: (id)kCVPixelBufferPixelFormatTypeKey]; 

    dispatch_queue_t videoQueue = dispatch_queue_create("videoQueue", NULL); 

    [videoDataOutput setSampleBufferDelegate:self queue:videoQueue]; 
    [session addOutput:videoDataOutput]; 

    // Finish session configuration 
    [session commitConfiguration]; 

    // Start the session 
    [session startRunning]; 
} 

#pragma mark - AVCaptureAudioDataOutputSampleBufferDelegate 

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 
    //NSImage *resultNSImage = [self imageFromSampleBuffer:sampleBuffer]; 

    //self.imageView.image = [self nsImageFromSampleBuffer:sampleBuffer]; 
    self.imageView.image = [[NSImage alloc] initWithData:imageToBuffer(sampleBuffer)]; 
}  

NSData* imageToBuffer(CMSampleBufferRef source) { 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(source); 
    CVPixelBufferLockBaseAddress(imageBuffer,0); 

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    void *src_buff = CVPixelBufferGetBaseAddress(imageBuffer); 

    NSData *data = [NSData dataWithBytes:src_buff length:bytesPerRow * height]; 

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 
    return data; 
} 

Antwort

1

Nein, Sie müssen die Startcodes von Anhang B entfernen und durch Größenwerte ersetzen. Gleiches Format wie MP4

Verwandte Themen