3#include <QtMultimedia/QAbstractVideoBuffer>
4#include <QtMultimedia/QVideoFrame>
7#include <gst/video/gstvideometa.h>
8#include <gst/video/video-hdr.h>
19 case GST_VIDEO_COLOR_MATRIX_BT601:
20 return QVideoFrameFormat::ColorSpace_BT601;
21 case GST_VIDEO_COLOR_MATRIX_BT709:
22 return QVideoFrameFormat::ColorSpace_BT709;
23 case GST_VIDEO_COLOR_MATRIX_BT2020:
24 return QVideoFrameFormat::ColorSpace_BT2020;
25 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
27 return QVideoFrameFormat::ColorSpace_AdobeRgb;
31 return QVideoFrameFormat::ColorSpace_Undefined;
39 case GST_VIDEO_TRANSFER_BT601:
40 return QVideoFrameFormat::ColorTransfer_BT601;
41 case GST_VIDEO_TRANSFER_BT2020_10:
42 case GST_VIDEO_TRANSFER_BT2020_12:
43 case GST_VIDEO_TRANSFER_BT709:
44 return QVideoFrameFormat::ColorTransfer_BT709;
45 case GST_VIDEO_TRANSFER_GAMMA20:
46 return QVideoFrameFormat::ColorTransfer_BT709;
48 case GST_VIDEO_TRANSFER_SMPTE240M:
49 case GST_VIDEO_TRANSFER_GAMMA22:
50 case GST_VIDEO_TRANSFER_SRGB:
51 case GST_VIDEO_TRANSFER_ADOBERGB:
52 return QVideoFrameFormat::ColorTransfer_Gamma22;
53 case GST_VIDEO_TRANSFER_GAMMA18:
54 return QVideoFrameFormat::ColorTransfer_BT709;
55 case GST_VIDEO_TRANSFER_GAMMA28:
56 return QVideoFrameFormat::ColorTransfer_Gamma28;
57 case GST_VIDEO_TRANSFER_GAMMA10:
58 return QVideoFrameFormat::ColorTransfer_Linear;
59 case GST_VIDEO_TRANSFER_SMPTE2084:
60 return QVideoFrameFormat::ColorTransfer_ST2084;
61 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
62 return QVideoFrameFormat::ColorTransfer_STD_B67;
65 return QVideoFrameFormat::ColorTransfer_Unknown;
76 return QVideoFrameFormat::Format_Invalid;
82 case GST_VIDEO_COLOR_RANGE_0_255:
83 return QVideoFrameFormat::ColorRange_Full;
84 case GST_VIDEO_COLOR_RANGE_16_235:
85 return QVideoFrameFormat::ColorRange_Video;
87 return QVideoFrameFormat::ColorRange_Unknown;
96 case GST_VIDEO_ORIENTATION_IDENTITY:
97 frame.setRotation(QtVideo::Rotation::None);
98 frame.setMirrored(
false);
100 case GST_VIDEO_ORIENTATION_90R:
101 frame.setRotation(QtVideo::Rotation::Clockwise90);
102 frame.setMirrored(
false);
104 case GST_VIDEO_ORIENTATION_180:
105 frame.setRotation(QtVideo::Rotation::Clockwise180);
106 frame.setMirrored(
false);
108 case GST_VIDEO_ORIENTATION_90L:
109 frame.setRotation(QtVideo::Rotation::Clockwise270);
110 frame.setMirrored(
false);
112 case GST_VIDEO_ORIENTATION_HORIZ:
113 frame.setRotation(QtVideo::Rotation::None);
114 frame.setMirrored(
true);
116 case GST_VIDEO_ORIENTATION_VERT:
117 frame.setRotation(QtVideo::Rotation::Clockwise180);
118 frame.setMirrored(
true);
120 case GST_VIDEO_ORIENTATION_UL_LR:
121 frame.setRotation(QtVideo::Rotation::Clockwise90);
122 frame.setMirrored(
true);
124 case GST_VIDEO_ORIENTATION_UR_LL:
125 frame.setRotation(QtVideo::Rotation::Clockwise270);
126 frame.setMirrored(
true);
129 static std::atomic<bool> s_warnedUnhandled{
false};
130 if (!s_warnedUnhandled.exchange(
true, std::memory_order_relaxed)) {
131 qCWarning(GStreamerFrameMapLog)
132 <<
"Unhandled GstVideoOrientationMethod" << method <<
"— treating as identity";
134 frame.setRotation(QtVideo::Rotation::None);
135 frame.setMirrored(
false);
144#ifdef QGC_HAS_GST_VIDEO_ORIENTATION_META
145 if (GstVideoOrientationMeta* meta = gst_buffer_get_video_orientation_meta(buffer)) {
149 if (streamOrientation !=
static_cast<int>(GST_VIDEO_ORIENTATION_IDENTITY)) {
152 if (GST_BUFFER_PTS_IS_VALID(buffer)) {
154 frame.setStartTime(GST_BUFFER_PTS(buffer) / GST_USECOND);
155 if (GST_BUFFER_DURATION_IS_VALID(buffer)) {
156 frame.setEndTime((GST_BUFFER_PTS(buffer) + GST_BUFFER_DURATION(buffer)) / GST_USECOND);
159 frame.setEndTime(GST_BUFFER_PTS(buffer) / GST_USECOND);
166 const GstVideoColorimetry& colorimetry = GST_VIDEO_INFO_COLORIMETRY(&info);
167 QVideoFrameFormat::ColorSpace colorSpace =
toQtColorSpace(colorimetry.matrix);
170 if (colorSpace == QVideoFrameFormat::ColorSpace_Undefined) {
171 const int height = GST_VIDEO_INFO_HEIGHT(&info);
173 colorSpace = (height > 576) ? QVideoFrameFormat::ColorSpace_BT709 : QVideoFrameFormat::ColorSpace_BT601;
176 format.setColorSpace(colorSpace);
178 QVideoFrameFormat::ColorRange range =
toQtColorRange(colorimetry.range);
181 const bool knownYuvMatrix =
182 (colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601) || (colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT709) ||
183 (colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT2020) ||
184 (colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_SMPTE240M) || (colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_FCC);
185 if (range == QVideoFrameFormat::ColorRange_Unknown && knownYuvMatrix) {
186 range = QVideoFrameFormat::ColorRange_Video;
188 format.setColorRange(range);
191 GstVideoContentLightLevel cll;
192 bool clipApplied =
false;
193 if (caps && gst_video_content_light_level_from_caps(&cll, caps) && cll.max_content_light_level > 0) {
194 format.setMaxLuminance(
static_cast<float>(cll.max_content_light_level));
198 GstVideoMasteringDisplayInfo masteringInfo;
199 if (caps && gst_video_mastering_display_info_from_caps(&masteringInfo, caps)) {
201 const double maxLuminance =
static_cast<double>(masteringInfo.max_display_mastering_luminance) / 10000.0;
202 if (maxLuminance > 0.0) {
203 format.setMaxLuminance(
static_cast<float>(maxLuminance));
213 if (GstVideoCropMeta* crop = gst_buffer_get_video_crop_meta(buffer)) {
214 format.setViewport(QRect(crop->x, crop->y, crop->width, crop->height));
224#if defined(QGC_HAS_ANY_GPU_PATH)
226 if (hwContext.gpuEnabled) {
229 if (GstSample* sample = gst_sample_new(buffer, caps,
nullptr,
nullptr)) {
230 auto hwBuf =
makeHwVideoBuffer(sample, info, format, hwContext, matchedPath, pathCache);
231 gst_sample_unref(sample);
233 out.
frame = QVideoFrame(std::move(hwBuf));
235 out.gpuPath = matchedPath;
243 out.gpuPath = matchedPath;
246 out.
frame = QVideoFrame(std::move(cpuBuf));
QVideoFrameFormat::PixelFormat toQtPixelFormat(GstVideoFormat fmt)
QVideoFrameFormat::ColorTransfer toQtColorTransfer(GstVideoTransferFunction transfer)
QVideoFrameFormat applyCropMeta(QVideoFrameFormat format, GstBuffer *buffer)
Apply video crop meta to format's viewport. Pass-through when no crop meta present.
void applyColorimetry(QVideoFrameFormat &format, const GstVideoInfo &info, GstCaps *caps)
MappedFrame mapSampleToFrame(GstBuffer *buffer, GstCaps *caps, const GstVideoInfo &info, const QVideoFrameFormat &format, const HwVideoBufferContext &hwContext, HwResolvedPathCache *pathCache) noexcept
QVideoFrameFormat::ColorSpace toQtColorSpace(GstVideoColorMatrix matrix)
Sample-to-frame helpers for qgcqvideosink's show_frame; pure functions, streaming-thread safe.
void applyOrientationAndTiming(QVideoFrame &frame, GstBuffer *buffer, int streamOrientation)
void applyOrientationToFrame(QVideoFrame &frame, GstVideoOrientationMethod method)
Apply rotation + mirror flags derived from GstVideoOrientationMethod.
QVideoFrameFormat::ColorRange toQtColorRange(GstVideoColorRange range)
std::unique_ptr< QHwVideoBuffer > makeHwVideoBuffer(GstSample *sample, const GstVideoInfo &info, QVideoFrameFormat format, const HwVideoBufferContext &context, HwVideoBufferPath &matchedPath, HwResolvedPathCache *cache)
HwVideoBufferPath
Identifies which GPU path was chosen; used by the adapter to increment the right counter.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
static QVideoFrame copyFromBuffer(GstBuffer *buffer, const GstVideoInfo &videoInfo, const QVideoFrameFormat &format)
Copy buffer's planes into a pool-allocated QVideoFrame; invalid on stride overflow or unsupported for...
static std::unique_ptr< QAbstractVideoBuffer > wrapZeroCopy(GstBuffer *buffer, const GstVideoInfo &info, const QVideoFrameFormat &format)
constexpr VideoFormatEntry kVideoFormatTable[]
Platform context for the factory; encapsulates EGL handles so callers don't need path-specific ifdefs...
enum MappedFrame::Source source