AVAssetWriter代码运行时没有错误但生成的格式视频无效

时间:2013-03-03 22:47:05

标签: avfoundation avassetwriter

我有以下测试代码,它应该在OSX中创建一个图像文件的视频文件。但是,如果运行成功,视频文件无法播放....

有人能想到我可能做错了什么或错过了吗?

- (void)testVideoWriter {

    NSImage *someImage = [NSImage imageNamed:@"002"];

    CGSize size = CGSizeMake(someImage.size.width, someImage.size.height);
    CMTime frameLength = CMTimeMake(1, 5);
    CMTime currentTime = kCMTimeZero;
    NSError *error = nil;


    //remember to delete video before re-runnign or you will get fails...

    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:@"/Users/petertribe/Desktop/testvideo.mov"] fileType:AVFileTypeMPEG4 error:&error];

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
                                   [NSNumber numberWithInt:size.width ], AVVideoWidthKey,
                                   [NSNumber numberWithInt:size.height ], AVVideoHeightKey, nil];

    AVAssetWriterInput *writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];

    NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                                           [NSNumber numberWithInt:k32ARGBPixelFormat],
                                                           kCVPixelBufferPixelFormatTypeKey, nil];


    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];


    [videoWriter addInput:writerInput];

    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];


    for (int i = 0; i < 100; i++)
    {

        CVPixelBufferRef pixel_buffer = [self fastImageFromNSImage:someImage];

        while (adaptor.assetWriterInput.readyForMoreMediaData == FALSE) {
            NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1];
            [[NSRunLoop currentRunLoop] runUntilDate:maxDate];
        }

        if(![adaptor appendPixelBuffer:pixel_buffer withPresentationTime:currentTime]) {
            NSLog(@"FAIL");
        } else {
            NSLog(@"Success:%d", i);
            currentTime = CMTimeAdd(currentTime, frameLength);
        }

        CVPixelBufferRelease(pixel_buffer);
    }


    [writerInput markAsFinished];
    NSLog(@"Done");
}


- (CVPixelBufferRef)fastImageFromNSImage:(NSImage *)image
{
    CVPixelBufferRef buffer = NULL;


    // config
    size_t width = [image size].width;
    size_t height = [image size].height;
    size_t bitsPerComponent = 8;
    CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    CGBitmapInfo bi = kCGImageAlphaNoneSkipFirst; 
    NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];

    // create pixel buffer
    CVPixelBufferCreate(kCFAllocatorDefault, width, height, k32ARGBPixelFormat, (__bridge CFDictionaryRef)d, &buffer);
    CVPixelBufferLockBaseAddress(buffer, 0);
    void *rasterData = CVPixelBufferGetBaseAddress(buffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);

    // context to draw in, set to pixel buffer's address
    CGContextRef ctxt = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, cs, bi);
    if(ctxt == NULL){
        NSLog(@"could not create context");
        return NULL;
    }

    // draw
    NSGraphicsContext *nsctxt = [NSGraphicsContext graphicsContextWithGraphicsPort:ctxt flipped:NO];
    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:nsctxt];
    [image drawAtPoint:NSMakePoint(0, 0) fromRect:NSMakeRect(0, 0, image.size.width, image.size.height) operation:NSCompositeCopy fraction:1];
    [NSGraphicsContext restoreGraphicsState];

    CVPixelBufferUnlockBaseAddress(buffer, 0);
    CFRelease(ctxt);

    return buffer;
}

1 个答案:

答案 0 :(得分:1)

好的,我必须有一些有趣的时刻,修复很简单......

只需添加

[videoWriter finishWriting];

到testVideoWriter方法的末尾,解决了问题