コード例 #1
0
ファイル: gstvideorate.c プロジェクト: ChinnaSuhas/ossbuild
static GstStateChangeReturn
gst_video_rate_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstVideoRate *videorate;

  videorate = GST_VIDEO_RATE (element);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      videorate->discont = TRUE;
      videorate->last_ts = -1;
      break;
    default:
      break;
  }

  ret = parent_class->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_video_rate_reset (videorate);
      break;
    default:
      break;
  }

  return ret;
}
コード例 #2
0
ファイル: gstvideorate.c プロジェクト: ChinnaSuhas/ossbuild
static void
gst_video_rate_init (GstVideoRate * videorate, GstVideoRateClass * klass)
{
  videorate->sinkpad =
      gst_pad_new_from_static_template (&gst_video_rate_sink_template, "sink");
  gst_pad_set_event_function (videorate->sinkpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_event));
  gst_pad_set_chain_function (videorate->sinkpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_chain));
  gst_pad_set_getcaps_function (videorate->sinkpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_getcaps));
  gst_pad_set_setcaps_function (videorate->sinkpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_setcaps));
  gst_element_add_pad (GST_ELEMENT (videorate), videorate->sinkpad);

  videorate->srcpad =
      gst_pad_new_from_static_template (&gst_video_rate_src_template, "src");
  gst_pad_set_query_function (videorate->srcpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_query));
  gst_pad_set_getcaps_function (videorate->srcpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_getcaps));
  gst_pad_set_setcaps_function (videorate->srcpad,
      GST_DEBUG_FUNCPTR (gst_video_rate_setcaps));
  gst_element_add_pad (GST_ELEMENT (videorate), videorate->srcpad);

  gst_video_rate_reset (videorate);
  videorate->silent = DEFAULT_SILENT;
  videorate->new_pref = DEFAULT_NEW_PREF;

  videorate->from_rate_numerator = 0;
  videorate->from_rate_denominator = 0;
  videorate->to_rate_numerator = 0;
  videorate->to_rate_denominator = 0;
}
コード例 #3
0
static void
gst_video_rate_init (GstVideoRate * videorate)
{
  gst_video_rate_reset (videorate);
  videorate->silent = DEFAULT_SILENT;
  videorate->new_pref = DEFAULT_NEW_PREF;
  videorate->drop_only = DEFAULT_DROP_ONLY;
  videorate->average_period = DEFAULT_AVERAGE_PERIOD;
  videorate->average_period_set = DEFAULT_AVERAGE_PERIOD;
  videorate->max_rate = DEFAULT_MAX_RATE;

  videorate->from_rate_numerator = 0;
  videorate->from_rate_denominator = 0;
  videorate->to_rate_numerator = 0;
  videorate->to_rate_denominator = 0;

  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (videorate), TRUE);
}
コード例 #4
0
static gboolean
gst_video_rate_sink_event (GstBaseTransform * trans, GstEvent * event)
{
  GstVideoRate *videorate;

  videorate = GST_VIDEO_RATE (trans);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
    {
      const GstSegment *segment;

      gst_event_parse_segment (event, &segment);

      if (segment->format != GST_FORMAT_TIME)
        goto format_error;

      GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");

      /* close up the previous segment, if appropriate */
      if (videorate->prevbuf) {
        gint count = 0;
        GstFlowReturn res;

        res = GST_FLOW_OK;
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) &&
                    videorate->next_ts - videorate->segment.base
                    < videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
        if (count > 1) {
          videorate->dup += count - 1;
          if (!videorate->silent)
            gst_video_rate_notify_duplicate (videorate);
        } else if (count == 0) {
          videorate->drop++;
          if (!videorate->silent)
            gst_video_rate_notify_drop (videorate);
        }
        /* clean up for the new one; _chain will resume from the new start */
        gst_video_rate_swap_prev (videorate, NULL, 0);
      }

      videorate->base_ts = 0;
      videorate->out_frame_count = 0;
      videorate->next_ts = GST_CLOCK_TIME_NONE;

      /* We just want to update the accumulated stream_time  */
      gst_segment_copy_into (segment, &videorate->segment);

      GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
          &videorate->segment);
      break;
    }
    case GST_EVENT_EOS:{
      gint count = 0;
      GstFlowReturn res = GST_FLOW_OK;

      GST_DEBUG_OBJECT (videorate, "Got EOS");

      /* If the segment has a stop position, fill the segment */
      if (GST_CLOCK_TIME_IS_VALID (videorate->segment.stop)) {
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((videorate->next_ts - videorate->segment.base <
                    videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
      } else if (videorate->prevbuf) {
        /* Output at least one frame but if the buffer duration is valid, output
         * enough frames to use the complete buffer duration */
        if (GST_BUFFER_DURATION_IS_VALID (videorate->prevbuf)) {
          GstClockTime end_ts =
              videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf);

          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
              ((videorate->next_ts - videorate->segment.base < end_ts)
                  || count < 1)) {
            res = gst_video_rate_flush_prev (videorate, count > 0);
            count++;
          }
        } else {
          res = gst_video_rate_flush_prev (videorate, FALSE);
          count = 1;
        }
      }

      if (count > 1) {
        videorate->dup += count - 1;
        if (!videorate->silent)
          gst_video_rate_notify_duplicate (videorate);
      } else if (count == 0) {
        videorate->drop++;
        if (!videorate->silent)
          gst_video_rate_notify_drop (videorate);
      }

      break;
    }
    case GST_EVENT_FLUSH_STOP:
      /* also resets the segment */
      GST_DEBUG_OBJECT (videorate, "Got FLUSH_STOP");
      gst_video_rate_reset (videorate);
      break;
    case GST_EVENT_GAP:
      /* no gaps after videorate, ignore the event */
      gst_event_unref (event);
      return TRUE;
    default:
      break;
  }

  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);

  /* ERRORS */
format_error:
  {
    GST_WARNING_OBJECT (videorate,
        "Got segment but doesn't have GST_FORMAT_TIME value");
    return FALSE;
  }
}
コード例 #5
0
static gboolean
gst_video_rate_stop (GstBaseTransform * trans)
{
  gst_video_rate_reset (GST_VIDEO_RATE (trans));
  return TRUE;
}
コード例 #6
0
ファイル: gstvideorate.c プロジェクト: ChinnaSuhas/ossbuild
static gboolean
gst_video_rate_event (GstPad * pad, GstEvent * event)
{
  GstVideoRate *videorate;
  gboolean ret;

  videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:
    {
      gint64 start, stop, time;
      gdouble rate, arate;
      gboolean update;
      GstFormat format;

      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
          &start, &stop, &time);

      if (format != GST_FORMAT_TIME)
        goto format_error;

      GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT");

      /* close up the previous segment, if appropriate */
      if (!update && videorate->prevbuf) {
        gint count = 0;
        GstFlowReturn res;

        res = GST_FLOW_OK;
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) &&
                    videorate->next_ts - videorate->segment.accum
                    < videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
        if (count > 1) {
          videorate->dup += count - 1;
          if (!videorate->silent)
            gst_video_rate_notify_duplicate (videorate);
        } else if (count == 0) {
          videorate->drop++;
          if (!videorate->silent)
            gst_video_rate_notify_drop (videorate);
        }
        /* clean up for the new one; _chain will resume from the new start */
        videorate->base_ts = 0;
        videorate->out_frame_count = 0;
        gst_video_rate_swap_prev (videorate, NULL, 0);
        videorate->next_ts = GST_CLOCK_TIME_NONE;
      }

      /* We just want to update the accumulated stream_time  */
      gst_segment_set_newsegment_full (&videorate->segment, update, rate, arate,
          format, start, stop, time);

      GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT,
          &videorate->segment);
      break;
    }
    case GST_EVENT_EOS:{
      gint count = 0;
      GstFlowReturn res = GST_FLOW_OK;

      GST_DEBUG_OBJECT (videorate, "Got EOS");

      /* If the segment has a stop position, fill the segment */
      if (GST_CLOCK_TIME_IS_VALID (videorate->segment.stop)) {
        /* fill up to the end of current segment,
         * or only send out the stored buffer if there is no specific stop.
         * regardless, prevent going loopy in strange cases */
        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
            ((videorate->next_ts - videorate->segment.accum <
                    videorate->segment.stop)
                || count < 1)) {
          res = gst_video_rate_flush_prev (videorate, count > 0);
          count++;
        }
      } else if (videorate->prevbuf) {
        /* Output at least one frame but if the buffer duration is valid, output
         * enough frames to use the complete buffer duration */
        if (GST_BUFFER_DURATION_IS_VALID (videorate->prevbuf)) {
          GstClockTime end_ts =
              videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf);

          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
              ((videorate->next_ts - videorate->segment.accum < end_ts)
                  || count < 1)) {
            res = gst_video_rate_flush_prev (videorate, count > 0);
            count++;
          }
        } else {
          res = gst_video_rate_flush_prev (videorate, FALSE);
          count = 1;
        }
      }

      if (count > 1) {
        videorate->dup += count - 1;
        if (!videorate->silent)
          gst_video_rate_notify_duplicate (videorate);
      } else if (count == 0) {
        videorate->drop++;
        if (!videorate->silent)
          gst_video_rate_notify_drop (videorate);
      }

      break;
    }
    case GST_EVENT_FLUSH_STOP:
      /* also resets the segment */
      GST_DEBUG_OBJECT (videorate, "Got FLUSH_STOP");
      gst_video_rate_reset (videorate);
      break;
    default:
      break;
  }

  ret = gst_pad_push_event (videorate->srcpad, event);

done:
  gst_object_unref (videorate);

  return ret;

  /* ERRORS */
format_error:
  {
    GST_WARNING_OBJECT (videorate,
        "Got segment but doesn't have GST_FORMAT_TIME value");
    gst_event_unref (event);
    ret = FALSE;
    goto done;
  }
}