Skip to content

Commit aee5f01

Browse files
committed
WIP: Copied over stream stuff from 4.0.8
1 parent f58b7af commit aee5f01

2 files changed

Lines changed: 142 additions & 92 deletions

File tree

src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgcvideosinkbin.cc

Lines changed: 141 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
#include "gstqgcvideosinkbin.h"
1111
#include "gstqgcelements.h"
1212

13-
#include <gst/gl/gl.h>
13+
#include <gst/gst.h>
1414

1515
#define GST_CAT_DEFAULT gst_qgc_video_sink_bin_debug
1616
GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT);
1717

18-
#define DEFAULT_ENABLE_LAST_SAMPLE FALSE
18+
#define DEFAULT_ENABLE_LAST_SAMPLE TRUE
1919
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
2020
#define DEFAULT_PAR_N 0
2121
#define DEFAULT_PAR_D 1
@@ -42,15 +42,6 @@ enum
4242

4343
static GParamSpec *properties[PROP_LAST];
4444

45-
enum
46-
{
47-
SIGNAL_0,
48-
SIGNAL_CREATE_ELEMENT,
49-
SIGNAL_LAST
50-
};
51-
52-
static guint gst_qgc_video_sink_bin_signals[SIGNAL_LAST] = { 0 };
53-
5445
#define gst_qgc_video_sink_bin_parent_class parent_class
5546
G_DEFINE_TYPE_WITH_CODE(
5647
GstQgcVideoSinkBin,
@@ -69,10 +60,44 @@ GST_ELEMENT_REGISTER_DEFINE_WITH_CODE(qgcvideosinkbin,"qgcvideosinkbin",
6960

7061
static void gst_qgc_video_sink_bin_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
7162
static void gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
72-
static GstElement *gst_qgc_video_sink_bin_on_glsinkbin_create_element(GstElement *object, gpointer udata);
7363
static void gst_qgc_video_sink_bin_dispose(GObject *object);
7464
static void gst_qgc_video_sink_bin_finalize(GObject *object);
7565

66+
// Query function to forward caps queries to glupload and context queries to qmlglsink
67+
static gboolean
68+
gst_qgc_video_sink_bin_sink_pad_query(GstPad *pad, GstObject *parent, GstQuery *query)
69+
{
70+
GstQgcVideoSinkBin *self = GST_QGC_VIDEO_SINK_BIN(parent);
71+
GstElement *element = NULL;
72+
73+
switch (GST_QUERY_TYPE(query)) {
74+
case GST_QUERY_CAPS:
75+
element = self->glupload;
76+
break;
77+
case GST_QUERY_CONTEXT:
78+
element = self->qmlglsink;
79+
break;
80+
default:
81+
return gst_pad_query_default(pad, parent, query);
82+
}
83+
84+
if (!element) {
85+
GST_ERROR_OBJECT(self, "No element found for query");
86+
return FALSE;
87+
}
88+
89+
GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
90+
if (!sinkpad) {
91+
GST_ERROR_OBJECT(self, "No sink pad found on element");
92+
return FALSE;
93+
}
94+
95+
gboolean ret = gst_pad_query(sinkpad, query);
96+
gst_object_unref(sinkpad);
97+
98+
return ret;
99+
}
100+
76101
static void
77102
gst_qgc_video_sink_bin_class_init(GstQgcVideoSinkBinClass *klass)
78103
{
@@ -100,7 +125,7 @@ gst_qgc_video_sink_bin_class_init(GstQgcVideoSinkBinClass *klass)
100125

101126
properties[PROP_WIDGET] = g_param_spec_pointer(
102127
"widget", "QQuickItem",
103-
"Owning QML item handed off to qml6glsink",
128+
"Owning QML item - handed off to qml6glsink",
104129
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
105130
);
106131

@@ -129,17 +154,6 @@ gst_qgc_video_sink_bin_class_init(GstQgcVideoSinkBinClass *klass)
129154

130155
g_object_class_install_properties(object_class, PROP_LAST, properties);
131156

132-
gst_qgc_video_sink_bin_signals[SIGNAL_CREATE_ELEMENT] = g_signal_new(
133-
"create-element", /* name */
134-
G_TYPE_FROM_CLASS(klass), /* owner type */
135-
G_SIGNAL_RUN_LAST, /* flags */
136-
0, /* class offset for default handler */
137-
NULL, NULL, /* accumulator / accu-data */
138-
NULL, /* generic marshaller */
139-
GST_TYPE_ELEMENT, /* return type */
140-
0 /* param count */
141-
);
142-
143157
gst_element_class_set_static_metadata(element_class,
144158
"QGC Video Sink Bin", "Sink/Video/Bin",
145159
"GL accelerated video sink wrapper used by QGroundControl",
@@ -150,49 +164,92 @@ gst_qgc_video_sink_bin_class_init(GstQgcVideoSinkBinClass *klass)
150164
static void
151165
gst_qgc_video_sink_bin_init(GstQgcVideoSinkBin *self)
152166
{
153-
self->glsinkbin = gst_element_factory_make("glsinkbin", NULL);
154-
if (!self->glsinkbin) {
155-
GST_ERROR_OBJECT(self, "gst_element_factory_make('glsinkbin') failed");
156-
return;
157-
}
167+
gboolean initialized = FALSE;
168+
GstElement *glcolorconvert = NULL;
169+
GstPad *pad = NULL;
170+
171+
do {
172+
// Create glupload element
173+
self->glupload = gst_element_factory_make("glupload", NULL);
174+
if (!self->glupload) {
175+
GST_ERROR_OBJECT(self, "gst_element_factory_make('glupload') failed");
176+
break;
177+
}
158178

159-
self->qmlglsink = gst_element_factory_make("qml6glsink", NULL);
160-
if (!self->qmlglsink) {
161-
GST_ERROR_OBJECT(self, "gst_element_factory_make('qml6glsink') failed");
162-
return;
163-
}
179+
// Create qml6glsink element
180+
self->qmlglsink = gst_element_factory_make("qml6glsink", NULL);
181+
if (!self->qmlglsink) {
182+
GST_ERROR_OBJECT(self, "gst_element_factory_make('qml6glsink') failed");
183+
break;
184+
}
164185

165-
g_object_set(self->glsinkbin,
166-
"sink", self->qmlglsink,
167-
PROP_ENABLE_LAST_SAMPLE_NAME, FALSE,
168-
NULL);
186+
// Create glcolorconvert element
187+
glcolorconvert = gst_element_factory_make("glcolorconvert", NULL);
188+
if (!glcolorconvert) {
189+
GST_ERROR_OBJECT(self, "gst_element_factory_make('glcolorconvert') failed");
190+
break;
191+
}
169192

170-
g_return_if_fail(gst_bin_add(GST_BIN(self), self->glsinkbin));
193+
// Get sink pad from glupload for ghost pad
194+
pad = gst_element_get_static_pad(self->glupload, "sink");
195+
if (!pad) {
196+
GST_ERROR_OBJECT(self, "gst_element_get_static_pad(glupload, 'sink') failed");
197+
break;
198+
}
171199

172-
g_signal_connect(self->glsinkbin,
173-
"create-element",
174-
G_CALLBACK(gst_qgc_video_sink_bin_on_glsinkbin_create_element),
175-
self);
200+
// Keep references to our elements
201+
gst_object_ref(self->glupload);
202+
gst_object_ref(self->qmlglsink);
176203

177-
GstPad *sinkpad = gst_element_get_static_pad(self->glsinkbin, "sink");
178-
if (!sinkpad) {
179-
GST_ERROR_OBJECT(self, "gst_element_get_static_pad('sink') failed");
180-
return;
181-
}
204+
// Add all elements to bin
205+
gst_bin_add_many(GST_BIN(self), self->glupload, glcolorconvert, self->qmlglsink, NULL);
182206

183-
GstPad *ghostpad = gst_ghost_pad_new("sink", sinkpad);
184-
if (!ghostpad) {
185-
GST_ERROR_OBJECT(self, "gst_ghost_pad_new('sink') failed");
186-
gst_object_unref(sinkpad);
187-
return;
207+
// Link: glupload -> glcolorconvert -> qmlglsink
208+
if (!gst_element_link_many(self->glupload, glcolorconvert, self->qmlglsink, NULL)) {
209+
GST_ERROR_OBJECT(self, "gst_element_link_many() failed");
210+
break;
211+
}
212+
213+
// glcolorconvert is now owned by the bin, clear our reference
214+
glcolorconvert = NULL;
215+
216+
// Create ghost pad for the bin's sink
217+
GstPad *ghostpad = gst_ghost_pad_new("sink", pad);
218+
if (!ghostpad) {
219+
GST_ERROR_OBJECT(self, "gst_ghost_pad_new('sink') failed");
220+
break;
221+
}
222+
223+
// Set custom query function to forward caps/context queries
224+
gst_pad_set_query_function(ghostpad, gst_qgc_video_sink_bin_sink_pad_query);
225+
226+
if (!gst_element_add_pad(GST_ELEMENT(self), ghostpad)) {
227+
GST_ERROR_OBJECT(self, "gst_element_add_pad() failed");
228+
break;
229+
}
230+
231+
initialized = TRUE;
232+
} while (0);
233+
234+
if (pad) {
235+
gst_object_unref(pad);
236+
pad = NULL;
188237
}
189238

190-
if (!gst_element_add_pad(GST_ELEMENT(self), ghostpad)) {
191-
GST_ERROR_OBJECT(self, "gst_element_add_pad() failed");
239+
if (glcolorconvert) {
240+
gst_object_unref(glcolorconvert);
241+
glcolorconvert = NULL;
192242
}
193243

194-
if (sinkpad) {
195-
gst_object_unref(sinkpad);
244+
if (!initialized) {
245+
if (self->qmlglsink) {
246+
gst_object_unref(self->qmlglsink);
247+
self->qmlglsink = NULL;
248+
}
249+
if (self->glupload) {
250+
gst_object_unref(self->glupload);
251+
self->glupload = NULL;
252+
}
196253
}
197254
}
198255

@@ -201,9 +258,13 @@ gst_qgc_video_sink_bin_set_property(GObject *object, guint prop_id, const GValue
201258
{
202259
GstQgcVideoSinkBin *self = GST_QGC_VIDEO_SINK_BIN(object);
203260

261+
if (!self->qmlglsink) {
262+
return;
263+
}
264+
204265
switch (prop_id) {
205266
case PROP_ENABLE_LAST_SAMPLE:
206-
g_object_set(self->glsinkbin,
267+
g_object_set(self->qmlglsink,
207268
PROP_ENABLE_LAST_SAMPLE_NAME,
208269
g_value_get_boolean(value),
209270
NULL);
@@ -215,23 +276,20 @@ gst_qgc_video_sink_bin_set_property(GObject *object, guint prop_id, const GValue
215276
NULL);
216277
break;
217278
case PROP_FORCE_ASPECT_RATIO:
218-
g_object_set(self->glsinkbin,
279+
g_object_set(self->qmlglsink,
219280
PROP_FORCE_ASPECT_RATIO_NAME,
220281
g_value_get_boolean(value),
221282
NULL);
222283
break;
223-
case PROP_PIXEL_ASPECT_RATIO: {
224-
const gint num = gst_value_get_fraction_numerator(value);
225-
const gint den = gst_value_get_fraction_denominator(value);
284+
case PROP_PIXEL_ASPECT_RATIO:
226285
g_object_set(self->qmlglsink,
227286
PROP_PIXEL_ASPECT_RATIO_NAME,
228-
num,
229-
den,
287+
gst_value_get_fraction_numerator(value),
288+
gst_value_get_fraction_denominator(value),
230289
NULL);
231290
break;
232-
}
233291
case PROP_SYNC:
234-
g_object_set(self->glsinkbin,
292+
g_object_set(self->qmlglsink,
235293
PROP_SYNC_NAME,
236294
g_value_get_boolean(value),
237295
NULL);
@@ -247,10 +305,14 @@ gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *valu
247305
{
248306
GstQgcVideoSinkBin *self = GST_QGC_VIDEO_SINK_BIN(object);
249307

308+
if (!self->qmlglsink) {
309+
return;
310+
}
311+
250312
switch (prop_id) {
251313
case PROP_ENABLE_LAST_SAMPLE: {
252314
gboolean enable = FALSE;
253-
g_object_get(self->glsinkbin,
315+
g_object_get(self->qmlglsink,
254316
PROP_ENABLE_LAST_SAMPLE_NAME,
255317
&enable,
256318
NULL);
@@ -259,7 +321,7 @@ gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *valu
259321
}
260322
case PROP_LAST_SAMPLE: {
261323
GstSample *sample = NULL;
262-
g_object_get(self->glsinkbin,
324+
g_object_get(self->qmlglsink,
263325
PROP_LAST_SAMPLE_NAME,
264326
&sample,
265327
NULL);
@@ -280,7 +342,7 @@ gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *valu
280342
}
281343
case PROP_FORCE_ASPECT_RATIO: {
282344
gboolean enable = FALSE;
283-
g_object_get(self->glsinkbin,
345+
g_object_get(self->qmlglsink,
284346
PROP_FORCE_ASPECT_RATIO_NAME,
285347
&enable,
286348
NULL);
@@ -298,7 +360,7 @@ gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *valu
298360
}
299361
case PROP_SYNC: {
300362
gboolean enable = FALSE;
301-
g_object_get(self->glsinkbin,
363+
g_object_get(self->qmlglsink,
302364
PROP_SYNC_NAME,
303365
&enable,
304366
NULL);
@@ -311,38 +373,26 @@ gst_qgc_video_sink_bin_get_property(GObject *object, guint prop_id, GValue *valu
311373
}
312374
}
313375

314-
static GstElement *
315-
gst_qgc_video_sink_bin_on_glsinkbin_create_element(GstElement *object, gpointer udata)
316-
{
317-
GstBin *glsinkbin = GST_BIN(object);
318-
GstQgcVideoSinkBin *qgcVideoSinkBin = GST_QGC_VIDEO_SINK_BIN(udata);
319-
320-
qgcVideoSinkBin->glsinkbin = GST_ELEMENT(glsinkbin);
321-
qgcVideoSinkBin->qmlglsink = gst_element_factory_make("qml6glsink", NULL);
322-
if (!qgcVideoSinkBin->qmlglsink) {
323-
GST_ERROR_OBJECT(qgcVideoSinkBin, "gst_element_factory_make('qml6glsink') failed");
324-
g_signal_emit(GST_ELEMENT(qgcVideoSinkBin), gst_qgc_video_sink_bin_signals[SIGNAL_CREATE_ELEMENT], 0, &qgcVideoSinkBin->qmlglsink);
325-
}
326-
327-
return qgcVideoSinkBin->qmlglsink;
328-
}
329-
330376
static void
331377
gst_qgc_video_sink_bin_dispose(GObject *object)
332378
{
333379
GstQgcVideoSinkBin *self = GST_QGC_VIDEO_SINK_BIN(object);
334380

335-
(void) self;
381+
if (self->qmlglsink) {
382+
gst_object_unref(self->qmlglsink);
383+
self->qmlglsink = NULL;
384+
}
385+
386+
if (self->glupload) {
387+
gst_object_unref(self->glupload);
388+
self->glupload = NULL;
389+
}
336390

337391
G_OBJECT_CLASS(parent_class)->dispose(object);
338392
}
339393

340394
static void
341395
gst_qgc_video_sink_bin_finalize(GObject *object)
342396
{
343-
GstQgcVideoSinkBin *self = GST_QGC_VIDEO_SINK_BIN(object);
344-
345-
(void) self;
346-
347397
G_OBJECT_CLASS(parent_class)->finalize(object);
348398
}

src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgcvideosinkbin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ G_DECLARE_FINAL_TYPE (GstQgcVideoSinkBin, gst_qgc_video_sink_bin, GST, QGC_VIDEO
1919
struct _GstQgcVideoSinkBin
2020
{
2121
GstBin parent;
22-
GstElement *glsinkbin;
22+
GstElement *glupload;
2323
GstElement *qmlglsink;
2424
};
2525

0 commit comments

Comments
 (0)