Open taontech opened 2 years ago
重点是这个设置
let outputSettings = [ AVVideoCodecKey: AVVideoCodecType.hevc, AVVideoWidthKey : NSNumber(value: Float(outputSize.width)), AVVideoHeightKey : NSNumber(value: Float(outputSize.height)), AVVideoColorPropertiesKey : [ AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_2100_HLG, AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_2020, AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_2020 ], AVVideoCompressionPropertiesKey: [AVVideoProfileLevelKey:kVTProfileLevel_HEVC_Main10_AutoLevel,AVVideoAverageBitRateKey:NSNumber(value: Float(3000000))] ] as [String:Any]
@IBAction func makeHDRMovie(){ let hdrimage = hdrImagePixelBuffer(uiImage:(self.imageView?.image)!) // todo make movie let fileManager = FileManager.default let urls = fileManager.urls(for: .cachesDirectory, in: .userDomainMask) guard let documentDirectory = urls.first else { fatalError("documentDir Error") } let videoOutputURL = documentDirectory.appendingPathComponent("hdr.mp4") if FileManager.default.fileExists(atPath: videoOutputURL.path) { do { try FileManager.default.removeItem(atPath: videoOutputURL.path) } catch { fatalError("Unable to delete file: \(error) : \(#function).") } } guard let videoWriter = try? AVAssetWriter(outputURL: videoOutputURL, fileType: AVFileType.mov) else{ fatalError("AVAssetWriter creat error") } let outputSize = (self.imageView?.image?.size)! let outputSettings = [ AVVideoCodecKey: AVVideoCodecType.hevc, AVVideoWidthKey : NSNumber(value: Float(outputSize.width)), AVVideoHeightKey : NSNumber(value: Float(outputSize.height)), // AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_2100_HLG, // AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_2020, // AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_2020, // AVVideoProfileLevelKey: kVTProfileLevel_HEVC_Main10_AutoLevel AVVideoColorPropertiesKey : [ AVVideoTransferFunctionKey: AVVideoTransferFunction_ITU_R_2100_HLG, AVVideoColorPrimariesKey: AVVideoColorPrimaries_ITU_R_2020, AVVideoYCbCrMatrixKey: AVVideoYCbCrMatrix_ITU_R_2020 ], AVVideoCompressionPropertiesKey: [AVVideoProfileLevelKey:kVTProfileLevel_HEVC_Main10_AutoLevel,AVVideoAverageBitRateKey:NSNumber(value: Float(3000000))] ] as [String:Any] guard videoWriter.canApply(outputSettings: outputSettings, forMediaType: .video) else { fatalError("输出设定不支持") } // let av = AVAsset(url: <#T##URL#>) // guard let exportSession = AVAssetExportSession(asset: <#T##AVAsset#>, presetName: <#T##String#>) let videoWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: outputSettings) let sourcePixelBufferAttributesDictionary = [ kCVPixelBufferPixelFormatTypeKey as String : NSNumber(value: kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange), kCVPixelBufferWidthKey as String: NSNumber(value: Float(outputSize.width)), kCVPixelBufferHeightKey as String: NSNumber(value: Float(outputSize.height)) ] pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoWriterInput, sourcePixelBufferAttributes: sourcePixelBufferAttributesDictionary) if videoWriter.canAdd(videoWriterInput){ videoWriter.add(videoWriterInput) } if videoWriter.startWriting(){ videoWriter.startSession(atSourceTime: .zero) assert(pixelBufferAdaptor?.pixelBufferPool != nil) let madia_queue = DispatchQueue(label: "madiaInputQueue") videoWriterInput.requestMediaDataWhenReady(on: madia_queue) { [self] in let fps: Int32 = 30 let frameDuration = CMTimeMake(value: 1, timescale: fps) var frameCount: Int64 = 0 var appendSucceded = true // do data things // 1st frame var lastFrameTime = CMTime(value: frameCount, timescale: fps) var presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration) var pixelBuffer: CVPixelBuffer? // DispatchQueue.main.sync { // pixelBuffer = buffer(from: (self.imageView?.image!)!) pixelBuffer = buffer(from: hdrimage!) // } guard let pixelBuffer = pixelBuffer else { return } while ( frameCount < 90 ){ if videoWriterInput.isReadyForMoreMediaData { lastFrameTime = CMTime(value: frameCount, timescale: fps) presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration) appendSucceded = ((pixelBufferAdaptor?.append(pixelBuffer, withPresentationTime: presentationTime)) != nil) } else { print("append fail") appendSucceded = false // sleep(1) continue } if !appendSucceded{ sleep(1) break } print(frameCount) frameCount = frameCount + 1 } // sleep(1) videoWriterInput.markAsFinished() videoWriter.finishWriting { print("done") self.saveVideoToLibrary(videoURL: videoOutputURL) } } } } func saveVideoToLibrary(videoURL: URL) { PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL) }) { saved, error in if let error = error { print("Error saving video to librayr: \(error.localizedDescription)") } if saved { print("Video save to library") } } } func buffer(from ciimage:CIImage) -> CVPixelBuffer?{ let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary var pixelBuffer : CVPixelBuffer? let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(ciimage.extent.width), Int(ciimage.extent.height), kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, attrs, &pixelBuffer) guard (status == kCVReturnSuccess) else { return nil } let context = CIContext() let cs = context.workingColorSpace print(cs) context.render(ciimage, to: pixelBuffer!, bounds: ciimage.extent, colorSpace: CGColorSpace(name: CGColorSpace.extendedITUR_2020)) return pixelBuffer } func hdrImagePixelBuffer(uiImage:UIImage) -> CIImage?{ let colorSpace = CGColorSpace(name: CGColorSpace.itur_709)! let ci = ciImage!.matchedFromWorkingSpace(to: colorSpace) let brightness: CIColorKernel = { let url = Bundle.main.url(forResource: "default", withExtension: ".metallib")! let data = try! Data.init(contentsOf: url) let nn = CIColorKernel.kernelNames(fromMetalLibraryData: data) // CIColorKernel.kernelNames(fromMetalLibraryData: ) print(nn) return try! CIColorKernel(functionName: "HDRHighlight", fromMetalLibraryData: data) }() let width = uiImage.size.width let height = uiImage.size.height let extent = CGRect(x: 0, y: 0, width: width, height: height) guard let final = brightness.apply(extent: extent, roiCallback: {(index,rect) in return rect }, arguments: [ci]) else { return nil } // let outcs = CGColorSpace(name: CGColorSpace.displayP3_PQ) return final }
弱鸡的苹果文档,无力吐槽了
关键代码
重点是这个设置