31
31
#include "gstcamerabinpreview.h"
32
32
#include "gstbasecamerasrc.h"
35
gst_camerabin_preview_pipeline_new_preroll (GstAppSink * appsink,
34
GST_DEBUG_CATEGORY_EXTERN (base_camera_src_debug);
35
#define GST_CAT_DEFAULT base_camera_src_debug
37
static void _gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData *
38
preview, GstCaps * caps);
41
bus_callback (GstBus * bus, GstMessage * message, gpointer user_data)
40
buffer = gst_app_sink_pull_preroll (appsink);
41
gst_buffer_unref (buffer);
43
switch (GST_MESSAGE_TYPE (message)) {
44
case GST_MESSAGE_ERROR:{
46
GstCameraBinPreviewPipelineData *data;
50
gst_message_parse_error (message, &err, NULL);
51
GST_WARNING ("Error from preview pipeline: %s", err->message);
54
/* TODO Not sure if we should post an Error or Warning here */
55
GST_ELEMENT_ERROR (data, CORE, FAILED,
56
("fatal error in preview pipeline, disposing the pipeline"), (NULL));
58
/* Possible error situations:
59
* 1) cond_wait pending. prevent deadlock by signalling the cond
60
* 2) preview_pipeline_post called with new buffer to handle. returns
61
* because data->pipeline is set to null
62
* 3) new preview caps incoming. returns because data->pipeline is null
66
gst_element_set_state (data->pipeline, GST_STATE_NULL);
67
gst_object_unref (data->pipeline);
68
data->pipeline = NULL;
71
g_cond_signal (data->processing_cond);
46
81
static GstFlowReturn
86
129
GstCameraBinPreviewPipelineData *data;
89
131
GstElement *vscale;
90
132
gboolean added = FALSE;
133
gboolean linkfail = FALSE;
91
135
GstAppSinkCallbacks callbacks = { 0, };
93
data = g_new (GstCameraBinPreviewPipelineData, 1);
137
data = g_new0 (GstCameraBinPreviewPipelineData, 1);
95
139
data->pipeline = gst_pipeline_new ("preview-pipeline");
96
140
data->appsrc = gst_element_factory_make ("appsrc", "preview-appsrc");
97
data->capsfilter = gst_element_factory_make ("capsfilter",
98
"preview-capsfilter");
99
141
data->appsink = gst_element_factory_make ("appsink", "preview-appsink");
100
csp = gst_element_factory_make ("ffmpegcolorspace", "preview-csp0");
101
csp2 = gst_element_factory_make ("ffmpegcolorspace", "preview-csp1");
142
csp = gst_element_factory_make ("ffmpegcolorspace", "preview-csp");
102
143
vscale = gst_element_factory_make ("videoscale", "preview-vscale");
104
if (!data->appsrc || !data->capsfilter || !data->appsink || !csp ||
145
if (!data->appsrc || !data->appsink || !csp || !vscale) {
109
gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter,
110
data->appsink, csp, csp2, vscale, NULL);
149
g_object_set (data->appsrc, "emit-signals", FALSE, NULL);
150
g_object_set (data->appsink, "sync", FALSE, "enable-last-buffer",
153
gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc,
154
data->appsink, csp, vscale, NULL);
112
156
gst_bin_add (GST_BIN (data->pipeline), gst_object_ref (filter));
116
if (!gst_element_link_many (data->appsrc, filter, csp, vscale, csp2,
117
data->capsfilter, data->appsink, NULL))
161
GST_PAD_LINK_FAILED (gst_element_link_pads_full (data->appsrc, "src",
162
filter, NULL, GST_PAD_LINK_CHECK_NOTHING));
164
GST_PAD_LINK_FAILED (gst_element_link_pads_full (filter, NULL,
165
vscale, "sink", GST_PAD_LINK_CHECK_CAPS));
120
if (!gst_element_link_many (data->appsrc, csp, vscale, csp2,
121
data->capsfilter, data->appsink, NULL))
125
callbacks.new_preroll = gst_camerabin_preview_pipeline_new_preroll;
168
GST_PAD_LINK_FAILED (gst_element_link_pads_full (data->appsrc, "src",
169
vscale, "sink", GST_PAD_LINK_CHECK_NOTHING));
173
GST_PAD_LINK_FAILED (gst_element_link_pads_full (vscale, "src", csp,
174
"sink", GST_PAD_LINK_CHECK_NOTHING));
176
GST_PAD_LINK_FAILED (gst_element_link_pads_full (csp, "src",
177
data->appsink, "sink", GST_PAD_LINK_CHECK_NOTHING));
180
GST_WARNING ("Failed to link preview pipeline elements");
126
184
callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer;
127
185
gst_app_sink_set_callbacks ((GstAppSink *) data->appsink, &callbacks, data,
188
bus = gst_pipeline_get_bus (GST_PIPELINE (data->pipeline));
189
gst_bus_add_watch (bus, bus_callback, data);
190
gst_object_unref (bus);
130
192
g_object_set (data->appsink, "sync", FALSE, NULL);
132
194
data->element = element;
133
195
data->filter = filter;
196
data->vscale = vscale;
198
data->processing_lock = g_mutex_new ();
199
data->processing_cond = g_cond_new ();
201
data->pending_preview_caps = NULL;
202
data->processing = 0;
188
263
g_return_val_if_fail (preview->pipeline != NULL, FALSE);
189
264
g_return_val_if_fail (buffer, FALSE);
266
g_mutex_lock (preview->processing_lock);
267
g_return_val_if_fail (preview->pipeline != NULL, FALSE);
269
if (preview->pending_preview_caps) {
270
if (preview->processing > 0) {
271
g_cond_wait (preview->processing_cond, preview->processing_lock);
273
_gst_camerabin_preview_set_caps (preview, preview->pending_preview_caps);
274
gst_caps_replace (&preview->pending_preview_caps, NULL);
277
preview->processing++;
191
279
gst_app_src_push_buffer ((GstAppSrc *) preview->appsrc,
192
280
gst_buffer_ref (buffer));
282
g_mutex_unlock (preview->processing_lock);
198
* gst_camerabin_preview_set_caps:
199
* @preview: the #GstCameraBinPreviewPipelineData
200
* @caps: the #GstCaps to be set
202
* The caps that preview buffers should have when posted
206
gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview,
288
_gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview,
209
291
GstState state, pending;
210
292
GstStateChangeReturn ret;
212
294
g_return_if_fail (preview != NULL);
295
g_return_if_fail (preview->pipeline != NULL);
214
297
ret = gst_element_get_state (preview->pipeline, &state, &pending, 0);
215
298
if (ret == GST_STATE_CHANGE_FAILURE) {
217
300
state = GST_STATE_PLAYING;
218
301
pending = GST_STATE_VOID_PENDING;
221
303
gst_element_set_state (preview->pipeline, GST_STATE_NULL);
222
g_object_set (preview->capsfilter, "caps", caps, NULL);
304
g_object_set (preview->appsink, "caps", caps, NULL);
223
305
if (pending != GST_STATE_VOID_PENDING)
225
307
gst_element_set_state (preview->pipeline, state);
311
* gst_camerabin_preview_set_caps:
312
* @preview: the #GstCameraBinPreviewPipelineData
313
* @caps: the #GstCaps to be set (a new ref will be taken)
315
* The caps that preview buffers should have when posted
319
gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview,
322
g_return_if_fail (preview != NULL);
324
g_mutex_lock (preview->processing_lock);
326
if (preview->processing == 0) {
327
_gst_camerabin_preview_set_caps (preview, caps);
329
GST_DEBUG ("Preview pipeline busy, storing new caps as pending");
330
gst_caps_replace (&preview->pending_preview_caps, caps);
332
g_mutex_unlock (preview->processing_lock);
336
* gst_camerabin_preview_set_filter:
337
* @preview: the #GstCameraBinPreviewPipelineData
338
* @filter: Custom filter to process preview data (an extra ref is taken)
340
* Set the filter element into preview pipeline.
342
* Returns: %TRUE on success
345
gst_camerabin_preview_set_filter (GstCameraBinPreviewPipelineData * preview,
351
g_return_val_if_fail (preview != NULL, FALSE);
353
GST_DEBUG ("Preview pipeline setting new filter %p", filter);
355
g_mutex_lock (preview->processing_lock);
357
gst_element_get_state (preview->pipeline, ¤t, NULL, 0);
359
if (preview->processing == 0 && current == GST_STATE_NULL) {
360
gboolean linkfail = FALSE;
362
if (preview->filter) {
363
/* Unlink and remove old filter */
364
gst_element_unlink (preview->appsrc, preview->filter);
365
gst_element_unlink (preview->filter, preview->vscale);
366
gst_bin_remove (GST_BIN (preview->pipeline), preview->filter);
368
/* Make room for filter by breaking the link between appsrc and vcale */
369
gst_element_unlink (preview->appsrc, preview->vscale);
373
/* Add and link the new filter between appsrc and vscale */
374
gst_bin_add (GST_BIN (preview->pipeline), gst_object_ref (filter));
377
GST_PAD_LINK_FAILED (gst_element_link_pads_full (preview->appsrc,
378
"src", filter, NULL, GST_PAD_LINK_CHECK_NOTHING));
381
GST_PAD_LINK_FAILED (gst_element_link_pads_full (filter, NULL,
382
preview->vscale, "sink", GST_PAD_LINK_CHECK_CAPS));
384
/* No filter was given. Just link the appsrc to vscale directly */
386
GST_PAD_LINK_FAILED (gst_element_link_pads_full (preview->appsrc,
387
"src", preview->vscale, "sink", GST_PAD_LINK_CHECK_NOTHING));
391
GST_WARNING ("Linking the filter to pipeline failed");
394
GST_DEBUG ("Linking the filter to pipeline successful");
395
preview->filter = filter;
398
GST_WARNING ("Cannot change filter when pipeline is running");
401
g_mutex_unlock (preview->processing_lock);