return } _streamingCounter += 1 _timer = DispatchSource.makeTimerSource(flags: .strict, queue: _timerQueue) _timer!.schedule(deadline: .now(), repeating: 1.0 / Double(kFrameRate), leeway: .seconds(0)) _timer!.setEventHandler { var err: OSStatus = 0 let now = CMClockGetTime(CMClockGetHostTimeClock()) var pixelBuffer: CVPixelBuffer? err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, self._bufferPool, self._bufferAuxAttributes, &pixelBuffer) if err != 0 { os_log(.error, "out of pixel buffers \(err)") } if let pixelBuffer = pixelBuffer { CVPixelBufferLockBaseAddress(pixelBuffer, []) var bufferPtr = CVPixelBufferGetBaseAddress(pixelBuffer)! let width = CVPixelBufferGetWidth(pixelBuffer) let height = CVPixelBufferGetHeight(pixelBuffer) let rowBytes = CVPixelBufferGetBytesPerRow(pixelBuffer) memset(bufferPtr, 0, rowBytes * height) let whiteStripeStartRow = self._whiteStripeStartRow if self._whiteStripeIsAscending { self._whiteStripeStartRow = whiteStripeStartRow - 1 self._whiteStripeIsAscending = self._whiteStripeStartRow > 0 } else { self._whiteStripeStartRow = whiteStripeStartRow + 1 self._whiteStripeIsAscending = self._whiteStripeStartRow >= (height - kWhiteStripeHeight) } bufferPtr += rowBytes * Int(whiteStripeStartRow) for _ in 0..<kWhiteStripeHeight { for _ in 0..<width { var white: UInt32 = 0xFFFFFFFF memcpy(bufferPtr, &white, MemoryLayout.size(ofValue: white)) bufferPtr += MemoryLayout.size(ofValue: white) } } CVPixelBufferUnlockBaseAddress(pixelBuffer, []) var sbuf: CMSampleBuffer! var timingInfo = CMSampleTimingInfo() timingInfo.presentationTimeStamp = CMClockGetTime(CMClockGetHostTimeClock()) err = CMSampleBufferCreateForImageBuffer(allocator: kCFAllocatorDefault, imageBuffer: pixelBuffer, dataReady: true, makeDataReadyCallback: nil, refcon: nil, formatDescription: self._videoDescription, sampleTiming: &timingInfo, sampleBufferOut: &sbuf) if err == 0 { self._streamSource.stream.send(sbuf, discontinuity: [], hostTimeInNanoseconds: UInt64(timingInfo.presentationTimeStamp.seconds * Double(NSEC_PER_SEC))) } os_log(.info, "video time \(timingInfo.presentationTimeStamp.seconds) now \(now.seconds) err \(err)") } } _timer!.setCancelHandler { } _timer!.resume() } &YUFOTJPO1SPWJEFSTXJGU DMBTT&YUFOTJPO%FWJDF4PVSDF