static void gst_au_parse_dispose (GObject * object) { GstAuParse *au = GST_AU_PARSE (object); if (au->adapter != NULL) { g_object_unref (au->adapter); au->adapter = NULL; } G_OBJECT_CLASS (parent_class)->dispose (object); }
static gboolean gst_au_parse_sink_event (GstPad * pad, GstEvent * event) { GstAuParse *auparse; gboolean ret; auparse = GST_AU_PARSE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (auparse); return ret; }
static GstStateChangeReturn gst_au_parse_change_state (GstElement * element, GstStateChange transition) { GstAuParse *auparse = GST_AU_PARSE (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; ret = parent_class->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_au_parse_reset (auparse); default: break; } return ret; }
static gboolean gst_au_parse_sink_event (GstPad * pad, GstEvent * event) { GstAuParse *auparse; gboolean ret = TRUE; auparse = GST_AU_PARSE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: { GstFormat format; gdouble rate, arate; gint64 start, stop, time, offset = 0; gboolean update; GstSegment segment; GstEvent *new_event = NULL; gst_segment_init (&segment, GST_FORMAT_UNDEFINED); gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); gst_segment_set_newsegment_full (&segment, update, rate, arate, format, start, stop, time); if (auparse->sample_size > 0) { if (start > 0) { offset = start; start -= auparse->offset; start = MAX (start, 0); } if (stop > 0) { stop -= auparse->offset; stop = MAX (stop, 0); } gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, start, GST_FORMAT_TIME, &start); gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, stop, GST_FORMAT_TIME, &stop); } if (auparse->srcpad) { GST_INFO_OBJECT (auparse, "new segment: %" GST_TIME_FORMAT " ... %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); new_event = gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME, start, stop, start); ret = gst_pad_push_event (auparse->srcpad, new_event); } auparse->buffer_offset = offset; gst_event_unref (event); break; } case GST_EVENT_EOS: if (!auparse->srcpad) { GST_ELEMENT_ERROR (auparse, STREAM, WRONG_TYPE, ("No valid input found before end of stream"), (NULL)); } /* fall-through */ default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (auparse); return ret; }
static gboolean gst_au_parse_src_query (GstPad * pad, GstQuery * query) { GstAuParse *auparse; gboolean ret = FALSE; auparse = GST_AU_PARSE (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION:{ GstFormat bformat = GST_FORMAT_BYTES; GstFormat format; gint64 len, val; gst_query_parse_duration (query, &format, NULL); if (!gst_pad_query_peer_duration (auparse->sinkpad, &bformat, &len)) { GST_DEBUG_OBJECT (auparse, "failed to query upstream length"); break; } GST_OBJECT_LOCK (auparse); len -= auparse->offset; GST_OBJECT_UNLOCK (auparse); ret = gst_au_parse_src_convert (auparse, bformat, len, format, &val); if (ret) { gst_query_set_duration (query, format, val); } break; } case GST_QUERY_POSITION:{ GstFormat bformat = GST_FORMAT_BYTES; GstFormat format; gint64 pos, val; gst_query_parse_position (query, &format, NULL); if (!gst_pad_query_peer_position (auparse->sinkpad, &bformat, &pos)) { GST_DEBUG_OBJECT (auparse, "failed to query upstream position"); break; } GST_OBJECT_LOCK (auparse); pos -= auparse->offset; GST_OBJECT_UNLOCK (auparse); ret = gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos, format, &val); if (ret) { gst_query_set_position (query, format, val); } break; } case GST_QUERY_SEEKING:{ GstFormat format; gst_query_parse_seeking (query, &format, NULL, NULL, NULL); /* FIXME: query duration in 'format' gst_query_set_seeking (query, format, TRUE, 0, duration); */ gst_query_set_seeking (query, format, TRUE, 0, GST_CLOCK_TIME_NONE); ret = TRUE; break; } default: ret = gst_pad_query_default (pad, query); break; } gst_object_unref (auparse); return ret; }
static GstFlowReturn gst_au_parse_chain (GstPad * pad, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; GstAuParse *auparse; gint avail, sendnow = 0; gint64 timestamp; gint64 duration; gint64 offset; auparse = GST_AU_PARSE (gst_pad_get_parent (pad)); GST_LOG_OBJECT (auparse, "got buffer of size %u", GST_BUFFER_SIZE (buf)); gst_adapter_push (auparse->adapter, buf); buf = NULL; /* if we haven't seen any data yet... */ if (auparse->srcpad == NULL) { if (gst_adapter_available (auparse->adapter) < AU_HEADER_SIZE) { GST_DEBUG_OBJECT (auparse, "need more data to parse header"); ret = GST_FLOW_OK; goto out; } ret = gst_au_parse_parse_header (auparse); if (ret != GST_FLOW_OK) goto out; gst_pad_push_event (auparse->srcpad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0)); } avail = gst_adapter_available (auparse->adapter); if (auparse->sample_size > 0) { /* Ensure we push a buffer that's a multiple of the frame size downstream */ sendnow = avail - (avail % auparse->sample_size); } else { /* It's something non-trivial (such as ADPCM), we don't understand it, so * just push downstream and assume it will know what to do with it */ sendnow = avail; } if (sendnow > 0) { GstBuffer *outbuf; const guint8 *data; gint64 pos; ret = gst_pad_alloc_buffer_and_set_caps (auparse->srcpad, auparse->buffer_offset, sendnow, GST_PAD_CAPS (auparse->srcpad), &outbuf); if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (auparse, "pad alloc flow: %s", gst_flow_get_name (ret)); goto out; } data = gst_adapter_peek (auparse->adapter, sendnow); memcpy (GST_BUFFER_DATA (outbuf), data, sendnow); gst_adapter_flush (auparse->adapter, sendnow); pos = auparse->buffer_offset - auparse->offset; pos = MAX (pos, 0); if (auparse->sample_size > 0 && auparse->samplerate > 0) { gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos, GST_FORMAT_DEFAULT, &offset); gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos, GST_FORMAT_TIME, ×tamp); gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, sendnow, GST_FORMAT_TIME, &duration); GST_BUFFER_OFFSET (outbuf) = offset; GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = duration; } auparse->buffer_offset += sendnow; ret = gst_pad_push (auparse->srcpad, outbuf); } out: gst_object_unref (auparse); return ret; }