Esempio n. 1
1
/**
 * 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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
  }
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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 ();
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
  }
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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,
              &params)) != 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;
}
Esempio n. 15
0
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;
}
Esempio n. 17
0
/*
 * 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;
  }
}