GST_STATIC_CAPS ("audio/x-celt")
);
-GST_BOILERPLATE (GstCeltDec, gst_celt_dec, GstAudioDecoder,
- GST_TYPE_AUDIO_DECODER);
+#define gst_celt_dec_parent_class parent_class
- G_DEFINE_TYPE (GstCeltDec, gst_celt_dec, GST_TYPE_ELEMENT);
-
- static gboolean celt_dec_sink_event (GstPad * pad, GstEvent * event);
- static GstFlowReturn celt_dec_chain (GstPad * pad, GstBuffer * buf);
- static gboolean celt_dec_sink_setcaps (GstPad * pad, GstCaps * caps);
- static GstStateChangeReturn celt_dec_change_state (GstElement * element,
- GstStateChange transition);
-
- static gboolean celt_dec_src_event (GstPad * pad, GstEvent * event);
- static gboolean celt_dec_src_query (GstPad * pad, GstQuery * query);
- static gboolean celt_dec_sink_query (GstPad * pad, GstQuery * query);
- static const GstQueryType *celt_get_src_query_types (GstPad * pad);
- static const GstQueryType *celt_get_sink_query_types (GstPad * pad);
- static gboolean celt_dec_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value);
-
- static GstFlowReturn celt_dec_chain_parse_data (GstCeltDec * dec,
- GstBuffer * buf, GstClockTime timestamp, GstClockTime duration);
- static GstFlowReturn celt_dec_chain_parse_header (GstCeltDec * dec,
- GstBuffer * buf);
- static GstFlowReturn celt_dec_chain_parse_comments (GstCeltDec * dec,
- GstBuffer * buf);
++G_DEFINE_TYPE (GstCeltDec, gst_celt_dec, GST_TYPE_AUDIO_DECODER);
+
+ static gboolean gst_celt_dec_start (GstAudioDecoder * dec);
+ static gboolean gst_celt_dec_stop (GstAudioDecoder * dec);
+ static gboolean gst_celt_dec_set_format (GstAudioDecoder * bdec,
+ GstCaps * caps);
+ static GstFlowReturn gst_celt_dec_handle_frame (GstAudioDecoder * dec,
+ GstBuffer * buffer);
static void
-gst_celt_dec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&celt_dec_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&celt_dec_sink_factory));
- gst_element_class_set_details_simple (element_class, "Celt audio decoder",
- "Codec/Decoder/Audio",
- "decode celt streams to audio",
- "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-}
-
-static void
gst_celt_dec_class_init (GstCeltDecClass * klass)
{
- GstElementClass *gstelement_class;
+ GstAudioDecoderClass *gstbase_class;
- gstelement_class = (GstElementClass *) klass;
+ gstbase_class = (GstAudioDecoderClass *) klass;
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (celt_dec_change_state);
+ gstbase_class->start = GST_DEBUG_FUNCPTR (gst_celt_dec_start);
+ gstbase_class->stop = GST_DEBUG_FUNCPTR (gst_celt_dec_stop);
+ gstbase_class->set_format = GST_DEBUG_FUNCPTR (gst_celt_dec_set_format);
+ gstbase_class->handle_frame = GST_DEBUG_FUNCPTR (gst_celt_dec_handle_frame);
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&celt_dec_src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&celt_dec_sink_factory));
+
+ gst_element_class_set_details_simple (gstelement_class, "Celt audio decoder",
+ "Codec/Decoder/Audio",
+ "decode celt streams to audio",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
GST_DEBUG_CATEGORY_INIT (celtdec_debug, "celtdec", 0,
"celt decoding element");
}
}
static void
-gst_celt_dec_init (GstCeltDec * dec, GstCeltDecClass * g_class)
+gst_celt_dec_init (GstCeltDec * dec)
{
- dec->sinkpad =
- gst_pad_new_from_static_template (&celt_dec_sink_factory, "sink");
- gst_pad_set_chain_function (dec->sinkpad, GST_DEBUG_FUNCPTR (celt_dec_chain));
- gst_pad_set_event_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (celt_dec_sink_event));
- gst_pad_set_query_type_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (celt_get_sink_query_types));
- gst_pad_set_query_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (celt_dec_sink_query));
- gst_pad_set_setcaps_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (celt_dec_sink_setcaps));
- gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
-
- dec->srcpad = gst_pad_new_from_static_template (&celt_dec_src_factory, "src");
- gst_pad_use_fixed_caps (dec->srcpad);
- gst_pad_set_event_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (celt_dec_src_event));
- gst_pad_set_query_type_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (celt_get_src_query_types));
- gst_pad_set_query_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (celt_dec_src_query));
- gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
-
gst_celt_dec_reset (dec);
}
GST_STATIC_CAPS ("audio/x-opus")
);
-GST_BOILERPLATE (GstOpusDec, gst_opus_dec, GstAudioDecoder,
- GST_TYPE_AUDIO_DECODER);
+G_DEFINE_TYPE (GstOpusDec, gst_opus_dec, GST_TYPE_AUDIO_DECODER);
+ static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec,
+ GstBuffer * buf);
static gboolean gst_opus_dec_start (GstAudioDecoder * dec);
static gboolean gst_opus_dec_stop (GstAudioDecoder * dec);
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * dec,
GstBuffer * buffer);
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
GstCaps * caps);
- static GstFlowReturn opus_dec_chain_parse_data (GstOpusDec * dec,
- GstBuffer * buf, GstClockTime timestamp, GstClockTime duration);
static void
-gst_opus_dec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&opus_dec_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&opus_dec_sink_factory));
- gst_element_class_set_details_simple (element_class, "Opus audio decoder",
- "Codec/Decoder/Audio",
- "decode opus streams to audio",
- "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-}
-
-static void
gst_opus_dec_class_init (GstOpusDecClass * klass)
{
GstAudioDecoderClass *adclass;
}
static GstFlowReturn
- opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
- GstClockTime timestamp, GstClockTime duration)
+ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf)
{
GstFlowReturn res = GST_FLOW_OK;
- gint size;
+ gsize size, out_size;
guint8 *data;
GstBuffer *outbuf;
gint16 *out_data;
}
if (buf) {
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
GST_DEBUG_OBJECT (dec, "received buffer of size %u", size);
-
- /* copy timestamp */
} else {
/* concealment data, pass NULL as the bits parameters */
GST_DEBUG_OBJECT (dec, "creating concealment data");
GstBuffer * buf);
static GstFlowReturn gst_opus_enc_pre_push (GstAudioEncoder * benc,
GstBuffer ** buffer);
+ static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
+
+ static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
-static void
-gst_opus_enc_setup_interfaces (GType opusenc_type)
-{
- static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
- const GInterfaceInfo preset_interface_info = {
- NULL, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
- g_type_add_interface_static (opusenc_type, GST_TYPE_TAG_SETTER,
- &tag_setter_info);
- g_type_add_interface_static (opusenc_type, GST_TYPE_PRESET,
- &preset_interface_info);
-
- GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
-}
+static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf);
+static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
-GST_BOILERPLATE_FULL (GstOpusEnc, gst_opus_enc, GstAudioEncoder,
- GST_TYPE_AUDIO_ENCODER, gst_opus_enc_setup_interfaces);
-
-static void
-gst_opus_enc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
- gst_element_class_set_details_simple (element_class, "Opus audio encoder",
- "Codec/Encoder/Audio",
- "Encodes audio in Opus format",
- "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-}
+#define gst_opus_enc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstOpusEnc, gst_opus_enc, GST_TYPE_AUDIO_ENCODER,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
static void
gst_opus_enc_class_init (GstOpusEncClass * klass)
GstAudioEncoderClass *base_class;
gobject_class = (GObjectClass *) klass;
- element_class = (GstElementClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
base_class = (GstAudioEncoderClass *) klass;
+ gobject_class->set_property = gst_opus_enc_set_property;
+ gobject_class->get_property = gst_opus_enc_get_property;
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
+ gst_element_class_set_details_simple (element_class, "Opus audio encoder",
+ "Codec/Encoder/Audio",
+ "Encodes audio in Opus format",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
base_class->start = GST_DEBUG_FUNCPTR (gst_opus_enc_start);
base_class->stop = GST_DEBUG_FUNCPTR (gst_opus_enc_stop);
base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format);
gint ret = GST_FLOW_OK;
if (G_LIKELY (buf)) {
+ bdata = GST_BUFFER_DATA (buf);
+ bsize = GST_BUFFER_SIZE (buf);
+ if (G_UNLIKELY (bsize % bytes)) {
+ GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
+
+ size = ((bsize / bytes) + 1) * bytes;
+ mdata = g_malloc0 (size);
+ memcpy (mdata, bdata, bsize);
+ bdata = NULL;
+ data = mdata;
+ } else {
+ data = bdata;
+ size = bsize;
+ }
+ } else {
+ GST_DEBUG_OBJECT (enc, "nothing to drain");
+ goto done;
+ }
+
++ return ret;
++}
++
++static GstFlowReturn
++gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
++{
++ guint8 *bdata, *data, *mdata = NULL;
++ gsize bsize, size;
++ gsize bytes = enc->frame_samples * enc->n_channels * 2;
++ gsize bytes_per_packet =
++ (enc->bitrate * enc->frame_samples / enc->sample_rate + 4) / 8;
++ gint ret = GST_FLOW_OK;
++
++ if (G_LIKELY (buf)) {
+ bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+
+ if (G_UNLIKELY (bsize % bytes)) {
+ GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
+
+ size = ((bsize / bytes) + 1) * bytes;
+ mdata = g_malloc0 (size);
+ memcpy (mdata, bdata, bsize);
+ gst_buffer_unmap (buf, bdata, bsize);
+ bdata = NULL;
+ data = mdata;
+ } else {
+ data = bdata;
+ size = bsize;
+ }
+ } else {
+ GST_DEBUG_OBJECT (enc, "nothing to drain");
+ goto done;
+ }
while (size) {
- gint outsize;
+ gint encoded_size;
+ unsigned char *out_data;
+ gsize out_size;
GstBuffer *outbuf;
- ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
- GST_BUFFER_OFFSET_NONE, bytes_per_packet,
- GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
-
- if (GST_FLOW_OK != ret)
+ outbuf = gst_buffer_new_and_alloc (bytes_per_packet);
+ if (!outbuf)
goto done;
GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes) to %d bytes",