static void gst_videodrop_chain (GstPad * pad, GstData * data) { GstVideodrop *videodrop = GST_VIDEODROP (gst_pad_get_parent (pad)); GstBuffer *buf; if (GST_IS_EVENT (data)) { GstEvent *event = GST_EVENT (data); if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) { /* since we rely on timestamps of the source, we need to handle * changes in time carefully. */ gint64 time; if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) { videodrop->total = videodrop->pass = 0; videodrop->time_adjust = time; } else { GST_ELEMENT_ERROR (videodrop, STREAM, TOO_LAZY, (NULL), ("Received discont, but no time information")); gst_event_unref (event); return; } /* FIXME: increase timestamp / speed */ } gst_pad_event_default (pad, event); return; } buf = GST_BUFFER (data); videodrop->total++; GST_DEBUG ("Received buffer at %u:%02u:%02u:%09u, fps=%lf, pass=%" G_GUINT64_FORMAT " of " G_GUINT64_FORMAT ", speed=%lf", (guint) (GST_BUFFER_TIMESTAMP (buf) / (GST_SECOND * 60 * 60)), (guint) ((GST_BUFFER_TIMESTAMP (buf) / (GST_SECOND * 60)) % 60), (guint) ((GST_BUFFER_TIMESTAMP (buf) / GST_SECOND) % 60), (guint) (GST_BUFFER_TIMESTAMP (buf) % GST_SECOND), videodrop->to_fps, videodrop->total, videodrop->pass, videodrop->speed); while (((GST_BUFFER_TIMESTAMP (buf) - videodrop->time_adjust) / videodrop->speed * videodrop->to_fps / GST_SECOND) >= videodrop->pass) { /* since we write to the struct (time/duration), we need a new struct, * but we don't want to copy around data - a subbuffer is the easiest * way to accomplish that... */ GstBuffer *copy = gst_buffer_create_sub (buf, 0, GST_BUFFER_SIZE (buf)); /* adjust timestamp/duration and push forward */ GST_BUFFER_TIMESTAMP (copy) = (videodrop->time_adjust / videodrop->speed) + GST_SECOND * videodrop->pass / videodrop->to_fps; GST_BUFFER_DURATION (copy) = GST_SECOND / videodrop->to_fps; GST_DEBUG ("Sending out buffer from out %u:%02u:%02u:%09u", (guint) (GST_BUFFER_TIMESTAMP (copy) / (GST_SECOND * 60 * 60)), (guint) ((GST_BUFFER_TIMESTAMP (copy) / (GST_SECOND * 60)) % 60), (guint) ((GST_BUFFER_TIMESTAMP (copy) / GST_SECOND) % 60), (guint) (GST_BUFFER_TIMESTAMP (copy) % GST_SECOND)); gst_pad_push (videodrop->srcpad, GST_DATA (copy)); videodrop->pass++; } gst_buffer_unref (buf); }
static gboolean dxr3videosink_handle_event (GstPad * pad, GstEvent * event) { GstEventType type; Dxr3VideoSink *sink; sink = DXR3VIDEOSINK (gst_pad_get_parent (pad)); type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; switch (type) { case GST_EVENT_EMPTY: //fprintf (stderr, "++++++ Video empty event\n"); { /* FIXME: Handle this with a discontinuity or something. */ /* Write an MPEG2 sequence end code, to ensure that the card actually displays the last picture. Apparently some DVDs are encoded without proper sequence end codes. */ static const guint8 sec[4] = { 0x00, 0x00, 0x01, 0xb7 }; if (sink->cur_buf != NULL) { dxr3videosink_write_data (sink, 0); } write (sink->video_fd, &sec, 4); } break; case GST_EVENT_DISCONTINUOUS: //fprintf (stderr, "++++++ Video discont event\n"); { gint64 time; gboolean has_time; unsigned cur_scr, mpeg_scr, diff; has_time = gst_event_discont_get_value (event, GST_FORMAT_TIME, &time); if (has_time) { /* fprintf (stderr, "^^^^^^ Discontinuous event has time %.4f\n", */ /* (double) time / GST_SECOND); */ /* If the SCR in the card is way off, fix it. */ ioctl (sink->control_fd, EM8300_IOCTL_SCR_GET, &cur_scr); mpeg_scr = MPEGTIME_TO_DXRTIME (GSTTIME_TO_MPEGTIME (time)); diff = cur_scr > mpeg_scr ? cur_scr - mpeg_scr : mpeg_scr - cur_scr; if (diff > 1800) { unsigned zero = 0; /* fprintf (stderr, "====== Adjusting SCR from video\n"); */ ioctl (sink->control_fd, EM8300_IOCTL_SCR_SET, &zero); ioctl (sink->control_fd, EM8300_IOCTL_SCR_SET, &mpeg_scr); } } else { /* fprintf (stderr, "^^^^^^ Discontinuous event has no time\n"); */ } } break; case GST_EVENT_FLUSH: dxr3videosink_reset_parser (sink); break; default: gst_pad_event_default (pad, event); break; } return TRUE; }