2012-12-07 13 views
7

Ich versuche, einen Film aus einigen Bildern zu erstellen. Es funktioniert gut mit HD-Bildern ({720, 1280}) oder niedrigeren Auflösungen. Aber wenn ich versuche, den Film mit vollen HD-Bildern {1080, 1920} zu erstellen, wird das Video verschlüsselt. Hier ist ein Link, um zu sehen, wie es aussieht http://www.youtube.com/watch?v=BfYldb8e_18. Hast du irgendwelche Ideen, was ich falsch machen könnte?iPhone - AVAssetWriter - Fehler beim Erstellen von Filmen aus Fotos bei 1920 × 1080 Pixel

- (void) createMovieWithOptions:(NSDictionary *) options 
{ 
@autoreleasepool { 
    NSString *path = [options valueForKey:@"path"]; 
    CGSize size = [(NSValue *)[options valueForKey:@"size"] CGSizeValue]; 
    NSArray *imageArray = [options valueForKey:@"pictures"]; 
    NSInteger recordingFPS = [[options valueForKey:@"fps"] integerValue]; 
    BOOL success=YES; 
    NSError *error = nil; 

    AVAssetWriter *assetWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 
                  fileType:AVFileTypeQuickTimeMovie 
                   error:&error]; 
    NSParameterAssert(assetWriter); 

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
            AVVideoCodecH264, AVVideoCodecKey, 
            [NSNumber numberWithFloat:size.width], AVVideoWidthKey, 
            [NSNumber numberWithFloat:size.height], AVVideoHeightKey, 
            nil]; 

    AVAssetWriterInput *videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 
                       outputSettings:videoSettings]; 

    // Configure settings for the pixel buffer adaptor. 
    NSDictionary* bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 
             [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil]; 

    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput 
                                sourcePixelBufferAttributes:bufferAttributes]; 

    NSParameterAssert(videoWriterInput); 
    NSParameterAssert([assetWriter canAddInput:videoWriterInput]); 

    videoWriterInput.expectsMediaDataInRealTime = NO; 
    [assetWriter addInput:videoWriterInput]; 

    //Start a session: 
    [assetWriter startWriting]; 
    [assetWriter startSessionAtSourceTime:kCMTimeZero]; 

    CVPixelBufferRef buffer = NULL; 

    //convert uiimage to CGImage. 

    int frameCount = 0; 
    float progress = 0; 
    float progressFromFrames = _progressView.progress; //only for create iflipbook movie 

    for(UIImage * img in imageArray) 
    { 
     if([[NSThread currentThread] isCancelled]) 
     { 
      [NSThread exit]; 
     } 

     [condCreateMovie lock]; 
     if(isCreateMoviePaused) 
     { 
      [condCreateMovie wait]; 
     } 

     uint64_t totalFreeSpace=[Utils getFreeDiskspace]; 
     if(((totalFreeSpace/1024ll)/1024ll)<50) 
     { 
      success=NO; 
      break; 
     } 

     //  @autoreleasepool { 
     NSLog(@"size:%@",NSStringFromCGSize(img.size)); 

     buffer = [[MovieWritter sharedMovieWritter] pixelBufferFromCGImage:[img CGImage] andSize:size]; 

     BOOL append_ok = NO; 
     int j = 0; 
     while (!append_ok && j < 60) 
     { 
      if(adaptor.assetWriterInput.readyForMoreMediaData) 
      { 
       CMTime frameTime = CMTimeMake(frameCount, recordingFPS); 
       append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]; 

       CVPixelBufferRelease(buffer); 

       [NSThread sleepForTimeInterval:0.1]; 


       if(isCreatingiFlipBookFromImported) 
        progress = (float)frameCount/(float)[imageArray count]/2.0 + progressFromFrames; 
       else 
        progress = (float)frameCount/(float)[imageArray count]; 

       [[NSNotificationCenter defaultCenter] postNotificationName:@"movieCreationProgress" object:[NSNumber numberWithFloat:progress]]; 
      } 
      else 
      { 
       [NSThread sleepForTimeInterval:0.5]; 
      } 
      j++; 
     } 
     if (!append_ok) 
     { 
      NSLog(@"error appending image %d times %d\n", frameCount, j); 
     } 
     frameCount++; 

     [condCreateMovie unlock]; 
    } 

    //Finish the session: 
    [videoWriterInput markAsFinished]; 
    [assetWriter finishWriting]; 

    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:success], @"success", 
          path, @"path", nil]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"movieCreationFinished" object:dict]; 
} 
} 

* Edit. Hier ist der Code für [[MovieWritter sharedMovieWritter] pixelBufferFromCGImage:]

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image andSize:(CGSize) size 
{ 
@autoreleasepool { 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 

    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, 
              size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
              &pxbuffer); 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 
    NSParameterAssert(pxdata != NULL); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, size.width, 
               size.height, 8, 4*size.width, rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
} 
} 
+1

Bitte postet sein muss Code für: [MovieWritter sharedMovieWritter] pixelBufferFromCGImage: auch. –

+0

Das sieht cool aus –

Antwort

2

Ziemlich sicher, dass dies entweder eine HW Einschränkung oder ein Fehler. Bitte reichen Sie ein Radar ein.

+0

Ich habe in dieses Problem selbst geraten und ja das ist 90% eine Hardware-Einschränkung, da im Simulator funktioniert wie erwartet. –

2

wie über dieses etwas wie Pixelpuffer

//you could use a cgiimageref here instead 
    CFDataRef imageData= CGDataProviderCopyData(CGImageGetDataProvider(imageView.image.CGImage)); 
    NSLog (@"copied image data"); 
    cvErr = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 
             FRAME_WIDTH, 
             FRAME_HEIGHT, 
             kCVPixelFormatType_32BGRA, 
             (void*)CFDataGetBytePtr(imageData), 
             CGImageGetBytesPerRow(imageView.image.CGImage), 
             NULL, 
             NULL, 
             NULL, 
             &pixelBuffer); 
    NSLog (@"CVPixelBufferCreateWithBytes returned %d", cvErr); 

    CFAbsoluteTime thisFrameWallClockTime = CFAbsoluteTimeGetCurrent(); 
    CFTimeInterval elapsedTime = thisFrameWallClockTime - firstFrameWallClockTime; 
    NSLog (@"elapsedTime: %f", elapsedTime); 
    CMTime presentationTime = CMTimeMake(elapsedTime * TIME_SCALE, TIME_SCALE); 

    // write the sample 
    BOOL appended = [assetWriterPixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentationTime]; 
    CVPixelBufferRelease(pixelBuffer); 
    CFRelease(imageData); 
    if (appended) { 
     NSLog (@"appended sample at time %lf", CMTimeGetSeconds(presentationTime)); 
    } else { 
     NSLog (@"failed to append"); 
     [self stopRecording]; 
     self.startStopButton.selected = NO; 
    } 
-1

Sie können auch die Aufnahmeeinstellungen voreingestellt einstellen wollen bekommen, obwohl hoch in der Regel geeignet ist, und das ist Standard */ Konstanten Capture Einstellung Voreinstellungen definieren Verwenden der sessionPreset-Eigenschaft.

NSString * const AVCaptureSessionPresetPhoto;

NSString * const AVCaptureSessionPresetHigh;

NSString * const AVCaptureSessionPresetMedium;

NSString * const AVCaptureSessionPresetLow;

NSString * const AVCaptureSessionPreset352x288;

NSString * const AVCaptureSessionPreset640x480;

NSString * const AVCaptureSessionPreset1280x720;

NSString * const AVCaptureSessionPreset1920x1080;

NSString * const AVCaptureSessionPresetiFrame960x540;

NSString * const AVCaptureSessionPresetiFrame1280x720; */

// es so gesetzt

self.captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;

// oder so, wenn Sie avcapturesession

[self.captureSession setSessionPreset: AVCaptureSessionPreset1920x1080] definieren;

+1

das ist am irrelevantsten. Mein Kollege und ich müssen dieses Problem beheben, wenn wir FULL HD-Bilder einem AVAssetWriterInputPixelBufferAdaptor zuführen. Bilder können aus der Kamerarolle genommen werden ...Wir passen die Größe an die FULL HD-Auflösung an. Wir erfassen auch Frames aus den Kamera-Puffern, funktionieren jedoch immer noch nicht mit dem AVAssetWriterInputPixelBufferAdaptor. Vielleicht ist dies ein Fehler oder eine Einschränkung mit AVAssetWriterInputPixelBufferAdaptor. –

+1

Ich habe einige Probleme, bevor ich das Preset nicht eingestellt habe, also habe ich es erwähnt, eine schlechte Einstellung wird dir keine schnellere Hilfe bringen. Könnte das Pixelformat falsch sein, versuche kCVPixelFormatType_32ARGB zu kCVPixelFormatType_32BGRA wie im Beispiel zu ändern, das ich zeige –

+0

Pixelformat hat hier nichts zu tun. appendPixelBuffer ... Methode gibt auch eine Antwort YES zurück. Wir haben die Größe, Einstellungen, alles überprüft, aber es funktioniert immer noch nicht. –

3

hatte ich das gleiche Problem und this answer es gelöst: die Größe des Videos ein Vielfaches von 16

+0

Vielen Dank! Ich habe tagelang mit verschiedenen Teilen davon gekämpft. Eine lächerliche Anforderung, aber Apple ist voll von diesen. – Linuxios