static gboolean gst_dvd_spu_video_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstDVDSpu *dvdspu = (GstDVDSpu *) parent; SpuState *state = &dvdspu->spu_state; gboolean res = TRUE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); res = gst_dvd_spu_video_set_caps (pad, caps); if (res) res = gst_pad_push_event (dvdspu->srcpad, event); else gst_event_unref (event); break; } case GST_EVENT_CUSTOM_DOWNSTREAM: case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: { gboolean in_still; if (gst_video_event_parse_still_frame (event, &in_still)) { GstBuffer *to_push = NULL; /* Forward the event before handling */ res = gst_pad_event_default (pad, parent, event); GST_DEBUG_OBJECT (dvdspu, "Still frame event on video pad: in-still = %d", in_still); DVD_SPU_LOCK (dvdspu); if (in_still) { state->flags |= SPU_STATE_STILL_FRAME; /* Entering still. Advance the SPU to make sure the state is * up to date */ gst_dvd_spu_check_still_updates (dvdspu); /* And re-draw the still frame to make sure it appears on * screen, otherwise the last frame might have been discarded * by QoS */ gst_dvd_spu_redraw_still (dvdspu, TRUE); to_push = dvdspu->pending_frame; dvdspu->pending_frame = NULL; } else { state->flags &= ~(SPU_STATE_STILL_FRAME); } DVD_SPU_UNLOCK (dvdspu); if (to_push) gst_pad_push (dvdspu->srcpad, to_push); } else { GST_DEBUG_OBJECT (dvdspu, "Custom event %" GST_PTR_FORMAT " on video pad", event); res = gst_pad_event_default (pad, parent, event); } break; } case GST_EVENT_SEGMENT: { GstSegment seg; gst_event_copy_segment (event, &seg); if (seg.format != GST_FORMAT_TIME) return FALSE; /* Only print updates if they have an end time (don't print start_time * updates */ GST_DEBUG_OBJECT (dvdspu, "video pad Segment: %" GST_SEGMENT_FORMAT, &seg); DVD_SPU_LOCK (dvdspu); if (seg.start > dvdspu->video_seg.position) { update_video_to_position (dvdspu, seg.start); } dvdspu->video_seg = seg; DVD_SPU_UNLOCK (dvdspu); res = gst_pad_event_default (pad, parent, event); break; } case GST_EVENT_GAP: { GstClockTime timestamp, duration; gst_event_parse_gap (event, ×tamp, &duration); if (GST_CLOCK_TIME_IS_VALID (duration)) timestamp += duration; DVD_SPU_LOCK (dvdspu); GST_LOG_OBJECT (dvdspu, "Received GAP. Advancing to %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); update_video_to_position (dvdspu, timestamp); DVD_SPU_UNLOCK (dvdspu); gst_event_unref (event); break; } case GST_EVENT_FLUSH_START: res = gst_pad_event_default (pad, parent, event); goto done; case GST_EVENT_FLUSH_STOP: res = gst_pad_event_default (pad, parent, event); DVD_SPU_LOCK (dvdspu); gst_segment_init (&dvdspu->video_seg, GST_FORMAT_UNDEFINED); gst_buffer_replace (&dvdspu->ref_frame, NULL); gst_buffer_replace (&dvdspu->pending_frame, NULL); DVD_SPU_UNLOCK (dvdspu); goto done; default: res = gst_pad_event_default (pad, parent, event); break; } done: return res; #if 0 error: gst_event_unref (event); return FALSE; #endif }
static gboolean rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) { gboolean ret = FALSE; RsnAudioMunge *munge = RSN_AUDIOMUNGE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: rsn_audiomunge_reset (munge); ret = gst_pad_push_event (munge->srcpad, event); break; case GST_EVENT_NEWSEGMENT: { GstSegment *segment; gboolean update; GstFormat format; gdouble rate, arate; gint64 start, stop, time; gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); /* we need TIME format */ if (format != GST_FORMAT_TIME) goto newseg_wrong_format; /* now configure the values */ segment = &munge->sink_segment; gst_segment_set_newsegment_full (segment, update, rate, arate, format, start, stop, time); /* * FIXME: * If this is a segment update and accum >= threshold, * or we're in a still frame and there's been no audio received, * then we need to generate some audio data. * * If caused by a segment start update (time advancing in a gap) adjust * the new-segment and send the buffer. * * Otherwise, send the buffer before the newsegment, so that it appears * in the closing segment. */ if (!update) { GST_DEBUG_OBJECT (munge, "Sending newsegment: update %d start %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, update, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (segment->accum)); ret = gst_pad_push_event (munge->srcpad, event); } if (!munge->have_audio) { if ((update && segment->accum >= AUDIO_FILL_THRESHOLD) || munge->in_still) { GST_DEBUG_OBJECT (munge, "Sending audio fill with ts %" GST_TIME_FORMAT ": accum = %" GST_TIME_FORMAT " still-state=%d", GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->accum), munge->in_still); /* Just generate a 200ms silence buffer for now. FIXME: Fill the gap */ if (rsn_audiomunge_make_audio (munge, segment->start, GST_SECOND / 5) == GST_FLOW_OK) munge->have_audio = TRUE; } else { GST_LOG_OBJECT (munge, "Not sending audio fill buffer: " "Not segment update, or segment accum below thresh: accum = %" GST_TIME_FORMAT, GST_TIME_ARGS (segment->accum)); } } if (update) { GST_DEBUG_OBJECT (munge, "Sending newsegment: update %d start %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, update, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (segment->accum)); ret = gst_pad_push_event (munge->srcpad, event); } break; } case GST_EVENT_CUSTOM_DOWNSTREAM: { gboolean in_still; if (gst_video_event_parse_still_frame (event, &in_still)) { /* Remember the still-frame state, so we can generate a pre-roll * buffer when a new-segment arrives */ munge->in_still = in_still; GST_INFO_OBJECT (munge, "AUDIO MUNGE: still-state now %d", munge->in_still); } ret = gst_pad_push_event (munge->srcpad, event); break; } default: ret = gst_pad_push_event (munge->srcpad, event); break; } gst_object_unref (munge); return ret; newseg_wrong_format: GST_DEBUG_OBJECT (munge, "received non TIME newsegment"); gst_event_unref (event); gst_object_unref (munge); return FALSE; }