本文介绍了使用AVAssetWriter从图像创建电影在3GS设备上无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
对appendPixelBuffer的调用在3GS设备(IOS 4.1)上返回NO,但在iPhone 4设备上运行良好。
以下对appendPixelBuffer的调用是问题的根源:
CVPixelBufferRef buffer = NULL;
buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@frame1.png] CGImage]];
BOOL result = [adapter appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
如果(结果==否)//在3GS上失败,但在iphone 4上工作
NSLog(@无法附加缓冲区);
}
完整代码:
- (void)writeImagesAsMovie:(NSArray *)数组toPath:(NSString *)path {
NSLog(路径);
NSError * error = nil;
AVAssetWriter * videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
error:& error];
if(error){
NSLog(@创建AssetWriter的错误:%@,[错误描述]);
}
错误(仅限3GS,iphone 4正常)是
NSDictionary * videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264,AVVideoCodecKey,
[NSNumber numberWithInt:frameSize.width],AVVideoWidthKey,
[NSNumber numberWithInt:frameSize.height],AVVideoHeightKey,
nil];
AVAssetWriterInput * writerInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
NSMutableDictionary * attributes = [[NSMutableDictionary alloc] init];
[attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString *)kCVPixelBufferWidthKey];
[属性setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString *)kCVPixelBufferHeightKey];
AVAssetWriterInputPixelBufferAdaptor * adapter = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:attributes];
[videoWriter addInput:writerInput];
//修复所有错误
writerInput.expectsMediaDataInRealTime = YES;
//开始一个会话:
BOOL start = [videoWriter startWriting];
NSLog(@会话开始?%d,开始);
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@frame1.png] CGImage]];
BOOL result = [adapter appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
如果(结果==否)//在3GS上失败,但在iphone 4上工作
NSLog(@无法附加缓冲区);
if(buffer)
CVBufferRelease(buffer);
[NSThread sleepForTimeInterval:0.05];
// for(int i = 1; i< [array count]; i ++)
for(int i = 1; i< 20; i ++)
{
if( adaptor.assetWriterInput.readyForMoreMediaData)
{
NSLog(@inside for loop%d,i);
CMTime frameTime = CMTimeMake(1,15);
CMTime lastTime = CMTimeMake(i,15);
CMTime presentTime = CMTimeAdd(lastTime,frameTime);
NSString * imgName = [NSString stringWithFormat:@frame%d.png,i];
UIImage * imgFrame = [UIImage imageNamed:imgName];
buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]];
BOOL result = [adapter appendPixelBuffer:buffer withPresentationTime:presentTime];
如果(结果==否)//在3GS上失败,但在iphone 4上工作
{
NSLog(@无法附加缓冲区);
NSLog(@错误是%@,[videoWriter错误]);
}
if(buffer)
CVBufferRelease(buffer);
[NSThread sleepForTimeInterval:0.05];
}
其他
{
NSLog(@错误);
i--;
}
}
//完成会话:
[writerInput markAsFinished];
[videoWriter finishWriting];
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
[videoWriter release];
[writerInput release];
NSLog(@电影创建成功);
}
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber] numberWithBool:YES],kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVPixelBufferCreate(kCFAllocatorDefault,self.view.frame.size.width,
self.view.frame.size.height,kCVPixelFormatType_32ARGB,(CFDictionaryRef)选项,
& pxbuffer );
CVPixelBufferLockBaseAddress(pxbuffer,0);
void * pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata,self.view.frame.size.width,
self.view.frame.size.height,8,4 * self.view.frame.size.width,rgbColorSpace ,
kCGImageAlphaNoneSkipFirst);
CGContextConcatCTM(context,CGAffineTransformMakeRotation(0));
CGContextDrawImage(context,CGRectMake(0,0,CGImageGetWidth(image),
CGImageGetHeight(image)),image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer,0);
返回pxbuffer;
}
解决方案
使用此。 / p>
The call to appendPixelBuffer is returning NO on 3GS device (IOS 4.1), but is working well on iPhone 4 devices.
The following call to appendPixelBuffer is the source of the problem:
CVPixelBufferRef buffer = NULL;
buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@"frame1.png"] CGImage]];
BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
if (result == NO) //failes on 3GS, but works on iphone 4
NSLog(@"failed to append buffer");
}
Full Code:
-(void)writeImagesAsMovie:(NSArray *)array toPath:(NSString*)path {
NSLog(path);
NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
error:&error];
if(error) {
NSLog(@"error creating AssetWriter: %@",[error description]);
}
The error (ONLY ON 3GS, iphone 4 is fine) is
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:frameSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:frameSize.height], AVVideoHeightKey,
nil];
AVAssetWriterInput* writerInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
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:
BOOL start = [videoWriter startWriting];
NSLog(@"Session started? %d", start);
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
buffer = [self pixelBufferFromCGImage:[[UIImage imageNamed:@"frame1.png"] 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);
[NSThread sleepForTimeInterval:0.05];
//for (int i = 1;i<[array count]; i++)
for (int i = 1;i<20; i++)
{
if (adaptor.assetWriterInput.readyForMoreMediaData)
{
NSLog(@"inside for loop %d",i);
CMTime frameTime = CMTimeMake(1, 15);
CMTime lastTime=CMTimeMake(i, 15);
CMTime presentTime=CMTimeAdd(lastTime, frameTime);
NSString *imgName = [NSString stringWithFormat:@"frame%d.png",i];
UIImage *imgFrame = [UIImage imageNamed:imgName] ;
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]);
}
if(buffer)
CVBufferRelease(buffer);
[NSThread sleepForTimeInterval:0.05];
}
else
{
NSLog(@"error");
i--;
}
}
//Finish the session:
[writerInput markAsFinished];
[videoWriter finishWriting];
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
[videoWriter release];
[writerInput release];
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, self.view.frame.size.width,
self.view.frame.size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,
&pxbuffer);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, self.view.frame.size.width,
self.view.frame.size.height, 8, 4*self.view.frame.size.width, rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
解决方案
use this https://github.com/caferrara/img-to-video it runs on iPhone 3gs device.
这篇关于使用AVAssetWriter从图像创建电影在3GS设备上无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!