GstCaps *
gst_fragment_get_caps (GstFragment * fragment)
{
  g_return_val_if_fail (fragment != NULL, NULL);

  if (!fragment->completed)
    return NULL;

  g_mutex_lock (&fragment->priv->lock);
  if (fragment->priv->caps == NULL) {
    guint64 offset, offset_end;

    /* FIXME: This is currently necessary as typefinding only
     * works with 0 offsets... need to find a better way to
     * do that */
    offset = GST_BUFFER_OFFSET (fragment->priv->buffer);
    offset_end = GST_BUFFER_OFFSET_END (fragment->priv->buffer);
    GST_BUFFER_OFFSET (fragment->priv->buffer) = GST_BUFFER_OFFSET_NONE;
    GST_BUFFER_OFFSET_END (fragment->priv->buffer) = GST_BUFFER_OFFSET_NONE;
    fragment->priv->caps =
        gst_type_find_helper_for_buffer (NULL, fragment->priv->buffer, NULL);
    GST_BUFFER_OFFSET (fragment->priv->buffer) = offset;
    GST_BUFFER_OFFSET_END (fragment->priv->buffer) = offset_end;
  }
  gst_caps_ref (fragment->priv->caps);
  g_mutex_unlock (&fragment->priv->lock);

  return fragment->priv->caps;
}
static GstCaps *
typefind_test_file (const gchar * filename)
{
  GstBuffer *buf;
  GError *err = NULL;
  GstCaps *caps = NULL;
  gchar *path, *data = NULL;
  gsize data_len;

  path = g_build_filename (GST_TEST_FILES_PATH, filename, NULL);
  GST_LOG ("reading file '%s'", path);
  if (!g_file_get_contents (path, &data, &data_len, &err)) {
    g_error ("error loading test file: %s", err->message);
  }

  buf = gst_buffer_new ();
  gst_buffer_append_memory (buf,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
          (gpointer) data, data_len, 0, data_len, NULL, NULL));

  GST_BUFFER_OFFSET (buf) = 0;

  caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
  fail_unless (caps != NULL);
  GST_LOG ("Found type: %" GST_PTR_FORMAT, caps);

  gst_buffer_unref (buf);
  g_free (data);
  g_free (path);

  return caps;
}
static gboolean
gst_hls_demux_get_next_fragment (GstHLSDemux * demux)
{
  GstBuffer *buf;
  guint avail;
  const gchar *next_fragment_uri;
  GstClockTime duration;
  GstClockTime timestamp;
  gboolean discont;

  if (!gst_m3u8_client_get_next_fragment (demux->client, &discont,
          &next_fragment_uri, &duration, &timestamp)) {
    GST_INFO_OBJECT (demux, "This playlist doesn't contain more fragments");
    demux->end_of_playlist = TRUE;
    gst_task_start (demux->task);
    return FALSE;
  }

  GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);

  if (!gst_hls_demux_fetch_location (demux, next_fragment_uri)) {
    /* FIXME: The gst_m3u8_get_next_fragment increments the sequence number
       but another thread might call get_next_fragment and this decrement
       will not redownload the failed fragment, but might duplicate the
       download of a succeeded fragment
     */
    g_atomic_int_add (&demux->client->sequence, -1);
    return FALSE;
  }

  avail = gst_adapter_available (demux->download);
  buf = gst_adapter_take_buffer (demux->download, avail);
  GST_BUFFER_DURATION (buf) = duration;
  GST_BUFFER_TIMESTAMP (buf) = timestamp;

  /* We actually need to do this every time we switch bitrate */
  if (G_UNLIKELY (demux->do_typefind)) {
    GstCaps *caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);

    if (!demux->input_caps || !gst_caps_is_equal (caps, demux->input_caps)) {
      gst_caps_replace (&demux->input_caps, caps);
      /* gst_pad_set_caps (demux->srcpad, demux->input_caps); */
      GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
          demux->input_caps);
      demux->do_typefind = FALSE;
    } else
      gst_caps_unref (caps);
  }
  gst_buffer_set_caps (buf, demux->input_caps);

  if (discont) {
    GST_DEBUG_OBJECT (demux, "Marking fragment as discontinuous");
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
  }

  g_queue_push_tail (demux->queue, buf);
  gst_task_start (demux->task);
  gst_adapter_clear (demux->download);
  return TRUE;
}
static GstFlowReturn
gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind)
{
  GstTypeFindProbability probability;
  GstCaps *caps;

  if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
    GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
        "(%u bytes)", GST_BUFFER_SIZE (typefind->store));
    return GST_FLOW_OK;
  }

  caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
      typefind->store, &probability);

  if (caps == NULL && GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
    GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
    stop_typefinding (typefind);
    return GST_FLOW_ERROR;
  } else if (caps == NULL) {
    GST_DEBUG_OBJECT (typefind, "no caps found with %u bytes of data, "
        "waiting for more data", GST_BUFFER_SIZE (typefind->store));
    return GST_FLOW_OK;
  }

  /* found a type */
  if (probability < typefind->min_probability) {
    GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
        "probability is %u which is lower than the required minimum of %u",
        caps, probability, typefind->min_probability);

    gst_caps_replace (&caps, NULL);

    if (GST_BUFFER_SIZE (typefind->store) >= TYPE_FIND_MAX_SIZE) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
      stop_typefinding (typefind);
      return GST_FLOW_ERROR;
    }

    GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
    return GST_FLOW_OK;
  }

  /* probability is good enough too, so let's make it known ... */
  g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
      probability, caps);

  /* .. and send out the accumulated data */
  stop_typefinding (typefind);
  gst_caps_unref (caps);
  return GST_FLOW_OK;
}
Exemple #5
0
static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
{
    res = gst_type_find_element_chain_do_typefinding (typefind);
    {
        GstCaps *caps;
        caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
          typefind->store, &probability);
        // gstreamer/libs/gst/base/gsttypefindhelper.c
        // All available typefinders will be called on the data in order of rank. If
        // a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
        // typefinding is stopped immediately and the found caps will be returned
        // right away. Otherwise, all available typefind functions will the tried,
        // and the caps with the highest probability will be returned
        {
            type_list = gst_type_find_factory_get_list ();
            type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

            gst_type_find_factory_call_function (helper.factory, &find);
            {
                // find function from factory
                new_factory =
                    GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory)));
                new_factory->function (find, new_factory->user_data);
                gst_object_unref (new_factory);
            } // gst_type_find_factory_call_function()
        } // gst_type_find_helper_for_buffer()

        /* probability is good enough too, so let's make it known ... */
        g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
            probability, caps);

        // stop typefind
        stop_typefinding (typefind);
        {
            // TODO: why set itself to NULL?
            gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

            // reset state to normal
            typefind->mode = MODE_NORMAL;

            // send cache event and buffers
            gst_type_find_element_send_cached_events (typefind);
            gst_pad_push (typefind->src, typefind->store);
        }
    } // gst_type_find_element_chain_do_typefinding()
}
Exemple #6
0
static gboolean
gst_hls_demux_get_next_fragment (GstHLSDemux * demux, gboolean retry)
{
  GstBuffer *buf;
  guint avail;
  const gchar *next_fragment_uri;
  GstClockTime duration;
  gboolean discont;

  if (!gst_m3u8_client_get_next_fragment (demux->client, &discont,
          &next_fragment_uri, &duration)) {
    GST_INFO_OBJECT (demux, "This playlist doesn't contain more fragments");
    demux->end_of_playlist = TRUE;
    GST_TASK_SIGNAL (demux->task);
    return FALSE;
  }

  GST_INFO_OBJECT (demux, "Fetching next fragment %s", next_fragment_uri);

  if (!gst_hls_demux_fetch_location (demux, next_fragment_uri))
    return FALSE;

  avail = gst_adapter_available (demux->download);
  buf = gst_adapter_take_buffer (demux->download, avail);
  GST_BUFFER_DURATION (buf) = duration;

  if (G_UNLIKELY (demux->input_caps == NULL)) {
    demux->input_caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
    if (demux->input_caps) {
      gst_pad_set_caps (demux->srcpad, demux->input_caps);
      GST_INFO_OBJECT (demux, "Input source caps: %" GST_PTR_FORMAT,
          demux->input_caps);
    }
  }

  if (discont) {
    GST_DEBUG_OBJECT (demux, "Marking fragment as discontinuous");
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
  }

  g_queue_push_tail (demux->queue, buf);
  GST_TASK_SIGNAL (demux->task);
  gst_adapter_clear (demux->download);
  return TRUE;
}
Exemple #7
0
GstCaps *
gst_fragment_get_caps (GstFragment * fragment)
{
  g_return_val_if_fail (fragment != NULL, NULL);

  if (!fragment->completed)
    return NULL;

  g_mutex_lock (&fragment->priv->lock);
  if (fragment->priv->caps == NULL) {
    GstBuffer *buf = gst_buffer_list_get (fragment->priv->buffer_list, 0, 0);
    fragment->priv->caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
  }
  gst_caps_ref (fragment->priv->caps);
  g_mutex_unlock (&fragment->priv->lock);

  return fragment->priv->caps;
}
static GstCaps *
typefind_data (const guint8 * data, gsize data_size,
    GstTypeFindProbability * prob)
{
  GstBuffer *buf;
  GstCaps *caps;

  GST_MEMDUMP ("typefind data", data, data_size);
  buf = gst_buffer_new ();
  gst_buffer_append_memory (buf,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
          (guint8 *) data, data_size, 0, data_size, NULL, NULL));
  GST_BUFFER_OFFSET (buf) = 0;

  caps = gst_type_find_helper_for_buffer (NULL, buf, prob);
  GST_INFO ("caps: %" GST_PTR_FORMAT ", probability=%u", caps, *prob);

  gst_buffer_unref (buf);

  return caps;
}
Exemple #9
0
static GstFlowReturn
gst_icydemux_typefind_or_forward (GstICYDemux * icydemux, GstBuffer * buf)
{
  if (icydemux->typefinding) {
    GstBuffer *tf_buf;
    GstCaps *caps = NULL;
    GstTypeFindProbability prob;

    /* If we have a content-type from upstream, let's see if we can shortcut
     * typefinding */
    if (G_UNLIKELY (icydemux->content_type)) {
      if (!g_ascii_strcasecmp (icydemux->content_type, "video/nsv")) {
        GST_DEBUG ("We have a NSV stream");
        caps = gst_caps_new_simple ("video/x-nsv", NULL);
      } else {
        GST_DEBUG ("Upstream Content-Type isn't supported");
        g_free (icydemux->content_type);
        icydemux->content_type = NULL;
      }
    }

    if (icydemux->typefind_buf) {
      icydemux->typefind_buf = gst_buffer_join (icydemux->typefind_buf, buf);
    } else {
      icydemux->typefind_buf = buf;
    }

    /* Only typefind if we haven't already got some caps */
    if (caps == NULL) {
      caps = gst_type_find_helper_for_buffer (GST_OBJECT (icydemux),
          icydemux->typefind_buf, &prob);

      if (caps == NULL) {
        if (GST_BUFFER_SIZE (icydemux->typefind_buf) < ICY_TYPE_FIND_MAX_SIZE) {
          /* Just break for more data */
          return GST_FLOW_OK;
        }

        /* We failed typefind */
        GST_ELEMENT_ERROR (icydemux, STREAM, TYPE_NOT_FOUND, (NULL),
            ("No caps found for contents within an ICY stream"));
        gst_buffer_unref (icydemux->typefind_buf);
        icydemux->typefind_buf = NULL;
        return GST_FLOW_ERROR;
      }
    }

    if (!gst_icydemux_add_srcpad (icydemux, caps)) {
      GST_DEBUG_OBJECT (icydemux, "Failed to add srcpad");
      gst_caps_unref (caps);
      gst_buffer_unref (icydemux->typefind_buf);
      icydemux->typefind_buf = NULL;
      return GST_FLOW_ERROR;
    }
    gst_caps_unref (caps);

    if (icydemux->cached_events) {
      gst_icydemux_send_cached_events (icydemux);
    }

    if (icydemux->cached_tags) {
      gst_icydemux_send_tag_event (icydemux, icydemux->cached_tags);
      icydemux->cached_tags = NULL;
    }

    /* Move onto streaming: call ourselves recursively with the typefind buffer
     * to get that forwarded. */
    icydemux->typefinding = FALSE;

    tf_buf = icydemux->typefind_buf;
    icydemux->typefind_buf = NULL;
    return gst_icydemux_typefind_or_forward (icydemux, tf_buf);
  } else {
    if (G_UNLIKELY (icydemux->srcpad == NULL)) {
      gst_buffer_unref (buf);
      return GST_FLOW_ERROR;
    }

    buf = gst_buffer_make_metadata_writable (buf);
    gst_buffer_set_caps (buf, icydemux->src_caps);

    /* Most things don't care, and it's a pain to track (we should preserve a
     * 0 offset on the first buffer though if it's there, for id3demux etc.) */
    if (GST_BUFFER_OFFSET (buf) != 0) {
      GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
    }

    return gst_pad_push (icydemux->srcpad, buf);
  }
}
Exemple #10
0
/**
 * gst_tag_image_data_to_image_sample:
 * @image_data: the (encoded) image
 * @image_data_len: the length of the encoded image data at @image_data
 * @image_type: type of the image, or #GST_TAG_IMAGE_TYPE_UNDEFINED. Pass
 *     #GST_TAG_IMAGE_TYPE_NONE if no image type should be set at all (e.g.
 *     for preview images)
 *
 * Helper function for tag-reading plugins to create a #GstSample suitable to
 * add to a #GstTagList as an image tag (such as #GST_TAG_IMAGE or
 * #GST_TAG_PREVIEW_IMAGE) from the encoded image data and an (optional) image
 * type.
 *
 * Background: cover art and other images in tags are usually stored as a
 * blob of binary image data, often accompanied by a MIME type or some other
 * content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an
 * 'image type' to indicate what kind of image this is (e.g. front cover,
 * back cover, artist, etc.). The image data may also be an URI to the image
 * rather than the image itself.
 *
 * In GStreamer, image tags are #GstSample<!-- -->s containing the raw image
 * data, with the sample caps describing the content type of the image
 * (e.g. image/jpeg, image/png, text/uri-list). The sample info may contain
 * an additional 'image-type' field of #GST_TYPE_TAG_IMAGE_TYPE to describe
 * the type of image (front cover, back cover etc.). #GST_TAG_PREVIEW_IMAGE
 * tags should not carry an image type, their type is already indicated via
 * the special tag name.
 *
 * This function will do various checks and typefind the encoded image
 * data (we can't trust the declared mime type).
 *
 * Returns: a newly-allocated image sample for use in tag lists, or NULL
 */
GstSample *
gst_tag_image_data_to_image_sample (const guint8 * image_data,
    guint image_data_len, GstTagImageType image_type)
{
  const gchar *name;
  GstBuffer *image;
  GstSample *sample;
  GstCaps *caps;
  GstMapInfo info;
  GstStructure *image_info = NULL;

  g_return_val_if_fail (image_data != NULL, NULL);
  g_return_val_if_fail (image_data_len > 0, NULL);
  g_return_val_if_fail (gst_tag_image_type_is_valid (image_type), NULL);

  GST_DEBUG ("image data len: %u bytes", image_data_len);

  /* allocate space for a NUL terminator for an uri too */
  image = gst_buffer_new_and_alloc (image_data_len + 1);
  if (image == NULL)
    goto alloc_failed;

  gst_buffer_map (image, &info, GST_MAP_WRITE);
  memcpy (info.data, image_data, image_data_len);
  info.data[image_data_len] = '\0';
  gst_buffer_unmap (image, &info);

  /* Find GStreamer media type, can't trust declared type */
  caps = gst_type_find_helper_for_buffer (NULL, image, NULL);

  if (caps == NULL)
    goto no_type;

  GST_DEBUG ("Found GStreamer media type: %" GST_PTR_FORMAT, caps);

  /* sanity check: make sure typefound/declared caps are either URI or image */
  name = gst_structure_get_name (gst_caps_get_structure (caps, 0));

  if (!g_str_has_prefix (name, "image/") &&
      !g_str_has_prefix (name, "video/") &&
      !g_str_equal (name, "text/uri-list")) {
    GST_DEBUG ("Unexpected image type '%s', ignoring image frame", name);
    goto error;
  }

  /* Decrease size by 1 if we don't have an URI list
   * to keep the original size of the image
   */
  if (!g_str_equal (name, "text/uri-list"))
    gst_buffer_set_size (image, image_data_len);

  if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
    GST_LOG ("Setting image type: %d", image_type);
    image_info = gst_structure_new ("GstTagImageInfo",
        "image-type", GST_TYPE_TAG_IMAGE_TYPE, image_type, NULL);
  }
  sample = gst_sample_new (image, caps, NULL, image_info);
  gst_buffer_unref (image);
  gst_caps_unref (caps);

  return sample;

/* ERRORS */
no_type:
  {
    GST_DEBUG ("Could not determine GStreamer media type, ignoring image");
    /* fall through */
  }
error:
  {
    if (image)
      gst_buffer_unref (image);
    if (caps)
      gst_caps_unref (caps);
    return NULL;
  }
alloc_failed:
  {
    GST_WARNING ("failed to allocate buffer of %d for image", image_data_len);
    gst_buffer_unref (image);
    return NULL;
  }

}
static gboolean
gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri,
    GError ** error)
{
  GstDataURISrc *src = GST_DATA_URI_SRC (handler);
  gboolean ret = FALSE;
  gchar *mimetype = NULL;
  const gchar *parameters_start;
  const gchar *data_start;
  const gchar *orig_uri = uri;
  GstCaps *caps;
  GstBuffer *buffer;
  gboolean base64 = FALSE;
  gchar *charset = NULL;
  gpointer bdata;
  gsize bsize;

  GST_OBJECT_LOCK (src);
  if (GST_STATE (src) >= GST_STATE_PAUSED)
    goto wrong_state;
  GST_OBJECT_UNLOCK (src);

  /* uri must be an URI as defined in RFC 2397
   * data:[<mediatype>][;base64],<data>
   */
  if (strncmp ("data:", uri, 5) != 0)
    goto invalid_uri;

  uri += 5;

  parameters_start = strchr (uri, ';');
  data_start = strchr (uri, ',');
  if (data_start == NULL)
    goto invalid_uri;

  if (data_start != uri && parameters_start != uri)
    mimetype =
        g_strndup (uri,
        (parameters_start ? parameters_start : data_start) - uri);
  else
    mimetype = g_strdup ("text/plain");

  GST_DEBUG_OBJECT (src, "Mimetype: %s", mimetype);

  if (parameters_start != NULL) {
    gchar **walk;
    gchar *parameters =
        g_strndup (parameters_start + 1, data_start - parameters_start - 1);
    gchar **parameters_strv;

    parameters_strv = g_strsplit (parameters, ";", -1);

    GST_DEBUG_OBJECT (src, "Parameters: ");
    walk = parameters_strv;
    while (*walk) {
      GST_DEBUG_OBJECT (src, "\t %s", *walk);
      if (strcmp ("base64", *walk) == 0) {
        base64 = TRUE;
      } else if (strncmp ("charset=", *walk, 8) == 0) {
        charset = g_strdup (*walk + 8);
      }
      walk++;
    }
    g_free (parameters);
    g_strfreev (parameters_strv);
  }

  /* Skip comma */
  data_start += 1;
  if (base64) {
    bdata = g_base64_decode (data_start, &bsize);
  } else {
    /* URI encoded, i.e. "percent" encoding */
    bdata = g_uri_unescape_string (data_start, NULL);
    if (bdata == NULL)
      goto invalid_uri_encoded_data;
    bsize = strlen (bdata) + 1;
  }
  /* Convert to UTF8 */
  if (strcmp ("text/plain", mimetype) == 0 &&
      charset && g_ascii_strcasecmp ("US-ASCII", charset) != 0
      && g_ascii_strcasecmp ("UTF-8", charset) != 0) {
    gsize read;
    gsize written;
    gpointer data;

    data =
        g_convert_with_fallback (bdata, -1, "UTF-8", charset, (char *) "*",
        &read, &written, NULL);
    g_free (bdata);

    bdata = data;
    bsize = written;
  }
  buffer = gst_buffer_new_wrapped (bdata, bsize);

  caps = gst_type_find_helper_for_buffer (GST_OBJECT (src), buffer, NULL);
  if (!caps)
    caps = gst_caps_new_empty_simple (mimetype);
  gst_base_src_set_caps (GST_BASE_SRC_CAST (src), caps);
  gst_caps_unref (caps);

  GST_OBJECT_LOCK (src);
  gst_buffer_replace (&src->buffer, buffer);
  gst_buffer_unref (buffer);
  g_free (src->uri);
  src->uri = g_strdup (orig_uri);
  GST_OBJECT_UNLOCK (src);

  ret = TRUE;

out:

  g_free (mimetype);
  g_free (charset);

  return ret;

wrong_state:
  {
    GST_WARNING_OBJECT (src, "Can't set URI in %s state",
        gst_element_state_get_name (GST_STATE (src)));
    GST_OBJECT_UNLOCK (src);
    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE,
        "Changing the 'uri' property on dataurisrc while it is running "
        "is not supported");
    goto out;
  }
invalid_uri:
  {
    GST_WARNING_OBJECT (src, "invalid URI '%s'", uri);
    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
        "Invalid data URI");
    goto out;
  }
invalid_uri_encoded_data:
  {
    GST_WARNING_OBJECT (src, "Failed to parse data encoded in URI '%s'", uri);
    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
        "Could not parse data encoded in data URI");
    goto out;
  }
}
static gboolean
gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
{
  gboolean res = FALSE;
  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
      GST_EVENT_TYPE_NAME (event), typefind->mode);

  switch (typefind->mode) {
    case MODE_TYPEFIND:
      switch (GST_EVENT_TYPE (event)) {
        case GST_EVENT_EOS:{
          GstTypeFindProbability prob = 0;
          GstCaps *caps = NULL;

          GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");

          /* we might not have started typefinding yet because there was not
           * enough data so far; just give it a shot now and see what we get */
          if (typefind->store) {
            caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
                typefind->store, &prob);

            if (caps && prob >= typefind->min_probability) {
              g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
                  0, prob, caps);
            } else {
              GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
                  (NULL), (NULL));
            }
            gst_caps_replace (&caps, NULL);
          } else {
            /* keep message in sync with the one in the pad activate function */
            GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
                (_("Stream contains no data.")),
                ("Can't typefind empty stream"));
          }

          stop_typefinding (typefind);
          res = gst_pad_push_event (typefind->src, event);
          break;
        }
        case GST_EVENT_FLUSH_STOP:
          g_list_foreach (typefind->cached_events,
              (GFunc) gst_mini_object_unref, NULL);
          g_list_free (typefind->cached_events);
          typefind->cached_events = NULL;
          gst_buffer_replace (&typefind->store, NULL);
          /* fall through */
        case GST_EVENT_FLUSH_START:
          res = gst_pad_push_event (typefind->src, event);
          break;
        default:
          GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
              GST_EVENT_TYPE_NAME (event));
          typefind->cached_events =
              g_list_append (typefind->cached_events, event);
          res = TRUE;
          break;
      }
      break;
    case MODE_NORMAL:
      res = gst_pad_push_event (typefind->src, event);
      break;
    case MODE_ERROR:
      break;
    default:
      g_assert_not_reached ();
  }
  return res;
}
Exemple #13
0
static GstFlowReturn
gst_bz2dec_chain (GstPad * pad, GstBuffer * in)
{
  GstFlowReturn flow;
  GstBuffer *out;
  GstBz2dec *b;
  int r = BZ_OK;

  b = GST_BZ2DEC (GST_PAD_PARENT (pad));

  if (!b->ready)
    goto not_ready;

  b->stream.next_in = (char *) GST_BUFFER_DATA (in);
  b->stream.avail_in = GST_BUFFER_SIZE (in);

  do {
    guint n;

    /* Create the output buffer */
    flow = gst_pad_alloc_buffer (b->src, b->offset,
        b->offset ? b->buffer_size : b->first_buffer_size,
        GST_PAD_CAPS (b->src), &out);

    if (flow != GST_FLOW_OK) {
      GST_DEBUG_OBJECT (b, "pad alloc failed: %s", gst_flow_get_name (flow));
      gst_bz2dec_decompress_init (b);
      break;
    }

    /* Decode */
    b->stream.next_out = (char *) GST_BUFFER_DATA (out);
    b->stream.avail_out = GST_BUFFER_SIZE (out);
    r = BZ2_bzDecompress (&b->stream);
    if ((r != BZ_OK) && (r != BZ_STREAM_END))
      goto decode_failed;

    if (b->stream.avail_out >= GST_BUFFER_SIZE (out)) {
      gst_buffer_unref (out);
      break;
    }
    GST_BUFFER_SIZE (out) -= b->stream.avail_out;
    GST_BUFFER_OFFSET (out) = b->stream.total_out_lo32 - GST_BUFFER_SIZE (out);

    /* Configure source pad (if necessary) */
    if (!b->offset) {
      GstCaps *caps = NULL;

      caps = gst_type_find_helper_for_buffer (GST_OBJECT (b), out, NULL);
      if (caps) {
        gst_buffer_set_caps (out, caps);
        gst_pad_set_caps (b->src, caps);
        gst_pad_use_fixed_caps (b->src);
        gst_caps_unref (caps);
      } else {
        /* FIXME: shouldn't we queue output buffers until we have a type? */
      }
    }

    /* Push data */
    n = GST_BUFFER_SIZE (out);
    flow = gst_pad_push (b->src, out);
    if (flow != GST_FLOW_OK)
      break;
    b->offset += n;
  } while (r != BZ_STREAM_END);

done:

  gst_buffer_unref (in);
  return flow;

/* ERRORS */
decode_failed:
  {
    GST_ELEMENT_ERROR (b, STREAM, DECODE, (NULL),
        ("Failed to decompress data (error code %i).", r));
    gst_bz2dec_decompress_init (b);
    gst_buffer_unref (out);
    flow = GST_FLOW_ERROR;
    goto done;
  }
not_ready:
  {
    GST_ELEMENT_ERROR (b, LIBRARY, FAILED, (NULL), ("Decompressor not ready."));
    flow = GST_FLOW_WRONG_STATE;
    goto done;
  }
}