Dan*_*iel 5 macos video core-graphics avfoundation color-space
我无法使渲染视频的颜色与源内容的颜色相匹配。我将图像渲染到 CGContext 中,将支持数据转换为 CVPixelBuffer 并将其作为帧附加到 AVAssetWriterInputPixelBufferAdaptor 中。这会导致我绘制到 CGContext 中的图像与生成的视频文件之间存在轻微的颜色差异。
\n\n看来有3件事需要解决:
\n\n该文档很糟糕,所以我希望获得有关如何执行这些操作的任何指导,或者我是否需要做其他事情来使颜色在整个过程中得以保留。
\n\n完整代码:
\n\nAVAssetWriter *_assetWriter;\nAVAssetWriterInput *_assetInput;\nAVAssetWriterInputPixelBufferAdaptor *_assetInputAdaptor;\n\nNSDictionary *outputSettings = @{ AVVideoCodecKey :AVVideoCodecH264,\n AVVideoWidthKey :@(outputWidth),\n AVVideoHeightKey:@(outputHeight)};\n\n_assetInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo\n outputSettings:outputSettings];\n\n\nNSDictionary *bufferAttributes = @{\xc3\xa5(NSString*)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32ARGB)};\n_assetInputAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_assetInput\n sourcePixelBufferAttributes:bufferAttributes];\n\n\n_assetWriter = [AVAssetWriter assetWriterWithURL:aURL fileType:AVFileTypeMPEG4 error:nil];\n[_assetWriter addInput:_assetInput];\n[_assetWriter startWriting];\n[_assetWriter startSessionAtSourceTime:kCMTimeZero];\n\nNSInteger bytesPerRow = outputWidth * 4;\nlong size = bytesPerRow * outputHeight;\nCGColorSpaceRef srgbSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);\n\nUInt8 *data = (UInt8 *)calloc(size, 1);\nCGContextRef ctx = CGBitmapContextCreateWithData(data, outputWidth, outputHeight, 8, bytesPerRow, srgbSpace, kCGImageAlphaPremultipliedFirst, NULL, NULL);\n\n// draw everything into ctx\n\nCVPixelBufferRef pixelBuffer;\nCVPixelBufferCreateWithBytes(kCFAllocatorSystemDefault,\n outputWidth, outputHeight,\n k32ARGBPixelFormat,\n data,\n bytesPerRow,\n ReleaseCVPixelBufferForCVPixelBufferCreateWithBytes,\n NULL,\n NULL,\n &pixelBuffer);\n\nNSDictionary *pbAttachements = @{(id)kCVImageBufferCGColorSpaceKey : (__bridge id)srgbSpace};\nCVBufferSetAttachments(pixelBuffer, (__bridge CFDictionaryRef)pbAttachements, kCVAttachmentMode_ShouldPropagate);\n[_assetInputAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(0, 60)];\n\nCGColorSpaceRelease(srgbSpace);\n\n[_assetInput markAsFinished];\n[_assetWriter finishWritingWithCompletionHandler:^{}];\nRun Code Online (Sandbox Code Playgroud)\n
这是一个相当令人困惑的主题,苹果文档确实没有多大帮助。我将描述我基于使用 BT.709 色彩空间而确定的解决方案,我相信有人会基于色度正确性和各种视频标准的怪异而提出反对,但这是一个复杂的话题。首先,不要使用 kCVPixelFormatType_32ARGB 作为像素类型。始终传递 kCVPixelFormatType_32BGRA,因为 BGRA 是 MacOSX 和 iPhone 硬件上的本机像素布局,并且 BGRA 速度更快。接下来,当您创建 CGBitmapContext 来渲染时,将使用 BT.709 色彩空间 (kCGColorSpaceITUR_709)。另外,不要渲染到 malloc() 缓冲区中,而是通过在同一内存上创建位图上下文来直接渲染到 CoreVideo 像素缓冲区中,CoreGraphics 将处理从任何输入图像到 BT.709 及其图像的色彩空间和伽玛转换。相关伽玛。然后,您需要告诉 AVFoundation 像素缓冲区的颜色空间,通过制作 ICC 配置文件副本并在 CoreVideo 像素缓冲区上设置 kCVImageBufferICCProfileKey 来做到这一点。这解决了您的问题 1 和 2,您不需要使用这种方法在同一色彩空间中输入图像。现在,这当然很复杂,并且很难获得实际工作的源代码(是的,确实有效)。这里有一个小项目的 github 链接,它执行这些确切的步骤,代码是 BSD 许可的,所以请随意使用它。特别注意 H264Encoder 类,它将所有这些可怕的事情包装到一个可重用的模块中。你可以在encode_h264.m中找到调用代码,它是一个小的MacOSX命令行工具,用于将PNG编码为M4V。还附上了与此主题相关的 3 个关键 Apple文档1、2、3。
| 归档时间: |
|
| 查看次数: |
1153 次 |
| 最近记录: |