gpt4 book ai didi

macos - 如何颜色管理 AVAssetWriter 输出

转载 作者:行者123 更新时间:2023-12-04 12:43:28 24 4
gpt4 key购买 nike

我在获取渲染视频的颜色以匹配源内容的颜色时遇到问题。我正在将图像渲染到 CGContext 中,将支持数据转换为 CVPixelBuffer 并将其作为帧附加到 AVAssetWriterInputPixelBufferAdaptor。这会导致我绘制到 CGContext 中的图像与生成的视频文件之间存在细微的颜色差异。

似乎有3件事需要解决:

  • 告诉 AVFoundation 视频所在的色彩空间。
  • 使 AVAssetWriterInputPixelBufferAdaptor 和我附加到它的 CVPixelBuffers 匹配该颜色空间。
  • 为 CGContext 使用相同的色彩空间。

  • 文档很糟糕,所以我很感激任何关于如何做这些事情的指导,或者我是否需要做其他事情来在整个过程中保留颜色。

    完整代码:
    AVAssetWriter                        *_assetWriter;
    AVAssetWriterInput *_assetInput;
    AVAssetWriterInputPixelBufferAdaptor *_assetInputAdaptor;

    NSDictionary *outputSettings = @{ AVVideoCodecKey :AVVideoCodecH264,
    AVVideoWidthKey :@(outputWidth),
    AVVideoHeightKey:@(outputHeight)};

    _assetInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:outputSettings];


    NSDictionary *bufferAttributes = @{å(NSString*)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32ARGB)};
    _assetInputAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_assetInput
    sourcePixelBufferAttributes:bufferAttributes];


    _assetWriter = [AVAssetWriter assetWriterWithURL:aURL fileType:AVFileTypeMPEG4 error:nil];
    [_assetWriter addInput:_assetInput];
    [_assetWriter startWriting];
    [_assetWriter startSessionAtSourceTime:kCMTimeZero];

    NSInteger bytesPerRow = outputWidth * 4;
    long size = bytesPerRow * outputHeight;
    CGColorSpaceRef srgbSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);

    UInt8 *data = (UInt8 *)calloc(size, 1);
    CGContextRef ctx = CGBitmapContextCreateWithData(data, outputWidth, outputHeight, 8, bytesPerRow, srgbSpace, kCGImageAlphaPremultipliedFirst, NULL, NULL);

    // draw everything into ctx

    CVPixelBufferRef pixelBuffer;
    CVPixelBufferCreateWithBytes(kCFAllocatorSystemDefault,
    outputWidth, outputHeight,
    k32ARGBPixelFormat,
    data,
    bytesPerRow,
    ReleaseCVPixelBufferForCVPixelBufferCreateWithBytes,
    NULL,
    NULL,
    &pixelBuffer);

    NSDictionary *pbAttachements = @{(id)kCVImageBufferCGColorSpaceKey : (__bridge id)srgbSpace};
    CVBufferSetAttachments(pixelBuffer, (__bridge CFDictionaryRef)pbAttachements, kCVAttachmentMode_ShouldPropagate);
    [_assetInputAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(0, 60)];

    CGColorSpaceRelease(srgbSpace);

    [_assetInput markAsFinished];
    [_assetWriter finishWritingWithCompletionHandler:^{}];

    最佳答案

    这是一个相当令人困惑的主题,Apple 文档确实没有多大帮助。我将描述我基于使用 BT.709 色彩空间确定的解决方案,我相信有人会基于色度正确性和各种视频标准的怪异性提出异议,但这是一个复杂的话题。首先,不要使用 kCVPixelFormatType_32ARGB 作为像素类型。始终传递 kCVPixelFormatType_32BGRA,因为 BGRA 是 MacOSX 和 iPhone 硬件上的原生像素布局,而且 BGRA 速度更快。接下来,当您创建 CGBitmapContext 以使用 BT.709 颜色空间 (kCGColorSpaceITUR_709) 进行渲染时。此外,不要渲染到 malloc() 缓冲区,通过在同一内存上创建位图上下文直接渲染到 CoreVideo 像素缓冲区,CoreGraphics 将处理从任何输入图像到 BT.709 及其的颜色空间和 Gamma 转换相关 Gamma 。然后你需要告诉 AVFoundation 像素缓冲区的颜色空间,通过制作 ICC 配置文件副本并在 CoreVideo 像素缓冲区上设置 kCVImageBufferICCProfileKey 来做到这一点。这可以解决您的问题 1 和 2,您不需要使用这种方法在相同的色彩空间中输入图像。现在,这当然很复杂,而且很难获得实际工作的源代码(是的,实际工作)。这是一个执行这些确切步骤的小项目的 github 链接,代码是 BSD 许可的,所以请随意使用它。特别注意 H264Encoder 类,它将所有这些恐怖内容包装到一个可重用的模块中。您可以在 encode_h264.m 中找到调用代码,它是一个小的 MacOSX 命令行工具,用于将 PNG 编码为 M4V。还附上了 3 个与此主题相关的 Apple 文档 1 , 2 , 3 .

    MetalBT709Decoder

    关于macos - 如何颜色管理 AVAssetWriter 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50880718/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com