/** * gst_app_src_get_caps: * @appsrc: a #GstAppSrc * * Get the configured caps on @appsrc. * * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage. */ GstCaps * gst_app_src_get_caps (GstAppSrc * appsrc) { g_return_val_if_fail (GST_IS_APP_SRC (appsrc), NULL); return gst_app_src_internal_get_caps (GST_BASE_SRC_CAST (appsrc), NULL); }
static gboolean gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event) { GstFakeSrc *src; src = GST_FAKE_SRC (basesrc); if (!src->silent) { const GstStructure *s; const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (src); g_free (src->last_message); tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); src->last_message = g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), tstr, GST_EVENT_TYPE (event), sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (src); g_object_notify_by_pspec ((GObject *) src, pspec_last_message); } return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); }
static void gst_cel_video_src_init (GstCelVideoSrc * self, GstCelVideoSrcClass * gclass) { GstBaseSrc *base_src = GST_BASE_SRC_CAST (self); gst_base_src_set_live (base_src, TRUE); gst_base_src_set_format (base_src, GST_FORMAT_TIME); self->ready_cond = g_cond_new (); }
static GstFlowReturn gst_neonhttp_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) { GstNeonhttpSrc *src; GstBaseSrc *basesrc; GstFlowReturn ret; gint read; src = GST_NEONHTTP_SRC (psrc); basesrc = GST_BASE_SRC_CAST (psrc); /* The caller should know the number of bytes and not read beyond EOS. */ if (G_UNLIKELY (src->eos)) goto eos; /* Create the buffer. */ ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (basesrc), basesrc->segment.last_stop, basesrc->blocksize, src->icy_caps ? src->icy_caps : GST_PAD_CAPS (GST_BASE_SRC_PAD (basesrc)), outbuf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto done; read = gst_neonhttp_src_request_dispatch (src, *outbuf); if (G_UNLIKELY (read < 0)) goto read_error; GST_LOG_OBJECT (src, "returning %u bytes", GST_BUFFER_SIZE (*outbuf)); done: return ret; /* ERRORS */ eos: { GST_DEBUG_OBJECT (src, "EOS reached"); return GST_FLOW_UNEXPECTED; } read_error: { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Could not read any bytes (%i, %s)", read, ne_get_error (src->session))); gst_buffer_unref (*outbuf); *outbuf = NULL; return GST_FLOW_ERROR; } }
static GstFlowReturn gst_vbisrc_create(GstPushSrc *psrc, GstBuffer **buf) { Gstvbisrc *vbisrc = GST_VBISRC_CAST(psrc); GstFlowReturn ret; GstMapInfo info; fd_set rd; int res; struct timeval timeout; int vbi_fd=vbi_capture_fd(vbisrc->pVbiCapt); vbi_capture_buffer *pVbiBuf; vbi_sliced *pVbiData; GstBuffer *outbuf; uint lineCount; uint line; FD_ZERO(&rd); FD_SET(vbi_fd,&rd); select(vbi_fd +1 ,&rd , NULL, NULL, NULL); if (FD_ISSET(vbi_fd,&rd)) { timeout.tv_sec = 0; timeout.tv_usec = 1000; res = vbi_capture_pull_sliced(vbisrc->pVbiCapt,&pVbiBuf,&timeout); if (res>0 && pVbiBuf !=NULL) { lineCount = ((unsigned int)pVbiBuf->size)/sizeof(vbi_sliced); pVbiData = pVbiBuf->data; GST_LOG_OBJECT(vbisrc,"Having %d lines in buffer",lineCount); for (line=0; line<lineCount; line++ ) { if((pVbiData[line].id & (VBI_SLICED_TELETEXT_B))!=0) { GST_LOG_OBJECT(vbisrc,"SLICED_TELETEXT found in line %d",pVbiData[line].line); } } ret=GST_BASE_SRC_CLASS(parent_class) -> alloc (GST_BASE_SRC_CAST(vbisrc), -1,pVbiBuf->size,&outbuf); gst_buffer_map(outbuf,&info,GST_MAP_WRITE); memcpy(info.data,(guint8*)pVbiBuf->data,pVbiBuf->size); gst_buffer_unmap(outbuf,&info); *buf=GST_BUFFER_CAST(outbuf); GST_LOG_OBJECT (vbisrc,"Buffer pushed with size: %d", pVbiBuf->size); return ret; } } return GST_FLOW_ERROR; }
static void gst_soup_http_src_got_chunk_cb (SoupMessage * msg, SoupBuffer * chunk, GstSoupHTTPSrc * src) { GstBaseSrc *basesrc; guint64 new_position; if (G_UNLIKELY (msg != src->msg)) { GST_DEBUG_OBJECT (src, "got chunk, but not for current message"); return; } if (G_UNLIKELY (src->session_io_status != GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING)) { /* Probably a redirect. */ return; } basesrc = GST_BASE_SRC_CAST (src); GST_DEBUG_OBJECT (src, "got chunk of %" G_GSIZE_FORMAT " bytes", chunk->length); /* Extract the GstBuffer from the SoupBuffer and set its fields. */ *src->outbuf = GST_BUFFER_CAST (soup_buffer_get_owner (chunk)); GST_BUFFER_SIZE (*src->outbuf) = chunk->length; GST_BUFFER_OFFSET (*src->outbuf) = basesrc->segment.last_stop; gst_buffer_set_caps (*src->outbuf, (src->src_caps) ? src->src_caps : GST_PAD_CAPS (GST_BASE_SRC_PAD (basesrc))); gst_buffer_ref (*src->outbuf); new_position = src->read_position + chunk->length; if (G_LIKELY (src->request_position == src->read_position)) src->request_position = new_position; src->read_position = new_position; src->ret = GST_FLOW_OK; g_main_loop_quit (src->loop); gst_soup_http_src_session_pause_message (src); }
static void gst_mio_video_src_init (GstMIOVideoSrc * self, GstMIOVideoSrcClass * gclass) { GstBaseSrc *base_src = GST_BASE_SRC_CAST (self); guint64 host_freq; gst_base_src_set_live (base_src, TRUE); gst_base_src_set_format (base_src, GST_FORMAT_TIME); host_freq = gst_gdouble_to_guint64 (CVGetHostClockFrequency ()); if (host_freq <= GST_SECOND) { self->cv_ratio_n = GST_SECOND / host_freq; self->cv_ratio_d = 1; } else { self->cv_ratio_n = 1; self->cv_ratio_d = host_freq / GST_SECOND; } self->queue = g_queue_new (); self->qlock = g_mutex_new (); self->qcond = g_cond_new (); }
static SoupBuffer * gst_soup_http_src_chunk_allocator (SoupMessage * msg, gsize max_len, gpointer user_data) { GstSoupHTTPSrc *src = (GstSoupHTTPSrc *) user_data; GstBaseSrc *basesrc = GST_BASE_SRC_CAST (src); GstBuffer *gstbuf; SoupBuffer *soupbuf; gsize length; GstFlowReturn rc; if (max_len) length = MIN (basesrc->blocksize, max_len); else length = basesrc->blocksize; GST_DEBUG_OBJECT (src, "alloc %" G_GSIZE_FORMAT " bytes <= %" G_GSIZE_FORMAT, length, max_len); rc = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (basesrc), GST_BUFFER_OFFSET_NONE, length, src->src_caps ? src->src_caps : GST_PAD_CAPS (GST_BASE_SRC_PAD (basesrc)), &gstbuf); if (G_UNLIKELY (rc != GST_FLOW_OK)) { /* Failed to allocate buffer. Stall SoupSession and return error code * to create(). */ src->ret = rc; g_main_loop_quit (src->loop); return NULL; } soupbuf = soup_buffer_new_with_owner (GST_BUFFER_DATA (gstbuf), length, gstbuf, gst_soup_http_src_chunk_free); return soupbuf; }
static GstFlowReturn gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) { GstFakeSrc *src; GstBuffer *buf; GstClockTime time; gsize size; src = GST_FAKE_SRC (basesrc); buf = gst_fake_src_create_buffer (src, &size); GST_BUFFER_OFFSET (buf) = offset; if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; GST_BUFFER_DURATION (buf) = size * GST_SECOND / src->datarate; } else if (gst_base_src_is_live (basesrc)) { GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT (src)); if (clock) { time = gst_clock_get_time (clock); time -= gst_element_get_base_time (GST_ELEMENT (src)); gst_object_unref (clock); } else { /* not an error not to have a clock */ time = GST_CLOCK_TIME_NONE; } } else { time = GST_CLOCK_TIME_NONE; } GST_BUFFER_DTS (buf) = time; GST_BUFFER_PTS (buf) = time; if (!src->silent) { gchar dts_str[64], pts_str[64], dur_str[64]; gchar *flag_str; GST_OBJECT_LOCK (src); g_free (src->last_message); if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DTS (buf))); } else { g_strlcpy (dts_str, "none", sizeof (dts_str)); } if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); } else { g_strlcpy (pts_str, "none", sizeof (pts_str)); } if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); } else { g_strlcpy (dur_str, "none", sizeof (dur_str)); } flag_str = gst_buffer_get_flags_string (buf); src->last_message = g_strdup_printf ("create ******* (%s:%s) (%u bytes, dts: %s, pts:%s" ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" G_GINT64_FORMAT ", flags: %08x %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size, dts_str, pts_str, dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf); g_free (flag_str); GST_OBJECT_UNLOCK (src); g_object_notify_by_pspec ((GObject *) src, pspec_last_message); } if (src->signal_handoffs) { GST_LOG_OBJECT (src, "pre handoff emit"); g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf, basesrc->srcpad); GST_LOG_OBJECT (src, "post handoff emit"); } src->bytes_sent += size; *ret = buf; return GST_FLOW_OK; }
static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query) { GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (!gst_audio_info_convert (&src->info, src_fmt, src_val, dest_fmt, &dest_val)) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); res = TRUE; break; } case GST_QUERY_SCHEDULING: { /* if we can operate in pull mode */ gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0); gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); if (src->can_activate_pull) gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL); res = TRUE; break; } case GST_QUERY_LATENCY: { if (src->info.rate > 0) { GstClockTime latency; latency = gst_util_uint64_scale (src->generate_samples_per_buffer, GST_SECOND, src->info.rate); gst_query_set_latency (query, gst_base_src_is_live (GST_BASE_SRC_CAST (src)), latency, GST_CLOCK_TIME_NONE); GST_DEBUG_OBJECT (src, "Reporting latency of %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); res = TRUE; } break; } default: res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); break; } return res; /* ERROR */ error: { GST_DEBUG_OBJECT (src, "query failed"); return FALSE; } }
static GstFlowReturn gst_nanomsgsrc_create(GstPushSrc *psrc, GstBuffer **buf) { gboolean try_again, flushing; GstNanomsgSrc *nanomsgsrc = GST_NANOMSGSRC_CAST(psrc); struct pollfd fds[2]; g_assert(nanomsgsrc->main_fd >= 0); /* Fetch the current state of the flushing flag * this can be modified in the unlock() function by * another thread, so synchronize the access */ LOCK_SRC_MUTEX(nanomsgsrc); flushing = nanomsgsrc->flushing; UNLOCK_SRC_MUTEX(nanomsgsrc); if (flushing) return GST_FLOW_FLUSHING; /* Set up structures for the poll() call below */ fds[0].fd = nanomsgsrc->ctrl_fds[0]; fds[0].events = POLLIN; fds[0].revents = 0; fds[1].fd = nanomsgsrc->watch_fd; fds[1].events = POLLIN; fds[1].revents = 0; do { int ret; try_again = FALSE; ret = poll(fds, 2, (nanomsgsrc->timeout == 0) ? -1 : nanomsgsrc->timeout); if (ret == -1) { /* poll() failed - exit loop and report error */ GST_ERROR_OBJECT(nanomsgsrc, "poll() error: %s", strerror(errno)); return GST_FLOW_ERROR; } else if (ret == 0) { /* Timeout was reached; post message and wait again for data */ GST_LOG_OBJECT(nanomsgsrc, "timeout reached - trying again"); try_again = TRUE; gst_element_post_message( GST_ELEMENT_CAST(nanomsgsrc), gst_message_new_element( GST_OBJECT_CAST(nanomsgsrc), gst_structure_new( "GstNanomsgSrcTimeout", "timeout", G_TYPE_UINT64, nanomsgsrc->timeout, NULL ) ) ); } else { /* At least one FD got data to read */ if (fds[0].revents & POLLIN) { /* Control pipe read end received a wakeup call * Sometimes, unlock_stop() is called so quickly after unlock() * that this loop isn't reached before the unlock_stop() call, * which means that sometimes this wakeup call should actually * be ignored, because the flushing period is over by this point. * For this reason, when a wakeup call is received, the code * checks if flushing is still actually required, and only if * this is the case, the function exits with GST_FLOW_FLUSHING */ char dummy_buf[1024]; if (read(fds[0].fd, dummy_buf, sizeof(dummy_buf)) == -1) GST_ERROR_OBJECT(nanomsgsrc, "error while receiving wakeup call over control pipe: %s", strerror(errno)); LOCK_SRC_MUTEX(nanomsgsrc); flushing = nanomsgsrc->flushing; UNLOCK_SRC_MUTEX(nanomsgsrc); if (flushing) return GST_FLOW_FLUSHING; else { /* Set try_again to TRUE in case no flushing is * actually needed and no data arrived yet */ try_again = TRUE; } } /* NOTE: no "else if". Sometimes, while the unlock() call mentioned * above is finished (instantly followed by the unlock_stop() call * sometimes), data is immediately sent to the SP socket, which means * that there is data to read. */ if (fds[1].revents & POLLIN) { GstBuffer *outbuf; char *msg = NULL; GstFlowReturn flow_ret; int msg_size; /* Get the message from the SP socket. NN_MSG means the returned * msg pointer refers to a buffer allocated internally by nanomsg * with the appropriate size. This is considered more efficient, * since nanomsg may be using zerocopy mechanisms here (and not * actually be allocating anything). Refer to the nn_recv() * reference for details. * Using nn_recv() with the NN_DONTWAIT flag, as an extra error check. * If nn_send() fails because it cannot write anything, then something * is wrong inside nanomsg, since we already waited with poll() for * writing to be possible. Without the NN_DONTWAIT we wouldn't get an * error, and block forever instead.*/ if ((msg_size = nn_recv(nanomsgsrc->main_fd, &msg, NN_MSG, NN_DONTWAIT)) < 0) { GST_ERROR_OBJECT(nanomsgsrc, "error while trying to receive data: %s", strerror(errno)); return GST_FLOW_ERROR; } /* Create a GstBuffer with the appropriate size */ if ((flow_ret = GST_BASE_SRC_CLASS(gst_nanomsgsrc_parent_class)->alloc(GST_BASE_SRC_CAST(psrc), -1, msg_size, &outbuf)) != GST_FLOW_OK) { GST_DEBUG_OBJECT(nanomsgsrc, "could not allocate new output buffer"); nn_freemsg(msg); return flow_ret; } /* Copy the message's bytes over to the GstBuffer */ gst_buffer_fill(outbuf, 0, msg, msg_size); /* Signal nanomsg that the message buffer isn't needed anymore */ nn_freemsg(msg); /* Data *was* actually received, so make sure the loop is exited * (try_again may have been set to TRUE after the control pipe * received a wakeup call even though no flushing was required) */ try_again = FALSE; /* Done */ *buf = outbuf; } } } while (G_UNLIKELY(try_again)); return GST_FLOW_OK; }
static GstFlowReturn gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) { GstFakeSrc *src; GstBuffer *buf; GstClockTime time; gsize size; src = GST_FAKE_SRC (basesrc); buf = gst_fake_src_create_buffer (src, &size); GST_BUFFER_OFFSET (buf) = offset; if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; GST_BUFFER_DURATION (buf) = size * GST_SECOND / src->datarate; } else if (gst_base_src_is_live (basesrc)) { GstClock *clock; clock = gst_element_get_clock (GST_ELEMENT (src)); if (clock) { time = gst_clock_get_time (clock); time -= gst_element_get_base_time (GST_ELEMENT (src)); gst_object_unref (clock); } else { /* not an error not to have a clock */ time = GST_CLOCK_TIME_NONE; } } else { time = GST_CLOCK_TIME_NONE; } GST_BUFFER_DTS (buf) = time; GST_BUFFER_PTS (buf) = time; if (!src->silent) { gchar dts_str[64], pts_str[64], dur_str[64]; gchar flag_str[100]; GST_OBJECT_LOCK (src); g_free (src->last_message); if (GST_BUFFER_DTS (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (dts_str, sizeof (dts_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DTS (buf))); } else { g_strlcpy (dts_str, "none", sizeof (dts_str)); } if (GST_BUFFER_PTS (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (pts_str, sizeof (pts_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); } else { g_strlcpy (pts_str, "none", sizeof (pts_str)); } if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) { g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); } else { g_strlcpy (dur_str, "none", sizeof (dur_str)); } { const char *flag_list[15] = { "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", "marker", "header", "gap", "droppable", "delta-unit", "in-caps" }; int i; char *end = flag_str; end[0] = '\0'; for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { strcpy (end, flag_list[i]); end += strlen (end); end[0] = ' '; end[1] = '\0'; end++; } } } src->last_message = g_strdup_printf ("create ******* (%s:%s) (%u bytes, dts: %s, pts:%s" ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %" G_GINT64_FORMAT ", flags: %08x %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), (guint) size, dts_str, pts_str, dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT_CAST (buf)->flags, flag_str, buf); GST_OBJECT_UNLOCK (src); g_object_notify_by_pspec ((GObject *) src, pspec_last_message); } if (src->signal_handoffs) { GST_LOG_OBJECT (src, "pre handoff emit"); g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf, basesrc->srcpad); GST_LOG_OBJECT (src, "post handoff emit"); } src->bytes_sent += size; *ret = buf; return GST_FLOW_OK; }
static void gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) { const char *value; GstTagList *tag_list; GstBaseSrc *basesrc; guint64 newsize; GHashTable *params = NULL; GST_DEBUG_OBJECT (src, "got headers:"); soup_message_headers_foreach (msg->response_headers, gst_soup_http_src_headers_foreach, src); if (msg->status_code == 407 && src->proxy_id && src->proxy_pw) return; if (src->automatic_redirect && SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { GST_DEBUG_OBJECT (src, "%u redirect to \"%s\"", msg->status_code, soup_message_headers_get_one (msg->response_headers, "Location")); return; } if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) return; src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING; /* Parse Content-Length. */ if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_CONTENT_LENGTH) { newsize = src->request_position + soup_message_headers_get_content_length (msg->response_headers); if (!src->have_size || (src->content_size != newsize)) { src->content_size = newsize; src->have_size = TRUE; src->seekable = TRUE; GST_DEBUG_OBJECT (src, "size = %" G_GUINT64_FORMAT, src->content_size); basesrc = GST_BASE_SRC_CAST (src); gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES, src->content_size); gst_element_post_message (GST_ELEMENT (src), gst_message_new_duration (GST_OBJECT (src), GST_FORMAT_BYTES, src->content_size)); } } /* Icecast stuff */ tag_list = gst_tag_list_new (); if ((value = soup_message_headers_get_one (msg->response_headers, "icy-metaint")) != NULL) { gint icy_metaint = atoi (value); GST_DEBUG_OBJECT (src, "icy-metaint: %s (parsed: %d)", value, icy_metaint); if (icy_metaint > 0) { if (src->src_caps) gst_caps_unref (src->src_caps); src->src_caps = gst_caps_new_simple ("application/x-icy", "metadata-interval", G_TYPE_INT, icy_metaint, NULL); } } if ((value = soup_message_headers_get_content_type (msg->response_headers, ¶ms)) != NULL) { GST_DEBUG_OBJECT (src, "Content-Type: %s", value); if (g_ascii_strcasecmp (value, "audio/L16") == 0) { gint channels = 2; gint rate = 44100; char *param; if (src->src_caps) gst_caps_unref (src->src_caps); param = g_hash_table_lookup (params, "channels"); if (param != NULL) channels = atol (param); param = g_hash_table_lookup (params, "rate"); if (param != NULL) rate = atol (param); src->src_caps = gst_caps_new_simple ("audio/x-raw-int", "channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, rate, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL); } else { /* Set the Content-Type field on the caps */ if (src->src_caps) gst_caps_set_simple (src->src_caps, "content-type", G_TYPE_STRING, value, NULL); } } if (params != NULL) g_hash_table_destroy (params); if ((value = soup_message_headers_get_one (msg->response_headers, "icy-name")) != NULL) { g_free (src->iradio_name); src->iradio_name = gst_soup_http_src_unicodify (value); if (src->iradio_name) { g_object_notify (G_OBJECT (src), "iradio-name"); gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, GST_TAG_ORGANIZATION, src->iradio_name, NULL); } } if ((value = soup_message_headers_get_one (msg->response_headers, "icy-genre")) != NULL) { g_free (src->iradio_genre); src->iradio_genre = gst_soup_http_src_unicodify (value); if (src->iradio_genre) { g_object_notify (G_OBJECT (src), "iradio-genre"); gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE, src->iradio_genre, NULL); } } if ((value = soup_message_headers_get_one (msg->response_headers, "icy-url")) != NULL) { g_free (src->iradio_url); src->iradio_url = gst_soup_http_src_unicodify (value); if (src->iradio_url) { g_object_notify (G_OBJECT (src), "iradio-url"); gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, GST_TAG_LOCATION, src->iradio_url, NULL); } } if (!gst_tag_list_is_empty (tag_list)) { GST_DEBUG_OBJECT (src, "calling gst_element_found_tags with %" GST_PTR_FORMAT, tag_list); gst_element_found_tags (GST_ELEMENT_CAST (src), tag_list); } else { gst_tag_list_free (tag_list); } /* Handle HTTP errors. */ gst_soup_http_src_parse_status (msg, src); /* Check if Range header was respected. */ if (src->ret == GST_FLOW_CUSTOM_ERROR && src->read_position && msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { src->seekable = FALSE; GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (_("Server does not support seeking.")), ("Server does not accept Range HTTP header, URL: %s", src->location)); src->ret = GST_FLOW_ERROR; } }
static GstFlowReturn gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc); GstFlowReturn flow_ret = GST_FLOW_OK; const guint8 *data; gsize data_size; VideoFrame *vf; CaptureFrame *f; GstCaps *caps; gboolean caps_changed = FALSE; g_mutex_lock (&self->lock); while (g_queue_is_empty (&self->current_frames) && !self->flushing) { g_cond_wait (&self->cond, &self->lock); } f = (CaptureFrame *) g_queue_pop_head (&self->current_frames); g_mutex_unlock (&self->lock); if (self->flushing) { if (f) capture_frame_free (f); GST_DEBUG_OBJECT (self, "Flushing"); return GST_FLOW_FLUSHING; } // If we're not flushing, we should have a valid frame from the queue g_assert (f != NULL); g_mutex_lock (&self->lock); if (self->caps_mode != f->mode) { if (self->mode == GST_DECKLINK_MODE_AUTO) { GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode, f->mode); caps_changed = TRUE; self->caps_mode = f->mode; } else { g_mutex_unlock (&self->lock); GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Invalid mode in captured frame"), ("Mode set to %d but captured %d", self->caps_mode, f->mode)); capture_frame_free (f); return GST_FLOW_NOT_NEGOTIATED; } } if (self->caps_format != f->format) { if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO) { GST_DEBUG_OBJECT (self, "Format changed from %d to %d", self->caps_format, f->format); caps_changed = TRUE; self->caps_format = f->format; } else { g_mutex_unlock (&self->lock); GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Invalid pixel format in captured frame"), ("Format set to %d but captured %d", self->caps_format, f->format)); capture_frame_free (f); return GST_FLOW_NOT_NEGOTIATED; } } g_mutex_unlock (&self->lock); if (caps_changed) { caps = gst_decklink_mode_get_caps (f->mode, f->format); gst_video_info_from_caps (&self->info, caps); gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps); gst_element_post_message (GST_ELEMENT_CAST (self), gst_message_new_latency (GST_OBJECT_CAST (self))); gst_caps_unref (caps); } f->frame->GetBytes ((gpointer *) & data); data_size = self->info.size; vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame)); *buffer = gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY, (gpointer) data, data_size, 0, data_size, vf, (GDestroyNotify) video_frame_free); vf->frame = f->frame; f->frame->AddRef (); vf->input = self->input->input; vf->input->AddRef (); GST_BUFFER_TIMESTAMP (*buffer) = f->capture_time; GST_BUFFER_DURATION (*buffer) = f->capture_duration; gst_buffer_add_video_time_code_meta (*buffer, f->tc); GST_DEBUG_OBJECT (self, "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %" GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer))); capture_frame_free (f); return flow_ret; }
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 GstFlowReturn gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc); GstFlowReturn flow_ret = GST_FLOW_OK; const guint8 *data; gsize data_size; VideoFrame *vf; CaptureFrame *f; GstCaps *caps; g_mutex_lock (&self->lock); while (g_queue_is_empty (&self->current_frames) && !self->flushing) { g_cond_wait (&self->cond, &self->lock); } f = (CaptureFrame *) g_queue_pop_head (&self->current_frames); g_mutex_unlock (&self->lock); if (self->flushing) { if (f) capture_frame_free (f); GST_DEBUG_OBJECT (self, "Flushing"); return GST_FLOW_FLUSHING; } g_mutex_lock (&self->lock); if (self->mode == GST_DECKLINK_MODE_AUTO && self->caps_mode != f->mode) { GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode, f->mode); self->caps_mode = f->mode; g_mutex_unlock (&self->lock); caps = gst_decklink_mode_get_caps (f->mode); gst_video_info_from_caps (&self->info, caps); gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps); gst_element_post_message (GST_ELEMENT_CAST (self), gst_message_new_latency (GST_OBJECT_CAST (self))); gst_caps_unref (caps); } else { g_mutex_unlock (&self->lock); } f->frame->GetBytes ((gpointer *) & data); data_size = self->info.size; vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame)); *buffer = gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY, (gpointer) data, data_size, 0, data_size, vf, (GDestroyNotify) video_frame_free); vf->frame = f->frame; f->frame->AddRef (); vf->input = self->input->input; vf->input->AddRef (); GST_BUFFER_TIMESTAMP (*buffer) = f->capture_time; GST_BUFFER_DURATION (*buffer) = f->capture_duration; GST_DEBUG_OBJECT (self, "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %" GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer))); capture_frame_free (f); return flow_ret; }
/* * Read a new buffer from src->reqoffset, takes care of events * and seeking and such. */ static GstFlowReturn gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer) { GstRTMPSrc *src; GstBuffer *buf; GstMapInfo map; guint8 *data; guint todo; gsize bsize; int read; int size; src = GST_RTMP_SRC (pushsrc); g_return_val_if_fail (src->rtmp != NULL, GST_FLOW_ERROR); size = GST_BASE_SRC_CAST (pushsrc)->blocksize; GST_DEBUG ("reading from %" G_GUINT64_FORMAT ", size %u", src->cur_offset, size); buf = gst_buffer_new_allocate (NULL, size, NULL); if (G_UNLIKELY (buf == NULL)) { GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size); return GST_FLOW_ERROR; } bsize = todo = size; gst_buffer_map (buf, &map, GST_MAP_WRITE); data = map.data; read = bsize = 0; while (todo > 0) { read = RTMP_Read (src->rtmp, (char *) data, todo); if (G_UNLIKELY (read == 0 && todo == size)) { goto eos; } else if (G_UNLIKELY (read == 0)) { todo = 0; break; } if (G_UNLIKELY (read < 0)) goto read_failed; if (read < todo) { data += read; todo -= read; bsize += read; } else { bsize += todo; todo = 0; } GST_LOG (" got size %d", read); } gst_buffer_unmap (buf, &map); gst_buffer_resize (buf, 0, bsize); if (src->discont) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); src->discont = FALSE; } GST_BUFFER_TIMESTAMP (buf) = src->last_timestamp; GST_BUFFER_OFFSET (buf) = src->cur_offset; src->cur_offset += size; if (src->last_timestamp == GST_CLOCK_TIME_NONE) src->last_timestamp = src->rtmp->m_mediaStamp * GST_MSECOND; else src->last_timestamp = MAX (src->last_timestamp, src->rtmp->m_mediaStamp * GST_MSECOND); GST_LOG_OBJECT (src, "Created buffer of size %u at %" G_GINT64_FORMAT " with timestamp %" GST_TIME_FORMAT, size, GST_BUFFER_OFFSET (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); /* we're done, return the buffer */ *buffer = buf; return GST_FLOW_OK; read_failed: { gst_buffer_unref (buf); GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Failed to read data")); return GST_FLOW_ERROR; } eos: { gst_buffer_unref (buf); GST_DEBUG_OBJECT (src, "Reading data gave EOS"); return GST_FLOW_EOS; } }