~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to ext/snapshot/gstsnapshot.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer
 
2
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
#include <string.h>
 
24
#include <inttypes.h>
 
25
 
 
26
#include "gstsnapshot.h"
 
27
#include <gst/video/video.h>
 
28
 
 
29
#define MAX_HEIGHT      2048
 
30
 
 
31
/* elementfactory information */
 
32
static const GstElementDetails snapshot_details =
 
33
GST_ELEMENT_DETAILS ("Snapshot",
 
34
    "Filter/Editor/Video",
 
35
    "Dump a frame to a png file",
 
36
    "Jeremy SIMON <jsimon13@yahoo.fr>");
 
37
 
 
38
static GstStaticPadTemplate snapshot_src_factory =
 
39
GST_STATIC_PAD_TEMPLATE ("src",
 
40
    GST_PAD_SRC,
 
41
    GST_PAD_ALWAYS,
 
42
    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB)
 
43
    );
 
44
 
 
45
static GstStaticPadTemplate snapshot_sink_factory =
 
46
GST_STATIC_PAD_TEMPLATE ("sink",
 
47
    GST_PAD_SINK,
 
48
    GST_PAD_ALWAYS,
 
49
    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB)
 
50
    );
 
51
 
 
52
/* Snapshot signals and args */
 
53
enum
 
54
{
 
55
  /* FILL ME */
 
56
  SNAPSHOT_SIGNAL,
 
57
  LAST_SIGNAL
 
58
};
 
59
 
 
60
enum
 
61
{
 
62
  ARG_0,
 
63
  ARG_FRAME,
 
64
  ARG_LOCATION
 
65
};
 
66
 
 
67
static GType gst_snapshot_get_type (void);
 
68
static void gst_snapshot_base_init (gpointer g_class);
 
69
static void gst_snapshot_class_init (GstSnapshotClass * klass);
 
70
static void gst_snapshot_init (GstSnapshot * snapshot);
 
71
 
 
72
static void gst_snapshot_chain (GstPad * pad, GstData * _data);
 
73
 
 
74
static void gst_snapshot_set_property (GObject * object, guint prop_id,
 
75
    const GValue * value, GParamSpec * pspec);
 
76
static void gst_snapshot_get_property (GObject * object, guint prop_id,
 
77
    GValue * value, GParamSpec * pspec);
 
78
static void snapshot_handler (GstElement * element);
 
79
 
 
80
static GstElementClass *parent_class = NULL;
 
81
static guint gst_snapshot_signals[LAST_SIGNAL] = { 0 };
 
82
 
 
83
 
 
84
static void
 
85
user_error_fn (png_structp png_ptr, png_const_charp error_msg)
 
86
{
 
87
  g_warning ("%s", error_msg);
 
88
}
 
89
 
 
90
static void
 
91
user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
 
92
{
 
93
  g_warning ("%s", warning_msg);
 
94
}
 
95
 
 
96
GType
 
97
gst_snapshot_get_type (void)
 
98
{
 
99
  static GType snapshot_type = 0;
 
100
 
 
101
  if (!snapshot_type) {
 
102
    static const GTypeInfo snapshot_info = {
 
103
      sizeof (GstSnapshotClass),
 
104
      gst_snapshot_base_init,
 
105
      NULL,
 
106
      (GClassInitFunc) gst_snapshot_class_init,
 
107
      NULL,
 
108
      NULL,
 
109
      sizeof (GstSnapshot),
 
110
      0,
 
111
      (GInstanceInitFunc) gst_snapshot_init,
 
112
    };
 
113
 
 
114
    snapshot_type =
 
115
        g_type_register_static (GST_TYPE_ELEMENT, "GstSnapshot", &snapshot_info,
 
116
        0);
 
117
  }
 
118
  return snapshot_type;
 
119
}
 
120
 
 
121
static void
 
122
gst_snapshot_base_init (gpointer g_class)
 
123
{
 
124
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
125
 
 
126
  gst_element_class_add_pad_template (element_class,
 
127
      gst_static_pad_template_get (&snapshot_sink_factory));
 
128
  gst_element_class_add_pad_template (element_class,
 
129
      gst_static_pad_template_get (&snapshot_src_factory));
 
130
 
 
131
  gst_element_class_set_details (element_class, &snapshot_details);
 
132
}
 
133
 
 
134
static void
 
135
gst_snapshot_class_init (GstSnapshotClass * klass)
 
136
{
 
137
  GObjectClass *gobject_class;
 
138
  GstElementClass *gstelement_class;
 
139
 
 
140
  gobject_class = (GObjectClass *) klass;
 
141
  gstelement_class = (GstElementClass *) klass;
 
142
 
 
143
  parent_class = g_type_class_peek_parent (klass);
 
144
 
 
145
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FRAME,
 
146
      g_param_spec_long ("frame", "frame", "frame",
 
147
          0, G_MAXLONG, 0, G_PARAM_READWRITE));
 
148
  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
 
149
      g_param_spec_string ("location", "location", "location",
 
150
          0, G_PARAM_READWRITE));
 
151
 
 
152
  gst_snapshot_signals[SNAPSHOT_SIGNAL] =
 
153
      g_signal_new ("snapshot", G_TYPE_FROM_CLASS (klass),
 
154
      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSnapshotClass, snapshot),
 
155
      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
156
 
 
157
  klass->snapshot = snapshot_handler;
 
158
 
 
159
  gobject_class->set_property = gst_snapshot_set_property;
 
160
  gobject_class->get_property = gst_snapshot_get_property;
 
161
}
 
162
 
 
163
static void
 
164
snapshot_handler (GstElement * element)
 
165
{
 
166
  GstSnapshot *snapshot;
 
167
 
 
168
  snapshot = GST_SNAPSHOT (element);
 
169
  snapshot->snapshot_asked = TRUE;
 
170
}
 
171
 
 
172
static gboolean
 
173
gst_snapshot_sinkconnect (GstPad * pad, const GstCaps * caps)
 
174
{
 
175
  GstSnapshot *filter;
 
176
  gdouble fps;
 
177
  GstStructure *structure;
 
178
 
 
179
  filter = GST_SNAPSHOT (gst_pad_get_parent (pad));
 
180
 
 
181
  structure = gst_caps_get_structure (caps, 0);
 
182
  gst_structure_get_int (structure, "width", &filter->width);
 
183
  gst_structure_get_int (structure, "height", &filter->height);
 
184
  gst_structure_get_double (structure, "framerate", &fps);
 
185
  gst_structure_get_fourcc (structure, "format", &filter->format);
 
186
  filter->to_bpp = 24;
 
187
 
 
188
  gst_pad_try_set_caps (filter->srcpad, caps);
 
189
 
 
190
  return GST_PAD_LINK_OK;
 
191
}
 
192
 
 
193
static void
 
194
gst_snapshot_init (GstSnapshot * snapshot)
 
195
{
 
196
  snapshot->sinkpad =
 
197
      gst_pad_new_from_static_template (&snapshot_sink_factory, "sink");
 
198
  gst_pad_set_link_function (snapshot->sinkpad, gst_snapshot_sinkconnect);
 
199
  gst_pad_set_chain_function (snapshot->sinkpad, gst_snapshot_chain);
 
200
  gst_element_add_pad (GST_ELEMENT (snapshot), snapshot->sinkpad);
 
201
 
 
202
  snapshot->srcpad =
 
203
      gst_pad_new_from_static_template (&snapshot_src_factory, "src");
 
204
  gst_element_add_pad (GST_ELEMENT (snapshot), snapshot->srcpad);
 
205
 
 
206
  snapshot->cur_frame = 0;
 
207
  snapshot->frame = -1;
 
208
  snapshot->snapshot_asked = FALSE;
 
209
}
 
210
 
 
211
 
 
212
static void
 
213
gst_snapshot_chain (GstPad * pad, GstData * _data)
 
214
{
 
215
  GstBuffer *buf = GST_BUFFER (_data);
 
216
  GstSnapshot *snapshot;
 
217
  guchar *data;
 
218
  gulong size;
 
219
  gint i;
 
220
  png_byte *row_pointers[MAX_HEIGHT];
 
221
  FILE *fp;
 
222
 
 
223
  g_return_if_fail (pad != NULL);
 
224
  g_return_if_fail (GST_IS_PAD (pad));
 
225
  g_return_if_fail (buf != NULL);
 
226
 
 
227
  snapshot = GST_SNAPSHOT (GST_OBJECT_PARENT (pad));
 
228
 
 
229
  data = GST_BUFFER_DATA (buf);
 
230
  size = GST_BUFFER_SIZE (buf);
 
231
 
 
232
  GST_DEBUG ("snapshot: have buffer of %d\n", GST_BUFFER_SIZE (buf));
 
233
 
 
234
  snapshot->cur_frame++;
 
235
  if (snapshot->cur_frame == snapshot->frame ||
 
236
      snapshot->snapshot_asked == TRUE) {
 
237
    snapshot->snapshot_asked = FALSE;
 
238
 
 
239
    GST_INFO ("dumpfile : %s\n", snapshot->location);
 
240
    fp = fopen (snapshot->location, "wb");
 
241
    if (fp == NULL)
 
242
      g_warning (" Can not open %s\n", snapshot->location);
 
243
    else {
 
244
      snapshot->png_struct_ptr =
 
245
          png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
 
246
          user_error_fn, user_warning_fn);
 
247
      if (snapshot->png_struct_ptr == NULL)
 
248
        g_warning ("Failed to initialize png structure");
 
249
 
 
250
      snapshot->png_info_ptr =
 
251
          png_create_info_struct (snapshot->png_struct_ptr);
 
252
 
 
253
      if (setjmp (snapshot->png_struct_ptr->jmpbuf))
 
254
        png_destroy_write_struct (&snapshot->png_struct_ptr,
 
255
            &snapshot->png_info_ptr);
 
256
 
 
257
      png_set_filter (snapshot->png_struct_ptr, 0,
 
258
          PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
 
259
      png_init_io (snapshot->png_struct_ptr, fp);
 
260
      png_set_compression_level (snapshot->png_struct_ptr, 9);
 
261
      png_set_IHDR (snapshot->png_struct_ptr,
 
262
          snapshot->png_info_ptr,
 
263
          snapshot->width,
 
264
          snapshot->height,
 
265
          snapshot->to_bpp / 3,
 
266
          PNG_COLOR_TYPE_RGB,
 
267
          PNG_INTERLACE_NONE,
 
268
          PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
269
 
 
270
      for (i = 0; i < snapshot->height; i++)
 
271
        row_pointers[i] = data + (snapshot->width * i * snapshot->to_bpp / 8);
 
272
 
 
273
      png_write_info (snapshot->png_struct_ptr, snapshot->png_info_ptr);
 
274
      png_write_image (snapshot->png_struct_ptr, row_pointers);
 
275
      png_write_end (snapshot->png_struct_ptr, NULL);
 
276
      png_destroy_info_struct (snapshot->png_struct_ptr,
 
277
          &snapshot->png_info_ptr);
 
278
      png_destroy_write_struct (&snapshot->png_struct_ptr, (png_infopp) NULL);
 
279
      fclose (fp);
 
280
    }
 
281
  }
 
282
 
 
283
  gst_pad_push (snapshot->srcpad, GST_DATA (buf));
 
284
}
 
285
 
 
286
static void
 
287
gst_snapshot_set_property (GObject * object, guint prop_id,
 
288
    const GValue * value, GParamSpec * pspec)
 
289
{
 
290
  GstSnapshot *snapshot;
 
291
 
 
292
  g_return_if_fail (GST_IS_SNAPSHOT (object));
 
293
  snapshot = GST_SNAPSHOT (object);
 
294
 
 
295
  switch (prop_id) {
 
296
    case ARG_LOCATION:
 
297
      snapshot->location = g_strdup (g_value_get_string (value));
 
298
      break;
 
299
    case ARG_FRAME:
 
300
      snapshot->frame = g_value_get_long (value);
 
301
      break;
 
302
    default:
 
303
      break;
 
304
  }
 
305
}
 
306
 
 
307
static void
 
308
gst_snapshot_get_property (GObject * object, guint prop_id, GValue * value,
 
309
    GParamSpec * pspec)
 
310
{
 
311
  GstSnapshot *snapshot;
 
312
 
 
313
  g_return_if_fail (GST_IS_SNAPSHOT (object));
 
314
  snapshot = GST_SNAPSHOT (object);
 
315
 
 
316
  switch (prop_id) {
 
317
    case ARG_LOCATION:
 
318
      g_value_set_string (value, snapshot->location);
 
319
      break;
 
320
    case ARG_FRAME:
 
321
      g_value_set_long (value, snapshot->frame);
 
322
      break;
 
323
    default:
 
324
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
325
      break;
 
326
  }
 
327
}
 
328
 
 
329
 
 
330
static gboolean
 
331
plugin_init (GstPlugin * plugin)
 
332
{
 
333
  if (!gst_element_register (plugin, "snapshot", GST_RANK_NONE,
 
334
          GST_TYPE_SNAPSHOT))
 
335
    return FALSE;
 
336
 
 
337
  return TRUE;
 
338
}
 
339
 
 
340
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
 
341
    GST_VERSION_MINOR,
 
342
    "snapshot",
 
343
    "Dump a frame to a png file",
 
344
    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)