/* Handles decrypted buffers only */ static GstFlowReturn gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force) { GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) { GstCaps *caps = NULL; GstMapInfo info; guint buffer_size; GstTypeFindProbability prob = GST_TYPE_FIND_NONE; if (hlsdemux->pending_typefind_buffer) buffer = gst_buffer_append (hlsdemux->pending_typefind_buffer, buffer); hlsdemux->pending_typefind_buffer = NULL; gst_buffer_map (buffer, &info, GST_MAP_READ); buffer_size = info.size; /* Typefind could miss if buffer is too small. In this case we * will retry later */ if (buffer_size >= (2 * 1024)) { caps = gst_type_find_helper_for_data (GST_OBJECT_CAST (hlsdemux), info.data, info.size, &prob); } gst_buffer_unmap (buffer, &info); if (G_UNLIKELY (!caps)) { /* Only fail typefinding if we already a good amount of data * and we still don't know the type */ if (buffer_size > (2 * 1024 * 1024) || force) { GST_ELEMENT_ERROR (hlsdemux, STREAM, TYPE_NOT_FOUND, ("Could not determine type of stream"), (NULL)); gst_buffer_unref (buffer); return GST_FLOW_NOT_NEGOTIATED; } else { hlsdemux->pending_typefind_buffer = buffer; return GST_FLOW_OK; } } GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d", caps, prob); gst_adaptive_demux_stream_set_caps (stream, caps); hlsdemux->do_typefind = FALSE; } g_assert (hlsdemux->pending_typefind_buffer == NULL); if (buffer) { buffer = gst_buffer_make_writable (buffer); GST_BUFFER_OFFSET (buffer) = hlsdemux->current_offset; hlsdemux->current_offset += gst_buffer_get_size (buffer); GST_BUFFER_OFFSET_END (buffer) = hlsdemux->current_offset; return gst_adaptive_demux_stream_push_buffer (stream, buffer); } return GST_FLOW_OK; }
/** * gst_type_find_helper_for_buffer: * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging) * @buf: (in) (transfer none): a #GstBuffer with data to typefind * @prob: (out) (allow-none): location to store the probability of the found * caps, or %NULL * * Tries to find what type of data is contained in the given #GstBuffer, the * assumption being that the buffer represents the beginning of the stream or * file. * * 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, or %NULL if * the content of the buffer could not be identified. * * Free-function: gst_caps_unref * * Returns: (transfer full) (nullable): the #GstCaps corresponding to the data, * or %NULL if no type could be found. The caller should free the caps * returned with gst_caps_unref(). */ GstCaps * gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf, GstTypeFindProbability * prob) { GstCaps *result; GstMapInfo info; g_return_val_if_fail (buf != NULL, NULL); g_return_val_if_fail (GST_IS_BUFFER (buf), NULL); g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 || GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL); if (!gst_buffer_map (buf, &info, GST_MAP_READ)) return NULL; result = gst_type_find_helper_for_data (obj, info.data, info.size, prob); gst_buffer_unmap (buf, &info); return result; }
static GstFlowReturn gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, gboolean check_avail, gboolean at_eos) { GstTypeFindProbability probability; GstCaps *caps = NULL; gsize avail; const guint8 *data; gboolean have_min, have_max; GST_OBJECT_LOCK (typefind); if (typefind->force_caps) { caps = gst_caps_ref (typefind->force_caps); probability = GST_TYPE_FIND_MAXIMUM; } if (!caps) { avail = gst_adapter_available (typefind->adapter); if (check_avail) { have_min = avail >= TYPE_FIND_MIN_SIZE; have_max = avail >= TYPE_FIND_MAX_SIZE; } else { have_min = avail > 0; have_max = TRUE; } if (!have_min) goto not_enough_data; /* map all available data */ data = gst_adapter_map (typefind->adapter, avail); caps = gst_type_find_helper_for_data (GST_OBJECT (typefind), data, avail, &probability); gst_adapter_unmap (typefind->adapter); if (caps == NULL && have_max) goto no_type_found; else if (caps == NULL) goto wait_for_data; /* found a type */ if (probability < typefind->min_probability) goto low_probability; } GST_OBJECT_UNLOCK (typefind); /* probability is good enough too, so let's make it known ... emiting this * signal calls our object handler which sets the caps. */ gst_type_find_element_emit_have_type (typefind, probability, caps); /* .. and send out the accumulated data */ stop_typefinding (typefind); gst_caps_unref (caps); return GST_FLOW_OK; not_enough_data: { GST_OBJECT_UNLOCK (typefind); if (at_eos) { GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (_("Stream doesn't contain enough data.")), ("Can't typefind stream")); return GST_FLOW_ERROR; } else { GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet " "(%" G_GSIZE_FORMAT " bytes)", avail); return GST_FLOW_OK; } } no_type_found: { GST_OBJECT_UNLOCK (typefind); GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); stop_typefinding (typefind); return GST_FLOW_ERROR; } wait_for_data: { GST_OBJECT_UNLOCK (typefind); if (at_eos) { GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (_("Stream doesn't contain enough data.")), ("Can't typefind stream")); return GST_FLOW_ERROR; } else { GST_DEBUG_OBJECT (typefind, "no caps found with %" G_GSIZE_FORMAT " bytes of data, " "waiting for more data", avail); return GST_FLOW_OK; } } low_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_unref (caps); if (have_max) goto no_type_found; GST_OBJECT_UNLOCK (typefind); GST_DEBUG_OBJECT (typefind, "waiting for more data to try again"); return GST_FLOW_OK; } }