Ejemplo n.º 1
0
static VALUE
segment_done_initialize(VALUE self, VALUE src, VALUE format, VALUE position)
{
    G_INITIALIZE(self, gst_message_new_segment_done(RVAL2GST_OBJ(src),
                                                    RVAL2GST_FORMAT(format),
                                                    NUM2LL(position)));
    return Qnil;
}
Ejemplo n.º 2
0
static void
gst_nuv_demux_send_eos (GstNuvDemux * nuv)
{
  gst_element_post_message (GST_ELEMENT (nuv),
      gst_message_new_segment_done (GST_OBJECT (nuv), GST_FORMAT_TIME, -1));

  if (nuv->src_video_pad)
    gst_pad_push_event (nuv->src_video_pad, gst_event_new_eos ());
  if (nuv->src_audio_pad)
    gst_pad_push_event (nuv->src_audio_pad, gst_event_new_eos ());
}
Ejemplo n.º 3
0
static void
gst_aiff_parse_loop (GstPad * pad)
{
  GstFlowReturn ret;
  GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));

  GST_LOG_OBJECT (aiff, "process data");

  switch (aiff->state) {
    case AIFF_PARSE_START:
      GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
      if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
        goto pause;

      aiff->state = AIFF_PARSE_HEADER;
      /* fall-through */

    case AIFF_PARSE_HEADER:
      GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
      if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
        goto pause;

      aiff->state = AIFF_PARSE_DATA;
      GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
      /* fall-through */

    case AIFF_PARSE_DATA:
      if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
        goto pause;
      break;
    default:
      g_assert_not_reached ();
  }
  return;

  /* ERRORS */
pause:
  {
    const gchar *reason = gst_flow_get_name (ret);

    GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
    aiff->segment_running = FALSE;
    gst_pad_pause_task (pad);

    if (ret == GST_FLOW_UNEXPECTED) {
      /* perform EOS logic */
      if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
        GstClockTime stop;

        if ((stop = aiff->segment.stop) == -1)
          stop = aiff->segment.duration;

        gst_element_post_message (GST_ELEMENT_CAST (aiff),
            gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
                aiff->segment.format, stop));
      } else {
        gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
      }
    } else if (ret < GST_FLOW_UNEXPECTED || ret == GST_FLOW_NOT_LINKED) {
      /* for fatal errors we post an error message, post the error
       * first so the app knows about the error first. */
      GST_ELEMENT_ERROR (aiff, STREAM, FAILED,
          (_("Internal data flow error.")),
          ("streaming task paused, reason %s (%d)", reason, ret));
      gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
    }
    return;
  }
}
Ejemplo n.º 4
0
static void
gst_musepackdec_loop (GstPad * sinkpad)
{
  GstMusepackDec *musepackdec;
  GstFlowReturn flow;
  GstBuffer *out;
  GstMapInfo info;
  mpc_frame_info frame;
  mpc_status err;
  gint num_samples, samplerate, bitspersample;

  musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));

  samplerate = g_atomic_int_get (&musepackdec->rate);

  if (samplerate == 0) {
    if (!gst_musepack_stream_init (musepackdec))
      goto pause_task;

    gst_musepackdec_send_newsegment (musepackdec);
    samplerate = g_atomic_int_get (&musepackdec->rate);
  }

  bitspersample = g_atomic_int_get (&musepackdec->bps);

  out = gst_buffer_new_allocate (NULL, MPC_DECODER_BUFFER_LENGTH * 4, NULL);

  gst_buffer_map (out, &info, GST_MAP_READWRITE);
  frame.buffer = (MPC_SAMPLE_FORMAT *) info.data;
  err = mpc_demux_decode (musepackdec->d, &frame);
  gst_buffer_unmap (out, &info);

  if (err != MPC_STATUS_OK) {
    GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
    GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
    goto pause_task;
  } else if (frame.bits == -1) {
    goto eos_and_pause;
  }

  num_samples = frame.samples;

  gst_buffer_set_size (out, num_samples * bitspersample);

  GST_BUFFER_OFFSET (out) = musepackdec->segment.position;
  GST_BUFFER_PTS (out) =
      gst_util_uint64_scale_int (musepackdec->segment.position,
      GST_SECOND, samplerate);
  GST_BUFFER_DURATION (out) =
      gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate);

  musepackdec->segment.position += num_samples;

  GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));

  flow = gst_pad_push (musepackdec->srcpad, out);
  if (flow != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
    goto pause_task;
  }

  /* check if we're at the end of a configured segment */
  if (musepackdec->segment.stop != -1 &&
      musepackdec->segment.position >= musepackdec->segment.stop) {
    gint64 stop_time;

    GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment");

    if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0)
      goto eos_and_pause;

    GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message");

    stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop,
        GST_SECOND, samplerate);

    gst_element_post_message (GST_ELEMENT (musepackdec),
        gst_message_new_segment_done (GST_OBJECT (musepackdec),
            GST_FORMAT_TIME, stop_time));
    gst_pad_push_event (musepackdec->srcpad,
        gst_event_new_segment_done (GST_FORMAT_TIME, stop_time));

    goto pause_task;
  }

  return;

eos_and_pause:
  {
    GST_DEBUG_OBJECT (musepackdec, "sending EOS event");
    gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
    /* fall through to pause */
  }

pause_task:
  {
    GST_DEBUG_OBJECT (musepackdec, "Pausing task");
    gst_pad_pause_task (sinkpad);
    return;
  }
}
static void
gst_type_find_element_loop (GstPad * pad)
{
  GstTypeFindElement *typefind;
  GstFlowReturn ret = GST_FLOW_OK;

  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  if (typefind->need_stream_start) {
    gchar *stream_id;
    GstEvent *event;

    stream_id = gst_pad_create_stream_id (typefind->src,
        GST_ELEMENT_CAST (typefind), NULL);

    GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START");
    event = gst_event_new_stream_start (stream_id);
    gst_event_set_group_id (event, gst_util_group_id_next ());
    gst_pad_push_event (typefind->src, event);

    typefind->need_stream_start = FALSE;
    g_free (stream_id);
  }

  if (typefind->mode == MODE_TYPEFIND) {
    GstPad *peer = NULL;
    GstCaps *found_caps = NULL;
    GstTypeFindProbability probability = GST_TYPE_FIND_NONE;

    GST_DEBUG_OBJECT (typefind, "find type in pull mode");

    GST_OBJECT_LOCK (typefind);
    if (typefind->force_caps) {
      found_caps = gst_caps_ref (typefind->force_caps);
      probability = GST_TYPE_FIND_MAXIMUM;
    }
    GST_OBJECT_UNLOCK (typefind);

    if (!found_caps) {
      peer = gst_pad_get_peer (pad);
      if (peer) {
        gint64 size;
        gchar *ext;

        if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
          GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
          gst_object_unref (peer);

          ret = GST_FLOW_ERROR;
          goto pause;
        }

        /* the size if 0, we cannot continue */
        if (size == 0) {
          /* keep message in sync with message in sink event handler */
          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
              (_("Stream contains no data.")), ("Can't typefind empty stream"));
          gst_object_unref (peer);
          ret = GST_FLOW_ERROR;
          goto pause;
        }
        ext = gst_type_find_get_extension (typefind, pad);

        found_caps =
            gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
            GST_OBJECT_PARENT (peer),
            (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
            (guint64) size, ext, &probability);
        g_free (ext);

        GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);

        gst_object_unref (peer);
      }
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_DEBUG ("Trying to guess using extension");
      gst_caps_replace (&found_caps, NULL);
      found_caps =
          gst_type_find_guess_by_extension (typefind, pad, &probability);
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
      gst_caps_replace (&found_caps, NULL);
      ret = GST_FLOW_ERROR;
      goto pause;
    }

    GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
    gst_type_find_element_emit_have_type (typefind, probability, found_caps);
    typefind->mode = MODE_NORMAL;
    gst_caps_unref (found_caps);
  } else if (typefind->mode == MODE_NORMAL) {
    GstBuffer *outbuf = NULL;

    if (typefind->need_segment) {
      typefind->need_segment = FALSE;
      gst_pad_push_event (typefind->src,
          gst_event_new_segment (&typefind->segment));
    }

    /* Pull 4k blocks and send downstream */
    ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;

    typefind->offset += gst_buffer_get_size (outbuf);

    ret = gst_pad_push (typefind->src, outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;
  } else {
    /* Error out */
    ret = GST_FLOW_ERROR;
    goto pause;
  }

  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (ret);
    gboolean push_eos = FALSE;

    GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason);
    gst_pad_pause_task (typefind->sink);

    if (ret == GST_FLOW_EOS) {
      /* perform EOS logic */

      if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
        gint64 stop;

        /* for segment playback we need to post when (in stream time)
         * we stopped, this is either stop (when set) or the duration. */
        if ((stop = typefind->segment.stop) == -1)
          stop = typefind->offset;

        GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment");
        gst_element_post_message (GST_ELEMENT (typefind),
            gst_message_new_segment_done (GST_OBJECT (typefind),
                GST_FORMAT_BYTES, stop));
        gst_pad_push_event (typefind->src,
            gst_event_new_segment_done (GST_FORMAT_BYTES, stop));
      } else {
        push_eos = TRUE;
      }
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
      /* for fatal errors we post an error message */
      GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL),
          ("stream stopped, reason %s", reason));
      push_eos = TRUE;
    }
    if (push_eos) {
      /* send EOS, and prevent hanging if no streams yet */
      GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream");
      gst_pad_push_event (typefind->src, gst_event_new_eos ());
    }
    return;
  }
}
Ejemplo n.º 6
0
static void
gst_raw_parse_loop (GstElement * element)
{
  GstRawParse *rp = GST_RAW_PARSE (element);
  GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp);
  GstFlowReturn ret;
  GstBuffer *buffer;
  gint size;

  if (!gst_raw_parse_set_src_caps (rp))
    goto no_caps;

  if (rp->start_segment) {
    GST_DEBUG_OBJECT (rp, "sending start segment");
    gst_pad_push_event (rp->srcpad, rp->start_segment);
    rp->start_segment = NULL;
  }

  if (rp_class->multiple_frames_per_buffer && rp->framesize < 4096)
    size = 4096 - (4096 % rp->framesize);
  else
    size = rp->framesize;

  if (rp->segment.rate >= 0) {
    if (rp->offset + size > rp->upstream_length) {
      GstFormat fmt = GST_FORMAT_BYTES;

      if (!gst_pad_peer_query_duration (rp->sinkpad, fmt, &rp->upstream_length)) {
        GST_WARNING_OBJECT (rp,
            "Could not get upstream duration, trying to pull frame by frame");
        size = rp->framesize;
      } else if (rp->upstream_length < rp->offset + rp->framesize) {
        ret = GST_FLOW_EOS;
        goto pause;
      } else if (rp->offset + size > rp->upstream_length) {
        size = rp->upstream_length - rp->offset;
        size -= size % rp->framesize;
      }
    }
  } else {
    if (rp->offset == 0) {
      ret = GST_FLOW_EOS;
      goto pause;
    } else if (rp->offset < size) {
      size -= rp->offset;
    }
    rp->offset -= size;
  }

  buffer = NULL;
  ret = gst_pad_pull_range (rp->sinkpad, rp->offset, size, &buffer);

  if (ret != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (rp, "pull_range (%" G_GINT64_FORMAT ", %u) "
        "failed, flow: %s", rp->offset, size, gst_flow_get_name (ret));
    buffer = NULL;
    goto pause;
  }

  if (gst_buffer_get_size (buffer) < size) {
    GST_DEBUG_OBJECT (rp, "Short read at offset %" G_GINT64_FORMAT
        ", got only %" G_GSIZE_FORMAT " of %u bytes", rp->offset,
        gst_buffer_get_size (buffer), size);

    if (size > rp->framesize) {
      gst_buffer_set_size (buffer, gst_buffer_get_size (buffer) -
          gst_buffer_get_size (buffer) % rp->framesize);
    } else {
      gst_buffer_unref (buffer);
      buffer = NULL;
      ret = GST_FLOW_EOS;
      goto pause;
    }
  }

  ret = gst_raw_parse_push_buffer (rp, buffer);
  if (ret != GST_FLOW_OK)
    goto pause;

  return;

  /* ERRORS */
no_caps:
  {
    GST_ERROR_OBJECT (rp, "could not negotiate caps");
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto pause;
  }
pause:
  {
    const gchar *reason = gst_flow_get_name (ret);

    GST_LOG_OBJECT (rp, "pausing task, reason %s", reason);
    gst_pad_pause_task (rp->sinkpad);

    if (ret == GST_FLOW_EOS) {
      if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) {
        GstClockTime stop;

        GST_LOG_OBJECT (rp, "Sending segment done");

        if ((stop = rp->segment.stop) == -1)
          stop = rp->segment.duration;

        gst_element_post_message (GST_ELEMENT_CAST (rp),
            gst_message_new_segment_done (GST_OBJECT_CAST (rp),
                rp->segment.format, stop));
        gst_pad_push_event (rp->srcpad,
            gst_event_new_segment_done (rp->segment.format, stop));
      } else {
        GST_LOG_OBJECT (rp, "Sending EOS, at end of stream");
        gst_pad_push_event (rp->srcpad, gst_event_new_eos ());
      }
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
      GST_ELEMENT_ERROR (rp, STREAM, FAILED,
          ("Internal data stream error."),
          ("stream stopped, reason %s", reason));
      gst_pad_push_event (rp->srcpad, gst_event_new_eos ());
    }
    return;
  }
}
Ejemplo n.º 7
0
static void
gst_musepackdec_loop (GstPad * sinkpad)
{
    GstMusepackDec *musepackdec;
    GstFlowReturn flow;
    GstBuffer *out;

#ifdef MPC_IS_OLD_API
    guint32 update_acc, update_bits;
#else
    mpc_frame_info frame;
    mpc_status err;
#endif
    gint num_samples, samplerate, bitspersample;

    musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));

    samplerate = g_atomic_int_get (&musepackdec->rate);

    if (samplerate == 0) {
        if (!gst_musepack_stream_init (musepackdec))
            goto pause_task;

        gst_musepackdec_send_newsegment (musepackdec);
        samplerate = g_atomic_int_get (&musepackdec->rate);
    }

    bitspersample = g_atomic_int_get (&musepackdec->bps);

    flow = gst_pad_alloc_buffer_and_set_caps (musepackdec->srcpad, -1,
            MPC_DECODER_BUFFER_LENGTH * 4, GST_PAD_CAPS (musepackdec->srcpad), &out);

    if (flow != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
        goto pause_task;
    }
#ifdef MPC_IS_OLD_API
    num_samples = mpc_decoder_decode (musepackdec->d,
                                      (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits);

    if (num_samples < 0) {
        GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
        GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
        goto pause_task;
    } else if (num_samples == 0) {
        goto eos_and_pause;
    }
#else
    frame.buffer = (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out);
    err = mpc_demux_decode (musepackdec->d, &frame);

    if (err != MPC_STATUS_OK) {
        GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
        GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
        goto pause_task;
    } else if (frame.bits == -1) {
        goto eos_and_pause;
    }

    num_samples = frame.samples;
#endif

    GST_BUFFER_SIZE (out) = num_samples * bitspersample;

    GST_BUFFER_OFFSET (out) = musepackdec->segment.last_stop;
    GST_BUFFER_TIMESTAMP (out) =
        gst_util_uint64_scale_int (musepackdec->segment.last_stop,
                                   GST_SECOND, samplerate);
    GST_BUFFER_DURATION (out) =
        gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate);

    musepackdec->segment.last_stop += num_samples;

    GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
                    GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));

    flow = gst_pad_push (musepackdec->srcpad, out);
    if (flow != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
        goto pause_task;
    }

    /* check if we're at the end of a configured segment */
    if (musepackdec->segment.stop != -1 &&
            musepackdec->segment.last_stop >= musepackdec->segment.stop) {
        gint64 stop_time;

        GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment");

        if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0)
            goto eos_and_pause;

        GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message");

        stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop,
                                               GST_SECOND, samplerate);

        gst_element_post_message (GST_ELEMENT (musepackdec),
                                  gst_message_new_segment_done (GST_OBJECT (musepackdec),
                                          GST_FORMAT_TIME, stop_time));

        goto pause_task;
    }

    return;

eos_and_pause:
    {
        GST_DEBUG_OBJECT (musepackdec, "sending EOS event");
        gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
        /* fall through to pause */
    }

pause_task:
    {
        GST_DEBUG_OBJECT (musepackdec, "Pausing task");
        gst_pad_pause_task (sinkpad);
        return;
    }
}
Ejemplo n.º 8
0
SegmentDoneMessagePtr SegmentDoneMessage::create(const ObjectPtr & source, Format format, qint64 position)
{
    GstMessage *m = gst_message_new_segment_done(source, static_cast<GstFormat>(format), position);
    return SegmentDoneMessagePtr::wrap(m, false);
}
Ejemplo n.º 9
0
static void
gst_real_audio_demux_loop (GstRealAudioDemux * demux)
{
  GstFlowReturn ret;
  GstBuffer *buf;
  guint bytes_needed;

  /* check how much data we need */
  switch (demux->state) {
    case REAL_AUDIO_DEMUX_STATE_MARKER:
      bytes_needed = 6 + 16;    /* 16 are beginning of header */
      break;
    case REAL_AUDIO_DEMUX_STATE_HEADER:
      if (!gst_real_audio_demux_get_data_offset_from_header (demux))
        goto parse_header_error;
      bytes_needed = demux->data_offset - (6 + 16);
      break;
    case REAL_AUDIO_DEMUX_STATE_DATA:
      if (demux->packet_size > 0) {
        /* TODO: should probably take into account width/height as well? */
        bytes_needed = demux->packet_size;
      } else {
        bytes_needed = 1024;
      }
      break;
    default:
      g_return_if_reached ();
  }

  /* now get the data */
  GST_LOG_OBJECT (demux, "getting data: %5u bytes @ %8" G_GINT64_MODIFIER "u",
      bytes_needed, demux->offset);

  if (demux->upstream_size > 0 && demux->offset >= demux->upstream_size)
    goto eos;

  ret = gst_pad_pull_range (demux->sinkpad, demux->offset, bytes_needed, &buf);

  if (ret != GST_FLOW_OK)
    goto pull_range_error;

  if (GST_BUFFER_SIZE (buf) != bytes_needed)
    goto pull_range_short_read;

  ret = gst_real_audio_demux_handle_buffer (demux, buf);
  if (ret != GST_FLOW_OK)
    goto handle_flow_error;

  /* TODO: increase this in chain function too (for timestamps)? */
  demux->offset += bytes_needed;

  /* check for the end of the segment */
  if (demux->segment.stop != -1 && demux->segment.last_stop != -1 &&
      demux->segment.last_stop > demux->segment.stop) {
    GST_DEBUG_OBJECT (demux, "reached end of segment");
    goto eos;
  }

  return;

/* ERRORS */
parse_header_error:
  {
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), (NULL));
    goto pause_task;
  }
handle_flow_error:
  {
    GST_WARNING_OBJECT (demux, "handle_buf flow: %s", gst_flow_get_name (ret));
    goto pause_task;
  }
pull_range_error:
  {
    GST_WARNING_OBJECT (demux, "pull range flow: %s", gst_flow_get_name (ret));
    goto pause_task;
  }
pull_range_short_read:
  {
    GST_WARNING_OBJECT (demux, "pull range short read: wanted %u bytes, but "
        "got only %u bytes", bytes_needed, GST_BUFFER_SIZE (buf));
    gst_buffer_unref (buf);
    goto eos;
  }
eos:
  {
    if (demux->state != REAL_AUDIO_DEMUX_STATE_DATA) {
      GST_WARNING_OBJECT (demux, "reached EOS before finished parsing header");
      goto parse_header_error;
    }
    GST_INFO_OBJECT (demux, "EOS");
    if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
      gint64 stop;

      /* for segment playback we need to post when (in stream time)
       * we stopped, this is either stop (when set) or the duration. */
      if ((stop = demux->segment.stop) == -1)
        stop = demux->segment.duration;

      GST_DEBUG_OBJECT (demux, "sending segment done, at end of segment");
      gst_element_post_message (GST_ELEMENT (demux),
          gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
              stop));
    } else {
      /* normal playback, send EOS event downstream */
      GST_DEBUG_OBJECT (demux, "sending EOS event, at end of stream");
      gst_pad_push_event (demux->srcpad, gst_event_new_eos ());
    }
    goto pause_task;
  }
pause_task:
  {
    demux->segment_running = FALSE;
    gst_pad_pause_task (demux->sinkpad);
    GST_DEBUG_OBJECT (demux, "pausing task");
    return;
  }
}
Ejemplo n.º 10
0
static void
gst_wavpack_parse_loop (GstElement * element)
{
  GstWavpackParse *parse = GST_WAVPACK_PARSE (element);

  GstFlowReturn flow_ret;
  WavpackHeader header = { {0,}, 0, };
  GstBuffer *buf = NULL;

  flow_ret = gst_wavpack_parse_resync_loop (parse, &header);

  if (flow_ret != GST_FLOW_OK)
    goto pause;

  GST_LOG_OBJECT (parse, "Read header at offset %" G_GINT64_FORMAT
      ": chunk size = %u+8", parse->current_offset, header.ckSize);

  buf = gst_wavpack_parse_pull_buffer (parse, parse->current_offset,
      header.ckSize + 8, &flow_ret);

  if (flow_ret != GST_FLOW_OK)
    goto pause;

  if (parse->srcpad == NULL) {
    if (!gst_wavpack_parse_create_src_pad (parse, buf, &header)) {
      GST_ERROR_OBJECT (parse, "Failed to create src pad");
      flow_ret = GST_FLOW_ERROR;
      goto pause;
    }
  }
  if (header.flags & INITIAL_BLOCK)
    gst_wavpack_parse_index_append_entry (parse, parse->current_offset,
        header.block_index, header.block_samples);

  flow_ret = gst_wavpack_parse_push_buffer (parse, buf, &header);
  if (flow_ret != GST_FLOW_OK)
    goto pause;

  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (flow_ret);

    GST_LOG_OBJECT (parse, "pausing task, reason %s", reason);
    gst_pad_pause_task (parse->sinkpad);

    if (GST_FLOW_IS_FATAL (flow_ret) || flow_ret == GST_FLOW_NOT_LINKED) {
      if (flow_ret == GST_FLOW_UNEXPECTED && parse->srcpad) {
        if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
          GstClockTime stop;

          GST_LOG_OBJECT (parse, "Sending segment done");

          if ((stop = parse->segment.stop) == -1)
            stop = parse->segment.duration;

          gst_element_post_message (GST_ELEMENT_CAST (parse),
              gst_message_new_segment_done (GST_OBJECT_CAST (parse),
                  parse->segment.format, stop));
        } else {
          GST_LOG_OBJECT (parse, "Sending EOS, at end of stream");
          gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
        }
      } else {
        GST_ELEMENT_ERROR (parse, STREAM, FAILED,
            (_("Internal data stream error.")),
            ("stream stopped, reason %s", reason));
        if (parse->srcpad)
          gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
      }
    }
    return;
  }
}
Ejemplo n.º 11
0
static void
gst_image_freeze_src_loop (GstPad * pad)
{
    GstImageFreeze *self = GST_IMAGE_FREEZE (GST_PAD_PARENT (pad));
    GstBuffer *buffer;
    guint64 offset;
    GstClockTime timestamp, timestamp_end;
    guint64 cstart, cstop;
    gboolean in_seg, eos;
    GstFlowReturn flow_ret = GST_FLOW_OK;

    g_mutex_lock (&self->lock);
    if (!gst_pad_has_current_caps (self->srcpad)) {
        GST_ERROR_OBJECT (pad, "Not negotiated yet");
        flow_ret = GST_FLOW_NOT_NEGOTIATED;
        g_mutex_unlock (&self->lock);
        goto pause_task;
    }

    if (!self->buffer) {
        GST_ERROR_OBJECT (pad, "Have no buffer yet");
        flow_ret = GST_FLOW_ERROR;
        g_mutex_unlock (&self->lock);
        goto pause_task;
    }
    buffer = gst_buffer_ref (self->buffer);
    buffer = gst_buffer_make_writable (buffer);
    g_mutex_unlock (&self->lock);

    if (self->need_segment) {
        GstEvent *e;

        GST_DEBUG_OBJECT (pad, "Pushing SEGMENT event: %" GST_SEGMENT_FORMAT,
                          &self->segment);
        e = gst_event_new_segment (&self->segment);

        g_mutex_lock (&self->lock);
        if (self->segment.rate >= 0) {
            self->offset =
                gst_util_uint64_scale (self->segment.start, self->fps_n,
                                       self->fps_d * GST_SECOND);
        } else {
            self->offset =
                gst_util_uint64_scale (self->segment.stop, self->fps_n,
                                       self->fps_d * GST_SECOND);
        }
        g_mutex_unlock (&self->lock);

        self->need_segment = FALSE;

        gst_pad_push_event (self->srcpad, e);
    }

    g_mutex_lock (&self->lock);
    offset = self->offset;

    if (self->fps_n != 0) {
        timestamp =
            gst_util_uint64_scale (offset, self->fps_d * GST_SECOND, self->fps_n);
        timestamp_end =
            gst_util_uint64_scale (offset + 1, self->fps_d * GST_SECOND,
                                   self->fps_n);
    } else {
        timestamp = self->segment.start;
        timestamp_end = GST_CLOCK_TIME_NONE;
    }

    eos = (self->fps_n == 0 && offset > 0) ||
          (self->segment.rate >= 0 && self->segment.stop != -1
           && timestamp > self->segment.stop) || (self->segment.rate < 0
                   && offset == 0) || (self->segment.rate < 0
                                       && self->segment.start != -1 && timestamp_end < self->segment.start);

    if (self->fps_n == 0 && offset > 0)
        in_seg = FALSE;
    else
        in_seg =
            gst_segment_clip (&self->segment, GST_FORMAT_TIME, timestamp,
                              timestamp_end, &cstart, &cstop);

    if (in_seg) {
        self->segment.position = cstart;
        if (self->segment.rate >= 0)
            self->segment.position = cstop;
    }

    if (self->segment.rate >= 0)
        self->offset++;
    else
        self->offset--;
    g_mutex_unlock (&self->lock);

    GST_DEBUG_OBJECT (pad, "Handling buffer with timestamp %" GST_TIME_FORMAT,
                      GST_TIME_ARGS (timestamp));

    if (in_seg) {
        GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE;
        GST_BUFFER_PTS (buffer) = cstart;
        GST_BUFFER_DURATION (buffer) = cstop - cstart;
        GST_BUFFER_OFFSET (buffer) = offset;
        GST_BUFFER_OFFSET_END (buffer) = offset + 1;
        flow_ret = gst_pad_push (self->srcpad, buffer);
        GST_DEBUG_OBJECT (pad, "Pushing buffer resulted in %s",
                          gst_flow_get_name (flow_ret));
        if (flow_ret != GST_FLOW_OK)
            goto pause_task;
    } else {
        gst_buffer_unref (buffer);
    }

    if (eos) {
        flow_ret = GST_FLOW_EOS;
        goto pause_task;
    }

    return;

pause_task:
    {
        const gchar *reason = gst_flow_get_name (flow_ret);

        GST_LOG_OBJECT (self, "pausing task, reason %s", reason);
        gst_pad_pause_task (pad);

        if (flow_ret == GST_FLOW_EOS) {
            if ((self->segment.flags & GST_SEEK_FLAG_SEGMENT)) {
                GstMessage *m;
                GstEvent *e;

                GST_DEBUG_OBJECT (pad, "Sending segment done at end of segment");
                if (self->segment.rate >= 0) {
                    m = gst_message_new_segment_done (GST_OBJECT_CAST (self),
                                                      GST_FORMAT_TIME, self->segment.stop);
                    e = gst_event_new_segment_done (GST_FORMAT_TIME, self->segment.stop);
                } else {
                    m = gst_message_new_segment_done (GST_OBJECT_CAST (self),
                                                      GST_FORMAT_TIME, self->segment.start);
                    e = gst_event_new_segment_done (GST_FORMAT_TIME, self->segment.start);
                }
                gst_element_post_message (GST_ELEMENT_CAST (self), m);
                gst_pad_push_event (self->srcpad, e);
            } else {
                GST_DEBUG_OBJECT (pad, "Sending EOS at end of segment");
                gst_pad_push_event (self->srcpad, gst_event_new_eos ());
            }
        } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
            GST_ELEMENT_ERROR (self, STREAM, FAILED,
                               ("Internal data stream error."),
                               ("stream stopped, reason %s", reason));
            gst_pad_push_event (self->srcpad, gst_event_new_eos ());
        }
        return;
    }
}