1
/* GStreamer mp2enc (mjpegtools) runtime wrapper
2
* Copyright (C) 2006 Mark Nauwelaerts <mnauw@users.sourceforge.net>
4
* mp2enc.c: gstreamer mp2enc runtime wrapper
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.
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.
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.
23
* SECTION:element-mp2enc
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).
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>.
46
#include "gstproctrans.h"
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))
59
typedef struct _GstMp2enc GstMp2enc;
60
typedef struct _GstMp2encClass GstMp2encClass;
66
GstPadEventFunction proc_event;
68
/* mp2enc parameters */
75
struct _GstMp2encClass {
76
GstProcTransClass parent_class;
79
GST_DEBUG_CATEGORY_STATIC (mp2enc_debug);
80
#define GST_CAT_DEFAULT mp2enc_debug
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");
88
static GstStaticPadTemplate sink_template =
89
GST_STATIC_PAD_TEMPLATE (GST_PROC_TRANS_SINK_NAME,
92
GST_STATIC_CAPS ("audio/x-wav, "
93
"rate = (int) { 32000, 44100, 48000 }, "
94
"channels = (int) [ 1, 2 ] ")
97
static GstStaticPadTemplate src_template =
98
GST_STATIC_PAD_TEMPLATE (GST_PROC_TRANS_SRC_NAME,
101
GST_STATIC_CAPS ("audio/mpeg, "
102
"mpegversion = (int) 1, "
103
"layer = (int) [ 1, 2], "
104
"bitrate = (int) [ 0, MAX ] ")
117
#define DEFAULT_BITRATE 224
118
#define DEFAULT_LAYER 2
119
#define DEFAULT_CRC FALSE
120
#define DEFAULT_VCD FALSE
122
static gboolean gst_mp2enc_set_caps (GstProcTrans * ptrans, GstCaps * incaps,
124
static gboolean gst_mp2enc_sink_event (GstPad * pad, GstEvent * event);
125
static GstStateChangeReturn gst_mp2enc_change_state (GstElement * element,
126
GstStateChange transition);
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);
134
GST_BOILERPLATE (GstMp2enc, gst_mp2enc, GstProcTrans, GST_TYPE_PROC_TRANS);
137
gst_mp2enc_base_init (gpointer klass)
139
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
141
gst_element_class_set_details (element_class, &gst_mp2enc_details);
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));
150
gst_mp2enc_class_init (GstMp2encClass * klass)
152
GstElementClass *element_class;
153
GObjectClass *gobject_class;
155
gobject_class = G_OBJECT_CLASS (klass);
156
element_class = GST_ELEMENT_CLASS (klass);
158
GST_DEBUG_CATEGORY_INIT (mp2enc_debug, "mp2enc", 0, "MPEG1/2 encoder");
160
gobject_class->set_property = gst_mp2enc_set_property;
161
gobject_class->get_property = gst_mp2enc_get_property;
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));
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));
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));
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));
180
element_class->change_state = GST_DEBUG_FUNCPTR (gst_mp2enc_change_state);
184
gst_mp2enc_init (GstMp2enc * enc, GstMp2encClass * klass )
186
GstProcTrans *proctrans = GST_PROC_TRANS (enc);
187
GstProcTransClass *proctransclass = GST_PROC_TRANS_CLASS (klass);
189
proctransclass->set_caps = GST_DEBUG_FUNCPTR (gst_mp2enc_set_caps);
191
/* most properties are initialized by base element */
192
proctrans->cmd = g_strdup ("mp2enc");
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));
201
enc->bitrate = DEFAULT_BITRATE;
202
enc->layer = DEFAULT_LAYER;
203
enc->crc = DEFAULT_CRC;
204
enc->vcd = DEFAULT_VCD;
208
gst_mp2enc_set_caps (GstProcTrans * ptrans, GstCaps * incaps,
211
GstMp2enc *enc = GST_MP2ENC (ptrans);
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);
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);
226
opt = g_strdup ("-e");
227
g_array_append_val (ptrans->args, opt);
231
opt = g_strdup ("-V");
232
g_array_append_val (ptrans->args, opt);
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)) {
239
opt = g_strdup ("2");
241
case GST_LEVEL_DEBUG:
243
opt = g_strdup ("1");
246
opt = g_strdup ("0");
249
g_array_append_val (ptrans->args, opt);
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);
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);
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. */
272
gst_mp2enc_sink_event (GstPad * pad, GstEvent * event)
276
enc = GST_MP2ENC (GST_PAD_PARENT (pad));
278
switch (GST_EVENT_TYPE (event)) {
279
case GST_EVENT_NEWSEGMENT:
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)
293
/* chain up to the parent */
294
return enc->proc_event (pad, event);
298
gst_mp2enc_set_property (GObject * object, guint prop_id,
299
const GValue * value, GParamSpec * pspec)
303
g_return_if_fail (GST_IS_MP2ENC (object));
305
enc = GST_MP2ENC (object);
309
enc->bitrate = g_value_get_uint (value);
312
enc->layer = g_value_get_uint (value);
315
enc->crc = g_value_get_boolean (value);
318
enc->vcd = g_value_get_boolean (value);
321
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
327
gst_mp2enc_get_property (GObject * object, guint prop_id, GValue * value,
332
g_return_if_fail (GST_IS_MP2ENC (object));
334
enc = GST_MP2ENC (object);
338
g_value_set_uint (value, enc->bitrate);
341
g_value_set_uint (value, enc->layer);
344
g_value_set_boolean (value, enc->crc);
347
g_value_set_boolean (value, enc->vcd);
350
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
355
static GstStateChangeReturn
356
gst_mp2enc_change_state (GstElement * element, GstStateChange transition)
358
GstStateChangeReturn ret;
360
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
361
if (ret == GST_STATE_CHANGE_FAILURE)
364
switch (transition) {
365
case GST_STATE_CHANGE_PAUSED_TO_READY: