2012-07-14 10 views
5

io sono relativamente nuovo per la programmazione e, anche se io sono ok con normali funzioni, io sono comunque completamente nuovo per l'editing videoNSArray di UIImages per errore video ha la distorsione nell'uscita

Così sono riuscito a trovare un po 'di codice in linea a fare i lavori di seguito riportate:

- (void)writeImagesAsMovie:(NSArray *)array { 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDirectory, YES); 
NSString *documentDirectory = [paths objectAtIndex:0]; 
NSString *saveLocation = [documentDirectory stringByAppendingString:@"/temp.mov"]; 

if ([[NSFileManager defaultManager] fileExistsAtPath:saveLocation]) { 
    [[NSFileManager defaultManager] removeItemAtPath:saveLocation error:NULL]; 
} 

UIImage *first = [array objectAtIndex:0]; 

CGSize frameSize = first.size; 

NSError *error = nil; 
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: 
           [NSURL fileURLWithPath:saveLocation] fileType:AVFileTypeQuickTimeMovie 
                  error:&error]; 

if(error) { 
    NSLog(@"error creating AssetWriter: %@",[error description]); 
} 
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           AVVideoCodecH264, AVVideoCodecKey, 
           [NSNumber numberWithInt:frameSize.width], AVVideoWidthKey, 
           [NSNumber numberWithInt:frameSize.height], AVVideoHeightKey, 
           nil]; 



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

NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString*)kCVPixelBufferWidthKey]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString*)kCVPixelBufferHeightKey]; 

AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor 
               assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput 
               sourcePixelBufferAttributes:attributes]; 

[videoWriter addInput:writerInput]; 

// fixes all errors 
writerInput.expectsMediaDataInRealTime = YES; 

//Start a session: 
[videoWriter startWriting]; 

[videoWriter startSessionAtSourceTime:kCMTimeZero]; 

CVPixelBufferRef buffer = NULL; 
buffer = [self pixelBufferFromCGImage:[first CGImage]]; 
BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; 

if (result == NO) //failes on 3GS, but works on iphone 4 
    NSLog(@"failed to append buffer"); 

if(buffer) { 
    CVBufferRelease(buffer); 
} 



//int reverseSort = NO; 
NSArray *newArray = array; 



int fps = 10; 


int i = 0; 
for (UIImage *image in newArray) 
{ 
    [NSThread sleepForTimeInterval:0.02]; 
    if (adaptor.assetWriterInput.readyForMoreMediaData) { 

     i++; 
     CMTime frameTime = CMTimeMake(1, fps); 
     CMTime lastTime = CMTimeMake(i, fps); 
     CMTime presentTime = CMTimeAdd(lastTime, frameTime); 

     UIImage *imgFrame = image;//[UIImage imageWithContentsOfFile:filePath] ; 
     buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]]; 
     BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]; 

     if (result == NO) //failes on 3GS, but works on iphone 4 
     { 
      NSLog(@"failed to append buffer"); 
      NSLog(@"The error is %@", [videoWriter error]); 
      [NSThread sleepForTimeInterval:0.5]; 
     } 

     if(buffer) { 
      CVBufferRelease(buffer); 
     } 


    } else { 
     NSLog(@"error"); 
     i--; 
    } 
} 

//Finish the session: 
[writerInput markAsFinished]; 
[videoWriter finishWriting]; 
CVPixelBufferPoolRelease(adaptor.pixelBufferPool); 

NSLog(@"Movie created successfully"); 
} 

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image 
{ 


    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 

    CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image), 
         CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
         &pxbuffer); 

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

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image), 
               CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 

    // CGAffineTransform flipVertical = CGAffineTransformMake(
    //               1, 0, 0, -1, 0, CGImageGetHeight(image) 
    //               ); 
    // CGContextConcatCTM(context, flipVertical); 



    // CGAffineTransform flipHorizontal = CGAffineTransformMake(
    //                -1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0 
    //               ); 
    // 
    // CGContextConcatCTM(context, flipHorizontal); 


    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
} 

Ma il problema che sto avendo è che l'uscita del video è in qualche modo danneggiato (essa riveste anche se ha battute divertenti illustrato di seguito: enter image description here

Sarei molto grato per qualsiasi aiuto

Molte grazie

Thomas

risposta

10

mi è stato vedere problemi con l'hardware di codifica video H264 dove può ingresso corrotta che non corrisponde a un rapporto di aspetto noto. Ad esempio, i miei test mostrano che se una dimensione video è inferiore a 128 pixel, il video non verrà codificato.

Quello che ho visto funzionare è 128x128, 192x128, 240x160, 480x320 e altri.

Vai a questa page on aspect ratios

P.S. Probabilmente vorrete usare lo AVAssetWriterInputPixelBufferAdaptor poiché contiene un buffer pool di pixel che è possibile utilizzare tramite CVPixelBufferPoolCreatePixelBuffer(). Inoltre, sarà necessario assert(adaptor.pixelBufferPool); dopo aver chiamato startSessionAtSourceTime per assicurarsi che l'adattatore possa scrivere sul writer.

+0

Grazie mille, ha funzionato perfettamente! –

+0

Molto utile. È possibile aggiornare il collegamento o condividere più informazioni relative alle proporzioni supportate? Ho notato che sebbene 960x540 sia supportato, 540x960 non lo è; i formati portrait non sono generalmente supportati da h264? – Morrowless

+0

Non c'è documentazione su questo ovunque, ho guardato. Devi solo provarlo con una dimensione specifica e vedere se funziona. Potresti non ricevere un codice di errore con una dimensione specifica, ma l'hardware potrebbe comunque scomporre i dati dell'immagine. H.264 dovrebbe funzionare con la maggior parte delle dimensioni (supponendo che entrambe le parti siano eventi), ma l'hardware da codificare per h.264 include con iOS è molto più difficile e difficile da gestire. – MoDJ

Problemi correlati