Beispiel #1
0
static void
user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
{
  GstPngDec *pngdec;
  GstBuffer *buffer;
  GstFlowReturn ret = GST_FLOW_OK;

  pngdec = GST_PNGDEC (png_ptr->io_ptr);

  GST_LOG ("reading %" G_GSIZE_FORMAT " bytes of data at offset %d", length,
      pngdec->offset);

  ret = gst_pad_pull_range (pngdec->sinkpad, pngdec->offset, length, &buffer);
  if ((ret != GST_FLOW_OK) || (GST_BUFFER_SIZE (buffer) != length))
    goto pause;

  memcpy (data, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));

  gst_buffer_unref (buffer);

  pngdec->offset += length;

  return;

pause:
  GST_INFO_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret));
  gst_pad_pause_task (pngdec->sinkpad);
  if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
    gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
    GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
        (_("Internal data stream error.")),
        ("stream stopped, reason %s", gst_flow_get_name (ret)));
  }
}
Beispiel #2
0
static GstFlowReturn
gst_cmml_enc_push_clip (GstCmmlEnc * enc, GstCmmlTagClip * clip,
    GstClockTime prev_clip_time)
{
  GstFlowReturn res;
  GstBuffer *buffer;
  gchar *clip_string;
  gint64 granulepos;

  /* encode the clip */
  clip_string =
      (gchar *) gst_cmml_parser_tag_clip_to_string (enc->parser, clip);

  res = gst_cmml_enc_new_buffer (enc,
      (guchar *) clip_string, strlen (clip_string), &buffer);
  g_free (clip_string);
  if (res != GST_FLOW_OK)
    goto done;

  GST_INFO_OBJECT (enc, "encoding clip"
      "(start-time: %" GST_TIME_FORMAT " end-time: %" GST_TIME_FORMAT,
      GST_TIME_ARGS (clip->start_time), GST_TIME_ARGS (clip->end_time));

  /* set the granulepos */
  granulepos = gst_cmml_clock_time_to_granule (prev_clip_time, clip->start_time,
      enc->granulerate_n, enc->granulerate_d, enc->granuleshift);
  if (granulepos == -1) {
    gst_buffer_unref (buffer);
    goto granule_overflow;
  }

  GST_BUFFER_OFFSET (buffer) = clip->start_time;
  GST_BUFFER_OFFSET_END (buffer) = granulepos;
  GST_BUFFER_TIMESTAMP (buffer) = clip->start_time;

  res = gst_cmml_enc_push (enc, buffer);
  if (GST_FLOW_IS_FATAL (res))
    goto done;

  if (clip->end_time != GST_CLOCK_TIME_NONE) {
    /* create a new empty clip for the same cmml track starting at end_time
     */
    GObject *end_clip = g_object_new (GST_TYPE_CMML_TAG_CLIP,
        "start-time", clip->end_time, "track", clip->track, NULL);

    /* encode the empty end clip */
    gst_cmml_enc_push_clip (enc, GST_CMML_TAG_CLIP (end_clip),
        clip->start_time);
    g_object_unref (end_clip);
  }
done:
  return res;

granule_overflow:
  GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), ("granulepos overflow"));
  return GST_FLOW_ERROR;
}
static GstFlowReturn
gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer)
{
  GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad);
  bool discont = FALSE;
  GstClockTime stop;

  if (!vdec->setup) {
    /* we are not setup */
    GST_WARNING_OBJECT (vdec, "Decoder not set up, failing");
    vdec->last_ret = GST_FLOW_FLUSHING;
    goto beach;
  }

  if (GST_FLOW_IS_FATAL (vdec->last_ret)) {
    GST_DEBUG_OBJECT (vdec, "last decoding iteration generated a fatal error "
        "%s", gst_flow_get_name (vdec->last_ret));
    goto beach;
  }

  /* check if duration is valid and use duration only when it's valid
     /* because dshow is not decoding frames having stop smaller than start */
  if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
    stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
  } else {
    stop = GST_BUFFER_TIMESTAMP (buffer);
  }

  GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec,
      "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT,
      GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
      GST_TIME_ARGS (stop));

  /* if the incoming buffer has discont flag set => flush decoder data */
  if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec,
        "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing",
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
    gst_dshowvideodec_flush (vdec);
    discont = TRUE;
  }

  /* push the buffer to the directshow decoder */
  vdec->fakesrc->GetOutputPin()->PushBuffer(
      GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), stop,
      GST_BUFFER_SIZE (buffer), discont);

beach:
  gst_buffer_unref (buffer);
  gst_object_unref (vdec);

  return vdec->last_ret;
}
Beispiel #4
0
static GstFlowReturn
gst_cmml_enc_push (GstCmmlEnc * enc, GstBuffer * buffer)
{
  GstFlowReturn res;

  /* FIXME: hack to make oggmux flush every cmml tag in its own page */
  GST_BUFFER_DURATION (buffer) = G_MAXINT64;

  res = gst_pad_push (enc->srcpad, buffer);
  if (GST_FLOW_IS_FATAL (res))
    GST_WARNING_OBJECT (enc, "push returned: %s", gst_flow_get_name (res));

  return res;
}
static GstFlowReturn
gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer)
{
  GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad);
  bool discont = FALSE;

  if (!adec->setup) {
    /* we are not set up */
    GST_WARNING_OBJECT (adec, "Decoder not set up, failing");
    adec->last_ret = GST_FLOW_WRONG_STATE;
    goto beach;
  }

  if (GST_FLOW_IS_FATAL (adec->last_ret)) {
    GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error "
        "%s", gst_flow_get_name (adec->last_ret));
    goto beach;
  }

  GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "chain (size %d)=> pts %"
      GST_TIME_FORMAT " stop %" GST_TIME_FORMAT,
      GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) +
          GST_BUFFER_DURATION (buffer)));

  /* if the incoming buffer has discont flag set => flush decoder data */
  if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec,
        "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing",
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
    gst_dshowaudiodec_flush (adec);
    discont = TRUE;
  }

  /* push the buffer to the directshow decoder */
  adec->fakesrc->GetOutputPin()->PushBuffer (
      GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer),
      GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
      GST_BUFFER_SIZE (buffer), (bool)discont);

beach:
  gst_buffer_unref (buffer);
  gst_object_unref (adec);
  return adec->last_ret;
}
Beispiel #6
0
/* encode the CMML head tag and push the CMML headers
 */
static void
gst_cmml_enc_parse_tag_head (GstCmmlEnc * enc, GstCmmlTagHead * head)
{
  GList *headers = NULL;
  GList *walk;
  guchar *head_string;
  GstCaps *caps;
  GstBuffer *ident_buf, *preamble_buf, *head_buf;
  GstBuffer *buffer;

  if (enc->preamble == NULL)
    goto flow_unexpected;

  GST_INFO_OBJECT (enc, "parsing head tag");

  enc->flow_return = gst_cmml_enc_new_ident_header (enc, &ident_buf);
  if (enc->flow_return != GST_FLOW_OK)
    goto alloc_error;
  headers = g_list_append (headers, ident_buf);

  enc->flow_return = gst_cmml_enc_new_buffer (enc,
      enc->preamble, strlen ((gchar *) enc->preamble), &preamble_buf);
  if (enc->flow_return != GST_FLOW_OK)
    goto alloc_error;
  headers = g_list_append (headers, preamble_buf);

  head_string = gst_cmml_parser_tag_head_to_string (enc->parser, head);
  enc->flow_return = gst_cmml_enc_new_buffer (enc,
      head_string, strlen ((gchar *) head_string), &head_buf);
  g_free (head_string);
  if (enc->flow_return != GST_FLOW_OK)
    goto alloc_error;
  headers = g_list_append (headers, head_buf);

  caps = gst_pad_get_caps (enc->srcpad);
  caps = gst_cmml_enc_set_header_on_caps (enc, caps,
      ident_buf, preamble_buf, head_buf);

  while (headers) {
    buffer = GST_BUFFER (headers->data);
    /* set granulepos 0 on headers */
    GST_BUFFER_OFFSET_END (buffer) = 0;
    gst_buffer_set_caps (buffer, caps);

    enc->flow_return = gst_cmml_enc_push (enc, buffer);
    headers = g_list_delete_link (headers, headers);

    if (GST_FLOW_IS_FATAL (enc->flow_return))
      goto push_error;
  }

  gst_caps_unref (caps);

  enc->sent_headers = TRUE;
  return;

flow_unexpected:
  GST_ELEMENT_ERROR (enc, STREAM, ENCODE,
      (NULL), ("got head tag before preamble"));
  enc->flow_return = GST_FLOW_ERROR;
  return;
push_error:
  gst_caps_unref (caps);
  /* fallthrough */
alloc_error:
  for (walk = headers; walk; walk = walk->next)
    gst_buffer_unref (GST_BUFFER (walk->data));
  g_list_free (headers);
  return;
}
Beispiel #7
0
static void
gst_pngdec_task (GstPad * pad)
{
  GstPngDec *pngdec;
  GstBuffer *buffer = NULL;
  size_t buffer_size = 0;
  gint i = 0;
  png_bytep *rows, inp;
  png_uint_32 rowbytes;
  GstFlowReturn ret = GST_FLOW_OK;

  pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad));

  GST_LOG_OBJECT (pngdec, "read frame");

  /* Let libpng come back here on error */
  if (setjmp (png_jmpbuf (pngdec->png))) {
    ret = GST_FLOW_ERROR;
    goto pause;
  }

  /* Set reading callback */
  png_set_read_fn (pngdec->png, pngdec, user_read_data);

  /* Read info */
  png_read_info (pngdec->png, pngdec->info);

  /* Generate the caps and configure */
  ret = gst_pngdec_caps_create_and_set (pngdec);
  if (ret != GST_FLOW_OK) {
    goto pause;
  }

  /* Allocate output buffer */
  rowbytes = png_get_rowbytes (pngdec->png, pngdec->info);
  if (rowbytes > (G_MAXUINT32 - 3) || pngdec->height > G_MAXUINT32 / rowbytes) {
    ret = GST_FLOW_ERROR;
    goto pause;
  }
  rowbytes = GST_ROUND_UP_4 (rowbytes);
  buffer_size = pngdec->height * rowbytes;
  ret =
      gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE,
      buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer);
  if (ret != GST_FLOW_OK)
    goto pause;

  rows = (png_bytep *) g_malloc (sizeof (png_bytep) * pngdec->height);

  inp = GST_BUFFER_DATA (buffer);

  for (i = 0; i < pngdec->height; i++) {
    rows[i] = inp;
    inp += rowbytes;
  }

  /* Read the actual picture */
  png_read_image (pngdec->png, rows);
  g_free (rows);

  /* Push the raw RGB frame */
  ret = gst_pad_push (pngdec->srcpad, buffer);
  if (ret != GST_FLOW_OK)
    goto pause;

  /* And we are done */
  gst_pad_pause_task (pngdec->sinkpad);
  gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
  return;

pause:
  {
    GST_INFO_OBJECT (pngdec, "pausing task, reason %s",
        gst_flow_get_name (ret));
    gst_pad_pause_task (pngdec->sinkpad);
    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
      GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
          (_("Internal data stream error.")),
          ("stream stopped, reason %s", gst_flow_get_name (ret)));
      gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
    }
  }
}
Beispiel #8
0
static void
gst_timidity_loop (GstPad * sinkpad)
{
  GstTimidity *timidity = GST_TIMIDITY (GST_PAD_PARENT (sinkpad));
  GstBuffer *out;
  GstFlowReturn ret;

  if (timidity->mididata_size == 0) {
    if (!gst_timidity_get_upstream_size (timidity, &timidity->mididata_size)) {
      GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL),
          ("Unable to get song length"));
      goto paused;
    }

    if (timidity->mididata)
      g_free (timidity->mididata);

    timidity->mididata = g_malloc (timidity->mididata_size);
    timidity->mididata_offset = 0;
    return;
  }

  if (timidity->mididata_offset < timidity->mididata_size) {
    GstBuffer *buffer;
    gint64 size;

    GST_DEBUG_OBJECT (timidity, "loading song");

    ret =
        gst_pad_pull_range (timidity->sinkpad, timidity->mididata_offset,
        -1, &buffer);
    if (ret != GST_FLOW_OK) {
      GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL),
          ("Unable to load song"));
      goto paused;
    }

    size = timidity->mididata_size - timidity->mididata_offset;
    if (GST_BUFFER_SIZE (buffer) < size)
      size = GST_BUFFER_SIZE (buffer);

    memmove (timidity->mididata + timidity->mididata_offset,
        GST_BUFFER_DATA (buffer), size);
    gst_buffer_unref (buffer);

    timidity->mididata_offset += size;
    GST_DEBUG_OBJECT (timidity, "Song loaded");
    return;
  }

  if (!timidity->song) {
    MidIStream *stream;
    GstTagList *tags = NULL;
    gchar *text;

    GST_DEBUG_OBJECT (timidity, "Parsing song");

    stream =
        mid_istream_open_mem (timidity->mididata, timidity->mididata_size, 0);

    timidity->song = mid_song_load (stream, timidity->song_options);
    mid_istream_close (stream);

    if (!timidity->song) {
      GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL),
          ("Unable to parse midi"));
      goto paused;
    }

    mid_song_start (timidity->song);
    timidity->o_len = (GST_MSECOND *
        (GstClockTime) mid_song_get_total_time (timidity->song)) /
        timidity->time_per_frame;
    gst_segment_set_newsegment (timidity->o_segment, FALSE, 1.0,
        GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0);


    gst_pad_push_event (timidity->srcpad,
        gst_timidity_get_new_segment_event (timidity, GST_FORMAT_TIME, FALSE));

    /* extract tags */
    text = mid_song_get_meta (timidity->song, MID_SONG_TEXT);
    if (text) {
      tags = gst_tag_list_new ();
      gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, NULL);

      //g_free (text);
    }

    text = mid_song_get_meta (timidity->song, MID_SONG_COPYRIGHT);
    if (text) {
      if (tags == NULL)
        tags = gst_tag_list_new ();
      gst_tag_list_add (tags, GST_TAG_MERGE_APPEND,
          GST_TAG_COPYRIGHT, text, NULL);

      //g_free (text);
    }

    if (tags) {
      gst_element_found_tags (GST_ELEMENT (timidity), tags);
    }

    GST_DEBUG_OBJECT (timidity, "Parsing song done");
    return;
  }

  if (timidity->o_segment_changed) {
    GstSegment *segment = gst_timidity_get_segment (timidity, GST_FORMAT_TIME,
        !timidity->o_new_segment);

    GST_LOG_OBJECT (timidity,
        "sending newsegment from %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT
        ", pos=%" GST_TIME_FORMAT, GST_TIME_ARGS ((guint64) segment->start),
        GST_TIME_ARGS ((guint64) segment->stop),
        GST_TIME_ARGS ((guint64) segment->time));

    if (timidity->o_segment->flags & GST_SEEK_FLAG_SEGMENT) {
      gst_element_post_message (GST_ELEMENT (timidity),
          gst_message_new_segment_start (GST_OBJECT (timidity),
              segment->format, segment->start));
    }

    gst_segment_free (segment);
    timidity->o_segment_changed = FALSE;
    return;
  }

  if (timidity->o_seek) {
    /* perform a seek internally */
    timidity->o_segment->last_stop = timidity->o_segment->time;
    mid_song_seek (timidity->song,
        (timidity->o_segment->last_stop * timidity->time_per_frame) /
        GST_MSECOND);
  }

  out = gst_timidity_get_buffer (timidity);
  if (!out) {
    GST_LOG_OBJECT (timidity, "Song ended, generating eos");
    gst_pad_push_event (timidity->srcpad, gst_event_new_eos ());
    timidity->o_seek = FALSE;
    goto paused;
  }

  if (timidity->o_seek) {
    GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT);
    timidity->o_seek = FALSE;
  }

  gst_buffer_set_caps (out, timidity->out_caps);
  ret = gst_pad_push (timidity->srcpad, out);

  if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED)
    goto error;

  return;

paused:
  {
    GST_DEBUG_OBJECT (timidity, "pausing task");
    gst_pad_pause_task (timidity->sinkpad);
    return;
  }
error:
  {
    GST_ELEMENT_ERROR (timidity, STREAM, FAILED,
        ("Internal data stream error"),
        ("Streaming stopped, reason %s", gst_flow_get_name (ret)));
    gst_pad_push_event (timidity->srcpad, gst_event_new_eos ());
    goto paused;
  }
}
static GstFlowReturn
gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer)
{
  GstFlowReturn result = GST_FLOW_OK;
  GstOggAviParse *ogg;
  guint8 *data;
  guint size;
  gchar *oggbuf;
  gint ret = -1;

  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));

  data = GST_BUFFER_DATA (buffer);
  size = GST_BUFFER_SIZE (buffer);

  GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size);

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    ogg_sync_reset (&ogg->sync);
    ogg->discont = TRUE;
  }

  /* write data to sync layer */
  oggbuf = ogg_sync_buffer (&ogg->sync, size);
  memcpy (oggbuf, data, size);
  ogg_sync_wrote (&ogg->sync, size);
  gst_buffer_unref (buffer);

  /* try to get as many packets out of the stream as possible */
  do {
    ogg_page page;

    /* try to swap out a page */
    ret = ogg_sync_pageout (&ogg->sync, &page);
    if (ret == 0) {
      GST_DEBUG_OBJECT (ogg, "need more data");
      break;
    } else if (ret == -1) {
      GST_DEBUG_OBJECT (ogg, "discont in pages");
      ogg->discont = TRUE;
    } else {
      /* new unknown stream, init the ogg stream with the serial number of the
       * page. */
      if (ogg->serial == -1) {
        ogg->serial = ogg_page_serialno (&page);
        ogg_stream_init (&ogg->stream, ogg->serial);
      }

      /* submit page */
      if (ogg_stream_pagein (&ogg->stream, &page) != 0) {
        GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream");
        ogg_sync_reset (&ogg->sync);
        ogg->discont = TRUE;
        continue;
      }

      /* try to get as many packets as possible out of the page */
      do {
        ogg_packet packet;

        ret = ogg_stream_packetout (&ogg->stream, &packet);
        GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
        switch (ret) {
          case 0:
            break;
          case -1:
            /* out of sync, We mark a DISCONT. */
            ogg->discont = TRUE;
            break;
          case 1:
            result = gst_ogg_avi_parse_push_packet (ogg, &packet);
            if (GST_FLOW_IS_FATAL (result))
              goto done;
            break;
          default:
            GST_WARNING_OBJECT (ogg,
                "invalid return value %d for ogg_stream_packetout, resetting stream",
                ret);
            break;
        }
      }
      while (ret != 0);
    }
  }
  while (ret != 0);

done:
  return result;
}
Beispiel #10
0
static void
spc_play (GstPad * pad)
{
  GstSpcDec *spc = GST_SPC_DEC (gst_pad_get_parent (pad));
  GstFlowReturn flow_return;
  GstBuffer *out;
  gboolean seeking = spc->seeking;
  gint64 duration, fade, end, position;

  if (!seeking) {
    out = gst_buffer_new_and_alloc (1600 * 4);
    gst_buffer_set_caps (out, GST_PAD_CAPS (pad));
    GST_BUFFER_TIMESTAMP (out) =
        (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND,
        32000 * 2 * 2);
    spc->byte_pos += OSPC_Run (-1, (short *) GST_BUFFER_DATA (out), 1600 * 4);
  } else {
    if (spc->seekpoint < spc->byte_pos) {
      OSPC_Init (GST_BUFFER_DATA (spc->buf), GST_BUFFER_SIZE (spc->buf));
      spc->byte_pos = 0;
    }
    spc->byte_pos += OSPC_Run (-1, NULL, 1600 * 4);
    if (spc->byte_pos >= spc->seekpoint) {
      spc->seeking = FALSE;
    }
    out = gst_buffer_new ();
    gst_buffer_set_caps (out, GST_PAD_CAPS (pad));
  }

  duration = gst_spc_duration (spc);
  fade = gst_spc_fadeout (spc);
  end = duration + fade;
  position =
      (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND,
      32000 * 2 * 2);

  if (position >= duration) {
    gint16 *data = (gint16 *) GST_BUFFER_DATA (out);
    guint32 size = GST_BUFFER_SIZE (out) / sizeof (gint16);
    unsigned int i;

    gint64 num = (fade - (position - duration));

    for (i = 0; i < size; i++) {
      /* Apply a parabolic volume envelope */
      data[i] = (gint16) (data[i] * num / fade * num / fade);
    }
  }

  if ((flow_return = gst_pad_push (spc->srcpad, out)) != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (spc, "pausing task, reason %s",
        gst_flow_get_name (flow_return));

    gst_pad_pause_task (pad);

    if (GST_FLOW_IS_FATAL (flow_return) || flow_return == GST_FLOW_NOT_LINKED) {
      gst_pad_push_event (pad, gst_event_new_eos ());
    }
  }

  if (position >= end) {
    gst_pad_pause_task (pad);
    gst_pad_push_event (pad, gst_event_new_eos ());
  }

  gst_object_unref (spc);

  return;
}
Beispiel #11
0
static GstFlowReturn
gst_nuv_demux_play (GstPad * pad)
{
  GstFlowReturn res = GST_FLOW_OK;
  GstNuvDemux *nuv = GST_NUV_DEMUX (GST_PAD_PARENT (pad));

  switch (nuv->state) {
    case GST_NUV_DEMUX_START:
      res = gst_nuv_demux_stream_file_header (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }
      if (nuv->state != GST_NUV_DEMUX_HEADER_DATA)
        break;

    case GST_NUV_DEMUX_HEADER_DATA:
      res = gst_nuv_demux_stream_header_data (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }
      if (nuv->state != GST_NUV_DEMUX_EXTRA_DATA)
        break;

    case GST_NUV_DEMUX_EXTRA_DATA:
      res = gst_nuv_demux_stream_extra_data (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }
      if (nuv->state != GST_NUV_DEMUX_MPEG_DATA)
        break;

    case GST_NUV_DEMUX_MPEG_DATA:
      res = gst_nuv_demux_stream_mpeg_data (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }

      if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER)
        break;

    case GST_NUV_DEMUX_EXTEND_HEADER:
      res = gst_nuv_demux_stream_extend_header (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }
      if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER_DATA)
        break;

    case GST_NUV_DEMUX_EXTEND_HEADER_DATA:
      res = gst_nuv_demux_stream_extend_header_data (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }

      if (nuv->state != GST_NUV_DEMUX_FRAME_HEADER)
        break;

    case GST_NUV_DEMUX_FRAME_HEADER:
      res = gst_nuv_demux_read_head_frame (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
        goto pause;
      }
      if (nuv->state != GST_NUV_DEMUX_MOVI)
        break;

    case GST_NUV_DEMUX_MOVI:
      res = gst_nuv_demux_stream_data (nuv);
      if ((res != GST_FLOW_OK) && (res != GST_FLOW_CUSTOM_ERROR)) {
        goto pause;
      }
      break;
    case GST_NUV_DEMUX_INVALID_DATA:
      goto pause;
      break;
    default:
      g_assert_not_reached ();
  }

  GST_DEBUG_OBJECT (nuv, "state: %d res:%s", nuv->state,
      gst_flow_get_name (res));

  return GST_FLOW_OK;

pause:
  GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res));
  gst_pad_pause_task (nuv->sinkpad);
  if (GST_FLOW_IS_FATAL (res)) {
    GST_ELEMENT_ERROR (nuv, STREAM, FAILED,
        (_("Internal data stream error.")),
        ("streaming stopped, reason %s", gst_flow_get_name (res)));

    gst_nuv_demux_send_eos (nuv);
  }
  return res;
}
Beispiel #12
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;
  }
}
Beispiel #13
0
static void
gst_wildmidi_loop (GstPad * sinkpad)
{
  GstWildmidi *wildmidi = GST_WILDMIDI (GST_PAD_PARENT (sinkpad));
  GstFlowReturn ret;

  switch (wildmidi->state) {
    case GST_WILDMIDI_STATE_LOAD:
    {
      GstBuffer *buffer;

      GST_DEBUG_OBJECT (wildmidi, "loading song");

      ret =
          gst_pad_pull_range (wildmidi->sinkpad, wildmidi->offset, -1, &buffer);

      if (ret == GST_FLOW_UNEXPECTED) {
        GST_DEBUG_OBJECT (wildmidi, "Song loaded");
        wildmidi->state = GST_WILDMIDI_STATE_PARSE;
      } else if (ret != GST_FLOW_OK) {
        GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL),
            ("Unable to read song"));
        goto pause;
      } else {
        GST_DEBUG_OBJECT (wildmidi, "pushing buffer");
        gst_adapter_push (wildmidi->adapter, buffer);
        wildmidi->offset += GST_BUFFER_SIZE (buffer);
      }
      break;
    }
    case GST_WILDMIDI_STATE_PARSE:
      ret = gst_wildmidi_parse_song (wildmidi);
      if (ret != GST_FLOW_OK)
        goto pause;
      wildmidi->state = GST_WILDMIDI_STATE_PLAY;
      break;
    case GST_WILDMIDI_STATE_PLAY:
      ret = gst_wildmidi_do_play (wildmidi);
      if (ret != GST_FLOW_OK)
        goto pause;
      break;
    default:
      break;
  }
  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (ret);
    GstEvent *event;

    GST_DEBUG_OBJECT (wildmidi, "pausing task, reason %s", reason);
    gst_pad_pause_task (sinkpad);
    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
      if (ret == GST_FLOW_UNEXPECTED) {
        /* perform EOS logic */
        event = gst_event_new_eos ();
        gst_pad_push_event (wildmidi->srcpad, event);
      } else {
        event = gst_event_new_eos ();
        /* for fatal errors we post an error message, post the error
         * first so the app knows about the error first. */
        GST_ELEMENT_ERROR (wildmidi, STREAM, FAILED,
            ("Internal data flow error."),
            ("streaming task paused, reason %s (%d)", reason, ret));
        gst_pad_push_event (wildmidi->srcpad, event);
      }
    }
  }
}
Beispiel #14
0
static void
gst_aiffparse_loop (GstPad * pad)
{
  GstFlowReturn ret;
  AIFFParse *aiff = AIFFPARSE (GST_PAD_PARENT (pad));

  GST_LOG_OBJECT (aiff, "process data");

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

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

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

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

    case AIFFPARSE_DATA:
      if ((ret = gst_aiffparse_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 (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
      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 {
        /* 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;
  }
}
static void
gst_rnd_buffer_size_loop (GstRndBufferSize * self)
{
  GstBuffer *buf = NULL;
  GstFlowReturn ret;
  guint num_bytes;

  if (G_UNLIKELY (self->min > self->max))
    goto bogus_minmax;

  if (G_UNLIKELY (self->min != self->max)) {
    num_bytes = g_rand_int_range (self->rand, self->min, self->max);
  } else {
    num_bytes = self->min;
  }

  GST_LOG_OBJECT (self, "pulling %u bytes at offset %" G_GUINT64_FORMAT,
      num_bytes, self->offset);

  ret = gst_pad_pull_range (self->sinkpad, self->offset, num_bytes, &buf);

  if (ret != GST_FLOW_OK)
    goto pull_failed;

  if (GST_BUFFER_SIZE (buf) < num_bytes) {
    GST_WARNING_OBJECT (self, "short buffer: %u bytes", GST_BUFFER_SIZE (buf));
  }

  self->offset += GST_BUFFER_SIZE (buf);

  ret = gst_pad_push (self->srcpad, buf);

  if (ret != GST_FLOW_OK)
    goto push_failed;

  return;

pause_task:
  {
    GST_DEBUG_OBJECT (self, "pausing task");
    gst_pad_pause_task (self->sinkpad);
    return;
  }

pull_failed:
  {
    if (ret == GST_FLOW_UNEXPECTED) {
      GST_DEBUG_OBJECT (self, "eos");
      gst_pad_push_event (self->srcpad, gst_event_new_eos ());
    } else {
      GST_WARNING_OBJECT (self, "pull_range flow: %s", gst_flow_get_name (ret));
    }
    goto pause_task;
  }

push_failed:
  {
    GST_DEBUG_OBJECT (self, "push flow: %s", gst_flow_get_name (ret));
    if (ret == GST_FLOW_UNEXPECTED) {
      GST_DEBUG_OBJECT (self, "eos");
      gst_pad_push_event (self->srcpad, gst_event_new_eos ());
    } else if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          ("Internal data stream error."),
          ("streaming stopped, reason: %s", gst_flow_get_name (ret)));
    }
    goto pause_task;
  }

bogus_minmax:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS,
        ("The minimum buffer size is smaller than the maximum buffer size."),
        ("buffer sizes: max=%ld, min=%ld", self->min, self->max));
    goto pause_task;
  }
}