Пример #1
0
static gboolean gst_sctp_dec_src_event(GstPad *pad, GstSctpDec *self, GstEvent *event)
{
    switch (GST_EVENT_TYPE(event)) {
        case GST_EVENT_RECONFIGURE:
        case GST_EVENT_FLUSH_STOP: {
            GstSctpDecPad *sctpdec_pad = GST_SCTP_DEC_PAD(pad);

            /* Unflush and start task again */
            gst_data_queue_set_flushing(sctpdec_pad->packet_queue, FALSE);
            gst_pad_start_task(pad, (GstTaskFunction)gst_sctp_data_srcpad_loop, pad, NULL);

            return gst_pad_event_default(pad, GST_OBJECT(self), event);
        }
        case GST_EVENT_FLUSH_START: {
            GstSctpDecPad *sctpdec_pad = GST_SCTP_DEC_PAD(pad);

            gst_data_queue_set_flushing(sctpdec_pad->packet_queue, TRUE);
            gst_data_queue_flush(sctpdec_pad->packet_queue);

            return gst_pad_event_default(pad, GST_OBJECT(self), event);
        }
        default:
            return gst_pad_event_default(pad, GST_OBJECT(self), event);
    }
}
Пример #2
0
static void gst_sctp_data_srcpad_loop(GstPad *pad)
{
    GstSctpDecPad *sctpdec_pad = GST_SCTP_DEC_PAD(pad);
    GstDataQueueItem *item;

    if (gst_data_queue_pop(sctpdec_pad->packet_queue, &item)) {
        GstFlowReturn flow_ret;

        flow_ret = gst_pad_push(pad, GST_BUFFER(item->object));
        item->object = NULL;
        if (G_UNLIKELY(flow_ret == GST_FLOW_FLUSHING || flow_ret == GST_FLOW_NOT_LINKED)) {
            GST_DEBUG_OBJECT(pad, "Push failed on packet source pad. Error: %s", gst_flow_get_name(flow_ret));
        } else if (G_UNLIKELY(flow_ret != GST_FLOW_OK)) {
            GST_ERROR_OBJECT(pad, "Push failed on packet source pad. Error: %s", gst_flow_get_name(flow_ret));
        }

        if (G_UNLIKELY(flow_ret != GST_FLOW_OK)) {
            GST_DEBUG_OBJECT(pad, "Pausing task because of an error");
            gst_data_queue_set_flushing(sctpdec_pad->packet_queue, TRUE);
            gst_data_queue_flush(sctpdec_pad->packet_queue);
            gst_pad_pause_task(pad);
        }

        item->destroy(item);
    } else {
        GST_DEBUG_OBJECT(pad, "Pausing task because we're flushing");
        gst_pad_pause_task(pad);
    }
}
static void
splitmux_part_pad_finalize (GObject * obj)
{
  GstSplitMuxPartPad *pad = (GstSplitMuxPartPad *) (obj);

  GST_DEBUG_OBJECT (obj, "finalize");
  gst_data_queue_set_flushing (pad->queue, TRUE);
  gst_data_queue_flush (pad->queue);
  gst_object_unref (GST_OBJECT_CAST (pad->queue));
  pad->queue = NULL;

  G_OBJECT_CLASS (gst_splitmux_part_pad_parent_class)->finalize (obj);
}
Пример #4
0
static void flush_srcpad(const GValue *item, gpointer user_data)
{
    GstSctpDecPad *sctpdec_pad = g_value_get_object(item);
    gboolean flush = GPOINTER_TO_INT(user_data);

    if (flush) {
        gst_data_queue_set_flushing(sctpdec_pad->packet_queue, TRUE);
        gst_data_queue_flush(sctpdec_pad->packet_queue);
    } else {
        gst_data_queue_set_flushing(sctpdec_pad->packet_queue, FALSE);
        gst_pad_start_task(GST_PAD(sctpdec_pad), (GstTaskFunction)gst_sctp_data_srcpad_loop, sctpdec_pad, NULL);
    }
}
void
gst_splitmux_part_reader_set_flushing_locked (GstSplitMuxPartReader * reader,
    gboolean flushing)
{
  GList *cur;

  GST_LOG_OBJECT (reader, "%s dataqueues",
      flushing ? "Flushing" : "Done flushing");
  for (cur = g_list_first (reader->pads); cur != NULL; cur = g_list_next (cur)) {
    GstSplitMuxPartPad *part_pad = SPLITMUX_PART_PAD_CAST (cur->data);
    gst_data_queue_set_flushing (part_pad->queue, flushing);
    if (flushing)
      gst_data_queue_flush (part_pad->queue);
  }
};
static gboolean
splitmux_part_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstSplitMuxPartPad *part_pad = SPLITMUX_PART_PAD_CAST (pad);
  GstSplitMuxPartReader *reader = part_pad->reader;
  gboolean ret = TRUE;
  SplitMuxSrcPad *target;
  GstDataQueueItem *item;

  SPLITMUX_PART_LOCK (reader);

  target = gst_object_ref (part_pad->target);

  GST_LOG_OBJECT (reader, "Pad %" GST_PTR_FORMAT " event %" GST_PTR_FORMAT, pad,
      event);

  if (part_pad->flushing && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP)
    goto drop_event;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:{
      GstSegment *seg = &part_pad->segment;

      GST_LOG_OBJECT (pad, "Received segment %" GST_PTR_FORMAT, event);

      gst_event_copy_segment (event, seg);
      gst_event_copy_segment (event, &part_pad->orig_segment);

      if (seg->format != GST_FORMAT_TIME)
        goto wrong_segment;

      /* Adjust segment */
      /* Adjust start/stop so the overall file is 0 + start_offset based */
      if (seg->stop != -1) {
        seg->stop -= seg->start;
        seg->stop += seg->time + reader->start_offset;
      }
      seg->start = seg->time + reader->start_offset;
      seg->time += reader->start_offset;
      seg->position += reader->start_offset;

      GST_LOG_OBJECT (pad, "Adjusted segment now %" GST_PTR_FORMAT, event);

      /* Replace event */
      gst_event_unref (event);
      event = gst_event_new_segment (seg);

      if (reader->prep_state != PART_STATE_PREPARING_COLLECT_STREAMS
          && reader->prep_state != PART_STATE_PREPARING_MEASURE_STREAMS)
        break;                  /* Only do further stuff with segments during initial measuring */

      /* Take the first segment from the first part */
      if (target->segment.format == GST_FORMAT_UNDEFINED) {
        gst_segment_copy_into (seg, &target->segment);
        GST_DEBUG_OBJECT (reader,
            "Target pad segment now %" GST_SEGMENT_FORMAT, &target->segment);
      }

      if (seg->stop != -1 && target->segment.stop != -1) {
        GstClockTime stop = seg->base + seg->stop;
        if (stop > target->segment.stop) {
          target->segment.stop = stop;
          GST_DEBUG_OBJECT (reader,
              "Adjusting segment stop by %" GST_TIME_FORMAT
              " output now %" GST_SEGMENT_FORMAT,
              GST_TIME_ARGS (reader->start_offset), &target->segment);
        }
      }
      GST_LOG_OBJECT (pad, "Forwarding segment %" GST_PTR_FORMAT, event);
      break;
    }
    case GST_EVENT_EOS:{

      GST_DEBUG_OBJECT (part_pad,
          "State %u EOS event. MaxTS seen %" GST_TIME_FORMAT,
          reader->prep_state, GST_TIME_ARGS (part_pad->max_ts));

      if (reader->prep_state == PART_STATE_PREPARING_COLLECT_STREAMS ||
          reader->prep_state == PART_STATE_PREPARING_MEASURE_STREAMS) {
        /* Mark this pad as EOS */
        part_pad->is_eos = TRUE;
        if (splitmux_part_is_eos_locked (reader)) {
          /* Finished measuring things, set state and tell the state change func
           * so it can seek back to the start */
          GST_LOG_OBJECT (reader,
              "EOS while measuring streams. Resetting for ready");
          reader->prep_state = PART_STATE_PREPARING_RESET_FOR_READY;
          SPLITMUX_PART_BROADCAST (reader);
        }
        goto drop_event;
      }
      break;
    }
    case GST_EVENT_FLUSH_START:
      reader->flushing = TRUE;
      part_pad->flushing = TRUE;
      GST_LOG_OBJECT (reader, "Pad %" GST_PTR_FORMAT " flushing dataqueue",
          part_pad);
      gst_data_queue_set_flushing (part_pad->queue, TRUE);
      SPLITMUX_PART_BROADCAST (reader);
      break;
    case GST_EVENT_FLUSH_STOP:{
      gst_data_queue_set_flushing (part_pad->queue, FALSE);
      gst_data_queue_flush (part_pad->queue);
      part_pad->seen_buffer = FALSE;
      part_pad->flushing = FALSE;
      part_pad->is_eos = FALSE;

      reader->flushing = splitmux_is_flushing (reader);
      GST_LOG_OBJECT (reader,
          "%s pad %" GST_PTR_FORMAT " flush_stop. Overall flushing=%d",
          reader->path, pad, reader->flushing);
      SPLITMUX_PART_BROADCAST (reader);
      break;
    }
    default:
      break;
  }

  /* Don't send events downstream while preparing */
  if (reader->prep_state != PART_STATE_READY)
    goto drop_event;

  /* Don't pass flush events - those are done by the parent */
  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START ||
      GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP)
    goto drop_event;

  if (!block_until_can_push (reader)) {
    SPLITMUX_PART_UNLOCK (reader);
    gst_object_unref (target);
    gst_event_unref (event);
    return FALSE;
  }

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_GAP:{
      /* FIXME: Drop initial gap (if any) in each segment, not all GAPs */
      goto drop_event;
    }
    default:
      break;
  }

  /* We are active, and one queue is empty, place this buffer in
   * the dataqueue */
  gst_object_ref (part_pad->queue);
  SPLITMUX_PART_UNLOCK (reader);

  GST_LOG_OBJECT (reader, "Enqueueing event %" GST_PTR_FORMAT, event);
  item = g_slice_new (GstDataQueueItem);
  item->destroy = (GDestroyNotify) splitmux_part_free_queue_item;
  item->object = GST_MINI_OBJECT (event);
  item->size = 0;
  item->duration = 0;
  if (item->duration == GST_CLOCK_TIME_NONE)
    item->duration = 0;
  item->visible = FALSE;

  if (!gst_data_queue_push (part_pad->queue, item)) {
    splitmux_part_free_queue_item (item);
    ret = FALSE;
  }

  gst_object_unref (part_pad->queue);
  gst_object_unref (target);

  return ret;
wrong_segment:
  gst_event_unref (event);
  gst_object_unref (target);
  SPLITMUX_PART_UNLOCK (reader);
  GST_ELEMENT_ERROR (reader, STREAM, FAILED, (NULL),
      ("Received non-time segment - reader %s pad %" GST_PTR_FORMAT,
          reader->path, pad));
  return FALSE;
drop_event:
  GST_LOG_OBJECT (pad, "Dropping event %" GST_PTR_FORMAT
      " from %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, event, pad, target);
  gst_event_unref (event);
  gst_object_unref (target);
  SPLITMUX_PART_UNLOCK (reader);
  return TRUE;
}