ASSETWriterInput per creare video da UIImages su problemi Iphone

Provo i seguenti 2 metodi per aggiungere il UIImage UIImage a ASSETWriterInput . Tutto sembra buono, tranne che non ci sono dati nel file video. Cosa c’è che non va?

1 class dell’adattatore

 AVAssetWriterInputPixelBufferAdaptor * avAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:NULL]; [avAdaptor appendPixelBufferixelBuffer withPresentationTime:CMTimeMake(1, 10)]; 

2 Fare il

 // Create sample buffer. CMSampleBufferRef sampleBuffer = NULL; result = CMSampleBufferCreateForImageBuffer(kCFAllocatorDef ault, pixelBuffer, true, NULL, NULL, videoInfo, &timing, &sampleBuffer); // Ship out the frame. NSParameterAssert(CMSampleBufferDataIsReady(sample Buffer)); NSParameterAssert([writerInput isReadyForMoreMediaData]); BOOL success = [writerInput appendSampleBuffer:sampleBuffer]; 

Ho scoperto che per qualche motivo dovevo aggiungere il buffer più di una volta. La tempistica in questo esempio di un’app di test che ho realizzato potrebbe non essere corretta, ma dal momento che funziona dovrebbe darti una buona idea.

 + (void)writeImageAsMovie:(UIImage*)image toPath:(NSString*)path size:(CGSize)size duration:(int)duration { NSError *error = nil; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie error:&error]; NSParameterAssert(videoWriter); NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:size.width], AVVideoWidthKey, [NSNumber numberWithInt:size.height], AVVideoHeightKey, nil]; AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil]; NSParameterAssert(writerInput); NSParameterAssert([videoWriter canAddInput:writerInput]); [videoWriter addInput:writerInput]; //Start a session: [videoWriter startWriting]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; //Write samples: CVPixelBufferRef buffer = [Utils pixelBufferFromCGImage:image.CGImage size:size]; [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; [adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(duration-1, 2)]; //Finish the session: [writerInput markAsFinished]; [videoWriter endSessionAtSourceTime:CMTimeMake(duration, 2)]; [videoWriter finishWriting]; } 

Questo metodo non è richiesto, ma qui viene utilizzato come esempio di origine di un buffer di pixel:

 + (CVPixelBufferRef) pixelBufferFromCGImage:(CGImageRef)image size:(CGSize)size { 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, (CFDictionaryRef) options, &pxbuffer); status=status;//Added to make the stupid compiler not show a stupid warning. 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); //CGContextTranslateCTM(context, 0, CGImageGetHeight(image)); //CGContextScaleCTM(context, 1.0, -1.0);//Flip vertically to account for different origin CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer; } 

Ho avuto un po ‘di problemi con questo codice. Come risultato, mi getta un’immagine distorta.

Mutevole:

 CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 8, 4 * size.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); 

A:

 CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 8, CVPixelBufferGetBytesPerRow(pxbuffer), rgbColorSpace, kCGImageAlphaNoneSkipFirst); 

aiutato.

Aspetta, anche se la risposta data da @Peter DeWeese è la direzione da seguire, il codice ha due enormi problemi: in primo luogo, devi aspettare mentre il sistema è pronto per aggiungere un nuovo media e in secondo luogo, hai una grande memoria perdita perché è necessario rilasciare il buffer dopo che è stato aggiunto al video writer.

Questo è vero nel tuo caso, ma ancora di più in un caso generale, in cui desideri eseguire il loop su più frame come segue:

 NSInteger i = 0; for (; i