diff --git a/ext/speex/gstspeexdec.c b/ext/speex/gstspeexdec.c index 46f774b8f9..4093fee9f8 100644 --- a/ext/speex/gstspeexdec.c +++ b/ext/speex/gstspeexdec.c @@ -76,7 +76,8 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_CAPS ("audio/x-speex") ); -GST_BOILERPLATE (GstSpeexDec, gst_speex_dec, GstElement, GST_TYPE_ELEMENT); +#define gst_speex_dec_parent_class parent_class +G_DEFINE_TYPE (GstSpeexDec, gst_speex_dec, GST_TYPE_ELEMENT); static gboolean speex_dec_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn speex_dec_chain (GstPad * pad, GstBuffer * buf); @@ -86,7 +87,6 @@ static GstStateChangeReturn speex_dec_change_state (GstElement * element, static gboolean speex_dec_src_event (GstPad * pad, GstEvent * event); static gboolean speex_dec_src_query (GstPad * pad, GstQuery * query); static gboolean speex_dec_sink_query (GstPad * pad, GstQuery * query); -static gboolean speex_dec_sink_setcaps (GstPad * pad, GstCaps * caps); static const GstQueryType *speex_get_src_query_types (GstPad * pad); static const GstQueryType *speex_get_sink_query_types (GstPad * pad); static gboolean speex_dec_convert (GstPad * pad, @@ -106,20 +106,6 @@ static GstFlowReturn speex_dec_chain_parse_header (GstSpeexDec * dec, static GstFlowReturn speex_dec_chain_parse_comments (GstSpeexDec * dec, GstBuffer * buf); -static void -gst_speex_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 (&speex_dec_src_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&speex_dec_sink_factory)); - gst_element_class_set_details_simple (element_class, "Speex audio decoder", - "Codec/Decoder/Audio", - "decode speex streams to audio", "Wim Taymans "); -} - static void gst_speex_dec_class_init (GstSpeexDecClass * klass) { @@ -138,6 +124,14 @@ gst_speex_dec_class_init (GstSpeexDecClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (speex_dec_change_state); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&speex_dec_src_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&speex_dec_sink_factory)); + gst_element_class_set_details_simple (gstelement_class, "Speex audio decoder", + "Codec/Decoder/Audio", + "decode speex streams to audio", "Wim Taymans "); + GST_DEBUG_CATEGORY_INIT (speexdec_debug, "speexdec", 0, "speex decoding element"); } @@ -169,7 +163,7 @@ gst_speex_dec_reset (GstSpeexDec * dec) } static void -gst_speex_dec_init (GstSpeexDec * dec, GstSpeexDecClass * g_class) +gst_speex_dec_init (GstSpeexDec * dec) { dec->sinkpad = gst_pad_new_from_static_template (&speex_dec_sink_factory, "sink"); @@ -181,8 +175,6 @@ gst_speex_dec_init (GstSpeexDec * dec, GstSpeexDecClass * g_class) GST_DEBUG_FUNCPTR (speex_get_sink_query_types)); gst_pad_set_query_function (dec->sinkpad, GST_DEBUG_FUNCPTR (speex_dec_sink_query)); - gst_pad_set_setcaps_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (speex_dec_sink_setcaps)); gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); dec->srcpad = @@ -402,7 +394,7 @@ speex_dec_src_query (GstPad * pad, GstQuery * query) } if ((res = speex_dec_convert (dec->srcpad, GST_FORMAT_TIME, - segment.last_stop, &format, &cur))) { + segment.position, &format, &cur))) { gst_query_set_position (query, format, cur); } break; @@ -496,43 +488,44 @@ speex_dec_sink_event (GstPad * pad, GstEvent * event) GST_LOG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT:{ - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; + case GST_EVENT_CAPS: + { + GstCaps *caps; - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); + gst_event_parse_caps (event, &caps); + ret = speex_dec_sink_setcaps (pad, caps); + gst_event_unref (event); + break; + } + case GST_EVENT_SEGMENT:{ + GstSegment segment; - if (format != GST_FORMAT_TIME) + gst_event_copy_segment (event, &segment); + + if (segment.format != GST_FORMAT_TIME) goto newseg_wrong_format; - if (rate <= 0.0) + if (segment.rate <= 0.0) goto newseg_wrong_rate; +#if 0 if (update) { /* time progressed without data, see if we can fill the gap with * some concealment data */ - if (dec->segment.last_stop < start) { + if (dec->segment.position < start) { GstClockTime duration; - duration = start - dec->segment.last_stop; - speex_dec_chain_parse_data (dec, NULL, dec->segment.last_stop, + duration = start - dec->segment.position; + speex_dec_chain_parse_data (dec, NULL, dec->segment.position, duration); } } +#endif /* now configure the values */ - gst_segment_set_newsegment_full (&dec->segment, update, - rate, arate, GST_FORMAT_TIME, start, stop, time); - - GST_DEBUG_OBJECT (dec, "segment now: cur = %" GST_TIME_FORMAT " [%" - GST_TIME_FORMAT " - %" GST_TIME_FORMAT "]", - GST_TIME_ARGS (dec->segment.last_stop), - GST_TIME_ARGS (dec->segment.start), - GST_TIME_ARGS (dec->segment.stop)); + dec->segment = segment; + GST_DEBUG_OBJECT (dec, "segment now: %" GST_SEGMENT_FORMAT, &segment); ret = gst_pad_push_event (dec->srcpad, event); break; } @@ -563,10 +556,13 @@ static GstFlowReturn speex_dec_chain_parse_header (GstSpeexDec * dec, GstBuffer * buf) { GstCaps *caps; + char *data; + gsize size; /* get the header */ - dec->header = speex_packet_to_header ((char *) GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); + data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + dec->header = speex_packet_to_header (data, size); + gst_buffer_unmap (buf, data, size); if (!dec->header) goto no_header; @@ -693,25 +689,24 @@ speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; - guint size; - guint8 *data; SpeexBits *bits; + gsize size; + char *data; if (!dec->frame_duration) goto not_negotiated; if (timestamp != -1) { - dec->segment.last_stop = timestamp; + dec->segment.position = timestamp; } else { - timestamp = dec->segment.last_stop; + timestamp = dec->segment.position; } if (buf) { - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - /* send data to the bitstream */ - speex_bits_read_from (&dec->bits, (char *) data, size); + data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + speex_bits_read_from (&dec->bits, data, size); + gst_buffer_unmap (buf, data, size); fpp = dec->header->frames_per_packet; bits = &dec->bits; @@ -734,7 +729,7 @@ speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp, bits ? speex_bits_remaining (bits) : -1); - +#if 0 res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (dec->srcpad), &outbuf); @@ -743,10 +738,17 @@ speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } +#endif + /* FIXME, we can use a bufferpool because we have fixed size buffers. We + * could also use an allocator */ + outbuf = + gst_buffer_new_allocate (NULL, + dec->frame_size * dec->header->nb_channels * 2, 0); - out_data = (gint16 *) GST_BUFFER_DATA (outbuf); - + out_data = gst_buffer_map (outbuf, &size, NULL, GST_MAP_WRITE); ret = speex_decode_int (dec->state, bits, out_data); + gst_buffer_unmap (outbuf, out_data, size); + if (ret == -1) { /* uh? end of stream */ if (fpp == 0 && speex_bits_remaining (bits) < 8) { @@ -777,8 +779,8 @@ speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = dec->frame_duration; - dec->segment.last_stop += dec->frame_duration; - timestamp = dec->segment.last_stop; + dec->segment.position += dec->frame_duration; + timestamp = dec->segment.position; GST_LOG_OBJECT (dec, "pushing buffer with ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), @@ -803,6 +805,26 @@ not_negotiated: } } +static gboolean +memcmp_buffers (GstBuffer * buf1, GstBuffer * buf2) +{ + gsize size1, size2; + gpointer data1; + gboolean res; + + size1 = gst_buffer_get_size (buf1); + size2 = gst_buffer_get_size (buf2); + + if (size1 != size2) + return FALSE; + + data1 = gst_buffer_map (buf1, NULL, NULL, GST_MAP_READ); + res = gst_buffer_memcmp (buf2, 0, data1, size1) == 0; + gst_buffer_unmap (buf1, data1, size1); + + return res; +} + static GstFlowReturn speex_dec_chain (GstPad * pad, GstBuffer * buf) { @@ -814,13 +836,9 @@ speex_dec_chain (GstPad * pad, GstBuffer * buf) /* If we have the streamheader and vorbiscomment from the caps already * ignore them here */ if (dec->streamheader && dec->vorbiscomment) { - if (GST_BUFFER_SIZE (dec->streamheader) == GST_BUFFER_SIZE (buf) - && memcmp (GST_BUFFER_DATA (dec->streamheader), GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)) == 0) { + if (memcmp_buffers (dec->streamheader, buf)) { res = GST_FLOW_OK; - } else if (GST_BUFFER_SIZE (dec->vorbiscomment) == GST_BUFFER_SIZE (buf) - && memcmp (GST_BUFFER_DATA (dec->vorbiscomment), GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)) == 0) { + } else if (memcmp_buffers (dec->vorbiscomment, buf)) { res = GST_FLOW_OK; } else { res = @@ -904,7 +922,7 @@ speex_dec_change_state (GstElement * element, GstStateChange transition) break; } - ret = parent_class->change_state (element, transition); + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret != GST_STATE_CHANGE_SUCCESS) return ret; diff --git a/ext/speex/gstspeexenc.c b/ext/speex/gstspeexenc.c index 6ace2da124..bfbb6d843e 100644 --- a/ext/speex/gstspeexenc.c +++ b/ext/speex/gstspeexenc.c @@ -135,7 +135,7 @@ gst_speex_enc_get_formats (GstPad * pad) static void gst_speex_enc_finalize (GObject * object); -static gboolean gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event); +static gboolean gst_speex_enc_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_speex_enc_chain (GstPad * pad, GstBuffer * buf); static gboolean gst_speex_enc_setup (GstSpeexEnc * enc); @@ -148,40 +148,10 @@ static GstStateChangeReturn gst_speex_enc_change_state (GstElement * element, static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush); -static void -gst_speex_enc_setup_interfaces (GType speexenc_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 (speexenc_type, GST_TYPE_TAG_SETTER, - &tag_setter_info); - g_type_add_interface_static (speexenc_type, GST_TYPE_PRESET, - &preset_interface_info); - - GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder"); -} - -GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstElement, GST_TYPE_ELEMENT, - gst_speex_enc_setup_interfaces); - -static void -gst_speex_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, "Speex audio encoder", - "Codec/Encoder/Audio", - "Encodes audio in Speex format", "Wim Taymans "); -} +#define gst_speex_enc_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstSpeexEnc, gst_speex_enc, GST_TYPE_ELEMENT, + G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL); + G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL)); static void gst_speex_enc_class_init (GstSpeexEncClass * klass) @@ -192,6 +162,7 @@ gst_speex_enc_class_init (GstSpeexEncClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gobject_class->finalize = gst_speex_enc_finalize; gobject_class->set_property = gst_speex_enc_set_property; gobject_class->get_property = gst_speex_enc_get_property; @@ -240,10 +211,18 @@ gst_speex_enc_class_init (GstSpeexEncClass * klass) "The last status message", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - gobject_class->finalize = gst_speex_enc_finalize; - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_speex_enc_change_state); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details_simple (gstelement_class, "Speex audio encoder", + "Codec/Encoder/Audio", + "Encodes audio in Speex format", "Wim Taymans "); + + GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder"); } static void @@ -279,13 +258,13 @@ gst_speex_enc_sink_setcaps (GstPad * pad, GstCaps * caps) static GstCaps * -gst_speex_enc_sink_getcaps (GstPad * pad) +gst_speex_enc_sink_getcaps (GstPad * pad, GstCaps * filter) { GstCaps *caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); GstCaps *peercaps = NULL; GstSpeexEnc *enc = GST_SPEEX_ENC (gst_pad_get_parent_element (pad)); - peercaps = gst_pad_peer_get_caps (enc->srcpad); + peercaps = gst_pad_peer_get_caps (enc->srcpad, filter); if (peercaps) { if (!gst_caps_is_empty (peercaps) && !gst_caps_is_any (peercaps)) { @@ -568,16 +547,14 @@ error: } static void -gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass) +gst_speex_enc_init (GstSpeexEnc * enc) { enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); gst_pad_set_event_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_speex_enc_sinkevent)); + GST_DEBUG_FUNCPTR (gst_speex_enc_sink_event)); gst_pad_set_chain_function (enc->sinkpad, GST_DEBUG_FUNCPTR (gst_speex_enc_chain)); - gst_pad_set_setcaps_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_speex_enc_sink_setcaps)); gst_pad_set_getcaps_function (enc->sinkpad, GST_DEBUG_FUNCPTR (gst_speex_enc_sink_getcaps)); gst_pad_set_query_function (enc->sinkpad, @@ -782,11 +759,11 @@ gst_speex_enc_buffer_from_data (GstSpeexEnc * enc, guchar * data, GstBuffer *outbuf; outbuf = gst_buffer_new_and_alloc (data_len); - memcpy (GST_BUFFER_DATA (outbuf), data, data_len); + gst_buffer_fill (outbuf, 0, data, data_len); GST_BUFFER_OFFSET (outbuf) = enc->bytes_out; GST_BUFFER_OFFSET_END (outbuf) = granulepos; - GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf)); + GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", data_len); return outbuf; } @@ -797,8 +774,7 @@ gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer) { guint size; - size = GST_BUFFER_SIZE (buffer); - + size = gst_buffer_get_size (buffer); enc->bytes_out += size; GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size); @@ -818,8 +794,8 @@ gst_speex_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1, caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); - g_assert (gst_buffer_is_metadata_writable (buf1)); - g_assert (gst_buffer_is_metadata_writable (buf2)); + g_assert (gst_buffer_is_writable (buf1)); + g_assert (gst_buffer_is_writable (buf2)); /* mark buffers */ GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS); @@ -847,7 +823,7 @@ gst_speex_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1, static gboolean -gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event) +gst_speex_enc_sink_event (GstPad * pad, GstEvent * event) { gboolean res = TRUE; GstSpeexEnc *enc; @@ -855,6 +831,15 @@ gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event) enc = GST_SPEEX_ENC (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + res = gst_speex_enc_sink_setcaps (pad, caps); + gst_event_unref (event); + break; + } case GST_EVENT_EOS: if (enc->setup) gst_speex_enc_encode (enc, TRUE); @@ -894,8 +879,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush) if (flush && gst_adapter_available (enc->adapter) % bytes != 0) { guint diff = gst_adapter_available (enc->adapter) % bytes; GstBuffer *buf = gst_buffer_new_and_alloc (diff); - - memset (GST_BUFFER_DATA (buf), 0, diff); + gst_buffer_memset (buf, 0, 0, diff); gst_adapter_push (enc->adapter, buf); } @@ -903,6 +887,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush) gint16 *data; gint outsize, written, dtx_ret; GstBuffer *outbuf; + gchar *outdata; data = (gint16 *) gst_adapter_take (enc->adapter, bytes); @@ -926,19 +911,21 @@ gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush) speex_bits_insert_terminator (&enc->bits); outsize = speex_bits_nbytes (&enc->bits); +#if 0 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf); - if ((GST_FLOW_OK != ret)) goto done; +#endif + outbuf = gst_buffer_new_allocate (NULL, outsize, 0); - written = speex_bits_write (&enc->bits, - (gchar *) GST_BUFFER_DATA (outbuf), outsize); + outdata = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE); + written = speex_bits_write (&enc->bits, outdata, outsize); if (G_UNLIKELY (written != outsize)) { GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize); - GST_BUFFER_SIZE (outbuf) = written; } + gst_buffer_unmap (outbuf, outdata, written); speex_bits_reset (&enc->bits); @@ -1001,7 +988,7 @@ gst_speex_enc_chain (GstPad * pad, GstBuffer * buf) buf2 = gst_speex_enc_create_metadata_buffer (enc); /* mark and put on caps */ - caps = gst_pad_get_caps (enc->srcpad); + caps = gst_pad_get_caps (enc->srcpad, NULL); caps = gst_speex_enc_set_header_on_caps (caps, buf1, buf2); gst_caps_set_simple (caps, @@ -1011,9 +998,6 @@ gst_speex_enc_chain (GstPad * pad, GstBuffer * buf) /* negotiate with these caps */ GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps); gst_pad_set_caps (enc->srcpad, caps); - - gst_buffer_set_caps (buf1, caps); - gst_buffer_set_caps (buf2, caps); gst_caps_unref (caps); /* push out buffers */ @@ -1061,13 +1045,12 @@ gst_speex_enc_chain (GstPad * pad, GstBuffer * buf) GST_TIME_ARGS (enc->next_ts)); diff_bytes = GST_CLOCK_TIME_TO_FRAMES (diff, enc->rate) * enc->channels * 2; - if (diff_bytes >= GST_BUFFER_SIZE (buf)) { + if (diff_bytes >= gst_buffer_get_size (buf)) { gst_buffer_unref (buf); return GST_FLOW_OK; } - buf = gst_buffer_make_metadata_writable (buf); - GST_BUFFER_DATA (buf) += diff_bytes; - GST_BUFFER_SIZE (buf) -= diff_bytes; + buf = gst_buffer_make_writable (buf); + gst_buffer_resize (buf, diff_bytes, -1); GST_BUFFER_TIMESTAMP (buf) += diff; if (GST_BUFFER_DURATION_IS_VALID (buf)) @@ -1100,7 +1083,8 @@ gst_speex_enc_chain (GstPad * pad, GstBuffer * buf) else enc->next_ts = GST_CLOCK_TIME_NONE; - GST_DEBUG_OBJECT (enc, "received buffer of %u bytes", GST_BUFFER_SIZE (buf)); + GST_DEBUG_OBJECT (enc, "received buffer of %u bytes", + gst_buffer_get_size (buf)); /* push buffer to adapter */ gst_adapter_push (enc->adapter, buf);