• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <string.h>
29 
30 #include "gstsbcutil.h"
31 #include "gstsbcenc.h"
32 
33 #define SBC_ENC_DEFAULT_MODE SBC_MODE_AUTO
34 #define SBC_ENC_DEFAULT_BLOCKS 0
35 #define SBC_ENC_DEFAULT_SUB_BANDS 0
36 #define SBC_ENC_DEFAULT_ALLOCATION SBC_AM_AUTO
37 #define SBC_ENC_DEFAULT_RATE 0
38 #define SBC_ENC_DEFAULT_CHANNELS 0
39 
40 #define SBC_ENC_BITPOOL_AUTO 1
41 #define SBC_ENC_BITPOOL_MIN 2
42 #define SBC_ENC_BITPOOL_MIN_STR "2"
43 #define SBC_ENC_BITPOOL_MAX 64
44 #define SBC_ENC_BITPOOL_MAX_STR "64"
45 
46 GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);
47 #define GST_CAT_DEFAULT sbc_enc_debug
48 
49 #define GST_TYPE_SBC_MODE (gst_sbc_mode_get_type())
50 
gst_sbc_mode_get_type(void)51 static GType gst_sbc_mode_get_type(void)
52 {
53 	static GType sbc_mode_type = 0;
54 	static GEnumValue sbc_modes[] = {
55 		{  SBC_MODE_MONO,		"Mono",		"mono"	},
56 		{  SBC_MODE_DUAL_CHANNEL,	"Dual Channel",	"dual"	},
57 		{  SBC_MODE_STEREO,		"Stereo",	"stereo"},
58 		{  SBC_MODE_JOINT_STEREO,	"Joint Stereo",	"joint"	},
59 		{  SBC_MODE_AUTO,		"Auto",		"auto"	},
60 		{ -1, NULL, NULL}
61 	};
62 
63 	if (!sbc_mode_type)
64 		sbc_mode_type = g_enum_register_static("GstSbcMode", sbc_modes);
65 
66 	return sbc_mode_type;
67 }
68 
69 #define GST_TYPE_SBC_ALLOCATION (gst_sbc_allocation_get_type())
70 
gst_sbc_allocation_get_type(void)71 static GType gst_sbc_allocation_get_type(void)
72 {
73 	static GType sbc_allocation_type = 0;
74 	static GEnumValue sbc_allocations[] = {
75 		{ SBC_AM_LOUDNESS,	"Loudness",	"loudness" },
76 		{ SBC_AM_SNR,		"SNR",		"snr" },
77 		{ SBC_AM_AUTO,		"Auto",		"auto" },
78 		{ -1, NULL, NULL}
79 	};
80 
81 	if (!sbc_allocation_type)
82 		sbc_allocation_type = g_enum_register_static(
83 				"GstSbcAllocation", sbc_allocations);
84 
85 	return sbc_allocation_type;
86 }
87 
88 #define GST_TYPE_SBC_BLOCKS (gst_sbc_blocks_get_type())
89 
gst_sbc_blocks_get_type(void)90 static GType gst_sbc_blocks_get_type(void)
91 {
92 	static GType sbc_blocks_type = 0;
93 	static GEnumValue sbc_blocks[] = {
94 		{ 0,	"Auto",		"auto" },
95 		{ 4,	"4",		"4" },
96 		{ 8,	"8",		"8" },
97 		{ 12,	"12",		"12" },
98 		{ 16,	"16",		"16" },
99 		{ -1, NULL, NULL}
100 	};
101 
102 	if (!sbc_blocks_type)
103 		sbc_blocks_type = g_enum_register_static(
104 				"GstSbcBlocks", sbc_blocks);
105 
106 	return sbc_blocks_type;
107 }
108 
109 #define GST_TYPE_SBC_SUBBANDS (gst_sbc_subbands_get_type())
110 
gst_sbc_subbands_get_type(void)111 static GType gst_sbc_subbands_get_type(void)
112 {
113 	static GType sbc_subbands_type = 0;
114 	static GEnumValue sbc_subbands[] = {
115 		{ 0,	"Auto",		"auto" },
116 		{ 4,	"4 subbands",	"4" },
117 		{ 8,	"8 subbands",	"8" },
118 		{ -1, NULL, NULL}
119 	};
120 
121 	if (!sbc_subbands_type)
122 		sbc_subbands_type = g_enum_register_static(
123 				"GstSbcSubbands", sbc_subbands);
124 
125 	return sbc_subbands_type;
126 }
127 
128 enum {
129 	PROP_0,
130 	PROP_MODE,
131 	PROP_ALLOCATION,
132 	PROP_BLOCKS,
133 	PROP_SUBBANDS,
134 	PROP_BITPOOL
135 };
136 
137 GST_BOILERPLATE(GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT);
138 
139 static const GstElementDetails sbc_enc_details =
140 	GST_ELEMENT_DETAILS("Bluetooth SBC encoder",
141 				"Codec/Encoder/Audio",
142 				"Encode a SBC audio stream",
143 				"Marcel Holtmann <marcel@holtmann.org>");
144 
145 static GstStaticPadTemplate sbc_enc_sink_factory =
146 	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
147 		GST_STATIC_CAPS("audio/x-raw-int, "
148 				"rate = (int) { 16000, 32000, 44100, 48000 }, "
149 				"channels = (int) [ 1, 2 ], "
150 				"endianness = (int) BYTE_ORDER, "
151 				"signed = (boolean) true, "
152 				"width = (int) 16, "
153 				"depth = (int) 16"));
154 
155 static GstStaticPadTemplate sbc_enc_src_factory =
156 	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
157 		GST_STATIC_CAPS("audio/x-sbc, "
158 				"rate = (int) { 16000, 32000, 44100, 48000 }, "
159 				"channels = (int) [ 1, 2 ], "
160 				"mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, "
161 				"blocks = (int) { 4, 8, 12, 16 }, "
162 				"subbands = (int) { 4, 8 }, "
163 				"allocation = (string) { \"snr\", \"loudness\" }, "
164 				"bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR
165 				", " SBC_ENC_BITPOOL_MAX_STR " ]"));
166 
167 gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps);
168 
sbc_enc_generate_srcpad_caps(GstSbcEnc * enc)169 static GstCaps *sbc_enc_generate_srcpad_caps(GstSbcEnc *enc)
170 {
171 	GstCaps *src_caps;
172 	GstStructure *structure;
173 	GEnumValue *enum_value;
174 	GEnumClass *enum_class;
175 	GValue *value;
176 
177 	src_caps = gst_caps_copy(gst_pad_get_pad_template_caps(enc->srcpad));
178 	structure = gst_caps_get_structure(src_caps, 0);
179 
180 	value = g_new0(GValue, 1);
181 
182 	if (enc->rate != 0)
183 		gst_sbc_util_set_structure_int_param(structure, "rate",
184 			enc->rate, value);
185 
186 	if (enc->channels != 0)
187 		gst_sbc_util_set_structure_int_param(structure, "channels",
188 			enc->channels, value);
189 
190 	if (enc->subbands != 0)
191 		gst_sbc_util_set_structure_int_param(structure, "subbands",
192 			enc->subbands, value);
193 
194 	if (enc->blocks != 0)
195 		gst_sbc_util_set_structure_int_param(structure, "blocks",
196 			enc->blocks, value);
197 
198 	if (enc->bitpool != SBC_ENC_BITPOOL_AUTO)
199 		gst_sbc_util_set_structure_int_param(structure, "bitpool",
200 			enc->bitpool, value);
201 
202 	if (enc->mode != SBC_ENC_DEFAULT_MODE) {
203 		enum_class = g_type_class_ref(GST_TYPE_SBC_MODE);
204 		enum_value = g_enum_get_value(enum_class, enc->mode);
205 		gst_sbc_util_set_structure_string_param(structure, "mode",
206 			enum_value->value_nick, value);
207 		g_type_class_unref(enum_class);
208 	}
209 
210 	if (enc->allocation != SBC_AM_AUTO) {
211 		enum_class = g_type_class_ref(GST_TYPE_SBC_ALLOCATION);
212 		enum_value = g_enum_get_value(enum_class, enc->allocation);
213 		gst_sbc_util_set_structure_string_param(structure, "allocation",
214 			enum_value->value_nick, value);
215 		g_type_class_unref(enum_class);
216 	}
217 
218 	g_free(value);
219 
220 	return src_caps;
221 }
222 
sbc_enc_src_getcaps(GstPad * pad)223 static GstCaps *sbc_enc_src_getcaps(GstPad *pad)
224 {
225 	GstSbcEnc *enc;
226 
227 	enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
228 
229 	return sbc_enc_generate_srcpad_caps(enc);
230 }
231 
sbc_enc_src_setcaps(GstPad * pad,GstCaps * caps)232 static gboolean sbc_enc_src_setcaps(GstPad *pad, GstCaps *caps)
233 {
234 	GstSbcEnc *enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
235 
236 	GST_LOG_OBJECT(enc, "setting srcpad caps");
237 
238 	return gst_sbc_enc_fill_sbc_params(enc, caps);
239 }
240 
sbc_enc_src_caps_fixate(GstSbcEnc * enc,GstCaps * caps)241 static GstCaps *sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps)
242 {
243 	gchar *error_message = NULL;
244 	GstCaps *result;
245 
246 	result = gst_sbc_util_caps_fixate(caps, &error_message);
247 
248 	if (!result) {
249 		GST_WARNING_OBJECT(enc, "Invalid input caps caused parsing "
250 				"error: %s", error_message);
251 		g_free(error_message);
252 		return NULL;
253 	}
254 
255 	return result;
256 }
257 
sbc_enc_get_fixed_srcpad_caps(GstSbcEnc * enc)258 static GstCaps *sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc)
259 {
260 	GstCaps *caps;
261 	gboolean res = TRUE;
262 	GstCaps *result_caps = NULL;
263 
264 	caps = gst_pad_get_allowed_caps(enc->srcpad);
265 	if (caps == NULL)
266 		caps = sbc_enc_src_getcaps(enc->srcpad);
267 
268 	if (caps == GST_CAPS_NONE || gst_caps_is_empty(caps)) {
269 		res = FALSE;
270 		goto done;
271 	}
272 
273 	result_caps = sbc_enc_src_caps_fixate(enc, caps);
274 
275 done:
276 	gst_caps_unref(caps);
277 
278 	if (!res)
279 		return NULL;
280 
281 	return result_caps;
282 }
283 
sbc_enc_sink_setcaps(GstPad * pad,GstCaps * caps)284 static gboolean sbc_enc_sink_setcaps(GstPad *pad, GstCaps *caps)
285 {
286 	GstSbcEnc *enc;
287 	GstStructure *structure;
288 	GstCaps *src_caps;
289 	gint rate, channels;
290 	gboolean res;
291 
292 	enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
293 	structure = gst_caps_get_structure(caps, 0);
294 
295 	if (!gst_structure_get_int(structure, "rate", &rate))
296 		return FALSE;
297 	if (!gst_structure_get_int(structure, "channels", &channels))
298 		return FALSE;
299 
300 	enc->rate = rate;
301 	enc->channels = channels;
302 
303 	src_caps = sbc_enc_get_fixed_srcpad_caps(enc);
304 	if (!src_caps)
305 		return FALSE;
306 	res = gst_pad_set_caps(enc->srcpad, src_caps);
307 	gst_caps_unref(src_caps);
308 
309 	return res;
310 }
311 
gst_sbc_enc_fill_sbc_params(GstSbcEnc * enc,GstCaps * caps)312 gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps)
313 {
314 	if (!gst_caps_is_fixed(caps)) {
315 		GST_DEBUG_OBJECT(enc, "didn't receive fixed caps, "
316 				"returning false");
317 		return FALSE;
318 	}
319 
320 	if (!gst_sbc_util_fill_sbc_params(&enc->sbc, caps))
321 		return FALSE;
322 
323 	if (enc->rate != 0 && gst_sbc_parse_rate_from_sbc(enc->sbc.frequency)
324 				 != enc->rate)
325 		goto fail;
326 
327 	if (enc->channels != 0 && gst_sbc_get_channel_number(enc->sbc.mode)
328 				!= enc->channels)
329 		goto fail;
330 
331 	if (enc->blocks != 0 && gst_sbc_parse_blocks_from_sbc(enc->sbc.blocks)
332 				 != enc->blocks)
333 		goto fail;
334 
335 	if (enc->subbands != 0 && gst_sbc_parse_subbands_from_sbc(
336 				enc->sbc.subbands) != enc->subbands)
337 		goto fail;
338 
339 	if (enc->mode != SBC_ENC_DEFAULT_MODE && enc->sbc.mode != enc->mode)
340 		goto fail;
341 
342 	if (enc->allocation != SBC_AM_AUTO &&
343 				enc->sbc.allocation != enc->allocation)
344 		goto fail;
345 
346 	if (enc->bitpool != SBC_ENC_BITPOOL_AUTO &&
347 				enc->sbc.bitpool != enc->bitpool)
348 		goto fail;
349 
350 	enc->codesize = sbc_get_codesize(&enc->sbc);
351 	enc->frame_length = sbc_get_frame_length(&enc->sbc);
352 	enc->frame_duration = sbc_get_frame_duration(&enc->sbc);
353 
354 	GST_DEBUG_OBJECT(enc, "codesize: %d, frame_length: %d, frame_duration:"
355 			" %d", enc->codesize, enc->frame_length,
356 			enc->frame_duration);
357 
358 	return TRUE;
359 
360 fail:
361 	memset(&enc->sbc, 0, sizeof(sbc_t));
362 	return FALSE;
363 }
364 
sbc_enc_chain(GstPad * pad,GstBuffer * buffer)365 static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer)
366 {
367 	GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad));
368 	GstAdapter *adapter = enc->adapter;
369 	GstFlowReturn res = GST_FLOW_OK;
370 
371 	gst_adapter_push(adapter, buffer);
372 
373 	while (gst_adapter_available(adapter) >= enc->codesize &&
374 							res == GST_FLOW_OK) {
375 		GstBuffer *output;
376 		GstCaps *caps;
377 		const guint8 *data;
378 		gint consumed;
379 
380 		caps = GST_PAD_CAPS(enc->srcpad);
381 		res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad,
382 						GST_BUFFER_OFFSET_NONE,
383 						enc->frame_length, caps,
384 						&output);
385 		if (res != GST_FLOW_OK)
386 			goto done;
387 
388 		data = gst_adapter_peek(adapter, enc->codesize);
389 
390 		consumed = sbc_encode(&enc->sbc, (gpointer) data,
391 					enc->codesize,
392 					GST_BUFFER_DATA(output),
393 					GST_BUFFER_SIZE(output), NULL);
394 		if (consumed <= 0) {
395 			GST_DEBUG_OBJECT(enc, "comsumed < 0, codesize: %d",
396 					enc->codesize);
397 			break;
398 		}
399 		gst_adapter_flush(adapter, consumed);
400 
401 		GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer);
402 		/* we have only 1 frame */
403 		GST_BUFFER_DURATION(output) = enc->frame_duration;
404 
405 		res = gst_pad_push(enc->srcpad, output);
406 
407 		if (res != GST_FLOW_OK)
408 			goto done;
409 	}
410 
411 done:
412 	gst_object_unref(enc);
413 
414 	return res;
415 }
416 
sbc_enc_change_state(GstElement * element,GstStateChange transition)417 static GstStateChangeReturn sbc_enc_change_state(GstElement *element,
418 						GstStateChange transition)
419 {
420 	GstSbcEnc *enc = GST_SBC_ENC(element);
421 
422 	switch (transition) {
423 	case GST_STATE_CHANGE_READY_TO_PAUSED:
424 		GST_DEBUG("Setup subband codec");
425 		sbc_init(&enc->sbc, 0);
426 		break;
427 
428 	case GST_STATE_CHANGE_PAUSED_TO_READY:
429 		GST_DEBUG("Finish subband codec");
430 		sbc_finish(&enc->sbc);
431 		break;
432 
433 	default:
434 		break;
435 	}
436 
437 	return parent_class->change_state(element, transition);
438 }
439 
gst_sbc_enc_dispose(GObject * object)440 static void gst_sbc_enc_dispose(GObject *object)
441 {
442 	GstSbcEnc *enc = GST_SBC_ENC(object);
443 
444 	if (enc->adapter != NULL)
445 		g_object_unref(G_OBJECT(enc->adapter));
446 
447 	enc->adapter = NULL;
448 }
449 
gst_sbc_enc_base_init(gpointer g_class)450 static void gst_sbc_enc_base_init(gpointer g_class)
451 {
452 	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
453 
454 	gst_element_class_add_pad_template(element_class,
455 		gst_static_pad_template_get(&sbc_enc_sink_factory));
456 
457 	gst_element_class_add_pad_template(element_class,
458 		gst_static_pad_template_get(&sbc_enc_src_factory));
459 
460 	gst_element_class_set_details(element_class, &sbc_enc_details);
461 }
462 
gst_sbc_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)463 static void gst_sbc_enc_set_property(GObject *object, guint prop_id,
464 					const GValue *value, GParamSpec *pspec)
465 {
466 	GstSbcEnc *enc = GST_SBC_ENC(object);
467 
468 	/* changes to those properties will only happen on the next caps
469 	 * negotiation */
470 
471 	switch (prop_id) {
472 	case PROP_MODE:
473 		enc->mode = g_value_get_enum(value);
474 		break;
475 	case PROP_ALLOCATION:
476 		enc->allocation = g_value_get_enum(value);
477 		break;
478 	case PROP_BLOCKS:
479 		enc->blocks = g_value_get_enum(value);
480 		break;
481 	case PROP_SUBBANDS:
482 		enc->subbands = g_value_get_enum(value);
483 		break;
484 	case PROP_BITPOOL:
485 		enc->bitpool = g_value_get_int(value);
486 		break;
487 	default:
488 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
489 		break;
490 	}
491 }
492 
gst_sbc_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)493 static void gst_sbc_enc_get_property(GObject *object, guint prop_id,
494 					GValue *value, GParamSpec *pspec)
495 {
496 	GstSbcEnc *enc = GST_SBC_ENC(object);
497 
498 	switch (prop_id) {
499 	case PROP_MODE:
500 		g_value_set_enum(value, enc->mode);
501 		break;
502 	case PROP_ALLOCATION:
503 		g_value_set_enum(value, enc->allocation);
504 		break;
505 	case PROP_BLOCKS:
506 		g_value_set_enum(value, enc->blocks);
507 		break;
508 	case PROP_SUBBANDS:
509 		g_value_set_enum(value, enc->subbands);
510 		break;
511 	case PROP_BITPOOL:
512 		g_value_set_int(value, enc->bitpool);
513 		break;
514 	default:
515 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
516 		break;
517 	}
518 }
519 
gst_sbc_enc_class_init(GstSbcEncClass * klass)520 static void gst_sbc_enc_class_init(GstSbcEncClass *klass)
521 {
522 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
523 	GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
524 
525 	parent_class = g_type_class_peek_parent(klass);
526 
527 	object_class->set_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_set_property);
528 	object_class->get_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_get_property);
529 	object_class->dispose = GST_DEBUG_FUNCPTR(gst_sbc_enc_dispose);
530 
531 	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_enc_change_state);
532 
533 	g_object_class_install_property(object_class, PROP_MODE,
534 			g_param_spec_enum("mode", "Mode",
535 				"Encoding mode", GST_TYPE_SBC_MODE,
536 				SBC_ENC_DEFAULT_MODE, G_PARAM_READWRITE));
537 
538 	g_object_class_install_property(object_class, PROP_ALLOCATION,
539 			g_param_spec_enum("allocation", "Allocation",
540 				"Allocation method", GST_TYPE_SBC_ALLOCATION,
541 				SBC_ENC_DEFAULT_ALLOCATION, G_PARAM_READWRITE));
542 
543 	g_object_class_install_property(object_class, PROP_BLOCKS,
544 			g_param_spec_enum("blocks", "Blocks",
545 				"Blocks", GST_TYPE_SBC_BLOCKS,
546 				SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE));
547 
548 	g_object_class_install_property(object_class, PROP_SUBBANDS,
549 			g_param_spec_enum("subbands", "Sub bands",
550 				"Number of sub bands", GST_TYPE_SBC_SUBBANDS,
551 				SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE));
552 
553 	g_object_class_install_property(object_class, PROP_BITPOOL,
554 			g_param_spec_int("bitpool", "Bitpool",
555 				"Bitpool (use 1 for automatic selection)",
556 				SBC_ENC_BITPOOL_AUTO, SBC_ENC_BITPOOL_MAX,
557 				SBC_ENC_BITPOOL_AUTO, G_PARAM_READWRITE));
558 
559 	GST_DEBUG_CATEGORY_INIT(sbc_enc_debug, "sbcenc", 0,
560 						"SBC encoding element");
561 }
562 
gst_sbc_enc_init(GstSbcEnc * self,GstSbcEncClass * klass)563 static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)
564 {
565 	self->sinkpad = gst_pad_new_from_static_template(
566 		&sbc_enc_sink_factory, "sink");
567 	gst_pad_set_setcaps_function(self->sinkpad,
568 			GST_DEBUG_FUNCPTR(sbc_enc_sink_setcaps));
569 	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
570 
571 	self->srcpad = gst_pad_new_from_static_template(
572 		&sbc_enc_src_factory, "src");
573 	gst_pad_set_getcaps_function(self->srcpad,
574 		GST_DEBUG_FUNCPTR(sbc_enc_src_getcaps));
575 	gst_pad_set_setcaps_function(self->srcpad,
576 		GST_DEBUG_FUNCPTR(sbc_enc_src_setcaps));
577 	gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
578 
579 	gst_pad_set_chain_function(self->sinkpad,
580 		GST_DEBUG_FUNCPTR(sbc_enc_chain));
581 
582 	self->subbands = SBC_ENC_DEFAULT_SUB_BANDS;
583 	self->blocks = SBC_ENC_DEFAULT_BLOCKS;
584 	self->mode = SBC_ENC_DEFAULT_MODE;
585 	self->allocation = SBC_ENC_DEFAULT_ALLOCATION;
586 	self->rate = SBC_ENC_DEFAULT_RATE;
587 	self->channels = SBC_ENC_DEFAULT_CHANNELS;
588 	self->bitpool = SBC_ENC_BITPOOL_AUTO;
589 
590 	self->frame_length = 0;
591 	self->frame_duration = 0;
592 
593 	self->adapter = gst_adapter_new();
594 }
595 
gst_sbc_enc_plugin_init(GstPlugin * plugin)596 gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin)
597 {
598 	return gst_element_register(plugin, "sbcenc",
599 			GST_RANK_NONE, GST_TYPE_SBC_ENC);
600 }
601 
602 
603