~ubuntu-branches/ubuntu/natty/gst-entrans/natty

« back to all changes in this revision

Viewing changes to gst/y4m/gstmp2enc.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2010-09-13 19:49:29 UTC
  • Revision ID: james.westby@ubuntu.com-20100913194929-qz90a14xyxln9yfz
Tags: upstream-0.10.2
ImportĀ upstreamĀ versionĀ 0.10.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer mp2enc (mjpegtools) runtime wrapper
 
2
 * Copyright (C) 2006 Mark Nauwelaerts <mnauw@users.sourceforge.net>
 
3
 *
 
4
 * mp2enc.c: gstreamer mp2enc runtime wrapper
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Library General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Library General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Library General Public
 
17
 * License along with this library; if not, write to the
 
18
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA 02110-1307, USA.
 
20
 */
 
21
 
 
22
 /**
 
23
 * SECTION:element-mp2enc
 
24
 *
 
25
 * <refsect2>
 
26
 * <para>
 
27
 * Performs MPEG-1 layer I/II encoding by means of the
 
28
 * mp2enc tool from the
 
29
 * <ulink url="http://mjpeg.sourceforge.net/">mjpegtools</ulink> suite
 
30
 * (used as a runtime child process).
 
31
 *
 
32
 * Note that mp2enc needs input in WAV format,
 
33
 * so you will typicall have to precede this element by
 
34
 * <link linkend="GstWavEnc">wavenc</link>.
 
35
 * </para>
 
36
 * </refsect2>
 
37
 */
 
38
 
 
39
 
 
40
#ifdef HAVE_CONFIG_H
 
41
#include "config.h"
 
42
#endif
 
43
 
 
44
#include <gst/gst.h>
 
45
 
 
46
#include "gstproctrans.h"
 
47
 
 
48
#define GST_TYPE_MP2ENC \
 
49
  gst_mp2enc_get_type ()
 
50
#define GST_MP2ENC(obj) \
 
51
  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MP2ENC, GstMp2enc))
 
52
#define GST_MP2ENC_CLASS(klass) \
 
53
  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_MP2ENC, GstMp2encClass))
 
54
#define GST_IS_MP2ENC(obj) \
 
55
  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_MP2ENC))
 
56
#define GST_IS_MP2ENC_CLASS(klass) \
 
57
  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_MP2ENC))
 
58
 
 
59
typedef struct _GstMp2enc GstMp2enc;
 
60
typedef struct _GstMp2encClass GstMp2encClass;
 
61
 
 
62
struct _GstMp2enc {
 
63
  GstProcTrans parent;
 
64
 
 
65
  /* a hack */
 
66
  GstPadEventFunction proc_event;
 
67
 
 
68
  /* mp2enc parameters */
 
69
  guint bitrate;
 
70
  guint layer;
 
71
  gboolean crc;
 
72
  gboolean vcd;
 
73
};
 
74
 
 
75
struct _GstMp2encClass {
 
76
  GstProcTransClass parent_class;
 
77
};
 
78
 
 
79
GST_DEBUG_CATEGORY_STATIC (mp2enc_debug);
 
80
#define GST_CAT_DEFAULT mp2enc_debug
 
81
 
 
82
static GstElementDetails gst_mp2enc_details =
 
83
GST_ELEMENT_DETAILS ("mp2enc audio encoder",
 
84
    "Codec/Encoder/Audio",
 
85
    "MPEG-1/2 audio encoder",
 
86
    "Mark Nauwelaerts <mnauw@users.sourceforge.net>, Andrew Stevens");
 
87
 
 
88
static GstStaticPadTemplate sink_template =
 
89
GST_STATIC_PAD_TEMPLATE (GST_PROC_TRANS_SINK_NAME,
 
90
    GST_PAD_SINK,
 
91
    GST_PAD_ALWAYS,
 
92
    GST_STATIC_CAPS ("audio/x-wav, "
 
93
        "rate = (int) { 32000, 44100, 48000 }, "
 
94
        "channels = (int) [ 1, 2 ] ")
 
95
    );
 
96
 
 
97
static GstStaticPadTemplate src_template =
 
98
GST_STATIC_PAD_TEMPLATE (GST_PROC_TRANS_SRC_NAME,
 
99
    GST_PAD_SRC,
 
100
    GST_PAD_ALWAYS,
 
101
    GST_STATIC_CAPS ("audio/mpeg, "
 
102
        "mpegversion = (int) 1, "
 
103
        "layer = (int) [ 1, 2], "
 
104
        "bitrate = (int) [ 0, MAX ] ")
 
105
    );
 
106
 
 
107
/* properties */
 
108
enum
 
109
{
 
110
  PROP_0,
 
111
  PROP_BITRATE,
 
112
  PROP_LAYER,
 
113
  PROP_CRC,
 
114
  PROP_VCD
 
115
};
 
116
 
 
117
#define DEFAULT_BITRATE  224
 
118
#define DEFAULT_LAYER      2
 
119
#define DEFAULT_CRC     FALSE
 
120
#define DEFAULT_VCD     FALSE
 
121
 
 
122
static gboolean gst_mp2enc_set_caps (GstProcTrans * ptrans, GstCaps * incaps,
 
123
    GstCaps ** outcaps);
 
124
static gboolean gst_mp2enc_sink_event (GstPad * pad, GstEvent * event);
 
125
static GstStateChangeReturn gst_mp2enc_change_state (GstElement * element,
 
126
    GstStateChange transition);
 
127
 
 
128
/* properties */
 
129
static void gst_mp2enc_set_property (GObject * object,
 
130
    guint prop_id, const GValue * value, GParamSpec * pspec);
 
131
static void gst_mp2enc_get_property (GObject * object,
 
132
    guint prop_id, GValue * value, GParamSpec * pspec);
 
133
 
 
134
GST_BOILERPLATE (GstMp2enc, gst_mp2enc, GstProcTrans, GST_TYPE_PROC_TRANS);
 
135
 
 
136
static void
 
137
gst_mp2enc_base_init (gpointer klass)
 
138
{
 
139
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
140
 
 
141
  gst_element_class_set_details (element_class, &gst_mp2enc_details);
 
142
 
 
143
  gst_element_class_add_pad_template (element_class,
 
144
      gst_static_pad_template_get (&src_template));
 
145
  gst_element_class_add_pad_template (element_class,
 
146
      gst_static_pad_template_get (&sink_template));
 
147
}
 
148
 
 
149
static void
 
150
gst_mp2enc_class_init (GstMp2encClass * klass)
 
151
{
 
152
  GstElementClass *element_class;
 
153
  GObjectClass *gobject_class;
 
154
 
 
155
  gobject_class = G_OBJECT_CLASS (klass);
 
156
  element_class = GST_ELEMENT_CLASS (klass);
 
157
 
 
158
  GST_DEBUG_CATEGORY_INIT (mp2enc_debug, "mp2enc", 0, "MPEG1/2 encoder");
 
159
 
 
160
  gobject_class->set_property = gst_mp2enc_set_property;
 
161
  gobject_class->get_property = gst_mp2enc_get_property;
 
162
 
 
163
  g_object_class_install_property (gobject_class, PROP_BITRATE,
 
164
      g_param_spec_uint ("bitrate", "Bitrate", "Compressed audio bitrate (kbps)",
 
165
          0, 10 * 1024, DEFAULT_BITRATE, G_PARAM_READWRITE));
 
166
 
 
167
  g_object_class_install_property (gobject_class, PROP_LAYER,
 
168
      g_param_spec_uint ("layer", "Layer", "MPEG-1 layer",
 
169
          1, 2, DEFAULT_LAYER, G_PARAM_READWRITE));
 
170
 
 
171
  g_object_class_install_property (gobject_class, PROP_CRC,
 
172
      g_param_spec_boolean ("crc", "CRC", "Use CRC error protection",
 
173
          DEFAULT_CRC, G_PARAM_READWRITE));
 
174
 
 
175
  g_object_class_install_property (gobject_class, PROP_VCD,
 
176
      g_param_spec_boolean ("vcd", "VCD", "Force VCD compatible output; "
 
177
         "restricts the possibilities for bitrate and sample rate must be 44.1 kbps",
 
178
          DEFAULT_VCD, G_PARAM_READWRITE));
 
179
 
 
180
  element_class->change_state = GST_DEBUG_FUNCPTR (gst_mp2enc_change_state);
 
181
}
 
182
 
 
183
static void
 
184
gst_mp2enc_init (GstMp2enc * enc, GstMp2encClass * klass )
 
185
{
 
186
  GstProcTrans *proctrans = GST_PROC_TRANS (enc);
 
187
  GstProcTransClass *proctransclass = GST_PROC_TRANS_CLASS (klass);
 
188
 
 
189
  proctransclass->set_caps = GST_DEBUG_FUNCPTR (gst_mp2enc_set_caps);
 
190
 
 
191
  /* most properties are initialized by base element */
 
192
  proctrans->cmd = g_strdup ("mp2enc");
 
193
 
 
194
  /* HACK to override event function so we can drop some */
 
195
  if (proctrans->sinkpad) {
 
196
        enc->proc_event = GST_PAD_EVENTFUNC (proctrans->sinkpad);
 
197
    gst_pad_set_event_function (proctrans->sinkpad,
 
198
        GST_DEBUG_FUNCPTR (gst_mp2enc_sink_event));
 
199
  }
 
200
 
 
201
  enc->bitrate = DEFAULT_BITRATE;
 
202
  enc->layer = DEFAULT_LAYER;
 
203
  enc->crc = DEFAULT_CRC;
 
204
  enc->vcd = DEFAULT_VCD;
 
205
}
 
206
 
 
207
static gboolean
 
208
gst_mp2enc_set_caps (GstProcTrans * ptrans, GstCaps * incaps,
 
209
    GstCaps ** outcaps)
 
210
{
 
211
  GstMp2enc *enc = GST_MP2ENC (ptrans);
 
212
  gchar *opt;
 
213
 
 
214
  /* bitrate */
 
215
  opt = g_strdup ("-b");
 
216
  g_array_append_val (ptrans->args, opt);
 
217
  opt = g_strdup_printf ("%u", enc->bitrate);
 
218
  g_array_append_val (ptrans->args, opt);
 
219
  /* layer */
 
220
  opt = g_strdup ("-l");
 
221
  g_array_append_val (ptrans->args, opt);
 
222
  opt = g_strdup_printf ("%u", enc->layer);
 
223
  g_array_append_val (ptrans->args, opt);
 
224
  /* crc */
 
225
  if (enc->crc) {
 
226
    opt = g_strdup ("-e");
 
227
    g_array_append_val (ptrans->args, opt);
 
228
  }
 
229
  /* vcd */
 
230
  if (enc->vcd) {
 
231
    opt = g_strdup ("-V");
 
232
    g_array_append_val (ptrans->args, opt);
 
233
  }
 
234
  /* align verbosity level with the debug category */
 
235
  opt = g_strdup ("-v");
 
236
  g_array_append_val (ptrans->args, opt);
 
237
  switch (gst_debug_category_get_threshold (mp2enc_debug)) {
 
238
    case GST_LEVEL_LOG:
 
239
      opt = g_strdup ("2");
 
240
      break;
 
241
    case GST_LEVEL_DEBUG:
 
242
    case GST_LEVEL_INFO:
 
243
      opt = g_strdup ("1");
 
244
      break;
 
245
    default:
 
246
      opt = g_strdup ("0");
 
247
      break;
 
248
  }
 
249
  g_array_append_val (ptrans->args, opt);
 
250
 
 
251
  /* output to standard out */
 
252
  opt = g_strdup ("-o");
 
253
  g_array_append_val (ptrans->args, opt);
 
254
  opt = g_strdup ("-");
 
255
  g_array_append_val (ptrans->args, opt);
 
256
 
 
257
  /* set the outgoing caps */
 
258
  *outcaps = gst_caps_new_simple ("audio/mpeg",
 
259
      "mpegversion", G_TYPE_INT, 1,
 
260
      "layer", G_TYPE_INT, enc->layer,
 
261
      "bitrate", G_TYPE_INT, enc->bitrate * 1000, NULL);
 
262
 
 
263
  return TRUE;
 
264
}
 
265
 
 
266
/* mp2enc needs to be preceded by wavenc, which typically sends new_segment
 
267
 * events expecting filesink to perform a seek to rewrite the header.
 
268
 * These need to be dropped here to prevent a seek from happening in the mp2
 
269
 * stream produced by mp2enc.
 
270
 * We'll accept for now that the wav header ends up encoded as audio at eos. */
 
271
static gboolean
 
272
gst_mp2enc_sink_event (GstPad * pad, GstEvent * event)
 
273
{
 
274
  GstMp2enc *enc;
 
275
 
 
276
  enc = GST_MP2ENC (GST_PAD_PARENT (pad));
 
277
 
 
278
  switch (GST_EVENT_TYPE (event)) {
 
279
    case GST_EVENT_NEWSEGMENT:
 
280
    {
 
281
      GstFormat format;
 
282
      
 
283
      gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL, NULL);
 
284
      /* eat this event if it is a byte-based one, so a seek request */
 
285
      if (format == GST_FORMAT_BYTES)
 
286
        return TRUE;
 
287
      break;
 
288
    }
 
289
    default:
 
290
      break;
 
291
  }
 
292
 
 
293
  /* chain up to the parent */
 
294
  return enc->proc_event (pad, event);
 
295
}
 
296
 
 
297
static void
 
298
gst_mp2enc_set_property (GObject * object, guint prop_id,
 
299
    const GValue * value, GParamSpec * pspec)
 
300
{
 
301
  GstMp2enc *enc;
 
302
 
 
303
  g_return_if_fail (GST_IS_MP2ENC (object));
 
304
 
 
305
  enc = GST_MP2ENC (object);
 
306
 
 
307
  switch (prop_id) {
 
308
    case PROP_BITRATE:
 
309
      enc->bitrate = g_value_get_uint (value);
 
310
      break;
 
311
    case PROP_LAYER:
 
312
      enc->layer = g_value_get_uint (value);
 
313
      break;
 
314
    case PROP_CRC:
 
315
      enc->crc = g_value_get_boolean (value);
 
316
      break;
 
317
    case PROP_VCD:
 
318
      enc->vcd = g_value_get_boolean (value);
 
319
      break;
 
320
    default:
 
321
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
322
      break;
 
323
  }
 
324
}
 
325
 
 
326
static void
 
327
gst_mp2enc_get_property (GObject * object, guint prop_id, GValue * value,
 
328
    GParamSpec * pspec)
 
329
{
 
330
  GstMp2enc *enc;
 
331
 
 
332
  g_return_if_fail (GST_IS_MP2ENC (object));
 
333
 
 
334
  enc = GST_MP2ENC (object);
 
335
 
 
336
  switch (prop_id) {
 
337
    case PROP_BITRATE:
 
338
      g_value_set_uint (value, enc->bitrate);
 
339
      break;
 
340
    case PROP_LAYER:
 
341
      g_value_set_uint (value, enc->layer);
 
342
      break;
 
343
    case PROP_CRC:
 
344
      g_value_set_boolean (value, enc->crc);
 
345
      break;
 
346
    case PROP_VCD:
 
347
      g_value_set_boolean (value, enc->vcd);
 
348
      break;
 
349
    default:
 
350
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
351
      break;
 
352
  }
 
353
}
 
354
 
 
355
static GstStateChangeReturn
 
356
gst_mp2enc_change_state (GstElement * element, GstStateChange transition)
 
357
{
 
358
  GstStateChangeReturn ret;
 
359
 
 
360
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
361
  if (ret == GST_STATE_CHANGE_FAILURE)
 
362
    goto done;
 
363
 
 
364
  switch (transition) {
 
365
    case GST_STATE_CHANGE_PAUSED_TO_READY:
 
366
      break;
 
367
    default:
 
368
      break;
 
369
  }
 
370
 
 
371
done:
 
372
  return ret;
 
373
}