static gboolean gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event) { GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad)); GST_LOG_OBJECT (dec, "Received %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: { GstFormat fmt; gboolean is_update; gint64 start, end, base; gdouble rate; gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start, &end, &base); if (fmt == GST_FORMAT_TIME) { GST_DEBUG ("Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%" GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start), GST_TIME_ARGS (end)); gst_segment_set_newsegment (&dec->segment, is_update, rate, fmt, start, end, base); } else { gst_segment_init (&dec->segment, GST_FORMAT_TIME); } break; } default: break; } gst_object_unref (dec); return gst_pad_event_default (pad, event); }
static GstFlowReturn gst_wildmidi_parse_song (GstWildmidi * wildmidi) { struct _WM_Info *info; GstCaps *outcaps; guint8 *data; guint size; GST_DEBUG_OBJECT (wildmidi, "Parsing song"); size = gst_adapter_available (wildmidi->adapter); data = gst_adapter_take (wildmidi->adapter, size); /* this method takes our memory block */ GST_OBJECT_LOCK (wildmidi); wildmidi->song = WildMidi_OpenBuffer (data, size); if (!wildmidi->song) goto open_failed; WildMidi_LoadSamples (wildmidi->song); WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, wildmidi->linear_volume); WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, wildmidi->high_quality); info = WildMidi_GetInfo (wildmidi->song); GST_OBJECT_UNLOCK (wildmidi); wildmidi->o_len = info->approx_total_samples; outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad)); gst_pad_set_caps (wildmidi->srcpad, outcaps); gst_caps_unref (outcaps); /* we keep an internal segment in samples */ gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); gst_pad_push_event (wildmidi->srcpad, gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME)); GST_DEBUG_OBJECT (wildmidi, "Parsing song done"); return GST_FLOW_OK; /* ERRORS */ open_failed: { GST_OBJECT_UNLOCK (wildmidi); GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), ("Unable to parse midi data")); return GST_FLOW_ERROR; } }
static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event) { GstBaseRTPPayload *basertppayload; GstBaseRTPPayloadClass *basertppayload_class; gboolean res; basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad)); basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload); if (basertppayload_class->handle_event) { res = basertppayload_class->handle_event (pad, event); if (res) goto done; } switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: res = gst_pad_event_default (pad, event); break; case GST_EVENT_FLUSH_STOP: res = gst_pad_event_default (pad, event); gst_segment_init (&basertppayload->segment, GST_FORMAT_UNDEFINED); break; case GST_EVENT_NEWSEGMENT: { gboolean update; gdouble rate; GstFormat fmt; gint64 start, stop, position; gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, &position); gst_segment_set_newsegment (&basertppayload->segment, update, rate, fmt, start, stop, position); /* fallthrough */ } default: res = gst_pad_event_default (pad, event); break; } done: gst_object_unref (basertppayload); return res; }
static gboolean gst_dshowvideodec_sink_event (GstPad * pad, GstEvent * event) { gboolean ret = TRUE; GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: gst_dshowvideodec_flush (vdec); ret = gst_pad_event_default (pad, event); break; case GST_EVENT_NEWSEGMENT: { GstFormat format; gdouble rate; gint64 start, stop, time; gboolean update; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); /* save the new segment in our local current segment */ gst_segment_set_newsegment (vdec->segment, update, rate, format, start, stop, time); GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "new segment received => start=%" GST_TIME_FORMAT " stop=%" GST_TIME_FORMAT, GST_TIME_ARGS (vdec->segment->start), GST_TIME_ARGS (vdec->segment->stop)); if (update) { GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "closing current segment flushing.."); gst_dshowvideodec_flush (vdec); } ret = gst_pad_event_default (pad, event); break; } default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (vdec); return ret; }
static gboolean gst_segment_clip_event (GstPad * pad, GstEvent * event) { GstSegmentClip *self = GST_SEGMENT_CLIP (gst_pad_get_parent (pad)); GstPad *otherpad; gboolean ret; GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad; ret = gst_pad_push_event (otherpad, event); if (ret) { switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT:{ GstFormat fmt; gboolean is_update; gint64 start, end, base; gdouble rate; gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start, &end, &base); GST_DEBUG_OBJECT (pad, "Got NEWSEGMENT event in %s format, passing on (%" GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", gst_format_get_name (fmt), GST_TIME_ARGS (start), GST_TIME_ARGS (end)); gst_segment_set_newsegment (&self->segment, is_update, rate, fmt, start, end, base); break; } case GST_EVENT_FLUSH_STOP: gst_segment_clip_reset (self); break; default: break; } } gst_object_unref (self); return ret; }
static gboolean gst_rdt_depay_sink_event (GstPad * pad, GstEvent * event) { GstRDTDepay *depay; gboolean res = TRUE; depay = GST_RDT_DEPAY (GST_OBJECT_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: res = gst_pad_push_event (depay->srcpad, event); gst_segment_init (&depay->segment, GST_FORMAT_UNDEFINED); depay->need_newsegment = TRUE; depay->next_seqnum = -1; break; case GST_EVENT_NEWSEGMENT: { gboolean update; gdouble rate; GstFormat fmt; gint64 start, stop, position; gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, &position); gst_segment_set_newsegment (&depay->segment, update, rate, fmt, start, stop, position); /* don't pass the event downstream, we generate our own segment * including the NTP time and other things we receive in caps */ gst_event_unref (event); break; } default: /* pass other events forward */ res = gst_pad_push_event (depay->srcpad, event); break; } return res; }
static gboolean gst_shape_wipe_video_sink_event (GstPad * pad, GstEvent * event) { GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); gboolean ret; GST_DEBUG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT:{ GstFormat fmt; gboolean is_update; gint64 start, end, base; gdouble rate; gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start, &end, &base); if (fmt == GST_FORMAT_TIME) { GST_DEBUG_OBJECT (pad, "Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%" GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start), GST_TIME_ARGS (end)); gst_segment_set_newsegment (&self->segment, is_update, rate, fmt, start, end, base); } else { gst_segment_init (&self->segment, GST_FORMAT_TIME); } } /* fall through */ case GST_EVENT_FLUSH_STOP: gst_shape_wipe_reset_qos (self); /* fall through */ default: ret = gst_pad_push_event (self->srcpad, event); break; } gst_object_unref (self); return ret; }
gboolean GStreamerReader::EventProbe(GstPad* aPad, GstEvent* aEvent) { GstElement* parent = GST_ELEMENT(gst_pad_get_parent(aPad)); switch(GST_EVENT_TYPE(aEvent)) { case GST_EVENT_NEWSEGMENT: { gboolean update; gdouble rate; GstFormat format; gint64 start, stop, position; GstSegment* segment; /* Store the segments so we can convert timestamps to stream time, which * is what the upper layers sync on. */ ReentrantMonitorAutoEnter mon(mGstThreadsMonitor); gst_event_parse_new_segment(aEvent, &update, &rate, &format, &start, &stop, &position); if (parent == GST_ELEMENT(mVideoAppSink)) segment = &mVideoSegment; else segment = &mAudioSegment; gst_segment_set_newsegment(segment, update, rate, format, start, stop, position); break; } case GST_EVENT_FLUSH_STOP: /* Reset on seeks */ ResetDecode(); break; default: break; } gst_object_unref(parent); return TRUE; }
static gboolean gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event) { GstBaseRTPDepayload *filter; gboolean res = TRUE; filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: res = gst_pad_push_event (filter->srcpad, event); gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED); filter->need_newsegment = TRUE; filter->priv->next_seqnum = -1; break; case GST_EVENT_NEWSEGMENT: { gboolean update; gdouble rate; GstFormat fmt; gint64 start, stop, position; gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, &position); gst_segment_set_newsegment (&filter->segment, update, rate, fmt, start, stop, position); /* don't pass the event downstream, we generate our own segment including * the NTP time and other things we receive in caps */ gst_event_unref (event); break; } case GST_EVENT_CUSTOM_DOWNSTREAM: { GstBaseRTPDepayloadClass *bclass; bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); if (gst_event_has_name (event, "GstRTPPacketLost")) { /* we get this event from the jitterbuffer when it considers a packet as * being lost. We send it to our packet_lost vmethod. The default * implementation will make time progress by pushing out a NEWSEGMENT * update event. Subclasses can override and to one of the following: * - Adjust timestamp/duration to something more accurate before * calling the parent (default) packet_lost method. * - do some more advanced error concealing on the already received * (fragmented) packets. * - ignore the packet lost. */ if (bclass->packet_lost) res = bclass->packet_lost (filter, event); } gst_event_unref (event); break; } default: /* pass other events forward */ res = gst_pad_push_event (filter->srcpad, event); break; } return res; }
static void gst_timidity_loop (GstPad * sinkpad) { GstTimidity *timidity = GST_TIMIDITY (GST_PAD_PARENT (sinkpad)); GstBuffer *out; GstFlowReturn ret; if (timidity->mididata_size == 0) { if (!gst_timidity_get_upstream_size (timidity, &timidity->mididata_size)) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to get song length")); goto paused; } if (timidity->mididata) g_free (timidity->mididata); timidity->mididata = g_malloc (timidity->mididata_size); timidity->mididata_offset = 0; return; } if (timidity->mididata_offset < timidity->mididata_size) { GstBuffer *buffer; gint64 size; GST_DEBUG_OBJECT (timidity, "loading song"); ret = gst_pad_pull_range (timidity->sinkpad, timidity->mididata_offset, -1, &buffer); if (ret != GST_FLOW_OK) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to load song")); goto paused; } size = timidity->mididata_size - timidity->mididata_offset; if (GST_BUFFER_SIZE (buffer) < size) size = GST_BUFFER_SIZE (buffer); memmove (timidity->mididata + timidity->mididata_offset, GST_BUFFER_DATA (buffer), size); gst_buffer_unref (buffer); timidity->mididata_offset += size; GST_DEBUG_OBJECT (timidity, "Song loaded"); return; } if (!timidity->song) { MidIStream *stream; GstTagList *tags = NULL; gchar *text; GST_DEBUG_OBJECT (timidity, "Parsing song"); stream = mid_istream_open_mem (timidity->mididata, timidity->mididata_size, 0); timidity->song = mid_song_load (stream, timidity->song_options); mid_istream_close (stream); if (!timidity->song) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to parse midi")); goto paused; } mid_song_start (timidity->song); timidity->o_len = (GST_MSECOND * (GstClockTime) mid_song_get_total_time (timidity->song)) / timidity->time_per_frame; gst_segment_set_newsegment (timidity->o_segment, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); gst_pad_push_event (timidity->srcpad, gst_timidity_get_new_segment_event (timidity, GST_FORMAT_TIME, FALSE)); /* extract tags */ text = mid_song_get_meta (timidity->song, MID_SONG_TEXT); if (text) { tags = gst_tag_list_new (); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, NULL); //g_free (text); } text = mid_song_get_meta (timidity->song, MID_SONG_COPYRIGHT); if (text) { if (tags == NULL) tags = gst_tag_list_new (); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_COPYRIGHT, text, NULL); //g_free (text); } if (tags) { gst_element_found_tags (GST_ELEMENT (timidity), tags); } GST_DEBUG_OBJECT (timidity, "Parsing song done"); return; } if (timidity->o_segment_changed) { GstSegment *segment = gst_timidity_get_segment (timidity, GST_FORMAT_TIME, !timidity->o_new_segment); GST_LOG_OBJECT (timidity, "sending newsegment from %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT ", pos=%" GST_TIME_FORMAT, GST_TIME_ARGS ((guint64) segment->start), GST_TIME_ARGS ((guint64) segment->stop), GST_TIME_ARGS ((guint64) segment->time)); if (timidity->o_segment->flags & GST_SEEK_FLAG_SEGMENT) { gst_element_post_message (GST_ELEMENT (timidity), gst_message_new_segment_start (GST_OBJECT (timidity), segment->format, segment->start)); } gst_segment_free (segment); timidity->o_segment_changed = FALSE; return; } if (timidity->o_seek) { /* perform a seek internally */ timidity->o_segment->last_stop = timidity->o_segment->time; mid_song_seek (timidity->song, (timidity->o_segment->last_stop * timidity->time_per_frame) / GST_MSECOND); } out = gst_timidity_get_buffer (timidity); if (!out) { GST_LOG_OBJECT (timidity, "Song ended, generating eos"); gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); timidity->o_seek = FALSE; goto paused; } if (timidity->o_seek) { GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT); timidity->o_seek = FALSE; } gst_buffer_set_caps (out, timidity->out_caps); ret = gst_pad_push (timidity->srcpad, out); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) goto error; return; paused: { GST_DEBUG_OBJECT (timidity, "pausing task"); gst_pad_pause_task (timidity->sinkpad); return; } error: { GST_ELEMENT_ERROR (timidity, STREAM, FAILED, ("Internal data stream error"), ("Streaming stopped, reason %s", gst_flow_get_name (ret))); gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); goto paused; } }
void test_buffer_clipping_samples() { GstSegment s; GstBuffer *buf; GstBuffer *ret; guint8 *data; xmlfile = "test_buffer_clipping_samples"; std_log(LOG_FILENAME_LINE, "Test Started test_buffer_clipping_samples"); /* Clip start and end */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, 800, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); fail_unless (GST_BUFFER_DURATION (ret) == 4 * GST_SECOND); fail_unless (GST_BUFFER_OFFSET (ret) == 400); fail_unless (GST_BUFFER_OFFSET_END (ret) == 800); fail_unless (GST_BUFFER_DATA (ret) == data + 200); fail_unless (GST_BUFFER_SIZE (ret) == 400); gst_buffer_unref (ret); /* Clip only start */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, 1200, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); fail_unless (GST_BUFFER_OFFSET (ret) == 400); fail_unless (GST_BUFFER_OFFSET_END (ret) == 1200); fail_unless (GST_BUFFER_DATA (ret) == data + 200); fail_unless (GST_BUFFER_SIZE (ret) == 800); gst_buffer_unref (ret); /* Clip only stop */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 200, 1000, 200); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless (GST_BUFFER_TIMESTAMP (ret) == 2 * GST_SECOND); fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); fail_unless (GST_BUFFER_OFFSET (ret) == 200); fail_unless (GST_BUFFER_OFFSET_END (ret) == 1000); fail_unless (GST_BUFFER_DATA (ret) == data); fail_unless (GST_BUFFER_SIZE (ret) == 800); gst_buffer_unref (ret); /* Buffer outside segment */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 1200, 2000, 1200); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret == NULL); /* Clip start and end but don't touch duration and offset_end */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, 800, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); fail_unless (GST_BUFFER_DURATION (ret) == GST_CLOCK_TIME_NONE); fail_unless (GST_BUFFER_OFFSET (ret) == 400); fail_unless (GST_BUFFER_OFFSET_END (ret) == GST_BUFFER_OFFSET_NONE); fail_unless (GST_BUFFER_DATA (ret) == data + 200); fail_unless (GST_BUFFER_SIZE (ret) == 400); gst_buffer_unref (ret); /* If the buffer has no offset it should assert() * FIXME: check if return value is the same as the input buffer. * probably can't be done because the assert() does a SIGABRT. */ buf = gst_buffer_new (); data = (guint8 *) g_malloc (1000); GST_BUFFER_SIZE (buf) = 1000; GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; gst_segment_init (&s, GST_FORMAT_DEFAULT); gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, 10, 0); GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ASSERT_CRITICAL (ret = gst_audio_buffer_clip (buf, &s, 100, 1)); gst_buffer_unref (buf); std_log(LOG_FILENAME_LINE, "Test Successful"); create_xml(0); }
static gboolean gst_schro_dec_sink_event (GstPad *pad, GstEvent *event) { GstSchroDec *dec; gboolean ret = FALSE; dec = GST_SCHRO_DEC (gst_pad_get_parent(pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: //GST_ERROR("unhandled flush start"); ret = gst_pad_push_event (dec->srcpad, event); break; case GST_EVENT_FLUSH_STOP: //GST_ERROR("unhandled flush stop"); gst_schro_dec_reset (dec); ret = gst_pad_push_event (dec->srcpad, event); break; case GST_EVENT_EOS: ret = gst_schro_dec_process_buffer (dec, NULL); ret = gst_pad_push_event (dec->srcpad, event); break; case GST_EVENT_NEWSEGMENT: { gboolean update; GstFormat format; gdouble rate; gint64 start, stop, time; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); if (format != GST_FORMAT_TIME) goto newseg_wrong_format; if (rate <= 0.0) goto newseg_wrong_rate; GST_DEBUG("newsegment %lld %lld", start, time); gst_segment_set_newsegment (&dec->segment, update, rate, format, start, stop, time); ret = gst_pad_push_event (dec->srcpad, event); break; } default: ret = gst_pad_push_event (dec->srcpad, event); break; } done: gst_object_unref (dec); return ret; newseg_wrong_format: GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); gst_event_unref (event); goto done; newseg_wrong_rate: GST_DEBUG_OBJECT (dec, "negative rates not supported"); gst_event_unref (event); goto done; }
static GstFlowReturn gst_mimenc_chain (GstPad * pad, GstBuffer * in) { GstMimEnc *mimenc; GstBuffer *out_buf = NULL, *buf = NULL; guchar *data; gint buffer_size; GstBuffer *header = NULL; GstFlowReturn res = GST_FLOW_OK; GstEvent *event = NULL; gboolean keyframe; g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); mimenc = GST_MIMENC (gst_pad_get_parent (pad)); g_return_val_if_fail (GST_IS_MIMENC (mimenc), GST_FLOW_ERROR); GST_OBJECT_LOCK (mimenc); if (mimenc->segment.format == GST_FORMAT_UNDEFINED) { GST_WARNING_OBJECT (mimenc, "No new-segment received," " initializing segment with time 0..-1"); gst_segment_init (&mimenc->segment, GST_FORMAT_TIME); gst_segment_set_newsegment (&mimenc->segment, FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); } if (mimenc->enc == NULL) { mimenc->enc = mimic_open (); if (mimenc->enc == NULL) { GST_WARNING_OBJECT (mimenc, "mimic_open error\n"); res = GST_FLOW_ERROR; goto out_unlock; } if (!mimic_encoder_init (mimenc->enc, mimenc->res)) { GST_WARNING_OBJECT (mimenc, "mimic_encoder_init error\n"); mimic_close (mimenc->enc); mimenc->enc = NULL; res = GST_FLOW_ERROR; goto out_unlock; } if (!mimic_get_property (mimenc->enc, "buffer_size", &mimenc->buffer_size)) { GST_WARNING_OBJECT (mimenc, "mimic_get_property('buffer_size') error\n"); mimic_close (mimenc->enc); mimenc->enc = NULL; res = GST_FLOW_ERROR; goto out_unlock; } } buf = in; data = GST_BUFFER_DATA (buf); out_buf = gst_buffer_new_and_alloc (mimenc->buffer_size); GST_BUFFER_TIMESTAMP (out_buf) = gst_segment_to_running_time (&mimenc->segment, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); mimenc->last_buffer = GST_BUFFER_TIMESTAMP (out_buf); buffer_size = mimenc->buffer_size; keyframe = (mimenc->frames % MAX_INTERFRAMES) == 0 ? TRUE : FALSE; if (!mimic_encode_frame (mimenc->enc, data, GST_BUFFER_DATA (out_buf), &buffer_size, keyframe)) { GST_WARNING_OBJECT (mimenc, "mimic_encode_frame error\n"); gst_buffer_unref (out_buf); gst_buffer_unref (buf); res = GST_FLOW_ERROR; goto out_unlock; } GST_BUFFER_SIZE (out_buf) = buffer_size; GST_DEBUG_OBJECT (mimenc, "incoming buf size %d, encoded size %d", GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (out_buf)); ++mimenc->frames; // now let's create that tcp header header = gst_mimenc_create_tcp_header (mimenc, buffer_size, GST_BUFFER_TIMESTAMP (out_buf), keyframe, FALSE); if (!header) { gst_buffer_unref (out_buf); GST_DEBUG_OBJECT (mimenc, "header not created succesfully"); res = GST_FLOW_ERROR; goto out_unlock; } if (mimenc->need_newsegment) { event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); mimenc->need_newsegment = FALSE; } GST_OBJECT_UNLOCK (mimenc); if (event) { if (!gst_pad_push_event (mimenc->srcpad, event)) GST_WARNING_OBJECT (mimenc, "Failed to push NEWSEGMENT event"); } res = gst_pad_push (mimenc->srcpad, header); if (res != GST_FLOW_OK) { gst_buffer_unref (out_buf); goto out; } res = gst_pad_push (mimenc->srcpad, out_buf); out: if (buf) gst_buffer_unref (buf); gst_object_unref (mimenc); return res; out_unlock: GST_OBJECT_UNLOCK (mimenc); goto out; }
static gboolean gst_sub_parse_sink_event (GstPad * pad, GstEvent * event) { GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad)); gboolean ret = FALSE; GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS:{ /* Make sure the last subrip chunk is pushed out even * if the file does not have an empty line at the end */ if (self->parser_type == GST_SUB_PARSE_FORMAT_SUBRIP || self->parser_type == GST_SUB_PARSE_FORMAT_TMPLAYER || self->parser_type == GST_SUB_PARSE_FORMAT_MPL2) { GstBuffer *buf = gst_buffer_new_and_alloc (2 + 1); GST_DEBUG ("EOS. Pushing remaining text (if any)"); GST_BUFFER_DATA (buf)[0] = '\n'; GST_BUFFER_DATA (buf)[1] = '\n'; GST_BUFFER_DATA (buf)[2] = '\0'; /* play it safe */ GST_BUFFER_SIZE (buf) = 2; GST_BUFFER_OFFSET (buf) = self->offset; gst_sub_parse_chain (pad, buf); } ret = gst_pad_event_default (pad, event); break; } case GST_EVENT_NEWSEGMENT: { GstFormat format; gdouble rate; gint64 start, stop, time; gboolean update; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); GST_DEBUG_OBJECT (self, "newsegment (%s)", gst_format_get_name (format)); if (format == GST_FORMAT_TIME) { gst_segment_set_newsegment (&self->segment, update, rate, format, start, stop, time); } else { /* if not time format, we'll either start with a 0 timestamp anyway or * it's following a seek in which case we'll have saved the requested * seek segment and don't want to overwrite it (remember that on a seek * we always just seek back to the start in BYTES format and just throw * away all text that's before the requested position; if the subtitles * come from an upstream demuxer, it won't be able to handle our BYTES * seek request and instead send us a newsegment from the seek request * it received via its video pads instead, so all is fine then too) */ } ret = TRUE; gst_event_unref (event); break; } case GST_EVENT_FLUSH_START: { self->flushing = TRUE; ret = gst_pad_event_default (pad, event); break; } case GST_EVENT_FLUSH_STOP: { self->flushing = FALSE; ret = gst_pad_event_default (pad, event); break; } default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (self); return ret; }
static GstFlowReturn gst_live_live_adder_chain (GstPad * pad, GstBuffer * buffer) { GstLiveAdder *adder = GST_LIVE_ADDER (gst_pad_get_parent_element (pad)); GstLiveAdderPadPrivate *padprivate = NULL; GstFlowReturn ret = GST_FLOW_OK; GList *item = NULL; GstClockTime skip = 0; gint64 drift = 0; /* Positive if new buffer after old buffer */ GST_OBJECT_LOCK (adder); ret = adder->srcresult; GST_DEBUG ("Incoming buffer time:%" GST_TIME_FORMAT " duration:%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (adder, "Passing non-ok result from src: %s", gst_flow_get_name (ret)); gst_buffer_unref (buffer); goto out; } padprivate = gst_pad_get_element_private (pad); if (!padprivate) { ret = GST_FLOW_NOT_LINKED; gst_buffer_unref (buffer); goto out; } if (padprivate->eos) { GST_DEBUG_OBJECT (adder, "Received buffer after EOS"); ret = GST_FLOW_UNEXPECTED; gst_buffer_unref (buffer); goto out; } if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) goto invalid_timestamp; if (padprivate->segment.format == GST_FORMAT_UNDEFINED) { GST_WARNING_OBJECT (adder, "No new-segment received," " initializing segment with time 0..-1"); gst_segment_init (&padprivate->segment, GST_FORMAT_TIME); gst_segment_set_newsegment (&padprivate->segment, FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); } if (padprivate->segment.format != GST_FORMAT_TIME) goto invalid_segment; buffer = gst_buffer_make_metadata_writable (buffer); drift = GST_BUFFER_TIMESTAMP (buffer) - padprivate->expected_timestamp; /* Just see if we receive invalid timestamp/durations */ if (GST_CLOCK_TIME_IS_VALID (padprivate->expected_timestamp) && !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT) && (drift != 0)) { GST_LOG_OBJECT (adder, "Timestamp discontinuity without the DISCONT flag set" " (expected %" GST_TIME_FORMAT ", got %" GST_TIME_FORMAT " drift:%" G_GINT64_FORMAT "ms)", GST_TIME_ARGS (padprivate->expected_timestamp), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), drift / GST_MSECOND); /* We accept drifts of 10ms */ if (ABS (drift) < (10 * GST_MSECOND)) { GST_DEBUG ("Correcting minor drift"); GST_BUFFER_TIMESTAMP (buffer) = padprivate->expected_timestamp; } } /* If there is no duration, lets set one */ if (!GST_BUFFER_DURATION_IS_VALID (buffer)) { GST_BUFFER_DURATION (buffer) = gst_audio_duration_from_pad_buffer (pad, buffer); padprivate->expected_timestamp = GST_CLOCK_TIME_NONE; } else { padprivate->expected_timestamp = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); } /* * Lets clip the buffer to the segment (so we don't have to worry about * cliping afterwards). * This should also guarantee us that we'll have valid timestamps and * durations afterwards */ buffer = gst_audio_buffer_clip (buffer, &padprivate->segment, adder->rate, adder->bps); /* buffer can be NULL if it's completely outside of the segment */ if (!buffer) { GST_DEBUG ("Buffer completely outside of configured segment, dropping it"); goto out; } /* * Make sure all incoming buffers share the same timestamping */ GST_BUFFER_TIMESTAMP (buffer) = gst_segment_to_running_time (&padprivate->segment, padprivate->segment.format, GST_BUFFER_TIMESTAMP (buffer)); if (GST_CLOCK_TIME_IS_VALID (adder->next_timestamp) && GST_BUFFER_TIMESTAMP (buffer) < adder->next_timestamp) { if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) < adder->next_timestamp) { GST_DEBUG_OBJECT (adder, "Buffer is late, dropping (ts: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT ")", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); gst_buffer_unref (buffer); goto out; } else { skip = adder->next_timestamp - GST_BUFFER_TIMESTAMP (buffer); GST_DEBUG_OBJECT (adder, "Buffer is partially late, skipping %" GST_TIME_FORMAT, GST_TIME_ARGS (skip)); } } /* If our new buffer's head is higher than the queue's head, lets wake up, * we may not have to wait for as long */ if (adder->clock_id && g_queue_peek_head (adder->buffers) != NULL && GST_BUFFER_TIMESTAMP (buffer) + skip < GST_BUFFER_TIMESTAMP (g_queue_peek_head (adder->buffers))) gst_clock_id_unschedule (adder->clock_id); for (item = g_queue_peek_head_link (adder->buffers); item; item = g_list_next (item)) { GstBuffer *oldbuffer = item->data; GstClockTime old_skip = 0; GstClockTime mix_duration = 0; GstClockTime mix_start = 0; GstClockTime mix_end = 0; /* We haven't reached our place yet */ if (GST_BUFFER_TIMESTAMP (buffer) + skip >= GST_BUFFER_TIMESTAMP (oldbuffer) + GST_BUFFER_DURATION (oldbuffer)) continue; /* We're past our place, lets insert ouselves here */ if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) <= GST_BUFFER_TIMESTAMP (oldbuffer)) break; /* if we reach this spot, we have overlap, so we must mix */ /* First make a subbuffer with the non-overlapping part */ if (GST_BUFFER_TIMESTAMP (buffer) + skip < GST_BUFFER_TIMESTAMP (oldbuffer)) { GstBuffer *subbuffer = NULL; GstClockTime subbuffer_duration = GST_BUFFER_TIMESTAMP (oldbuffer) - (GST_BUFFER_TIMESTAMP (buffer) + skip); subbuffer = gst_buffer_create_sub (buffer, gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, subbuffer_duration)); GST_BUFFER_TIMESTAMP (subbuffer) = GST_BUFFER_TIMESTAMP (buffer) + skip; GST_BUFFER_DURATION (subbuffer) = subbuffer_duration; skip += subbuffer_duration; g_queue_insert_before (adder->buffers, item, subbuffer); } /* Now we are on the overlapping part */ oldbuffer = gst_buffer_make_writable (oldbuffer); item->data = oldbuffer; old_skip = GST_BUFFER_TIMESTAMP (buffer) + skip - GST_BUFFER_TIMESTAMP (oldbuffer); mix_start = GST_BUFFER_TIMESTAMP (oldbuffer) + old_skip; if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) < GST_BUFFER_TIMESTAMP (oldbuffer) + GST_BUFFER_DURATION (oldbuffer)) mix_end = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); else mix_end = GST_BUFFER_TIMESTAMP (oldbuffer) + GST_BUFFER_DURATION (oldbuffer); mix_duration = mix_end - mix_start; adder->func (GST_BUFFER_DATA (oldbuffer) + gst_live_adder_length_from_duration (adder, old_skip), GST_BUFFER_DATA (buffer) + gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, mix_duration)); skip += mix_duration; } g_cond_broadcast (adder->not_empty_cond); if (skip == GST_BUFFER_DURATION (buffer)) { gst_buffer_unref (buffer); } else { if (skip) { GstClockTime subbuffer_duration = GST_BUFFER_DURATION (buffer) - skip; GstClockTime subbuffer_ts = GST_BUFFER_TIMESTAMP (buffer) + skip; GstBuffer *new_buffer = gst_buffer_create_sub (buffer, gst_live_adder_length_from_duration (adder, skip), gst_live_adder_length_from_duration (adder, subbuffer_duration)); gst_buffer_unref (buffer); buffer = new_buffer; GST_BUFFER_TIMESTAMP (buffer) = subbuffer_ts; GST_BUFFER_DURATION (buffer) = subbuffer_duration; } if (item) g_queue_insert_before (adder->buffers, item, buffer); else g_queue_push_tail (adder->buffers, buffer); } out: GST_OBJECT_UNLOCK (adder); gst_object_unref (adder); return ret; invalid_timestamp: GST_OBJECT_UNLOCK (adder); gst_buffer_unref (buffer); GST_ELEMENT_ERROR (adder, STREAM, FAILED, ("Buffer without a valid timestamp received"), ("Invalid timestamp received on buffer")); return GST_FLOW_ERROR; invalid_segment: { const gchar *format = gst_format_get_name (padprivate->segment.format); GST_OBJECT_UNLOCK (adder); gst_buffer_unref (buffer); GST_ELEMENT_ERROR (adder, STREAM, FAILED, ("This element only supports TIME segments, received other type"), ("Received a segment of type %s, only support time segment", format)); return GST_FLOW_ERROR; } }
static gboolean gst_base_video_codec_sink_event (GstPad * pad, GstEvent * event) { GstBaseVideoCodec *base_video_codec; gboolean ret = FALSE; base_video_codec = GST_BASE_VIDEO_CODEC (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: ret = gst_pad_push_event (base_video_codec->srcpad, event); break; case GST_EVENT_FLUSH_STOP: gst_base_video_codec_reset (base_video_codec); ret = gst_pad_push_event (base_video_codec->srcpad, event); break; case GST_EVENT_EOS: if (gst_base_video_codec_push_all (base_video_codec, FALSE) == GST_FLOW_ERROR) { gst_event_unref (event); return FALSE; } ret = gst_pad_push_event (base_video_codec->srcpad, event); break; case GST_EVENT_NEWSEGMENT: { gboolean update; GstFormat format; gdouble rate; gint64 start, stop, time; gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); if (format != GST_FORMAT_TIME) goto newseg_wrong_format; if (rate <= 0.0) goto newseg_wrong_rate; GST_DEBUG ("newsegment %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (time)); gst_segment_set_newsegment (&base_video_codec->state.segment, update, rate, format, start, stop, time); ret = gst_pad_push_event (base_video_codec->srcpad, event); break; } default: ret = gst_pad_push_event (base_video_codec->srcpad, event); break; } done: gst_object_unref (base_video_codec); return ret; newseg_wrong_format: GST_DEBUG_OBJECT (base_video_codec, "received non TIME newsegment"); gst_event_unref (event); goto done; newseg_wrong_rate: GST_DEBUG_OBJECT (base_video_codec, "negative rates not supported"); gst_event_unref (event); goto done; }
static gboolean gst_a52dec_sink_event (GstPad * pad, GstEvent * event) { GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad)); gboolean ret = FALSE; GST_LOG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: { GstFormat fmt; gboolean update; gint64 start, end, pos; gdouble rate, arate; gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt, &start, &end, &pos); /* drain queued buffers before activating the segment so that we can clip * against the old segment first */ gst_a52dec_drain (a52dec); if (fmt != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (start)) { GST_WARNING ("No time in newsegment event %p (format is %s)", event, gst_format_get_name (fmt)); gst_event_unref (event); a52dec->sent_segment = FALSE; /* set some dummy values, FIXME: do proper conversion */ a52dec->time = start = pos = 0; fmt = GST_FORMAT_TIME; end = -1; } else { a52dec->time = start; a52dec->sent_segment = TRUE; GST_DEBUG_OBJECT (a52dec, "Pushing newseg rate %g, applied rate %g, format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", pos %" G_GINT64_FORMAT, rate, arate, fmt, start, end, time); ret = gst_pad_push_event (a52dec->srcpad, event); } gst_segment_set_newsegment (&a52dec->segment, update, rate, fmt, start, end, pos); break; } case GST_EVENT_TAG: ret = gst_pad_push_event (a52dec->srcpad, event); break; case GST_EVENT_EOS: gst_a52dec_drain (a52dec); ret = gst_pad_push_event (a52dec->srcpad, event); break; case GST_EVENT_FLUSH_START: ret = gst_pad_push_event (a52dec->srcpad, event); break; case GST_EVENT_FLUSH_STOP: if (a52dec->cache) { gst_buffer_unref (a52dec->cache); a52dec->cache = NULL; } clear_queued (a52dec); gst_segment_init (&a52dec->segment, GST_FORMAT_UNDEFINED); ret = gst_pad_push_event (a52dec->srcpad, event); break; default: ret = gst_pad_push_event (a52dec->srcpad, event); break; } gst_object_unref (a52dec); return ret; }