Example #1
0
static void
gst_gme_play (GstPad * pad)
{
  GstGmeDec *gme = GST_GME_DEC (gst_pad_get_parent (pad));
  GstFlowReturn flow_return;
  GstBuffer *out;
  gboolean seeking = gme->seeking;
  gme_err_t gme_err = NULL;
  const int NUM_SAMPLES = 1600; /* 4 bytes (stereo 16-bit) per sample */

  if (!seeking) {
    GstMapInfo map;

    out = gst_buffer_new_and_alloc (NUM_SAMPLES * 4);
    GST_BUFFER_TIMESTAMP (out) = gme_tell (gme->player) * GST_MSECOND;

    gst_buffer_map (out, &map, GST_MAP_WRITE);
    gme_err = gme_play (gme->player, NUM_SAMPLES * 2, (short *) map.data);
    gst_buffer_unmap (out, &map);

    if (gme_err) {
      GST_ELEMENT_ERROR (gme, STREAM, DEMUX, (NULL), ("%s", gme_err));
      gst_pad_pause_task (pad);
      gst_pad_push_event (pad, gst_event_new_eos ());
      gst_object_unref (gme);
      return;
    }
  } else {
    gme_seek (gme->player, gme->seekpoint);
    gme->seeking = FALSE;

    out = gst_buffer_new ();
  }

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

    gst_pad_pause_task (pad);

    if (flow_return == GST_FLOW_EOS) {
      gst_pad_push_event (pad, gst_event_new_eos ());
    } else if (flow_return < GST_FLOW_EOS || flow_return == GST_FLOW_NOT_LINKED) {
      GST_ELEMENT_FLOW_ERROR (gme, flow_return);
      gst_pad_push_event (pad, gst_event_new_eos ());
    }
  }

  if (gme_tell (gme->player) * GST_MSECOND > gme->total_duration) {
    gst_pad_pause_task (pad);
    gst_pad_push_event (pad, gst_event_new_eos ());
  }

  gst_object_unref (gme);

  return;
}
static void
gst_tta_parse_loop (GstTtaParse * ttaparse)
{
  GstFlowReturn ret;

  if (!ttaparse->header_parsed)
    if ((ret = gst_tta_parse_parse_header (ttaparse)) != GST_FLOW_OK)
      goto pause;
  if ((ret = gst_tta_parse_stream_data (ttaparse)) != GST_FLOW_OK)
    goto pause;

  return;

pause:
  GST_LOG_OBJECT (ttaparse, "pausing task, %s", gst_flow_get_name (ret));
  gst_pad_pause_task (ttaparse->sinkpad);
  if (ret == GST_FLOW_UNEXPECTED) {
    gst_pad_push_event (ttaparse->srcpad, gst_event_new_eos ());
  } else if (ret < GST_FLOW_UNEXPECTED || ret == GST_FLOW_NOT_LINKED) {
    GST_ELEMENT_FLOW_ERROR (ttaparse, ret);
    gst_pad_push_event (ttaparse->srcpad, gst_event_new_eos ());
  }
}
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_FLOW_ERROR (typefind, ret);
      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;
  }
}