66- (
void)captureOutput:(AVCaptureOutput *)captureOutput
67 didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
68 fromConnection:(AVCaptureConnection *)connection
70 Q_UNUSED(captureOutput);
75 CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
76 if (!imageBuffer || CFGetTypeID(imageBuffer) != CVPixelBufferGetTypeID()) {
77 qWarning() <<
"Cannot get image buffer from sample buffer";
81 auto pixelBuffer = QAVFHelpers::QSharedCVPixelBuffer(
83 QAVFHelpers::QSharedCVPixelBuffer::RefMode::NeedsRef);
88 q23::expected<QAVFHelpers::QSharedCVPixelBuffer, QString> copyResult =
89 QFFmpeg::deepCopyCvPixelBuffer(pixelBuffer.get());
91 qCWarning(qLcAvfSampleBufferDelegate)
92 <<
"Failed to copy incoming pixel buffer:" << copyResult.error();
95 pixelBuffer = std::move(*copyResult);
97 QSize incomingFrameSize {
98 static_cast<
int>(CVPixelBufferGetWidth(pixelBuffer.get())),
99 static_cast<
int>(CVPixelBufferGetHeight(pixelBuffer.get())) };
100 Q_ASSERT(!incomingFrameSize.isEmpty());
101 CvPixelFormat incomingCvPixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer.get());
104 m_accel->updateFramesContext(
105 av_map_videotoolbox_format_to_pixfmt(incomingCvPixelFormat),
108 std::chrono::microseconds frameTime =
109 QAVFHelpers::CMTimeToMicroseconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer));
111 baseTime = frameTime;
112 startTime = frameTime;
115 QVideoFrameFormat format = QAVFHelpers::videoFormatForImageBuffer(pixelBuffer.get());
116 if (!format.isValid()) {
117 qWarning() <<
"Cannot get get video format for image buffer"
118 << CVPixelBufferGetWidth(pixelBuffer.get()) <<
'x'
119 << CVPixelBufferGetHeight(pixelBuffer.get());
123 std::optional<QFFmpeg::QAVFSampleBufferDelegateTransform> transform;
124 if (transformationProvider) {
125 transform = transformationProvider(connection);
126 const VideoTransformation &surfaceTransform = transform.value().surfaceTransform;
127 format.setRotation(surfaceTransform.rotation);
128 format.setMirrored(surfaceTransform.mirroredHorizontallyAfterRotation);
131 format.setStreamFrameRate(frameRate);
134 q23::expected<QVideoFrame, QString> frameResult = QFFmpeg::qVideoFrameFromCvPixelBuffer(
136 startTime - *baseTime,
140 qCWarning(qLcAvfSampleBufferDelegate) << frameResult.error();
142 frame = *frameResult;
144 if (!frame.isValid())
145 frame = QVideoFramePrivate::createFrame(
146 std::make_unique<QFFmpeg::CVImageVideoBuffer>(std::move(pixelBuffer)),
149 if (transform.has_value()) {
150 const VideoTransformation &presentationTransform = transform.value().presentationTransform;
151 frame.setRotation(presentationTransform.rotation);
152 frame.setMirrored(presentationTransform.mirroredHorizontallyAfterRotation);
155 frame.setStartTime((startTime - *baseTime).count());
156 frame.setEndTime((frameTime - *baseTime).count());
157 startTime = frameTime;