static GstPadProbeReturn event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; GstEvent *event = GST_PAD_PROBE_INFO_DATA (info); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_STREAM_START:{ guint group_id; g_mutex_lock (&test_mutex); fail_unless (gst_event_parse_group_id (event, &group_id)); if (have_group_id) { if (group_id_pre != group_id) { event = gst_event_copy (event); gst_event_set_group_id (event, group_id_pre); gst_event_replace ((GstEvent **) & info->data, event); gst_event_unref (event); } } else { group_id_pre = group_id; have_group_id = TRUE; } g_mutex_unlock (&test_mutex); break; } default: break; } return ret; }
static gboolean prepare_src_pad (MpegTSBase * base, MpegTSParse2 * parse) { GstEvent *event; gchar *stream_id; GstCaps *caps; if (!parse->first) return TRUE; /* If there's no packet_size yet, we can't set caps yet */ if (G_UNLIKELY (base->packetizer->packet_size == 0)) return FALSE; stream_id = gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (base), "multi-program"); event = gst_pad_get_sticky_event (parse->parent.sinkpad, GST_EVENT_STREAM_START, 0); if (event) { if (gst_event_parse_group_id (event, &parse->group_id)) parse->have_group_id = TRUE; else parse->have_group_id = FALSE; gst_event_unref (event); } else if (!parse->have_group_id) { parse->have_group_id = TRUE; parse->group_id = gst_util_group_id_next (); } event = gst_event_new_stream_start (stream_id); if (parse->have_group_id) gst_event_set_group_id (event, parse->group_id); gst_pad_push_event (parse->srcpad, event); g_free (stream_id); caps = gst_caps_new_simple ("video/mpegts", "systemstream", G_TYPE_BOOLEAN, TRUE, "packetsize", G_TYPE_INT, base->packetizer->packet_size, NULL); gst_pad_set_caps (parse->srcpad, caps); gst_caps_unref (caps); /* If setting output timestamps, ensure that the output segment is TIME */ if (parse->set_timestamps == FALSE || base->segment.format == GST_FORMAT_TIME) gst_pad_push_event (parse->srcpad, gst_event_new_segment (&base->segment)); else { GstSegment seg; gst_segment_init (&seg, GST_FORMAT_TIME); GST_DEBUG_OBJECT (parse, "Generating time output segment %" GST_SEGMENT_FORMAT, &seg); gst_pad_push_event (parse->srcpad, gst_event_new_segment (&seg)); } parse->first = FALSE; return TRUE; }
static gboolean gst_droidcamsrc_mode_negotiate_pad (GstDroidCamSrcMode * mode, GstPad * pad, gboolean force) { GstDroidCamSrcPad *data = gst_pad_get_element_private (pad); /* take pad lock */ g_mutex_lock (&data->lock); if (!force) { if (!gst_pad_check_reconfigure (data->pad)) { g_mutex_unlock (&data->lock); return TRUE; } } /* * stream start * we must send it before we send our CAPS event */ if (G_UNLIKELY (data->open_stream)) { gchar *stream_id; GstEvent *event; stream_id = gst_pad_create_stream_id (data->pad, GST_ELEMENT_CAST (mode->src), GST_PAD_NAME (data->pad)); GST_DEBUG_OBJECT (pad, "Pushing STREAM_START for pad"); event = gst_event_new_stream_start (stream_id); gst_event_set_group_id (event, gst_util_group_id_next ()); if (!gst_pad_push_event (data->pad, event)) { GST_ERROR_OBJECT (mode->src, "failed to push STREAM_START event for pad %s", GST_PAD_NAME (data->pad)); } g_free (stream_id); data->open_stream = FALSE; } /* negotiate */ if (!data->negotiate (data)) { GST_ELEMENT_ERROR (mode->src, STREAM, FORMAT, (NULL), ("failed to negotiate %s.", GST_PAD_NAME (data->pad))); g_mutex_unlock (&data->lock); return FALSE; } /* toss pad queue */ g_queue_foreach (data->queue, (GFunc) gst_buffer_unref, NULL); g_queue_clear (data->queue); /* unlock */ g_mutex_unlock (&data->lock); return TRUE; }
static void gst_decklink_src_send_initial_events (GstDecklinkSrc * src) { GstSegment segment; GstEvent *event; guint group_id; guint32 audio_id, video_id; gchar stream_id[9]; /* stream-start */ audio_id = g_random_int (); video_id = g_random_int (); while (video_id == audio_id) video_id = g_random_int (); group_id = gst_util_group_id_next (); g_snprintf (stream_id, sizeof (stream_id), "%08x", audio_id); event = gst_event_new_stream_start (stream_id); gst_event_set_group_id (event, group_id); gst_pad_push_event (src->audiosrcpad, event); g_snprintf (stream_id, sizeof (stream_id), "%08x", video_id); event = gst_event_new_stream_start (stream_id); gst_event_set_group_id (event, group_id); gst_pad_push_event (src->videosrcpad, event); /* segment */ gst_segment_init (&segment, GST_FORMAT_TIME); event = gst_event_new_segment (&segment); gst_pad_push_event (src->videosrcpad, gst_event_ref (event)); gst_pad_push_event (src->audiosrcpad, event); /* caps */ gst_pad_push_event (src->audiosrcpad, gst_event_new_caps (gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16LE", "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, "layout", G_TYPE_STRING, "interleaved", NULL))); gst_pad_push_event (src->videosrcpad, gst_event_new_caps (gst_decklink_mode_get_caps (src->mode))); }
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; } }
/* Probe on the output of a parser chain (the last * src pad) */ static GstPadProbeReturn parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info, DecodebinInputStream * input) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; if (GST_IS_EVENT (GST_PAD_PROBE_INFO_DATA (info))) { GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info); GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (ev)); switch (GST_EVENT_TYPE (ev)) { case GST_EVENT_STREAM_START: { GstStream *stream = NULL; guint group_id = G_MAXUINT32; gst_event_parse_group_id (ev, &group_id); GST_DEBUG_OBJECT (pad, "Got stream-start, group_id:%d, input %p", group_id, input->input); if (set_input_group_id (input->input, &group_id)) { ev = gst_event_make_writable (ev); gst_event_set_group_id (ev, group_id); GST_PAD_PROBE_INFO_DATA (info) = ev; } input->saw_eos = FALSE; gst_event_parse_stream (ev, &stream); /* FIXME : Would we ever end up with a stream already set on the input ?? */ if (stream) { if (input->active_stream != stream) { MultiQueueSlot *slot; if (input->active_stream) gst_object_unref (input->active_stream); input->active_stream = stream; /* We have the beginning of a stream, get a multiqueue slot and link to it */ g_mutex_lock (&input->dbin->selection_lock); slot = get_slot_for_input (input->dbin, input); link_input_to_slot (input, slot); g_mutex_unlock (&input->dbin->selection_lock); } else gst_object_unref (stream); } } break; case GST_EVENT_CAPS: { GstCaps *caps = NULL; gst_event_parse_caps (ev, &caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); if (caps && input->active_stream) gst_stream_set_caps (input->active_stream, caps); } break; case GST_EVENT_EOS: input->saw_eos = TRUE; if (all_inputs_are_eos (input->dbin)) { GST_DEBUG_OBJECT (pad, "real input pad, marking as EOS"); check_all_streams_for_eos (input->dbin); } else { GstPad *peer = gst_pad_get_peer (input->srcpad); if (peer) { /* Send custom-eos event to multiqueue slot */ GstStructure *s; GstEvent *event; GST_DEBUG_OBJECT (pad, "Got EOS end of input stream, post custom-eos"); s = gst_structure_new_empty ("decodebin3-custom-eos"); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); gst_pad_send_event (peer, event); gst_object_unref (peer); } else { GST_FIXME_OBJECT (pad, "No peer, what should we do ?"); } } ret = GST_PAD_PROBE_DROP; break; case GST_EVENT_FLUSH_STOP: GST_DEBUG_OBJECT (pad, "Clear saw_eos flag"); input->saw_eos = FALSE; default: break; } } else if (GST_IS_QUERY (GST_PAD_PROBE_INFO_DATA (info))) { GstQuery *q = GST_PAD_PROBE_INFO_QUERY (info); GST_DEBUG_OBJECT (pad, "Seeing query %s", GST_QUERY_TYPE_NAME (q)); /* If we have a parser, we want to reply to the caps query */ /* FIXME: Set a flag when the input stream is created for * streams where we shouldn't reply to these queries */ if (GST_QUERY_TYPE (q) == GST_QUERY_CAPS && (info->type & GST_PAD_PROBE_TYPE_PULL)) { GstCaps *filter = NULL; GstCaps *allowed; gst_query_parse_caps (q, &filter); allowed = get_parser_caps_filter (input->dbin, filter); GST_DEBUG_OBJECT (pad, "Intercepting caps query, setting %" GST_PTR_FORMAT, allowed); gst_query_set_caps_result (q, allowed); gst_caps_unref (allowed); ret = GST_PAD_PROBE_HANDLED; } else if (GST_QUERY_TYPE (q) == GST_QUERY_ACCEPT_CAPS) { GstCaps *prop = NULL; gst_query_parse_accept_caps (q, &prop); /* Fast check against target caps */ if (gst_caps_can_intersect (prop, input->dbin->caps)) gst_query_set_accept_caps_result (q, TRUE); else { gboolean accepted = check_parser_caps_filter (input->dbin, prop); /* check against caps filter */ gst_query_set_accept_caps_result (q, accepted); GST_DEBUG_OBJECT (pad, "ACCEPT_CAPS query, returning %d", accepted); } ret = GST_PAD_PROBE_HANDLED; } } return ret; }
static GstMultipartPad * gst_multipart_find_pad_by_mime (GstMultipartDemux * demux, gchar * mime, gboolean * created) { GSList *walk; walk = demux->srcpads; while (walk) { GstMultipartPad *pad = (GstMultipartPad *) walk->data; if (!strcmp (pad->mime, mime)) { if (created) { *created = FALSE; } return pad; } walk = walk->next; } /* pad not found, create it */ { GstPad *pad; GstMultipartPad *mppad; gchar *name; const gchar *capsname; GstCaps *caps; gchar *stream_id; GstEvent *event; mppad = g_new0 (GstMultipartPad, 1); GST_DEBUG_OBJECT (demux, "creating pad with mime: %s", mime); name = g_strdup_printf ("src_%u", demux->numpads); pad = gst_pad_new_from_static_template (&multipart_demux_src_template_factory, name); g_free (name); mppad->pad = pad; mppad->mime = g_strdup (mime); mppad->last_ret = GST_FLOW_OK; mppad->last_ts = GST_CLOCK_TIME_NONE; mppad->discont = TRUE; demux->srcpads = g_slist_prepend (demux->srcpads, mppad); demux->numpads++; gst_pad_use_fixed_caps (pad); gst_pad_set_active (pad, TRUE); /* prepare and send stream-start */ if (!demux->have_group_id) { event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0); if (event) { demux->have_group_id = gst_event_parse_group_id (event, &demux->group_id); gst_event_unref (event); } else if (!demux->have_group_id) { demux->have_group_id = TRUE; demux->group_id = gst_util_group_id_next (); } } stream_id = gst_pad_create_stream_id (pad, GST_ELEMENT_CAST (demux), demux->mime_type); event = gst_event_new_stream_start (stream_id); if (demux->have_group_id) gst_event_set_group_id (event, demux->group_id); gst_pad_store_sticky_event (pad, event); g_free (stream_id); gst_event_unref (event); /* take the mime type, convert it to the caps name */ capsname = gst_multipart_demux_get_gstname (demux, mime); caps = gst_caps_from_string (capsname); GST_DEBUG_OBJECT (demux, "caps for pad: %s", capsname); gst_pad_set_caps (pad, caps); gst_element_add_pad (GST_ELEMENT_CAST (demux), pad); gst_caps_unref (caps); if (created) { *created = TRUE; } if (demux->singleStream) { gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); } return mppad; } }
static GstFlowReturn gst_real_audio_demux_parse_header (GstRealAudioDemux * demux) { const guint8 *data; gchar *codec_name = NULL; GstCaps *caps = NULL; GstEvent *event; gchar *stream_id; guint avail; g_assert (demux->ra_version == 4 || demux->ra_version == 3); avail = gst_adapter_available (demux->adapter); if (avail < 16) return GST_FLOW_OK; if (!gst_real_audio_demux_get_data_offset_from_header (demux)) return GST_FLOW_ERROR; /* shouldn't happen */ GST_DEBUG_OBJECT (demux, "data_offset = %u", demux->data_offset); if (avail + 6 < demux->data_offset) { GST_DEBUG_OBJECT (demux, "Need %u bytes, but only %u available now", demux->data_offset - 6, avail); return GST_FLOW_OK; } data = gst_adapter_map (demux->adapter, demux->data_offset - 6); g_assert (data); switch (demux->ra_version) { case 3: demux->fourcc = GST_RM_AUD_14_4; demux->packet_size = 20; demux->sample_rate = 8000; demux->channels = 1; demux->sample_width = 16; demux->flavour = 1; demux->leaf_size = 0; demux->height = 0; break; case 4: demux->flavour = GST_READ_UINT16_BE (data + 16); /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */ demux->leaf_size = GST_READ_UINT16_BE (data + 38); demux->height = GST_READ_UINT16_BE (data + 34); demux->packet_size = GST_READ_UINT32_BE (data + 18); demux->sample_rate = GST_READ_UINT16_BE (data + 42); demux->sample_width = GST_READ_UINT16_BE (data + 46); demux->channels = GST_READ_UINT16_BE (data + 48); demux->fourcc = GST_READ_UINT32_LE (data + 56); demux->pending_tags = gst_rm_utils_read_tags (data + 63, demux->data_offset - 63, gst_rm_utils_read_string8); if (demux->pending_tags) gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL); break; default: g_assert_not_reached (); #if 0 case 5: demux->flavour = GST_READ_UINT16_BE (data + 16); /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */ demux->leaf_size = GST_READ_UINT16_BE (data + 38); demux->height = GST_READ_UINT16_BE (data + 34); demux->sample_rate = GST_READ_UINT16_BE (data + 48); demux->sample_width = GST_READ_UINT16_BE (data + 52); demux->n_channels = GST_READ_UINT16_BE (data + 54); demux->fourcc = RMDEMUX_FOURCC_GET (data + 60); break; #endif } GST_INFO_OBJECT (demux, "packet_size = %u", demux->packet_size); GST_INFO_OBJECT (demux, "sample_rate = %u", demux->sample_rate); GST_INFO_OBJECT (demux, "sample_width = %u", demux->sample_width); GST_INFO_OBJECT (demux, "channels = %u", demux->channels); GST_INFO_OBJECT (demux, "fourcc = '%" GST_FOURCC_FORMAT "' (%08X)", GST_FOURCC_ARGS (demux->fourcc), demux->fourcc); switch (demux->fourcc) { case GST_RM_AUD_14_4: caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion", G_TYPE_INT, 1, NULL); demux->byterate_num = 1000; demux->byterate_denom = 1; break; case GST_RM_AUD_28_8: /* FIXME: needs descrambling */ caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion", G_TYPE_INT, 2, NULL); break; case GST_RM_AUD_DNET: caps = gst_caps_new_simple ("audio/x-ac3", "rate", G_TYPE_INT, demux->sample_rate, NULL); if (demux->packet_size == 0 || demux->sample_rate == 0) goto broken_file; demux->byterate_num = demux->packet_size * demux->sample_rate; demux->byterate_denom = 1536; break; /* Sipro/ACELP.NET Voice Codec (MIME unknown) */ case GST_RM_AUD_SIPR: caps = gst_caps_new_empty_simple ("audio/x-sipro"); break; default: GST_WARNING_OBJECT (demux, "unknown fourcc %08X", demux->fourcc); break; } if (caps == NULL) goto unknown_fourcc; gst_caps_set_simple (caps, "flavor", G_TYPE_INT, demux->flavour, "rate", G_TYPE_INT, demux->sample_rate, "channels", G_TYPE_INT, demux->channels, "width", G_TYPE_INT, demux->sample_width, "leaf_size", G_TYPE_INT, demux->leaf_size, "packet_size", G_TYPE_INT, demux->packet_size, "height", G_TYPE_INT, demux->height, NULL); GST_INFO_OBJECT (demux, "Adding source pad, caps %" GST_PTR_FORMAT, caps); demux->srcpad = gst_pad_new_from_static_template (&src_template, "src"); gst_pad_set_event_function (demux->srcpad, GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_event)); gst_pad_set_query_function (demux->srcpad, GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_query)); gst_pad_set_active (demux->srcpad, TRUE); gst_pad_use_fixed_caps (demux->srcpad); stream_id = gst_pad_create_stream_id (demux->srcpad, GST_ELEMENT_CAST (demux), NULL); event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0); if (event) { if (gst_event_parse_group_id (event, &demux->group_id)) demux->have_group_id = TRUE; else demux->have_group_id = FALSE; gst_event_unref (event); } else if (!demux->have_group_id) { demux->have_group_id = TRUE; demux->group_id = gst_util_group_id_next (); } event = gst_event_new_stream_start (stream_id); if (demux->have_group_id) gst_event_set_group_id (event, demux->group_id); gst_pad_push_event (demux->srcpad, event); g_free (stream_id); gst_pad_set_caps (demux->srcpad, caps); codec_name = gst_pb_utils_get_codec_description (caps); gst_caps_unref (caps); gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad); if (demux->byterate_num > 0 && demux->byterate_denom > 0) { GstFormat bformat = GST_FORMAT_BYTES; gint64 size_bytes = 0; GST_INFO_OBJECT (demux, "byte rate = %u/%u = %u bytes/sec", demux->byterate_num, demux->byterate_denom, demux->byterate_num / demux->byterate_denom); if (gst_pad_peer_query_duration (demux->sinkpad, bformat, &size_bytes)) { demux->duration = gst_real_demux_get_timestamp_from_offset (demux, size_bytes); demux->upstream_size = size_bytes; GST_INFO_OBJECT (demux, "upstream_size = %" G_GUINT64_FORMAT, demux->upstream_size); GST_INFO_OBJECT (demux, "duration = %" GST_TIME_FORMAT, GST_TIME_ARGS (demux->duration)); } } demux->need_newsegment = TRUE; if (codec_name) { if (demux->pending_tags == NULL) { demux->pending_tags = gst_tag_list_new_empty (); gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL); } gst_tag_list_add (demux->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec_name, NULL); g_free (codec_name); } gst_adapter_unmap (demux->adapter); gst_adapter_flush (demux->adapter, demux->data_offset - 6); demux->state = REAL_AUDIO_DEMUX_STATE_DATA; demux->need_newsegment = TRUE; return GST_FLOW_OK; /* ERRORS */ unknown_fourcc: { GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL), ("Unknown fourcc '%" GST_FOURCC_FORMAT "'", GST_FOURCC_ARGS (demux->fourcc))); return GST_FLOW_ERROR; } broken_file: { GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL), ("Broken file - invalid sample_rate or other header value")); return GST_FLOW_ERROR; } }
static GstFlowReturn gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf, GstVideoCaptionMeta * meta) { GstBuffer *outbuf = NULL; GstEvent *event; gchar *captionid; GstFlowReturn flow; GST_DEBUG_OBJECT (filter, "Handling meta"); /* Check if the meta type matches the configured one */ if (filter->captionpad != NULL && meta->caption_type != filter->caption_type) { GST_ERROR_OBJECT (filter, "GstVideoCaptionMeta type changed, Not handled currently"); flow = GST_FLOW_NOT_NEGOTIATED; goto out; } if (filter->captionpad == NULL) { GstCaps *caption_caps = NULL; GstEvent *stream_event; GST_DEBUG_OBJECT (filter, "Creating new caption pad"); switch (meta->caption_type) { case GST_VIDEO_CAPTION_TYPE_CEA608_RAW: caption_caps = gst_caps_from_string ("closedcaption/x-cea-608,format=(string)raw"); break; case GST_VIDEO_CAPTION_TYPE_CEA608_IN_CEA708_RAW: caption_caps = gst_caps_from_string ("closedcaption/x-cea-608,format=(string)cc_data"); break; case GST_VIDEO_CAPTION_TYPE_CEA708_RAW: caption_caps = gst_caps_from_string ("closedcaption/x-cea-708,format=(string)cc_data"); break; case GST_VIDEO_CAPTION_TYPE_CEA708_CDP: caption_caps = gst_caps_from_string ("closedcaption/x-cea-708,format=(string)cdp"); break; default: break; } if (caption_caps == NULL) { GST_ERROR_OBJECT (filter, "Unknown/invalid caption type"); return GST_FLOW_NOT_NEGOTIATED; } /* Create the caption pad and set the caps */ filter->captionpad = gst_pad_new_from_static_template (&captiontemplate, "caption"); gst_pad_set_iterate_internal_links_function (filter->sinkpad, GST_DEBUG_FUNCPTR (gst_cc_extractor_iterate_internal_links)); gst_pad_set_active (filter->captionpad, TRUE); gst_element_add_pad (GST_ELEMENT (filter), filter->captionpad); gst_flow_combiner_add_pad (filter->combiner, filter->captionpad); captionid = gst_pad_create_stream_id (filter->captionpad, (GstElement *) filter, "caption"); stream_event = gst_event_new_stream_start (captionid); g_free (captionid); /* FIXME : Create a proper stream-id */ if ((event = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_STREAM_START, 0))) { guint group_id; if (gst_event_parse_group_id (event, &group_id)) gst_event_set_group_id (stream_event, group_id); gst_event_unref (event); } gst_pad_push_event (filter->captionpad, stream_event); gst_pad_set_caps (filter->captionpad, caption_caps); gst_caps_unref (caption_caps); /* Carry over sticky events */ if ((event = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_SEGMENT, 0))) gst_pad_push_event (filter->captionpad, event); if ((event = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_TAG, 0))) gst_pad_push_event (filter->captionpad, event); filter->caption_type = meta->caption_type; } GST_DEBUG_OBJECT (filter, "Creating new buffer of size %" G_GSIZE_FORMAT " bytes", meta->size); /* Extract caption data into new buffer with identical buffer timestamps */ outbuf = gst_buffer_new_allocate (NULL, meta->size, NULL); gst_buffer_fill (outbuf, 0, meta->data, meta->size); GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf); GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); /* We don't really care about the flow return */ flow = gst_pad_push (filter->captionpad, outbuf); out: /* Set flow return on pad and return combined value */ return gst_flow_combiner_update_pad_flow (filter->combiner, filter->captionpad, flow); }
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 (G_UNLIKELY (rp->push_stream_start)) { gchar *stream_id; GstEvent *event; stream_id = gst_pad_create_stream_id (rp->srcpad, GST_ELEMENT_CAST (rp), NULL); event = gst_event_new_stream_start (stream_id); gst_event_set_group_id (event, gst_util_group_id_next ()); GST_DEBUG_OBJECT (rp, "Pushing STREAM_START"); gst_pad_push_event (rp->srcpad, event); rp->push_stream_start = FALSE; g_free (stream_id); } 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; } }