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",