简体   繁体   English

AVAssetWriter可以透明地写入文件吗?

[英]Possible for AVAssetWriter to write files with transparency?

Every file I write with AVAssetWriter has a black background, if the images I include do not fill the entire render area. 如果我包含的图像不能填满整个渲染区域,则我使用AVAssetWriter编写的每个文件都具有黑色背景。 Is there any way to write with transparency? 有透明的书写方式吗? Here's the method I use to get the pixel buffer: 这是我用来获取像素缓冲区的方法:

- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image {

    CGSize size = self.renderSize;

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    CVPixelBufferRef pxbuffer = NULL;
    CVPixelBufferPoolCreatePixelBuffer(NULL, self.adaptor.pixelBufferPool, &pxbuffer);

    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                          size.width,
                                          size.height,
                                          kCVPixelFormatType_32ARGB,
                                          (__bridge CFDictionaryRef) options,
                                          &pxbuffer);


    if (status != kCVReturnSuccess){
        NSLog(@"Failed to create pixel buffer");
    }

    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
                                                 size.height, 8, 4*size.width, rgbColorSpace,
                                                 (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

    return pxbuffer;
}

And the AVAssetWriter code: 以及AVAssetWriter代码:

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

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

NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil];
self.adaptor = [AVAssetWriterInputPixelBufferAdaptor
                    assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
                    sourcePixelBufferAttributes:bufferAttributes];

buffer = [self pixelBufferFromCGImage:[stickerImage CGImage]];

BOOL append_ok = YES;
    int j = 0;
    while (append_ok && j < totalFrames) {
        if (self.adaptor.assetWriterInput.readyForMoreMediaData)  {

            CMTime frameTime = CMTimeMake(frameCount,(int32_t) fps);
            append_ok = [self.adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
            if(!append_ok){
                NSError *error = self.assetWriter.error;
                if(error!=nil) {
                    NSLog(@"Unresolved error %@,%@.", error, [error userInfo]);
                }
            }
        }
        else {
            printf("adaptor not ready %d, %d\n", frameCount, j);
            [NSThread sleepForTimeInterval:0.1];
        }
        j++;
        frameCount++;
    }
    if (!append_ok) {
        printf("error appending image %d times %d\n, with error.", frameCount, j);
    }

In short, This is not possible. 简而言之,这是不可能的。 AVAssetWriter outputs using the h264 video codec. AVAssetWriter使用h264视频编解码器输出。 The h264 video codec does not support an alpha channel, so you are unfortunately out of luck. h264视频编解码器不支持Alpha通道,因此很遗憾,您不走运。

A more involved solution would involve rendering the alpha channel (transparency) into a grayscale h264 encoded video and compositiong the rub and alpha information back together when viewing. 一种更复杂的解决方案将涉及将alpha通道(透明度)渲染为h264灰度编码的视频,并在观看时将摩擦和alpha信息重新组合在一起。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM