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);
}
예제 #2
0
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;
}