UIImage的NSArrayvideo错误在输出中有失真

我对编程相对比较陌生,虽然我对正常的function还是很满意的,但是我对video编辑却是全新的

所以我已经设法在网上find一些代码来完成如下所示的工作:

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

但我遇到的问题是,video的输出是一些如何损坏(它确实发挥,虽然它有下面显示的有趣的行: 在这里输入图像说明

我会很感激任何帮助

非常感谢

托马斯

我一直在看H264video编码硬件的问题,它可能会损坏不符合已知宽高比的input。 例如,我的testing表明,如果一个video尺寸小于128像素,video将不会编码。

我所看到的工作是128×128,192×128,240×160,480×320,等等。

请参阅此页面上的纵横比

PS您可能会想要使用AVAssetWriterInputPixelBufferAdaptor因为它包含可以通过CVPixelBufferPoolCreatePixelBuffer()使用的像素缓冲池。 另外,你会想assert(adaptor.pixelBufferPool); 在调用startSessionAtSourceTime ,确保您的适配器可以写入作者。