iphone – 视频错误的UIImage的NSArray在输出中有失真
发布时间:2020-12-14 19:26:55 所属栏目:百科 来源:网络整理
导读:我对编程比较陌生,虽然我对正常的功能很满意,但我对视频编辑还是全新的 所以我设法在网上找到一些代码来完成下面显示的工作: - (void)writeImagesAsMovie:(NSArray *)array {NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSU
我对编程比较陌生,虽然我对正常的功能很满意,但我对视频编辑还是全新的
所以我设法在网上找到一些代码来完成下面显示的工作: - (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,8,4*CGImageGetWidth(image),rgbColorSpace,kCGImageAlphaNoneSkipFirst); CGContextConcatCTM(context,CGAffineTransformMakeRotation(0)); // CGAffineTransform flipVertical = CGAffineTransformMake( // 1,-1,CGImageGetHeight(image) // ); // CGContextConcatCTM(context,flipVertical); // CGAffineTransform flipHorizontal = CGAffineTransformMake( // -1.0,0.0,1.0,0.0 // ); // // CGContextConcatCTM(context,flipHorizontal); CGContextDrawImage(context,CGRectMake(0,CGImageGetHeight(image)),image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer,0); return pxbuffer; } 但我遇到的问题是视频的输出有些损坏(尽管它有如下所示的有趣线条,但确实会播放) 我会非常感激任何帮助 非常感谢 托马斯 解决方法
我一直看到H264视频编码硬件存在问题,它可以破坏与已知宽高比不匹配的输入.例如,我的测试显示,如果一个视频维度小于128像素,则视频将不会编码.
我所看到的工作是128×128,192×128,240×160,480×320等. 见这page on aspect ratios 附:您可能希望使用AVAssetWriterInputPixelBufferAdaptor,因为它包含可以通过CVPixelBufferPoolCreatePixelBuffer()使用的像素缓冲池.另外,你需要断言(adaptor.pixelBufferPool);在调用startSessionAtSourceTime之后,确保您的适配器可以写入writer. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |