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

« back to all changes in this revision

Viewing changes to gst/chart/gstchart.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
/* gstchart.c: implementation of chart drawing element
 
2
 * Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
 
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
 
 
24
#include <gst/gst.h>
 
25
#include <gst/video/video.h>
 
26
 
 
27
#define GST_TYPE_CHART (gst_chart_get_type())
 
28
#define GST_CHART(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CHART,GstChart))
 
29
#define GST_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CHART,GstChart))
 
30
#define GST_IS_CHART(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CHART))
 
31
#define GST_IS_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CHART))
 
32
 
 
33
typedef struct _GstChart GstChart;
 
34
typedef struct _GstChartClass GstChartClass;
 
35
 
 
36
struct _GstChart
 
37
{
 
38
  GstElement element;
 
39
 
 
40
  /* pads */
 
41
  GstPad *sinkpad, *srcpad;
 
42
 
 
43
  /* the timestamp of the next frame */
 
44
  guint64 next_time;
 
45
 
 
46
  /* video state */
 
47
  gint bpp;
 
48
  gint depth;
 
49
  gint width;
 
50
  gint height;
 
51
 
 
52
  gint samplerate;
 
53
  gdouble framerate;            /* desired frame rate */
 
54
  gint samples_between_frames;  /* number of samples between start of successive frames */
 
55
  gint samples_since_last_frame;        /* number of samples between start of successive frames */
 
56
};
 
57
 
 
58
struct _GstChartClass
 
59
{
 
60
  GstElementClass parent_class;
 
61
};
 
62
 
 
63
GType gst_chart_get_type (void);
 
64
 
 
65
 
 
66
/* elementfactory information */
 
67
static const GstElementDetails gst_chart_details =
 
68
GST_ELEMENT_DETAILS ("Chart drawer",
 
69
    "Visualization",
 
70
    "Takes frames of data and outputs video frames of a chart of data",
 
71
    "Richard Boulton <richard@tartarus.org>");
 
72
 
 
73
/* signals and args */
 
74
enum
 
75
{
 
76
  /* FILL ME */
 
77
  LAST_SIGNAL
 
78
};
 
79
 
 
80
enum
 
81
{
 
82
  ARG_0,
 
83
  /* FILL ME */
 
84
};
 
85
 
 
86
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
 
87
    GST_PAD_SRC,
 
88
    GST_PAD_ALWAYS,
 
89
    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_16)
 
90
    );
 
91
 
 
92
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
 
93
    GST_PAD_SINK,
 
94
    GST_PAD_ALWAYS,
 
95
    GST_STATIC_CAPS ("audio/x-raw-int, "
 
96
        "endianness = (int) BYTE_ORDER, "
 
97
        "signed = (boolean) TRUE, "
 
98
        "width = (int) 16, "
 
99
        "depth = (int) 16, "
 
100
        "rate = (int) [ 8000, 96000 ], " "channels = (int) 1")
 
101
    );
 
102
 
 
103
static void gst_chart_base_init (gpointer g_class);
 
104
static void gst_chart_class_init (GstChartClass * klass);
 
105
static void gst_chart_init (GstChart * chart);
 
106
 
 
107
static void gst_chart_set_property (GObject * object, guint prop_id,
 
108
    const GValue * value, GParamSpec * pspec);
 
109
static void gst_chart_get_property (GObject * object, guint prop_id,
 
110
    GValue * value, GParamSpec * pspec);
 
111
 
 
112
static void gst_chart_chain (GstPad * pad, GstData * _data);
 
113
 
 
114
static GstPadLinkReturn
 
115
gst_chart_sinkconnect (GstPad * pad, const GstCaps * caps);
 
116
static GstPadLinkReturn
 
117
gst_chart_srcconnect (GstPad * pad, const GstCaps * caps);
 
118
 
 
119
static GstElementClass *parent_class = NULL;
 
120
 
 
121
GType
 
122
gst_chart_get_type (void)
 
123
{
 
124
  static GType type = 0;
 
125
 
 
126
  if (!type) {
 
127
    static const GTypeInfo info = {
 
128
      sizeof (GstChartClass),
 
129
      gst_chart_base_init,
 
130
      NULL,
 
131
      (GClassInitFunc) gst_chart_class_init,
 
132
      NULL,
 
133
      NULL,
 
134
      sizeof (GstChart),
 
135
      0,
 
136
      (GInstanceInitFunc) gst_chart_init,
 
137
    };
 
138
 
 
139
    type = g_type_register_static (GST_TYPE_ELEMENT, "GstChart", &info, 0);
 
140
  }
 
141
  return type;
 
142
}
 
143
 
 
144
static void
 
145
gst_chart_base_init (gpointer g_class)
 
146
{
 
147
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
148
 
 
149
  gst_element_class_add_pad_template (element_class,
 
150
      gst_static_pad_template_get (&src_factory));
 
151
  gst_element_class_add_pad_template (element_class,
 
152
      gst_static_pad_template_get (&sink_factory));
 
153
  gst_element_class_set_details (element_class, &gst_chart_details);
 
154
}
 
155
 
 
156
static void
 
157
gst_chart_class_init (GstChartClass * klass)
 
158
{
 
159
  GObjectClass *gobject_class;
 
160
  GstElementClass *gstelement_class;
 
161
 
 
162
  gobject_class = (GObjectClass *) klass;
 
163
  gstelement_class = (GstElementClass *) klass;
 
164
 
 
165
  parent_class = g_type_class_peek_parent (klass);
 
166
 
 
167
  gobject_class->set_property = gst_chart_set_property;
 
168
  gobject_class->get_property = gst_chart_get_property;
 
169
}
 
170
 
 
171
static void
 
172
gst_chart_init (GstChart * chart)
 
173
{
 
174
  /* create the sink and src pads */
 
175
  chart->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
 
176
  chart->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
 
177
  gst_element_add_pad (GST_ELEMENT (chart), chart->sinkpad);
 
178
  gst_element_add_pad (GST_ELEMENT (chart), chart->srcpad);
 
179
 
 
180
  gst_pad_set_chain_function (chart->sinkpad, gst_chart_chain);
 
181
  gst_pad_set_link_function (chart->sinkpad, gst_chart_sinkconnect);
 
182
  gst_pad_set_link_function (chart->srcpad, gst_chart_srcconnect);
 
183
 
 
184
  chart->next_time = 0;
 
185
 
 
186
  /* reset the initial video state */
 
187
  chart->bpp = 16;
 
188
  chart->depth = 16;
 
189
  chart->width = 256;
 
190
  chart->height = 128;
 
191
 
 
192
  chart->samplerate = -1;
 
193
  chart->framerate = 25;        /* desired frame rate */
 
194
  chart->samples_between_frames = 0;    /* number of samples between start of successive frames */
 
195
  chart->samples_since_last_frame = 0;
 
196
}
 
197
 
 
198
static GstPadLinkReturn
 
199
gst_chart_sinkconnect (GstPad * pad, const GstCaps * caps)
 
200
{
 
201
  GstChart *chart;
 
202
  GstStructure *structure;
 
203
 
 
204
  chart = GST_CHART (gst_pad_get_parent (pad));
 
205
 
 
206
  structure = gst_caps_get_structure (caps, 0);
 
207
 
 
208
  gst_structure_get_int (structure, "rate", &chart->samplerate);
 
209
  chart->samples_between_frames = chart->samplerate / chart->framerate;
 
210
 
 
211
  GST_DEBUG ("CHART: new sink caps: rate %d", chart->samplerate);
 
212
  /*gst_chart_sync_parms (chart); */
 
213
  /* */
 
214
  return GST_PAD_LINK_OK;
 
215
}
 
216
 
 
217
static GstPadLinkReturn
 
218
gst_chart_srcconnect (GstPad * pad, const GstCaps * caps)
 
219
{
 
220
  GstChart *chart;
 
221
  GstStructure *structure;
 
222
 
 
223
  chart = GST_CHART (gst_pad_get_parent (pad));
 
224
 
 
225
  structure = gst_caps_get_structure (caps, 0);
 
226
 
 
227
  if (!gst_structure_get_double (structure, "framerate", &chart->framerate) ||
 
228
      !gst_structure_get_int (structure, "width", &chart->width) ||
 
229
      !gst_structure_get_int (structure, "height", &chart->height))
 
230
    return GST_PAD_LINK_REFUSED;
 
231
 
 
232
  chart->samples_between_frames = chart->samplerate / chart->framerate;
 
233
  GST_DEBUG ("CHART: new src caps: framerate %f, %dx%d",
 
234
      chart->framerate, chart->width, chart->height);
 
235
 
 
236
  return GST_PAD_LINK_OK;
 
237
}
 
238
 
 
239
static void
 
240
draw_chart_16bpp (guchar * output, gint width, gint height,
 
241
    gint16 * src_data, gint src_size)
 
242
{
 
243
  gint i;
 
244
  guint16 *colstart;
 
245
  gint16 *in;
 
246
 
 
247
  GST_DEBUG
 
248
      ("CHART: drawing frame to %p, width = %d, height = %d, src_data = %p, src_size = %d",
 
249
      output, width, height, src_data, src_size);
 
250
 
 
251
  for (colstart = (guint16 *) output, in = (gint16 *) src_data, i = 0;
 
252
      i < width; colstart++, in++, i++) {
 
253
    guint16 *pos = colstart;
 
254
    gint h1;
 
255
 
 
256
    h1 = (((gint) (*in)) * height / (1 << 16)) + height / 2;
 
257
    if (h1 >= height)
 
258
      h1 = height;
 
259
 
 
260
    if (h1 < height / 2) {
 
261
      while (pos < colstart + h1 * width) {
 
262
        *pos = 0x0000;
 
263
        pos += width;
 
264
      }
 
265
      while (pos < colstart + height / 2 * width) {
 
266
        *pos = 0x07e0;
 
267
        pos += width;
 
268
      }
 
269
      while (pos < colstart + height * width) {
 
270
        *pos = 0x0000;
 
271
        pos += width;
 
272
      }
 
273
    } else {
 
274
      while (pos < colstart + height / 2 * width) {
 
275
        *pos = 0x0000;
 
276
        pos += width;
 
277
      }
 
278
      while (pos < colstart + h1 * width) {
 
279
        *pos = 0x07e0;
 
280
        pos += width;
 
281
      }
 
282
      while (pos < colstart + height * width) {
 
283
        *pos = 0x0000;
 
284
        pos += width;
 
285
      }
 
286
    }
 
287
  }
 
288
}
 
289
 
 
290
static void
 
291
gst_chart_chain (GstPad * pad, GstData * _data)
 
292
{
 
293
  GstBuffer *bufin = GST_BUFFER (_data);
 
294
  GstChart *chart;
 
295
  GstBuffer *bufout;
 
296
  guint32 samples_in;
 
297
  guint32 sizeout;
 
298
  gint16 *datain;
 
299
  guchar *dataout;
 
300
 
 
301
  g_return_if_fail (bufin != NULL);
 
302
  g_return_if_fail (pad != NULL);
 
303
  g_return_if_fail (GST_IS_PAD (pad));
 
304
  g_return_if_fail (GST_IS_CHART (GST_OBJECT_PARENT (pad)));
 
305
  chart = GST_CHART (GST_OBJECT_PARENT (pad));
 
306
  g_return_if_fail (chart != NULL);
 
307
 
 
308
  GST_DEBUG ("CHART: chainfunc called");
 
309
 
 
310
  samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
 
311
  datain = (gint16 *) (GST_BUFFER_DATA (bufin));
 
312
  GST_DEBUG ("input buffer has %d samples", samples_in);
 
313
  if (chart->next_time <= GST_BUFFER_TIMESTAMP (bufin)) {
 
314
    chart->next_time = GST_BUFFER_TIMESTAMP (bufin);
 
315
    GST_DEBUG ("in:  %" G_GINT64_FORMAT, GST_BUFFER_TIMESTAMP (bufin));
 
316
  }
 
317
 
 
318
  chart->samples_since_last_frame += samples_in;
 
319
  if (chart->samples_between_frames <= chart->samples_since_last_frame) {
 
320
    chart->samples_since_last_frame = 0;
 
321
 
 
322
    /* get data to draw into buffer */
 
323
    if (samples_in >= chart->width) {
 
324
      /* make a new buffer for the output */
 
325
      bufout = gst_buffer_new ();
 
326
      sizeout = chart->bpp / 8 * chart->width * chart->height;
 
327
      dataout = g_malloc (sizeout);
 
328
      GST_BUFFER_SIZE (bufout) = sizeout;
 
329
      GST_BUFFER_DATA (bufout) = dataout;
 
330
      GST_DEBUG ("CHART: made new buffer: size %d, width %d, height %d",
 
331
          sizeout, chart->width, chart->height);
 
332
 
 
333
      /* take data and draw to new buffer */
 
334
      /* FIXME: call different routines for different properties */
 
335
      draw_chart_16bpp (dataout, chart->width, chart->height, (gint16 *) datain,
 
336
          samples_in);
 
337
 
 
338
      gst_buffer_unref (bufin);
 
339
 
 
340
      /* set timestamp */
 
341
      GST_BUFFER_TIMESTAMP (bufout) = chart->next_time;
 
342
 
 
343
      GST_DEBUG ("CHART: outputting buffer");
 
344
      /* output buffer */
 
345
      GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_READONLY);
 
346
      gst_pad_push (chart->srcpad, GST_DATA (bufout));
 
347
    }
 
348
  } else {
 
349
    GST_DEBUG ("CHART: skipping buffer");
 
350
    gst_buffer_unref (bufin);
 
351
  }
 
352
 
 
353
  GST_DEBUG ("CHART: exiting chainfunc");
 
354
}
 
355
 
 
356
static void
 
357
gst_chart_set_property (GObject * object, guint prop_id, const GValue * value,
 
358
    GParamSpec * pspec)
 
359
{
 
360
  GstChart *chart;
 
361
 
 
362
  g_return_if_fail (GST_IS_CHART (object));
 
363
  chart = GST_CHART (object);
 
364
 
 
365
  switch (prop_id) {
 
366
    default:
 
367
      break;
 
368
  }
 
369
}
 
370
 
 
371
static void
 
372
gst_chart_get_property (GObject * object, guint prop_id, GValue * value,
 
373
    GParamSpec * pspec)
 
374
{
 
375
  GstChart *chart;
 
376
 
 
377
  g_return_if_fail (GST_IS_CHART (object));
 
378
  chart = GST_CHART (object);
 
379
 
 
380
  switch (prop_id) {
 
381
    default:
 
382
      break;
 
383
  }
 
384
}
 
385
 
 
386
static gboolean
 
387
plugin_init (GstPlugin * plugin)
 
388
{
 
389
  if (!gst_element_register (plugin, "chart", GST_RANK_NONE, GST_TYPE_CHART))
 
390
    return FALSE;
 
391
 
 
392
  return TRUE;
 
393
}
 
394
 
 
395
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
 
396
    GST_VERSION_MINOR,
 
397
    "chart",
 
398
    "Takes frames of data and outputs video frames of a chart of data",
 
399
    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)