iOS AVFoundation 利用裁剪后的图片(视频帧)拼接视频

1.初始化视频设置

- (void)initVideoSetting{
    NSDictionary *outputSettings =
    [NSDictionary dictionaryWithObjectsAndKeys:
     
     [NSNumber numberWithInt:720], AVVideoWidthKey,
     [NSNumber numberWithInt:1280], AVVideoHeightKey,
     AVVideoCodecH264, AVVideoCodecKey,
     
     nil];
    
    _assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                           outputSettings:outputSettings];
    
    _pixelBufferAdaptor =[[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:_assetWriterInput sourcePixelBufferAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],kCVPixelBufferPixelFormatTypeKey,nil]];
    
    NSString *outputFielPath=[NSTemporaryDirectory() stringByAppendingString:@"1613.mov"];
    NSURL *fileUrl=[NSURL fileURLWithPath:outputFielPath];
    
    _assetWriter = [[AVAssetWriter alloc] initWithURL:fileUrl fileType:AVFileTypeQuickTimeMovie error:nil];
    [_assetWriter addInput:_assetWriterInput];
    _assetWriterInput.expectsMediaDataInRealTime = YES;
    [_assetWriter startWriting];
    [_assetWriter startSessionAtSourceTime:kCMTimeZero];
}

2.在视频处理帧的代理方法中调用裁剪合成方法

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    @autoreleasepool {
        @try {
             [self cropSampleBuffer:sampleBuffer inRect:裁剪的尺寸];
        } @catch ( NSException  *e) {
            
        }
    }
}

3.裁剪sampleBuffer的方法

- (void)cropSampleBuffer:(CMSampleBufferRef)sampleBuffer inRect:(CGRect)rect{
    CFRetain(sampleBuffer);
    UIImage *originImage = [self imageFromSampleBuffer:sampleBuffer];//请自行搜索
    UIImage *cropImage = [self cropImage:originImage atRect:rect];//请自行搜索
    [self startTakingVideo:[self pixelBufferFromUIImage:cropImage]];
    CFRelease(sampleBuffer);
}

4.将裁减后的UIImage转成CVPixelBufferRef

CGImageRef image = [originImage CGImage];
    int height = 1280;
    int width = 720;
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    CVPixelBufferRef pxbuffer = NULL;
    
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width,
                                          height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options,
                                          &pxbuffer);
    
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
    
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    NSParameterAssert(pxdata != NULL);
    
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef context = CGBitmapContextCreate(pxdata, width,
                                                 height, 8, 4*width, rgbColorSpace,
                                                 kCGImageAlphaNoneSkipFirst);
    NSParameterAssert(context);
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);
    
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
    
    return pxbuffer;

5.开始将裁减后的图和成视频

- (void)startTakingVideo:(CVPixelBufferRef)sampleBuffer{
    // a very dense way to keep track of the time at which this frame
    // occurs relative to the output stream, but it's just an example!
    static int64_t frameNumber = 0;
    if(_assetWriterInput.readyForMoreMediaData)
        [_pixelBufferAdaptor appendPixelBuffer:sampleBuffer
                         withPresentationTime:CMTimeMake(frameNumber, 25)];
    frameNumber++;
}

6.停止录制,并保存视频

- (void)stopTakingVideo{
    [_assetWriter finishWriting];//方法已经deprecated,如果找到麻烦告诉下博主
}

最后一些注意事项

请不要使用AVCaptureMovieFileOutput AVCaptureMovieFileOutput是和AVAssetWriterInputPixelBufferAdaptor有冲突的,具体的内容还是参见苹果官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 原文:AVFoundation Programming Guide 写在前面 简单翻译一下AVFoundation...
    朦胧1919阅读 11,437评论 1 14
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,686评论 4 61
  • 目前只翻译完一小部分,先保存一下.之后有空继续....(好长好长啊...). 翻译的比较渣,但应该可以看懂......
    NaitY阅读 11,225评论 2 12
  • 在路上需要一个和你同甘共苦的人一起走,需要一个懂你的人,那个人你在哪,希望能够遇见你。
    遇见知己阅读 1,351评论 0 1
  • 企业的需求与转变,决定后期人员流动的状态,管理层要不断的创新模式,改变原有的现状。 参与磨合期的发展,对于新老员工...
    杨平的阅读 1,580评论 0 0

友情链接更多精彩内容