예제 #1
0
static gboolean
gst_base_video_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstBaseVideoParse *base_video_parse;
  gboolean ret = FALSE;

  base_video_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_START:
      ret =
          gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse),
          event);
      break;
    case GST_EVENT_FLUSH_STOP:
      gst_base_video_parse_reset (base_video_parse);
      ret =
          gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse),
          event);
      break;
    case GST_EVENT_EOS:
      if (gst_base_video_parse_push_all (base_video_parse,
              FALSE) == GST_FLOW_ERROR) {
        gst_event_unref (event);
        return FALSE;
      }

      ret =
          gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse),
          event);
      break;
    case GST_EVENT_NEWSEGMENT:
    {
      gboolean update;
      GstFormat format;
      gdouble rate;
      gint64 start, stop, time;

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

      if (format != GST_FORMAT_TIME)
        goto newseg_wrong_format;

      if (rate <= 0.0)
        goto newseg_wrong_rate;

      GST_DEBUG ("newsegment %" GST_TIME_FORMAT " %" GST_TIME_FORMAT,
          GST_TIME_ARGS (start), GST_TIME_ARGS (time));
      gst_segment_set_newsegment (&base_video_parse->segment, update,
          rate, format, start, stop, time);

      ret =
          gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse),
          event);
      break;
    }
    default:
      ret =
          gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse),
          event);
      break;
  }
done:
  gst_object_unref (base_video_parse);
  return ret;

newseg_wrong_format:
  GST_DEBUG_OBJECT (base_video_parse, "received non TIME newsegment");
  gst_event_unref (event);
  goto done;

newseg_wrong_rate:
  GST_DEBUG_OBJECT (base_video_parse, "negative rates not supported");
  gst_event_unref (event);
  goto done;
}
예제 #2
0
static gboolean
gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event)
{
  GstBaseRTPDepayload *filter;
  gboolean res = TRUE;
  gboolean forward = TRUE;

  filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
      gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED);
      filter->need_newsegment = TRUE;
      filter->priv->next_seqnum = -1;
      break;
    case GST_EVENT_NEWSEGMENT:
    {
      gboolean update;
      gdouble rate;
      GstFormat fmt;
      gint64 start, stop, position;

      gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop,
          &position);

      gst_segment_set_newsegment (&filter->segment, update, rate, fmt,
          start, stop, position);

      /* don't pass the event downstream, we generate our own segment including
       * the NTP time and other things we receive in caps */
      forward = FALSE;
      break;
    }
    case GST_EVENT_CUSTOM_DOWNSTREAM:
    {
      GstBaseRTPDepayloadClass *bclass;

      bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);

      if (gst_event_has_name (event, "GstRTPPacketLost")) {
        /* we get this event from the jitterbuffer when it considers a packet as
         * being lost. We send it to our packet_lost vmethod. The default
         * implementation will make time progress by pushing out a NEWSEGMENT
         * update event. Subclasses can override and to one of the following:
         *  - Adjust timestamp/duration to something more accurate before
         *    calling the parent (default) packet_lost method.
         *  - do some more advanced error concealing on the already received
         *    (fragmented) packets.
         *  - ignore the packet lost.
         */
        if (bclass->packet_lost)
          res = bclass->packet_lost (filter, event);
        forward = FALSE;
      }
      break;
    }
    default:
      break;
  }

  if (forward)
    res = gst_pad_push_event (filter->srcpad, event);
  else
    gst_event_unref (event);

  return res;
}
예제 #3
0
static gboolean
gst_identity_event (GstBaseTransform * trans, GstEvent * event)
{
  GstIdentity *identity;
  gboolean ret = TRUE;

  identity = GST_IDENTITY (trans);

  if (!identity->silent) {
    const GstStructure *s;
    gchar *sstr;

    GST_OBJECT_LOCK (identity);
    g_free (identity->last_message);

    if ((s = gst_event_get_structure (event)))
      sstr = gst_structure_to_string (s);
    else
      sstr = g_strdup ("");

    identity->last_message =
        g_strdup_printf ("event   ******* (%s:%s) E (type: %d, %s) %p",
        GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), sstr,
        event);
    g_free (sstr);
    GST_OBJECT_UNLOCK (identity);

    gst_identity_notify_last_message (identity);
  }

  if (identity->single_segment
      && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
    if (trans->have_newsegment == FALSE) {
      GstEvent *news;
      GstFormat format;

      gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
          NULL);

      /* This is the first newsegment, send out a (0, -1) newsegment */
      news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);

      gst_pad_event_default (trans->sinkpad, news);
    }
  }

  /* Reset previous timestamp, duration and offsets on NEWSEGMENT
   * to prevent false warnings when checking for perfect streams */
  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
    identity->prev_timestamp = identity->prev_duration = GST_CLOCK_TIME_NONE;
    identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE;
  }

  ret = parent_class->event (trans, event);

  if (identity->single_segment
      && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
    /* eat up segments */
    ret = FALSE;
  }

  return ret;
}
예제 #4
0
static gboolean
gst_sub_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad));
  gboolean ret = FALSE;

  GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:{
      /* Make sure the last subrip chunk is pushed out even
       * if the file does not have an empty line at the end */
      if (self->parser_type == GST_SUB_PARSE_FORMAT_SUBRIP ||
          self->parser_type == GST_SUB_PARSE_FORMAT_TMPLAYER ||
          self->parser_type == GST_SUB_PARSE_FORMAT_MPL2) {
        GstBuffer *buf = gst_buffer_new_and_alloc (2 + 1);

        GST_DEBUG ("EOS. Pushing remaining text (if any)");
        GST_BUFFER_DATA (buf)[0] = '\n';
        GST_BUFFER_DATA (buf)[1] = '\n';
        GST_BUFFER_DATA (buf)[2] = '\0';        /* play it safe */
        GST_BUFFER_SIZE (buf) = 2;
        GST_BUFFER_OFFSET (buf) = self->offset;
        gst_sub_parse_chain (pad, buf);
      }
      ret = gst_pad_event_default (pad, event);
      break;
    }
    case GST_EVENT_NEWSEGMENT:
    {
      GstFormat format;
      gdouble rate;
      gint64 start, stop, time;
      gboolean update;

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

      GST_DEBUG_OBJECT (self, "newsegment (%s)", gst_format_get_name (format));

      if (format == GST_FORMAT_TIME) {
        gst_segment_set_newsegment (&self->segment, update, rate, format,
            start, stop, time);
      } else {
        /* if not time format, we'll either start with a 0 timestamp anyway or
         * it's following a seek in which case we'll have saved the requested
         * seek segment and don't want to overwrite it (remember that on a seek
         * we always just seek back to the start in BYTES format and just throw
         * away all text that's before the requested position; if the subtitles
         * come from an upstream demuxer, it won't be able to handle our BYTES
         * seek request and instead send us a newsegment from the seek request
         * it received via its video pads instead, so all is fine then too) */
      }

      ret = TRUE;
      gst_event_unref (event);
      break;
    }
    case GST_EVENT_FLUSH_START:
    {
      self->flushing = TRUE;

      ret = gst_pad_event_default (pad, event);
      break;
    }
    case GST_EVENT_FLUSH_STOP:
    {
      self->flushing = FALSE;

      ret = gst_pad_event_default (pad, event);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (self);

  return ret;
}
/*=============================================================================
 FUNCTION:      mfw_gst_spdifrx_sink_event
 DESCRIPTION:       Handles an event on the sink pad.
 ARGUMENTS PASSED:
        pad        -    pointer to pad
        event      -    pointer to event
 RETURN VALUE:
        TRUE       -    if event is sent to sink properly
        FALSE      -    if event is not sent to sink properly
 PRE-CONDITIONS:    None
 POST-CONDITIONS:   None
 IMPORTANT NOTES:   None
=============================================================================*/
static gboolean 
mfw_gst_spdifrx_sink_event(GstPad * pad, GstEvent * event)
{
    MfwGstSpdifRX *filter = MFW_GST_SPDIFRX (GST_PAD_PARENT(pad));
    gboolean result = TRUE;

    switch (GST_EVENT_TYPE(event)) {
    case GST_EVENT_NEWSEGMENT:
    {
        GstFormat format;
        gint64 start, stop, position;
        gint64 nstart, nstop;
        gst_event_parse_new_segment(event, NULL, NULL, &format, &start,
                                    &stop, &position);

        if (format == GST_FORMAT_TIME) {
                result = gst_pad_push_event(filter->srcpad, event);
                if (TRUE != result) {
                    GST_ERROR
                         ("\n Error in pushing the event,result is %d\n", result);
            }

            GST_DEBUG("\nCame to the FORMAT_TIME call\n");
        } else {
            g_print("Newsegment event in format %s",
                      gst_format_get_name(format));
            result = gst_pad_push_event(filter->srcpad, event);
            if (TRUE != result) {
                GST_ERROR
                ("\n Error in pushing the event,result  is %d\n",
                 result);
            }
        }
        break;
    }

    case GST_EVENT_EOS:
    {
        gboolean ret;
        GST_DEBUG("\nSPDIF Receiver converter: Get EOS event\n");
        if (filter->format == SPDIF_FORMAT_NONPCM) {
            mfw_gst_spdifrx_push(filter);
            while(ret == TRUE) {
                ret = mfw_gst_spdifrx_push(filter);
            };
            mfw_gst_spdifrx_pushavail(filter);
        }
        
        result = gst_pad_event_default(pad, event);
        if (result != TRUE) {
            GST_ERROR("\n Error in pushing the event, result is %d\n",result);
        }
        break;
    }
    default:
    {
        result = gst_pad_event_default(pad, event);
        break;
    }

    }

    GST_DEBUG("Out of mfw_gst_spdifrx_sink_event() function \n ");
    return result;
}
예제 #6
0
static gboolean
gst_kate_enc_sink_event (GstPad * pad, GstEvent * event)
{
  GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad));
  GstStructure *structure;
  gboolean ret;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:
      GST_LOG_OBJECT (ke, "Got newsegment event");
      if (ke->initialized) {
        GST_LOG_OBJECT (ke, "ensuring all headers are in");
        if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
          GST_WARNING_OBJECT (ke, "Failed to flush headers");
        } else {
          GstFormat format;
          gint64 timestamp;

          gst_event_parse_new_segment (event, NULL, NULL, &format, &timestamp,
              NULL, NULL);
          if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (timestamp)) {
            GST_WARNING_OBJECT (ke,
                "No time in newsegment event %p, format %d, timestamp %"
                G_GINT64_FORMAT, event, (int) format, timestamp);
            /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a
               good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a
               timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we
               run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */
          } else {
            float t = timestamp / (double) GST_SECOND;

            if (ke->delayed_spu
                && t - ke->delayed_start / (double) GST_SECOND >=
                ke->default_spu_duration) {
              if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke,
                          timestamp) != GST_FLOW_OK)) {
                GST_WARNING_OBJECT (ke, "Failed to encode delayed packet");
                /* continue with new segment handling anyway */
              }
            }

            GST_LOG_OBJECT (ke, "ts %f, last %f (min %f)", t,
                ke->last_timestamp / (double) GST_SECOND,
                ke->keepalive_min_time);
            if (ke->keepalive_min_time > 0.0f
                && t - ke->last_timestamp / (double) GST_SECOND >=
                ke->keepalive_min_time) {
              /* we only generate a keepalive if there is no SPU waiting, as it would
                 mean out of sequence start times - and granulepos */
              if (!ke->delayed_spu) {
                gst_kate_enc_generate_keepalive (ke, timestamp);
              }
            }
          }
        }
      }
      ret = gst_pad_push_event (ke->srcpad, event);
      break;

    case GST_EVENT_CUSTOM_DOWNSTREAM:
      GST_LOG_OBJECT (ke, "Got custom downstream event");
      /* adapted from the dvdsubdec element */
      structure = event->structure;
      if (structure != NULL
          && gst_structure_has_name (structure, "application/x-gst-dvd")) {
        if (ke->initialized) {
          GST_LOG_OBJECT (ke, "ensuring all headers are in");
          if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
            GST_WARNING_OBJECT (ke, "Failed to flush headers");
          } else {
            const gchar *event_name =
                gst_structure_get_string (structure, "event");
            if (event_name) {
              if (!strcmp (event_name, "dvd-spu-clut-change")) {
                gchar name[16];
                int idx;
                gboolean found;
                gint value;
                GST_INFO_OBJECT (ke, "New CLUT received");
                for (idx = 0; idx < 16; ++idx) {
                  g_snprintf (name, sizeof (name), "clut%02d", idx);
                  found = gst_structure_get_int (structure, name, &value);
                  if (found) {
                    ke->spu_clut[idx] = value;
                  } else {
                    GST_WARNING_OBJECT (ke,
                        "DVD CLUT event did not contain %s field", name);
                  }
                }
              } else if (!strcmp (event_name, "dvd-lang-codes")) {
                /* we can't know which stream corresponds to us */
              }
            } else {
              GST_WARNING_OBJECT (ke, "custom downstream event with no name");
            }
          }
        }
      }
      ret = gst_pad_push_event (ke->srcpad, event);
      break;

    case GST_EVENT_TAG:
      GST_LOG_OBJECT (ke, "Got tag event");
      if (ke->tags) {
        GstTagList *list;

        gst_event_parse_tag (event, &list);
        gst_tag_list_insert (ke->tags, list,
            gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke)));
      } else {
        g_assert_not_reached ();
      }
      ret = gst_pad_event_default (pad, event);
      break;

    case GST_EVENT_EOS:
      GST_INFO_OBJECT (ke, "Got EOS event");
      if (ke->initialized) {
        GST_LOG_OBJECT (ke, "ensuring all headers are in");
        if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
          GST_WARNING_OBJECT (ke, "Failed to flush headers");
        } else {
          kate_packet kp;
          int ret;
          GstClockTime delayed_end =
              ke->delayed_start + ke->default_spu_duration * GST_SECOND;

          if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke,
                      delayed_end) != GST_FLOW_OK)) {
            GST_WARNING_OBJECT (ke, "Failed to encode delayed packet");
            /* continue with EOS handling anyway */
          }

          ret = kate_encode_finish (&ke->k, -1, &kp);
          if (ret < 0) {
            GST_WARNING_OBJECT (ke, "Failed to encode EOS packet: %d", ret);
          } else {
            kate_int64_t granpos = kate_encode_get_granule (&ke->k);
            GST_LOG_OBJECT (ke, "EOS packet encoded");
            if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos,
                    ke->latest_end_time, 0, FALSE)) {
              GST_WARNING_OBJECT (ke, "Failed to push EOS packet");
            }
          }
        }
      }
      ret = gst_pad_event_default (pad, event);
      break;

    default:
      GST_LOG_OBJECT (ke, "Got unhandled event");
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (ke);
  return ret;
}
예제 #7
0
/* handle events (search) */
static gboolean
gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
{
  GstEventType type;
  GstFileSink *filesink;

  filesink = GST_FILE_SINK (sink);

  type = GST_EVENT_TYPE (event);

  switch (type) {
    case GST_EVENT_NEWSEGMENT:
    {
      gint64 start, stop, pos;
      GstFormat format;

      gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
          &stop, &pos);

      if (format == GST_FORMAT_BYTES) {
        /* only try to seek and fail when we are going to a different
         * position */
        if (filesink->current_pos != start) {
          /* FIXME, the seek should be performed on the pos field, start/stop are
           * just boundaries for valid bytes offsets. We should also fill the file
           * with zeroes if the new position extends the current EOF (sparse streams
           * and segment accumulation). */
          if (!gst_file_sink_do_seek (filesink, (guint64) start))
            goto seek_failed;
        } else {
          GST_DEBUG_OBJECT (filesink, "Ignored NEWSEGMENT, no seek needed");
        }
      } else {
        GST_DEBUG_OBJECT (filesink,
            "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
            gst_format_get_name (format));
      }
      break;
    }
    case GST_EVENT_EOS:
      if (fflush (filesink->file))
        goto flush_failed;
      break;
    default:
      break;
  }

  return TRUE;

  /* ERRORS */
seek_failed:
  {
    GST_ELEMENT_ERROR (filesink, RESOURCE, SEEK,
        (_("Error while seeking in file \"%s\"."), filesink->filename),
        GST_ERROR_SYSTEM);
    return FALSE;
  }
flush_failed:
  {
    GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
        (_("Error while writing to file \"%s\"."), filesink->filename),
        GST_ERROR_SYSTEM);
    return FALSE;
  }
}