~ubuntu-branches/ubuntu/quantal/gst-plugins-bad0.10/quantal-proposed

« back to all changes in this revision

Viewing changes to gst/camerabin/camerabinpreview.c

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2011-07-19 14:32:43 UTC
  • mfrom: (18.4.21 sid)
  • Revision ID: james.westby@ubuntu.com-20110719143243-p7pnkh45akfp0ihk
Tags: 0.10.22-2ubuntu1
* Rebased on debian unstable, remaining changes:
  - debian/gstreamer-plugins-bad.install
    * don't include dtmf, liveadder, rtpmux, autoconvert and shm, we include 
      them in -good

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
 
61
61
/**
62
62
 * gst_camerabin_preview_create_pipeline:
 
63
 * @element: #GstCameraBin element
63
64
 * @caps: pointer to the caps used in pipeline
 
65
 * @src_filter: source filter element
64
66
 *
65
67
 * Create a preview converter pipeline that outputs the format defined in
66
68
 * @caps parameter.
67
69
 *
68
 
 * Returns: New pipeline, or NULL if error occured.
 
70
 * Returns: New pipeline data structure, or NULL if error occured.
69
71
 */
70
 
GstElement *
71
 
gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps,
 
72
GstCameraBinPreviewPipelineData *
 
73
gst_camerabin_preview_create_pipeline (GstElement * element, GstCaps * caps,
72
74
    GstElement * src_filter)
73
75
{
74
 
  GstElement *pipe, *src, *csp, *filter, *vscale, *sink;
 
76
  GstElement *csp = NULL, *vscale = NULL;
75
77
  GError *error = NULL;
 
78
  GstCameraBinPreviewPipelineData *data;
76
79
 
77
 
  g_return_val_if_fail (caps != NULL, FALSE);
 
80
  g_return_val_if_fail (caps != NULL, NULL);
78
81
 
79
82
  GST_DEBUG ("creating elements");
80
83
 
81
 
  if (!create_element ("appsrc", "prev_src", &src, &error) ||
82
 
      !create_element ("videoscale", NULL, &vscale, &error) ||
83
 
      !create_element ("ffmpegcolorspace", NULL, &csp, &error) ||
84
 
      !create_element ("capsfilter", NULL, &filter, &error) ||
85
 
      !create_element ("fakesink", "prev_sink", &sink, &error))
86
 
    goto no_elements;
 
84
  data = g_new (GstCameraBinPreviewPipelineData, 1);
87
85
 
88
86
  /* We have multiple pipelines created by using this function, so we can't
89
87
   * give a name to them. Another way would to ensure the uniqueness of the
90
88
   * name here*/
91
 
  pipe = gst_pipeline_new (NULL);
92
 
  if (pipe == NULL)
93
 
    goto no_pipeline;
 
89
  data->pipeline = gst_pipeline_new (NULL);
 
90
  if (!data->pipeline)
 
91
    goto create_error;
 
92
 
 
93
  if (!create_element ("appsrc", "prev_src", &data->appsrc, &error) ||
 
94
      !create_element ("videoscale", NULL, &vscale, &error) ||
 
95
      !create_element ("ffmpegcolorspace", NULL, &csp, &error) ||
 
96
      !create_element ("capsfilter", NULL, &data->capsfilter, &error) ||
 
97
      !create_element ("fakesink", "prev_sink", &data->appsink, &error))
 
98
    goto create_error;
94
99
 
95
100
  GST_DEBUG ("adding elements");
96
 
  gst_bin_add_many (GST_BIN (pipe), src, csp, filter, vscale, sink, NULL);
 
101
  gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, csp,
 
102
      data->capsfilter, vscale, data->appsink, NULL);
97
103
  if (src_filter) {
98
 
    gst_bin_add (GST_BIN (pipe), src_filter);
 
104
    gst_bin_add (GST_BIN (data->pipeline), src_filter);
99
105
  }
100
106
 
 
107
  data->element = element;
 
108
 
101
109
  GST_DEBUG ("preview format is: %" GST_PTR_FORMAT, caps);
102
110
 
103
 
  g_object_set (filter, "caps", caps, NULL);
104
 
  g_object_set (sink, "preroll-queue-len", 1, "signal-handoffs", TRUE, NULL);
 
111
  g_object_set (data->capsfilter, "caps", caps, NULL);
 
112
  g_object_set (data->appsink, "preroll-queue-len", 1, "signal-handoffs", TRUE,
 
113
      NULL);
105
114
  g_object_set (vscale, "method", 0, NULL);
106
115
 
107
 
  /* FIXME: linking is still way too expensive, profile this properly */
108
116
  GST_DEBUG ("linking src->vscale");
109
 
  if (!gst_element_link_pads_full (src, "src", vscale, "sink",
110
 
          GST_PAD_LINK_CHECK_CAPS))
111
 
    return FALSE;
 
117
  if (!gst_element_link_pads (data->appsrc, "src", vscale, "sink"))
 
118
    goto link_error;
112
119
 
113
120
  if (src_filter) {
114
 
    GST_DEBUG ("linking vscale->filter");
115
 
    if (!gst_element_link_pads_full (vscale, "src", src_filter, "sink",
116
 
            GST_PAD_LINK_CHECK_CAPS)) {
117
 
      return FALSE;
 
121
    GST_DEBUG ("linking vscale->src_filter");
 
122
    if (!gst_element_link_pads (vscale, "src", src_filter, "sink")) {
 
123
      goto link_error;
118
124
    }
119
125
    GST_DEBUG ("linking filter->csp");
120
 
    if (!gst_element_link_pads_full (src_filter, "src", csp, "sink",
121
 
            GST_PAD_LINK_CHECK_CAPS)) {
122
 
      return FALSE;
 
126
    if (!gst_element_link_pads (src_filter, "src", csp, "sink")) {
 
127
      goto link_error;
123
128
    }
124
129
  } else {
125
130
    GST_DEBUG ("linking vscale->csp");
126
 
    if (!gst_element_link_pads_full (vscale, "src", csp, "sink",
127
 
            GST_PAD_LINK_CHECK_CAPS))
128
 
      return FALSE;
 
131
    if (!gst_element_link_pads (vscale, "src", csp, "sink"))
 
132
      goto link_error;
129
133
  }
130
134
 
131
135
  GST_DEBUG ("linking csp->capsfilter");
132
 
  if (!gst_element_link_pads_full (csp, "src", filter, "sink",
133
 
          GST_PAD_LINK_CHECK_CAPS))
134
 
    return FALSE;
 
136
  if (!gst_element_link_pads (csp, "src", data->capsfilter, "sink"))
 
137
    goto link_error;
135
138
 
136
139
  GST_DEBUG ("linking capsfilter->sink");
137
 
  if (!gst_element_link_pads_full (filter, "src", sink, "sink",
138
 
          GST_PAD_LINK_CHECK_CAPS))
139
 
    return FALSE;
140
 
 
141
 
  return pipe;
142
 
 
143
 
  /* ERRORS */
144
 
no_elements:
145
 
  {
146
 
    g_warning ("Could not make preview pipeline: %s", error->message);
 
140
  if (!gst_element_link_pads (data->capsfilter, "src", data->appsink, "sink"))
 
141
    goto link_error;
 
142
 
 
143
  return data;
 
144
 
 
145
create_error:
 
146
  if (error) {
 
147
    GST_WARNING ("Preview pipeline element creation failed: %s",
 
148
        error->message);
147
149
    g_error_free (error);
148
 
    return NULL;
149
 
  }
150
 
no_pipeline:
151
 
  {
152
 
    g_warning ("Could not make preview pipeline: %s",
153
 
        "no pipeline (unknown error)");
154
 
    return NULL;
155
 
  }
 
150
  }
 
151
  if (csp)
 
152
    gst_object_unref (csp);
 
153
  if (vscale)
 
154
    gst_object_unref (vscale);
 
155
  if (data->appsrc)
 
156
    gst_object_unref (data->appsrc);
 
157
  if (data->capsfilter)
 
158
    gst_object_unref (data->capsfilter);
 
159
  if (data->appsink)
 
160
    gst_object_unref (data->appsink);
 
161
 
 
162
link_error:
 
163
  GST_WARNING ("Could not create preview pipeline");
 
164
  gst_camerabin_preview_destroy_pipeline (data);
 
165
 
 
166
  return NULL;
156
167
}
157
168
 
158
169
 
159
170
/**
160
171
 * gst_camerabin_preview_destroy_pipeline:
161
 
 * @camera: camerabin object
162
 
 * @pipeline: the pipeline to be destroyed
 
172
 * @data: the pipeline data to be destroyed
163
173
 *
164
174
 * Destroy preview converter pipeline.
165
175
 */
166
176
void
167
 
gst_camerabin_preview_destroy_pipeline (GstCameraBin * camera,
168
 
    GstElement * pipeline)
 
177
gst_camerabin_preview_destroy_pipeline (GstCameraBinPreviewPipelineData * data)
169
178
{
170
 
  g_return_if_fail (pipeline != NULL);
171
 
 
172
 
  gst_element_set_state (pipeline, GST_STATE_NULL);
173
 
  gst_object_unref (pipeline);
 
179
  if (data->pipeline) {
 
180
    gst_element_set_state (data->pipeline, GST_STATE_NULL);
 
181
    gst_object_unref (data->pipeline);
 
182
  }
 
183
  g_free (data);
174
184
}
175
185
 
176
186
 
177
187
/**
178
188
 * gst_camerabin_preview_convert:
179
 
 * @camera: camerabin object
180
 
 * @pipeline: preview pipeline to use
 
189
 * @data: preview pipeline data to use
181
190
 * @buf: #GstBuffer that contains the frame to be converted
182
191
 *
183
192
 * Create a preview image of the given frame.
185
194
 * Returns: converted preview image, or NULL if operation failed.
186
195
 */
187
196
GstBuffer *
188
 
gst_camerabin_preview_convert (GstCameraBin * camera,
189
 
    GstElement * pipeline, GstBuffer * buf)
 
197
gst_camerabin_preview_convert (GstCameraBinPreviewPipelineData * data,
 
198
    GstBuffer * buf)
190
199
{
191
200
  GstMessage *msg;
192
201
  GstBuffer *result = NULL;
197
206
  GstFlowReturn fret;
198
207
 
199
208
  g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL);
 
209
  g_return_val_if_fail (data != NULL, NULL);
200
210
 
201
 
  if (pipeline == NULL) {
 
211
  if (data->pipeline == NULL) {
202
212
    GST_WARNING ("pipeline is NULL");
203
213
    goto no_pipeline;
204
214
  }
205
215
 
206
 
  src = gst_bin_get_by_name (GST_BIN (pipeline), "prev_src");
207
 
  sink = gst_bin_get_by_name (GST_BIN (pipeline), "prev_sink");
 
216
  src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src");
 
217
  sink = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_sink");
208
218
 
209
219
  if (!src || !sink) {
210
220
    GST_WARNING ("pipeline doesn't have src / sink elements");
222
232
 
223
233
  GST_DEBUG ("running conversion pipeline, source is: %" GST_PTR_FORMAT,
224
234
      GST_BUFFER_CAPS (buf));
225
 
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
235
  gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
226
236
 
227
237
  g_signal_emit_by_name (src, "push-buffer", buf, &fret);
228
238
 
229
 
  bus = gst_element_get_bus (pipeline);
 
239
  bus = gst_element_get_bus (data->pipeline);
230
240
  msg = gst_bus_timed_pop_filtered (bus, (25 * GST_SECOND),
231
241
      GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
232
242
  gst_object_unref (bus);
268
278
 
269
279
  g_signal_handlers_disconnect_by_func (sink, G_CALLBACK (save_result),
270
280
      &result);
271
 
  gst_element_set_state (pipeline, GST_STATE_READY);
 
281
  gst_element_set_state (data->pipeline, GST_STATE_READY);
272
282
 
273
283
  GST_BUFFER_FLAGS (buf) = bflags;
274
284
 
297
307
 
298
308
/**
299
309
 * gst_camerabin_preview_send_event:
300
 
 * @camera: the #GstCameraBin
 
310
 * @data: preview pipeline data to use
301
311
 * @evt: The #GstEvent to be pushed, takes ownership
302
312
 *
303
313
 * Pushes an event to the preview pipeline.
305
315
 * Returns: True if the event was handled
306
316
 */
307
317
gboolean
308
 
gst_camerabin_preview_send_event (GstCameraBin * camera, GstElement * pipeline,
 
318
gst_camerabin_preview_send_event (GstCameraBinPreviewPipelineData * data,
309
319
    GstEvent * evt)
310
320
{
311
321
  GstElement *src;
312
 
  gboolean ret = FALSE;
313
322
 
314
 
  src = gst_bin_get_by_name (GST_BIN (pipeline), "prev_src");
 
323
  src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src");
315
324
  if (!src) {
316
325
    GST_WARNING ("Preview pipeline doesn't have src element, can't push event");
317
326
    gst_event_unref (evt);
318
 
  } else {
319
 
    GST_DEBUG_OBJECT (camera, "Pushing event %p to preview pipeline", evt);
320
 
    ret = gst_element_send_event (src, evt);
321
 
    gst_object_unref (src);
322
 
  }
323
 
 
324
 
  return ret;
 
327
    return FALSE;
 
328
  }
 
329
 
 
330
  GST_DEBUG_OBJECT (data->element, "Pushing event %p to preview pipeline", evt);
 
331
 
 
332
  return gst_element_send_event (src, evt);
 
333
}
 
334
 
 
335
/**
 
336
 * gst_camerabin_preview_set_caps:
 
337
 * @data: preview pipeline data to use
 
338
 * @caps: New #GstCaps to be set for the pipeline
 
339
 *
 
340
 * Sets new caps for the preview pipeline
 
341
 */
 
342
void
 
343
gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * data,
 
344
    GstCaps * caps)
 
345
{
 
346
  GstState state, pending;
 
347
  GstStateChangeReturn ret;
 
348
 
 
349
  g_return_if_fail (data->pipeline != NULL);
 
350
  g_return_if_fail (caps != NULL);
 
351
 
 
352
  ret = gst_element_get_state (data->pipeline, &state, &pending, 0);
 
353
  if (ret == GST_STATE_CHANGE_FAILURE) {
 
354
    /* make it try again */
 
355
    state = GST_STATE_PLAYING;
 
356
    pending = GST_STATE_VOID_PENDING;
 
357
  }
 
358
 
 
359
  gst_element_set_state (data->pipeline, GST_STATE_NULL);
 
360
  g_object_set (data->capsfilter, "caps", caps, NULL);
 
361
  if (pending != GST_STATE_VOID_PENDING)
 
362
    state = pending;
 
363
  gst_element_set_state (data->pipeline, state);
325
364
}