Как преобразовать RTCI420Buffer в CMSampleBuffer?

#swift #objective-c #webrtc

#swift #objective-c #webrtc

Вопрос:

Прежде всего, извините, я не знаком с английским языком.

Я пытаюсь записать удаленное видео на webrtc.

Однако тип буфера из удаленного фрейма — RTCI420buffer .

Я нашел способ преобразовать rtci420buffer в cmsamplebuffer с помощью поиска в Google.

Буфер добавляется avassetwriter, но выводится только черный экран.

Что-то не так с тем, как я пытался?

Это конвертер, который я использовал. https://gist.github.com/shalyf/69880f70ca9470a1e91440196cb7d127

Это код, который преобразуется в CVPixelBuffer

 func buffer(from image: CIImage) -> CVPixelBuffer? {
    
                let attrs = [kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
    
                var pixelBuffer : CVPixelBuffer?
    
                let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.extent.width), Int(image.extent.height), kCVPixelFormatType_32BGRA, attrs, amp;pixelBuffer)
    
                guard (status == kCVReturnSuccess) else {
                    return nil
                }
    
       return pixelBuffer
}
 

И это мой код для создания cmsamplebuffer

 let pixelBuffer = buffer(from: CIImage(image: Converter.convert(frame))!)
            
            let presentTime = CMTime.init(value: frame.timeStampNs, timescale: CMTimeScale(powf(10.0, 9.0)))
            var sampleBuffer: CMSampleBuffer? = nil
            var timimgInfo: CMSampleTimingInfo = CMSampleTimingInfo.init(duration: CMTime.indefinite, presentationTimeStamp: presentTime, decodeTimeStamp: CMTime.indefinite)
            var videoInfo: CMVideoFormatDescription? = nil

            CMVideoFormatDescriptionCreateForImageBuffer(allocator: nil,
                                                         imageBuffer: pixelBuffer!,
                                                         formatDescriptionOut: amp;videoInfo)
            CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault,
                                               imageBuffer:  pixelBuffer!,
                                               dataReady: true,
                                               makeDataReadyCallback: nil,
                                               refcon: nil,
                                               formatDescription: videoInfo!,
                                               sampleTiming: amp;timimgInfo,
                                               sampleBufferOut: amp;sampleBuffer)
 

И это мои локальные настройки AVAssetWriter

 self.assetWriter!.movieFragmentInterval = CMTimeMakeWithSeconds(1.0, preferredTimescale: 1000)
        var localSettings:[String:AnyObject] = Dictionary.init()
        localSettings[AVVideoWidthKey] =  NSNumber.init(value: Float(videoSize.width))
        localSettings[AVVideoHeightKey] = NSNumber.init(value: Float(videoSize.height))
        localSettings[AVVideoCodecKey] =  AVVideoCodecType.h264 as NSString
        
        self.videoWriteInput = AVAssetWriterInput(mediaType:AVMediaType.video, outputSettings:localSettings)
 

Это CMSampleBuffer

 Optional(CMSampleBuffer 0x115d928e0 retainCount: 9 allocator: 0x1f3225860
    invalid = NO
    dataReady = YES
    makeDataReadyCallback = 0x0
    makeDataReadyRefcon = 0x0
    formatDescription = <CMVideoFormatDescription 0x280c6c420 [0x1f3225860]> {
    mediaType:'vide' 
    mediaSubType:'BGRA' 
    mediaSpecific: {
        codecType: 'BGRA'       dimensions: 1280 x 720 
    } 
    extensions: {{
    CVBytesPerRow = 5120;
    Version = 2;
}}
}
    sbufToTrackReadiness = 0x0
    numSamples = 1
    outputPTS = {60493883000000/1000000000 = 60493.883}(based on cachedOutputPresentationTimeStamp)
    sampleTimingArray[1] = {
        {PTS = {60493883000000/1000000000 = 60493.883}, DTS = {INDEFINITE}, duration = {INDEFINITE}},
    }
    imageBuffer = 0x28339d540
)
 

Комментарии:

1. Ваш вопрос понятен. Но TBH это слишком много для распаковки. Слишком много мест, чтобы скрыть ошибку. Не могли бы вы попробовать разделить каждую часть как подпрограмму и попробовать протестировать ее отдельно? Например. сделайте неподвижное изображение и убедитесь, что ваш AVAssetWriter работает. Затем создайте все еще предопределенное изображение CIImage и убедитесь, что преобразование в CMSampleBuffer работает и т. Д. Побочное замечание заключается в том, что вы хотите получить файл H264, но вместо того, чтобы записывать его из wire, вы позволяете WebRTC сначала его декодировать, затем выполняете кучу преобразований и снова кодируете. Для меня это пустая трата процессора…