Transparent overlay changes color in HDR video

Overlay changes color in HDR video When I’m using trying to add an overlay to an image with AVMutableVideoComposition, When the video is in HDR the overlay colors are changing and white becomes grey screen shot from original HDR video result from the code with the wrong overlay colorthe result when reducing to SDR (the right overlay color)

the distorted colorsthe way it should look(sdr)

Im creating the overlay with a CGContext


class  CustomHdrCompositor: NSObject, AVVideoCompositing {

       private let coreImageContext = CIContext(options: [CIContextOption.cacheIntermediates: false])
       let combinedFilter =  CIFilter(name: "CISourceOverCompositing")!
       var sourcePixelBufferAttributes: [String: Any]? = [String(kCVPixelBufferPixelFormatTypeKey): [kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange]]
       var requiredPixelBufferAttributesForRenderContext: [String: Any] =
           [String(kCVPixelBufferPixelFormatTypeKey): [kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange]]
       var supportsWideColorSourceFrames = true
       var supportsHDRSourceFrames = true
       func renderContextChanged(_ newRenderContext: AVVideoCompositionRenderContext) {
           return
       }

         func startRequest(_ request: AVAsynchronousVideoCompositionRequest) {
         guard let outputPixelBuffer = request.renderContext.newPixelBuffer() else {
               print("No valid pixel buffer found. Returning.")
               request.finish(with: CustomCompositorError.ciFilterFailedToProduceOutputImage)
               return
           }

           guard let requiredTrackIDs = request.videoCompositionInstruction.requiredSourceTrackIDs, !requiredTrackIDs.isEmpty else {
               print("No valid track IDs found in composition instruction.")
               return
           }

           let sourceCount = requiredTrackIDs.count
           if sourceCount > 1 {
               request.finish(with: CustomCompositorError.notSupportingMoreThanOneSources)
               return
           }

           if sourceCount == 1 {
               let sourceID = requiredTrackIDs[0]
               let sourceBuffer = request.sourceFrame(byTrackID: sourceID.value(of: Int32.self)!)!
               let sourceCIImage = CIImage(cvPixelBuffer: sourceBuffer)
               var textImage = TextLayerPlayer.instance.getTextLayerAtTimesStamp(ts:request.compositionTime.seconds) 
               combinedFilter.setValue(textImage, forKey: "inputImage") 
               if let outputImage = combinedFilter.outputImage { 
                   let renderDestination = CIRenderDestination(pixelBuffer: outputPixelBuffer) 
                   do {
                       try coreImageContext.startTask(toRender: outputImage, to: renderDestination)
                   } catch { 
                   } 
               } 
           } 
           request.finish(withComposedVideoFrame: outputPixelBuffer) 
       }
   }
func regularCompositionHdr(asset: AVAsset) -> AVVideoComposition

   {
       self.isHdr = checkHdr(asset: asset)
        let avComposition = AVMutableComposition()
       let composition = AVMutableVideoComposition()
       composition.colorPrimaries = AVVideoColorPrimaries_ITU_R_2020
       composition.colorTransferFunction = AVVideoTransferFunction_ITU_R_2100_HLG
       composition.colorYCbCrMatrix = AVVideoYCbCrMatrix_ITU_R_2020
       composition.renderSize = assetSize
       composition.frameDuration = CMTime(value: 1, timescale: 30)
       composition.customVideoCompositorClass = CustomHdrCompositor.self
       composition.perFrameHDRDisplayMetadataPolicy = .propagate
       return composition
   } 

I’m using this function to transfer the transparent CGImage to CIImage that supports HDR


func convertToHDRCIImage(from cgImage: CGImage,

                                      maxBrightness: CGFloat = 3.0) -> CIImage? {

            // Create a CIImage from the input CGImage

            let baseImage = CIImage(cgImage: cgImage)

            

            // Create HDR color adjustment filter

            let colorAdjust = CIFilter(name: "CIColorMatrix")!
            colorAdjust.setValue(baseImage, forKey: kCIInputImageKey)
            // Calculate HDR multipliers based on maxBrightness

            // This will maintain color ratios while increasing brightness
            colorAdjust.setValue(CIVector(x: maxBrightness, y: 0, z: 0, w: 0), forKey: "inputRVector")
            colorAdjust.setValue(CIVector(x: 0, y: maxBrightness, z: 0, w: 0), forKey: "inputGVector")
            colorAdjust.setValue(CIVector(x: 0, y: 0, z: maxBrightness, w: 0), forKey: "inputBVector")
            // Maintain alpha channel
            colorAdjust.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
            guard let adjustedImage = colorAdjust.outputImage else {
                return nil
            }
        // Apply color space transformation using CIImage's colorSpace property
            let transformedImage = adjustedImage.matchedFromWorkingSpace(to: hdrWorkingSpace)!

            // Create context with HDR color space

            let context = CIContext(options: [
                 .workingColorSpace: hdrColorSpace,
                .outputColorSpace: hdrColorSpace
            ])

            // Get the image bounds
        let bounds = transformedImage.extent
            // Create a new pixel buffer with HDR format
            var pixelBuffer: CVPixelBuffer?
            let pixelBufferAttributes = [
                kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_64RGBAHalf,
                kCVPixelBufferMetalCompatibilityKey: true
            ] as CFDictionary
            CVPixelBufferCreate(kCFAllocatorDefault,
                               Int(bounds.width),
                               Int(bounds.height),
                               kCVPixelFormatType_64RGBAHalf,
                               pixelBufferAttributes,
                               &pixelBuffer)

            guard let destinationBuffer = pixelBuffer else {
                return nil
            }

            context.render(transformedImage,
                          to: destinationBuffer,
                          bounds: bounds,
                          colorSpace: hdrColorSpace)

            // Create final CIImage from the HDR pixel buffer
            let finalImage = CIImage(cvPixelBuffer: destinationBuffer,
                                   options: [.colorSpace: hdrColorSpace])

            return finalImage
        }

When reducing the HDR to SDR it keeps the right color of the overlay with, but than it reduces the HDR effect which I want to keep

Transparent overlay changes color in HDR video
 
 
Q