コード例 #1
0
ファイル: gstdvdspu.c プロジェクト: agx/gst-plugins-bad
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, &timestamp, &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
}
コード例 #2
0
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;
}