|
1 /* GStreamer AAC encoder |
|
2 * Copyright 2009 Collabora Multimedia, |
|
3 * Copyright 2009 Nokia Corporation |
|
4 * @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>. |
|
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., 59 Temple Place - Suite 330, |
|
19 * Boston, MA 02111-1307, USA. |
|
20 */ |
|
21 |
|
22 /* TODO non-GPL license */ |
|
23 |
|
24 /** |
|
25 * SECTION:element-nokiaaacenc |
|
26 * @seealso: nokiaaacdec |
|
27 * |
|
28 * nokiaaacenc encodes raw audio to AAC streams. |
|
29 */ |
|
30 |
|
31 #ifdef HAVE_CONFIG_H |
|
32 #include "config.h" |
|
33 #endif |
|
34 #include <gst/gst.h> |
|
35 #include <gst/audio/audio.h> |
|
36 #include <string.h> |
|
37 |
|
38 #include "gstaacenc.h" |
|
39 |
|
40 GST_DEBUG_CATEGORY_STATIC (aac_enc); |
|
41 #define GST_CAT_DEFAULT aac_enc |
|
42 |
|
43 enum |
|
44 { |
|
45 AAC_PROFILE_AUTO = 0, |
|
46 AAC_PROFILE_LC = 2, |
|
47 AAC_PROFILE_HE = 5 |
|
48 }; |
|
49 |
|
50 #define GST_TYPE_AAC_ENC_PROFILE (gst_aac_enc_profile_get_type ()) |
|
51 static GType |
|
52 gst_aac_enc_profile_get_type (void) |
|
53 { |
|
54 static GType gst_aac_enc_profile_type = 0; |
|
55 |
|
56 if (!gst_aac_enc_profile_type) { |
|
57 static GEnumValue gst_aac_enc_profile[] = { |
|
58 {AAC_PROFILE_AUTO, "Codec selects LC or HE", "AUTO"}, |
|
59 {AAC_PROFILE_LC, "Low complexity profile", "LC"}, |
|
60 {AAC_PROFILE_HE, "High Efficiency", "HE"}, |
|
61 {0, NULL, NULL}, |
|
62 }; |
|
63 |
|
64 gst_aac_enc_profile_type = g_enum_register_static ("GstNokiaAacEncProfile", |
|
65 gst_aac_enc_profile); |
|
66 } |
|
67 |
|
68 return gst_aac_enc_profile_type; |
|
69 } |
|
70 |
|
71 #define GST_TYPE_AAC_ENC_OUTPUTFORMAT (gst_aac_enc_outputformat_get_type ()) |
|
72 static GType |
|
73 gst_aac_enc_outputformat_get_type (void) |
|
74 { |
|
75 static GType gst_aac_enc_outputformat_type = 0; |
|
76 |
|
77 if (!gst_aac_enc_outputformat_type) { |
|
78 static GEnumValue gst_aac_enc_outputformat[] = { |
|
79 {RAW, "AAC Raw format", "RAW"}, |
|
80 {USE_ADTS, "Audio Data Transport Stream format", "ADTS"}, |
|
81 {USE_ADIF, "Audio Data Interchange Format", "ADIF"}, |
|
82 {0, NULL, NULL}, |
|
83 }; |
|
84 |
|
85 gst_aac_enc_outputformat_type = |
|
86 g_enum_register_static ("GstNokiaAacEncOutputFormat", |
|
87 gst_aac_enc_outputformat); |
|
88 } |
|
89 |
|
90 return gst_aac_enc_outputformat_type; |
|
91 } |
|
92 |
|
93 enum |
|
94 { |
|
95 PROP_0, |
|
96 PROP_BITRATE, |
|
97 PROP_PROFILE, |
|
98 PROP_FORMAT |
|
99 }; |
|
100 |
|
101 static GstStaticPadTemplate gst_aac_enc_sink_template = |
|
102 GST_STATIC_PAD_TEMPLATE ("sink", |
|
103 GST_PAD_SINK, |
|
104 GST_PAD_ALWAYS, |
|
105 GST_STATIC_CAPS ("audio/x-raw-int, " |
|
106 "endianness = (int) BYTE_ORDER, " |
|
107 "signed = (bool) TRUE, " |
|
108 "width = (int) 16, " |
|
109 "depth = (int) 16, " |
|
110 "rate = (int) [ 8000, 96000 ], channels = (int) [ 1, 2 ] ") |
|
111 ); |
|
112 |
|
113 static GstStaticPadTemplate gst_aac_enc_src_template = |
|
114 GST_STATIC_PAD_TEMPLATE ("src", |
|
115 GST_PAD_SRC, |
|
116 GST_PAD_ALWAYS, |
|
117 GST_STATIC_CAPS ("audio/mpeg, " "mpegversion = (int) 4, " |
|
118 "rate = (int) [ 8000, 96000 ], channels = (int) [ 1, 2 ] ") |
|
119 ); |
|
120 |
|
121 static void gst_aac_enc_base_init (gpointer g_class); |
|
122 static void gst_aac_enc_class_init (GstAACEncClass * klass); |
|
123 static void gst_aac_enc_init (GstAACEnc * filter, GstAACEncClass * klass); |
|
124 |
|
125 static void gst_aac_enc_set_property (GObject * object, guint prop_id, |
|
126 const GValue * value, GParamSpec * pspec); |
|
127 static void gst_aac_enc_get_property (GObject * object, guint prop_id, |
|
128 GValue * value, GParamSpec * pspec); |
|
129 |
|
130 static void gst_aac_enc_finalize (GObject * object); |
|
131 static void gst_aac_enc_reset (GstAACEnc * enc); |
|
132 static GstStateChangeReturn gst_aac_enc_change_state (GstElement * element, |
|
133 GstStateChange transition); |
|
134 static gboolean gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps); |
|
135 static GstFlowReturn gst_aac_enc_chain (GstPad * pad, GstBuffer * buffer); |
|
136 |
|
137 GST_BOILERPLATE (GstNokiaAACEnc, gst_aac_enc, GstElement, GST_TYPE_ELEMENT); |
|
138 |
|
139 static void |
|
140 gst_aac_enc_base_init (gpointer g_class) |
|
141 { |
|
142 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); |
|
143 |
|
144 gst_element_class_set_details_simple (element_class, |
|
145 "Nokia AAC encoder", "Codec/Encoder/Audio", |
|
146 "Nokia AAC encoder", |
|
147 "MCC, Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>"); |
|
148 |
|
149 gst_element_class_add_pad_template (element_class, |
|
150 gst_static_pad_template_get (&gst_aac_enc_src_template)); |
|
151 gst_element_class_add_pad_template (element_class, |
|
152 gst_static_pad_template_get (&gst_aac_enc_sink_template)); |
|
153 } |
|
154 |
|
155 /* initialize the plugin's class */ |
|
156 static void |
|
157 gst_aac_enc_class_init (GstAACEncClass * klass) |
|
158 { |
|
159 GObjectClass *gobject_class; |
|
160 GstElementClass *gstelement_class; |
|
161 |
|
162 gobject_class = (GObjectClass *) klass; |
|
163 gstelement_class = (GstElementClass *) klass; |
|
164 |
|
165 GST_DEBUG_CATEGORY_INIT (aac_enc, "nokiaaacenc", 0, "Nokia AAC encoder"); |
|
166 |
|
167 gobject_class->set_property = gst_aac_enc_set_property; |
|
168 gobject_class->get_property = gst_aac_enc_get_property; |
|
169 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_aac_enc_finalize); |
|
170 |
|
171 /* properties */ |
|
172 g_object_class_install_property (gobject_class, PROP_BITRATE, |
|
173 g_param_spec_int ("bitrate", "Bitrate (bps)", "Bitrate in bits/sec", |
|
174 8 * 1000, 320 * 1000, 128 * 1000, |
|
175 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT))); |
|
176 g_object_class_install_property (gobject_class, PROP_PROFILE, |
|
177 g_param_spec_enum ("profile", "Profile", |
|
178 "MPEG/AAC encoding profile", |
|
179 GST_TYPE_AAC_ENC_PROFILE, AAC_PROFILE_LC, |
|
180 G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); |
|
181 g_object_class_install_property (gobject_class, PROP_FORMAT, |
|
182 g_param_spec_enum ("output-format", "Output format", |
|
183 "Format of output frames", |
|
184 GST_TYPE_AAC_ENC_OUTPUTFORMAT, RAW, |
|
185 G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); |
|
186 |
|
187 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_aac_enc_change_state); |
|
188 } |
|
189 |
|
190 static void |
|
191 gst_aac_enc_init (GstAACEnc * enc, GstAACEncClass * klass) |
|
192 { |
|
193 enc->sinkpad = |
|
194 gst_pad_new_from_static_template (&gst_aac_enc_sink_template, "sink"); |
|
195 gst_pad_set_setcaps_function (enc->sinkpad, |
|
196 GST_DEBUG_FUNCPTR (gst_aac_enc_sink_setcaps)); |
|
197 gst_pad_set_chain_function (enc->sinkpad, |
|
198 GST_DEBUG_FUNCPTR (gst_aac_enc_chain)); |
|
199 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); |
|
200 |
|
201 enc->srcpad = |
|
202 gst_pad_new_from_static_template (&gst_aac_enc_src_template, "src"); |
|
203 gst_pad_use_fixed_caps (enc->srcpad); |
|
204 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad); |
|
205 |
|
206 #ifndef GST_DISABLE_GST_DEBUG |
|
207 gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), aac_enc); |
|
208 #else |
|
209 gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), NULL); |
|
210 #endif |
|
211 |
|
212 gst_aac_enc_reset (enc); |
|
213 } |
|
214 |
|
215 static void |
|
216 gst_aac_enc_reset (GstAACEnc * enc) |
|
217 { |
|
218 gst_framed_audio_enc_reset (&enc->enc); |
|
219 if (enc->encoder) |
|
220 EnAACPlus_Enc_Delete (enc->encoder); |
|
221 enc->encoder = NULL; |
|
222 g_free (enc->buffer); |
|
223 enc->buffer = NULL; |
|
224 } |
|
225 |
|
226 static void |
|
227 gst_aac_enc_finalize (GObject * object) |
|
228 { |
|
229 GstAACEnc *enc = (GstAACEnc *) object; |
|
230 |
|
231 gst_framed_audio_enc_finalize (&enc->enc); |
|
232 |
|
233 G_OBJECT_CLASS (parent_class)->finalize (object); |
|
234 } |
|
235 |
|
236 static gboolean |
|
237 gst_aac_enc_setup_encoder (GstAACEnc * enc) |
|
238 { |
|
239 AACPLUS_ENC_CONFIG enc_params; |
|
240 AACPLUS_ENC_MODE mode; |
|
241 gint rate, channels; |
|
242 guint maxbitrate; |
|
243 |
|
244 rate = enc->rate; |
|
245 channels = enc->channels; |
|
246 |
|
247 /* only up to 2 channels supported */ |
|
248 enc_params.sampleRate = rate; |
|
249 enc_params.bitRate = enc->bitrate; |
|
250 enc_params.nChannels = channels; |
|
251 enc_params.aac_tools = USE_ALL; |
|
252 enc_params.pcm_mode = 16; |
|
253 enc_params.format = enc->format; |
|
254 |
|
255 /* check, warn and correct if the max bitrate for the given samplerate is |
|
256 * exceeded. Maximum of 6144 bit for a channel */ |
|
257 maxbitrate = |
|
258 (guint) (6144.0 * (gdouble) rate / (gdouble) 1024.0 + .5) * channels; |
|
259 if (enc_params.bitRate > maxbitrate) { |
|
260 GST_ELEMENT_INFO (enc, RESOURCE, SETTINGS, (NULL), |
|
261 ("bitrate %d exceeds maximum allowed bitrate of %d for samplerate %d " |
|
262 "and %d channels. Setting bitrate to %d", |
|
263 enc_params.bitRate, maxbitrate, rate, channels, maxbitrate)); |
|
264 enc_params.bitRate = maxbitrate; |
|
265 } |
|
266 |
|
267 /* set up encoder */ |
|
268 if (enc->encoder) |
|
269 EnAACPlus_Enc_Delete (enc->encoder); |
|
270 |
|
271 /* only these profiles are really known to and supported by codec */ |
|
272 switch (enc->profile) { |
|
273 case AAC_PROFILE_LC: |
|
274 mode = MODE_AACLC; |
|
275 break; |
|
276 case AAC_PROFILE_HE: |
|
277 mode = MODE_EAACPLUS; |
|
278 break; |
|
279 case AAC_PROFILE_AUTO: |
|
280 mode = MODE_AUTO; |
|
281 break; |
|
282 default: |
|
283 mode = MODE_AACLC; |
|
284 g_assert_not_reached (); |
|
285 break; |
|
286 } |
|
287 enc->encoder = EnAACPlus_Enc_Create (&enc_params, mode); |
|
288 |
|
289 if (!enc->encoder) |
|
290 goto setup_failed; |
|
291 |
|
292 /* query and setup params, |
|
293 * also set up some buffers for fancy HE */ |
|
294 EnAACPlus_Enc_GetSetParam (enc->encoder, &enc->info); |
|
295 |
|
296 #define DUMP_FIELD(f) \ |
|
297 GST_DEBUG_OBJECT (enc, "encoder info: " G_STRINGIFY (f) " = %d", enc->info.f); |
|
298 |
|
299 DUMP_FIELD (InBufSize); |
|
300 DUMP_FIELD (OutBufSize); |
|
301 DUMP_FIELD (Frame_Size); |
|
302 DUMP_FIELD (writeOffset); |
|
303 DUMP_FIELD (InBufSize); |
|
304 |
|
305 enc->raw_frame_size = enc->info.Frame_Size; |
|
306 enc->codec_frame_size = enc->info.OutBufSize; |
|
307 enc->frame_duration = |
|
308 GST_FRAMES_TO_CLOCK_TIME (enc->raw_frame_size / enc->channels / 2, |
|
309 enc->rate); |
|
310 |
|
311 g_free (enc->buffer); |
|
312 /* safety margin */ |
|
313 enc->buffer = g_malloc (enc->info.InBufSize * 2); |
|
314 |
|
315 return TRUE; |
|
316 |
|
317 /* ERRORS */ |
|
318 setup_failed: |
|
319 { |
|
320 GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL)); |
|
321 return FALSE; |
|
322 } |
|
323 } |
|
324 |
|
325 static gint |
|
326 gst_aac_enc_rate_idx (gint rate) |
|
327 { |
|
328 static int rates[] = { |
|
329 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, |
|
330 8000, 7350 |
|
331 }; |
|
332 guint i; |
|
333 |
|
334 for (i = 0; i < G_N_ELEMENTS (rates); ++i) |
|
335 if (rates[i] == rate) |
|
336 return i; |
|
337 |
|
338 return 0xF; |
|
339 } |
|
340 |
|
341 static gboolean |
|
342 gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps) |
|
343 { |
|
344 GstAACEnc *enc; |
|
345 gboolean ret = TRUE; |
|
346 GstStructure *s; |
|
347 GstBuffer *buf = NULL; |
|
348 gint rate, channels; |
|
349 |
|
350 enc = GST_AAC_ENC (GST_PAD_PARENT (pad)); |
|
351 |
|
352 /* extract stream properties */ |
|
353 s = gst_caps_get_structure (caps, 0); |
|
354 |
|
355 if (!s) |
|
356 goto refuse_caps; |
|
357 |
|
358 ret = gst_structure_get_int (s, "rate", &rate); |
|
359 ret &= gst_structure_get_int (s, "channels", &channels); |
|
360 |
|
361 if (!ret) |
|
362 goto refuse_caps; |
|
363 |
|
364 enc->rate = rate; |
|
365 enc->channels = channels; |
|
366 |
|
367 /* NOTE: |
|
368 * - codec only supports LC or HE (= LC + SBR etc) |
|
369 * - HE has (more) restrictive samplerate/channels/bitrate combination |
|
370 * - AUTO makes codec select between LC or HE (depending on settings) |
|
371 */ |
|
372 |
|
373 gst_aac_enc_setup_encoder (enc); |
|
374 if (!enc->encoder) |
|
375 return FALSE; |
|
376 |
|
377 /* HE iff writeOffset <> 0 iff Frame_Size <> 1024 * 2 * channels */ |
|
378 if (enc->info.writeOffset) |
|
379 rate /= 2; |
|
380 |
|
381 /* create codec_data if raw output */ |
|
382 if (enc->format == RAW) { |
|
383 gint rate_idx; |
|
384 guint8 *data; |
|
385 |
|
386 buf = gst_buffer_new_and_alloc (5); |
|
387 data = GST_BUFFER_DATA (buf); |
|
388 rate_idx = gst_aac_enc_rate_idx (rate); |
|
389 |
|
390 GST_DEBUG_OBJECT (enc, "codec_data: profile=%d, sri=%d, channels=%d", |
|
391 enc->profile, rate_idx, enc->channels); |
|
392 |
|
393 /* always write LC profile, and use implicit signaling for HE SBR */ |
|
394 data[0] = ((2 & 0x1F) << 3) | ((rate_idx & 0xE) >> 1); |
|
395 data[1] = ((rate_idx & 0x1) << 7); |
|
396 if (rate_idx != 0x0F) { |
|
397 data[1] |= ((channels & 0xF) << 3); |
|
398 GST_BUFFER_SIZE (buf) = 2; |
|
399 } else { |
|
400 gint srate; |
|
401 |
|
402 srate = rate << 7; |
|
403 data[1] |= ((srate >> 24) & 0xFF); |
|
404 data[2] = ((srate >> 16) & 0xFF); |
|
405 data[3] = ((srate >> 8) & 0xFF); |
|
406 data[4] = (srate & 0xFF); |
|
407 data[4] |= ((channels & 0xF) << 3); |
|
408 GST_BUFFER_SIZE (buf) = 5; |
|
409 } |
|
410 } |
|
411 |
|
412 /* fix some in src template */ |
|
413 caps = gst_caps_copy (gst_pad_get_pad_template_caps (enc->srcpad)); |
|
414 gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, |
|
415 "channels", G_TYPE_INT, channels, NULL); |
|
416 if (buf) { |
|
417 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL); |
|
418 gst_buffer_unref (buf); |
|
419 } |
|
420 ret = gst_pad_set_caps (enc->srcpad, caps); |
|
421 gst_caps_unref (caps); |
|
422 |
|
423 return ret; |
|
424 |
|
425 /* ERRORS */ |
|
426 refuse_caps: |
|
427 { |
|
428 GST_WARNING_OBJECT (enc, "refused caps %" GST_PTR_FORMAT, caps); |
|
429 return FALSE; |
|
430 } |
|
431 } |
|
432 |
|
433 static gint |
|
434 gst_aac_enc_get_data (GstElement * element, const guint8 * in, guint8 * out, |
|
435 GstDtxDecision * dtx) |
|
436 { |
|
437 GstAACEnc *enc; |
|
438 gint res; |
|
439 gint offset; |
|
440 UWord32 used, encoded; |
|
441 Word8 *inbuffer; |
|
442 |
|
443 enc = GST_AAC_ENC_CAST (element); |
|
444 |
|
445 offset = enc->info.writeOffset; |
|
446 if (offset) { |
|
447 memcpy (enc->buffer + offset, in, enc->raw_frame_size); |
|
448 inbuffer = (Word8 *) enc->buffer; |
|
449 } else { |
|
450 inbuffer = (Word8 *) in; |
|
451 } |
|
452 |
|
453 res = EnAACPlus_Enc_Encode (enc->encoder, &enc->info, inbuffer, &used, |
|
454 (UWord8 *) out, &encoded); |
|
455 |
|
456 if (offset) { |
|
457 memcpy (enc->buffer, enc->buffer + used, offset); |
|
458 } |
|
459 |
|
460 return res == 0 ? encoded : -1; |
|
461 } |
|
462 |
|
463 /* set parameters */ |
|
464 #define AUDIO_SAMPLE_RATE ((GST_AAC_ENC (enc->element))->rate) |
|
465 #define RAW_FRAME_SIZE ((GST_AAC_ENC (enc->element))->raw_frame_size) |
|
466 /* safe maximum frame size */ |
|
467 #define CODEC_FRAME_SIZE ((GST_AAC_ENC (enc->element))->codec_frame_size) |
|
468 /* do not set variable frame; |
|
469 * this will make every frame act as a silence frame and force output */ |
|
470 /* #define CODEC_FRAME_VARIABLE 1 */ |
|
471 #define FRAME_DURATION ((GST_AAC_ENC (enc->element))->frame_duration) |
|
472 #define codec_get_data(enc, in, out, dtx) \ |
|
473 gst_aac_enc_get_data (enc, in, out, dtx) |
|
474 |
|
475 /* and include code */ |
|
476 #include "gstframedaudioenc.c" |
|
477 |
|
478 static GstFlowReturn |
|
479 gst_aac_enc_chain (GstPad * pad, GstBuffer * buf) |
|
480 { |
|
481 GstAACEnc *enc; |
|
482 |
|
483 enc = GST_AAC_ENC (GST_PAD_PARENT (pad)); |
|
484 |
|
485 if (G_UNLIKELY (enc->encoder == NULL)) |
|
486 goto not_negotiated; |
|
487 |
|
488 return gst_framed_audio_enc_chain (&enc->enc, buf, enc->srcpad, &enc->cnpad); |
|
489 |
|
490 /* ERRORS */ |
|
491 not_negotiated: |
|
492 { |
|
493 GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL), |
|
494 ("format wasn't negotiated before chain function")); |
|
495 gst_buffer_unref (buf); |
|
496 return GST_FLOW_NOT_NEGOTIATED; |
|
497 } |
|
498 } |
|
499 |
|
500 static void |
|
501 gst_aac_enc_set_property (GObject * object, guint prop_id, |
|
502 const GValue * value, GParamSpec * pspec) |
|
503 { |
|
504 GstAACEnc *enc; |
|
505 |
|
506 enc = GST_AAC_ENC (object); |
|
507 |
|
508 switch (prop_id) { |
|
509 case PROP_BITRATE: |
|
510 enc->bitrate = g_value_get_int (value); |
|
511 break; |
|
512 case PROP_PROFILE: |
|
513 enc->profile = g_value_get_enum (value); |
|
514 break; |
|
515 case PROP_FORMAT: |
|
516 enc->format = g_value_get_enum (value); |
|
517 break; |
|
518 default: |
|
519 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
520 break; |
|
521 } |
|
522 } |
|
523 |
|
524 static void |
|
525 gst_aac_enc_get_property (GObject * object, guint prop_id, |
|
526 GValue * value, GParamSpec * pspec) |
|
527 { |
|
528 GstAACEnc *enc; |
|
529 |
|
530 enc = GST_AAC_ENC (object); |
|
531 |
|
532 switch (prop_id) { |
|
533 case PROP_BITRATE: |
|
534 g_value_set_int (value, enc->bitrate); |
|
535 break; |
|
536 case PROP_PROFILE: |
|
537 g_value_set_enum (value, enc->profile); |
|
538 break; |
|
539 case PROP_FORMAT: |
|
540 g_value_set_enum (value, enc->format); |
|
541 break; |
|
542 default: |
|
543 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
544 break; |
|
545 } |
|
546 } |
|
547 |
|
548 static GstStateChangeReturn |
|
549 gst_aac_enc_change_state (GstElement * element, GstStateChange transition) |
|
550 { |
|
551 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; |
|
552 GstAACEnc *enc = GST_AAC_ENC (element); |
|
553 |
|
554 switch (transition) { |
|
555 case GST_STATE_CHANGE_NULL_TO_READY: |
|
556 break; |
|
557 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
558 break; |
|
559 default: |
|
560 break; |
|
561 } |
|
562 |
|
563 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
564 if (ret == GST_STATE_CHANGE_FAILURE) |
|
565 return ret; |
|
566 |
|
567 switch (transition) { |
|
568 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
569 gst_aac_enc_reset (enc); |
|
570 break; |
|
571 case GST_STATE_CHANGE_READY_TO_NULL: |
|
572 break; |
|
573 default: |
|
574 break; |
|
575 } |
|
576 |
|
577 return ret; |
|
578 } |
|
579 |
|
580 static gboolean |
|
581 plugin_init (GstPlugin * plugin) |
|
582 { |
|
583 |
|
584 if (!gst_element_register (plugin, "nokiaaacenc", GST_RANK_SECONDARY, |
|
585 GST_TYPE_AAC_ENC)) |
|
586 return FALSE; |
|
587 |
|
588 return TRUE; |
|
589 } |
|
590 |
|
591 /* this is the structure that gst-register looks for |
|
592 * so keep the name plugin_desc, or you cannot get your plug-in registered */ |
|
593 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, |
|
594 GST_VERSION_MINOR, |
|
595 "nokiaaacenc", |
|
596 "Nokia AAC MCC codec", |
|
597 plugin_init, VERSION, "Proprietary", "gst-nokia-speech", "") |
|
598 |
|
599 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC() |
|
600 { |
|
601 return &gst_plugin_desc; |
|
602 } |
|
603 |