4#include <QtMultimedia/private/qtmultimediaglobal_p.h>
7#include <QtCore/qdatetime.h>
8#include <QtCore/qdir.h>
9#include <QtCore/qbytearray.h>
10#include <QtCore/qvariant.h>
11#include <QtCore/qregularexpression.h>
12#include <QtCore/qsize.h>
13#include <QtCore/qset.h>
14#include <QtCore/qstringlist.h>
15#include <QtGui/qimage.h>
17#include <QtCore/qelapsedtimer.h>
18#include <QtMultimedia/qvideoframeformat.h>
19#include <private/qmultimediautils_p.h>
21#include <gst/audio/audio.h>
22#include <gst/video/video.h>
24template<
typename T,
int N>
constexpr int lengthOf(
const T (&)[N]) {
return N; }
33#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
76 if (
s.name() !=
"audio/x-raw")
79 auto rate =
s[
"rate"].toInt();
80 auto channels =
s[
"channels"].toInt();
86 format.setChannelCount(*channels);
104 auto sampleFormat =
format.sampleFormat();
105 auto caps = gst_caps_new_simple(
107 "format" , G_TYPE_STRING, audioSampleFormatNames[sampleFormat],
108 "rate" , G_TYPE_INT ,
format.sampleRate(),
109 "channels", G_TYPE_INT ,
format.channelCount(),
110 "layout" , G_TYPE_STRING,
"interleaved",
118 if (!GST_VALUE_HOLDS_LIST(
value))
122 guint nFormats = gst_value_list_get_size(
value);
123 for (guint
f = 0;
f < nFormats; ++
f) {
125 auto *
name =
v.toString();
139 GstVideoFormat gstFormat;
142static const VideoFormat qt_videoFormatLookup[] =
161#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
172 for (
int i = 0;
i <
lengthOf(qt_videoFormatLookup); ++
i)
173 if (qt_videoFormatLookup[
i].pixelFormat ==
format)
179static int indexOfVideoFormat(GstVideoFormat
format)
181 for (
int i = 0;
i <
lengthOf(qt_videoFormatLookup); ++
i)
182 if (qt_videoFormatLookup[
i].gstFormat ==
format)
192 GstVideoInfo vidInfo;
193 GstVideoInfo *infoPtr =
info ?
info : &vidInfo;
195 if (gst_video_info_from_caps(infoPtr, caps)) {
196 int index = indexOfVideoFormat(infoPtr->finfo->format);
200 QSize(infoPtr->width, infoPtr->height),
201 qt_videoFormatLookup[
index].pixelFormat);
203 if (infoPtr->fps_d > 0)
204 format.setFrameRate(
qreal(infoPtr->fps_n) / infoPtr->fps_d);
207 switch (infoPtr->colorimetry.range) {
208 case GST_VIDEO_COLOR_RANGE_UNKNOWN:
210 case GST_VIDEO_COLOR_RANGE_0_255:
213 case GST_VIDEO_COLOR_RANGE_16_235:
220 switch (infoPtr->colorimetry.matrix) {
221 case GST_VIDEO_COLOR_MATRIX_UNKNOWN:
222 case GST_VIDEO_COLOR_MATRIX_RGB:
223 case GST_VIDEO_COLOR_MATRIX_FCC:
225 case GST_VIDEO_COLOR_MATRIX_BT709:
228 case GST_VIDEO_COLOR_MATRIX_BT601:
231 case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
234 case GST_VIDEO_COLOR_MATRIX_BT2020:
238 format.setColorSpace(colorSpace);
241 switch (infoPtr->colorimetry.transfer) {
242 case GST_VIDEO_TRANSFER_UNKNOWN:
244 case GST_VIDEO_TRANSFER_GAMMA10:
247 case GST_VIDEO_TRANSFER_GAMMA22:
248 case GST_VIDEO_TRANSFER_SMPTE240M:
249 case GST_VIDEO_TRANSFER_SRGB:
250 case GST_VIDEO_TRANSFER_ADOBERGB:
253 case GST_VIDEO_TRANSFER_GAMMA18:
254 case GST_VIDEO_TRANSFER_GAMMA20:
256 case GST_VIDEO_TRANSFER_BT709:
257 case GST_VIDEO_TRANSFER_BT2020_12:
260 case GST_VIDEO_TRANSFER_GAMMA28:
263 case GST_VIDEO_TRANSFER_LOG100:
264 case GST_VIDEO_TRANSFER_LOG316:
266#if GST_CHECK_VERSION(1, 18, 0)
267 case GST_VIDEO_TRANSFER_SMPTE2084:
270 case GST_VIDEO_TRANSFER_ARIB_STD_B67:
273 case GST_VIDEO_TRANSFER_BT2020_10:
276 case GST_VIDEO_TRANSFER_BT601:
281 format.setColorTransfer(transfer);
291 if (!gst_caps_is_writable(caps))
292 caps = gst_caps_make_writable(caps);
295 g_value_init(&
list, GST_TYPE_LIST);
303 g_value_init(&
item, G_TYPE_STRING);
304 g_value_set_string(&
item, gst_video_format_to_string(qt_videoFormatLookup[
index].gstFormat));
305 gst_value_list_append_value(&
list, &
item);
306 g_value_unset(&
item);
309 auto *structure = gst_structure_new(
"video/x-raw",
310 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
311 "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
312 "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
314 gst_structure_set_value(structure,
"format", &
list);
315 gst_caps_append_structure(caps, structure);
316 g_value_unset(&
list);
319 gst_caps_set_features(caps,
size() - 1, gst_caps_features_from_string(modifier));
325 GstStructure *structure =
nullptr;
327 structure = gst_structure_new(
"image/jpeg",
328 "width" , G_TYPE_INT,
size.width(),
329 "height" , G_TYPE_INT,
size.height(),
332 int index = indexOfVideoFormat(
format.pixelFormat());
335 auto gstFormat = qt_videoFormatLookup[
index].gstFormat;
336 structure = gst_structure_new(
"video/x-raw",
337 "format" , G_TYPE_STRING, gst_video_format_to_string(gstFormat),
338 "width" , G_TYPE_INT,
size.width(),
339 "height" , G_TYPE_INT,
size.height(),
343 gst_caps_append_structure(caps.caps, structure);
356 frame->setEndTime((
startTime + duration)/G_GINT64_CONSTANT (1000));
366 gst_structure_get_int(
structure,
"width", &
w) &&
367 gst_structure_get_int(
structure,
"height", &
h)) {
382 if (gst_structure_has_name(
structure,
"video/x-raw")) {
383 const gchar *
s = gst_structure_get_string(
structure,
"format");
385 GstVideoFormat
format = gst_video_format_from_string(
s);
391 }
else if (gst_structure_has_name(
structure,
"image/jpeg")) {
406 auto extractFraction = [] (
const GValue *
v) ->
float {
407 return (
float)gst_value_get_fraction_numerator(
v)/(float)gst_value_get_fraction_denominator(
v);
409 auto extractFrameRate = [&] (
const GValue *
v) {
410 auto insert = [&] (
float min,
float max) {
417 if (GST_VALUE_HOLDS_FRACTION(
v)) {
418 float rate = extractFraction(
v);
420 }
else if (GST_VALUE_HOLDS_FRACTION_RANGE(
v)) {
421 auto *min = gst_value_get_fraction_range_max(
v);
422 auto *max = gst_value_get_fraction_range_max(
v);
423 insert(extractFraction(min), extractFraction(max));
427 const GValue *gstFrameRates = gst_structure_get_value(
structure,
"framerate");
429 if (GST_VALUE_HOLDS_LIST(gstFrameRates)) {
430 guint nFrameRates = gst_value_list_get_size(gstFrameRates);
431 for (guint
f = 0;
f < nFrameRates; ++
f) {
432 extractFrameRate(gst_value_list_get_value(gstFrameRates,
f));
435 extractFrameRate(gstFrameRates);
438 const GValue *min = gst_structure_get_value(
structure,
"min-framerate");
439 const GValue *max = gst_structure_get_value(
structure,
"max-framerate");
441 minRate = extractFraction(min);
442 maxRate = extractFraction(max);
446 return {minRate, maxRate};
451 return gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK
452 | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO,
Q_MULTIMEDIA_EXPORT QList< QAudioFormat::SampleFormat > getSampleFormats() const
void addPixelFormats(const QList< QVideoFrameFormat::PixelFormat > &formats, const char *modifier=nullptr)
static QGstCaps fromCameraFormat(const QCameraFormat &format)
QGstStructure at(int index) const
QVideoFrameFormat formatForCaps(GstVideoInfo *info) const
Q_MULTIMEDIA_EXPORT QSize resolution() const
const GstStructure * structure
Q_MULTIMEDIA_EXPORT QGRange< float > frameRateRange() const
Q_MULTIMEDIA_EXPORT QVideoFrameFormat::PixelFormat pixelFormat() const
The QVideoFrame class represents a frame of video data.
cache insert(employee->id(), employee)
void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer)
Q_MULTIMEDIA_EXPORT QGstCaps capsForAudioFormat(const QAudioFormat &format)
QAudioFormat audioFormatForCaps(const QGstCaps &caps)
Q_MULTIMEDIA_EXPORT QAudioFormat audioFormatForSample(GstSample *sample)
Combined button and popup list for selecting options.
static const char * audioSampleFormatNames[QAudioFormat::NSampleFormats]
static QAudioFormat::SampleFormat gstSampleFormatToSampleFormat(const char *fmt)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GList * qt_gst_video_sinks()
constexpr int lengthOf(const T(&)[N])
GLsizei const GLfloat * v
[13]
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
QVideoFrameFormat::PixelFormat fmt
QFileInfo info(fileName)
[8]
char * toString(const MyType &t)
[31]