示例#1
0
static gboolean
gst_rtmp_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
  GstRTMPSink *sink = GST_RTMP_SINK (handler);

  if (GST_STATE (sink) >= GST_STATE_PAUSED)
    return FALSE;

  g_free (sink->uri);
  sink->uri = NULL;

  if (uri != NULL) {
    int protocol;
    AVal host;
    unsigned int port;
    AVal playpath, app;

    if (!RTMP_ParseURL (uri, &protocol, &host, &port, &playpath, &app) ||
        !host.av_len || !playpath.av_len) {
      GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
          ("Failed to parse URI %s", uri), (NULL));
      return FALSE;
    }
    sink->uri = g_strdup (uri);
  }

  GST_DEBUG_OBJECT (sink, "Changed URI to %s", GST_STR_NULL (uri));

  return TRUE;
}
示例#2
0
static gboolean
gst_rtmp_sink_start (GstBaseSink * basesink)
{
  GstRTMPSink *sink = GST_RTMP_SINK (basesink);

  if (!sink->uri) {
    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
        ("Please set URI for RTMP output"), ("No URI set before starting"));
    return FALSE;
  }

  sink->rtmp_uri = g_strdup (sink->uri);
  sink->rtmp = RTMP_Alloc ();
  RTMP_Init (sink->rtmp);
  if (!RTMP_SetupURL (sink->rtmp, sink->rtmp_uri)) {
    GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
        ("Failed to setup URL '%s'", sink->uri));
    RTMP_Free (sink->rtmp);
    sink->rtmp = NULL;
    g_free (sink->rtmp_uri);
    sink->rtmp_uri = NULL;
    return FALSE;
  }

  GST_DEBUG_OBJECT (sink, "Created RTMP object");

  /* Mark this as an output connection */
  RTMP_EnableWrite (sink->rtmp);

  sink->first = TRUE;

  return TRUE;
}
示例#3
0
static const gchar *
gst_rtmp_sink_uri_get_uri (GstURIHandler * handler)
{
  GstRTMPSink *sink = GST_RTMP_SINK (handler);

  return sink->uri;
}
示例#4
0
static gchar *
gst_rtmp_sink_uri_get_uri (GstURIHandler * handler)
{
  GstRTMPSink *sink = GST_RTMP_SINK (handler);

  /* FIXME: make thread-safe */
  return g_strdup (sink->uri);
}
示例#5
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;

  if (sink->first) {
    /* open the connection */
    if (!RTMP_IsConnected (sink->rtmp)) {
      if (!RTMP_Connect (sink->rtmp, NULL)
          || !RTMP_ConnectStream (sink->rtmp, 0)) {
        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
        RTMP_Free (sink->rtmp);
        sink->rtmp = NULL;
        g_free (sink->rtmp_uri);
        sink->rtmp_uri = NULL;
        return GST_FLOW_ERROR;
      }
      GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
    }

    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
        GST_BUFFER_SIZE (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
        GST_BUFFER_SIZE (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_join (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
      GST_BUFFER_SIZE (buf));

  if (!RTMP_Write (sink->rtmp,
          (char *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf))) {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }

  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;
}
示例#6
0
static void
gst_rtmp_sink_finalize (GObject * object)
{
  GstRTMPSink *sink = GST_RTMP_SINK (object);

#ifdef G_OS_WIN32
  WSACleanup ();
#endif
  g_free (sink->uri);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
示例#7
0
static void
gst_rtmp_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstRTMPSink *sink = GST_RTMP_SINK (object);

  switch (prop_id) {
    case PROP_LOCATION:
      g_value_set_string (value, sink->uri);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
示例#8
0
static gboolean
gst_rtmp_sink_event (GstBaseSink * sink, GstEvent * event)
{
  GstRTMPSink *rtmpsink = GST_RTMP_SINK (sink);

  switch (event->type) {
    case GST_EVENT_FLUSH_STOP:
      rtmpsink->have_write_error = FALSE;
      break;
    default:
      break;
  }

  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
}
示例#9
0
static void
gst_rtmp_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRTMPSink *sink = GST_RTMP_SINK (object);

  switch (prop_id) {
    case PROP_LOCATION:
      gst_rtmp_sink_uri_set_uri (GST_URI_HANDLER (sink),
          g_value_get_string (value), NULL);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
示例#10
0
static gboolean
gst_rtmp_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
    GError ** error)
{
  GstRTMPSink *sink = GST_RTMP_SINK (handler);
  gboolean ret = TRUE;

  if (GST_STATE (sink) >= GST_STATE_PAUSED) {
    g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE,
        "Changing the URI on rtmpsink when it is running is not supported");
    return FALSE;
  }

  g_free (sink->uri);
  sink->uri = NULL;

  if (uri != NULL) {
    int protocol;
    AVal host;
    unsigned int port;
    AVal playpath, app;

    if (!RTMP_ParseURL (uri, &protocol, &host, &port, &playpath, &app) ||
        !host.av_len) {
      GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
          ("Failed to parse URI %s", uri), (NULL));
      g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
          "Could not parse RTMP URI");
      ret = FALSE;
    } else {
      sink->uri = g_strdup (uri);
    }

    if (playpath.av_val)
      free (playpath.av_val);
  }

  if (ret) {
    sink->have_write_error = FALSE;
    GST_DEBUG_OBJECT (sink, "Changed URI to %s", GST_STR_NULL (uri));
  }

  return ret;
}
示例#11
0
static gboolean
gst_rtmp_sink_stop (GstBaseSink * basesink)
{
  GstRTMPSink *sink = GST_RTMP_SINK (basesink);

  gst_buffer_replace (&sink->cache, NULL);

  if (sink->rtmp) {
    RTMP_Close (sink->rtmp);
    RTMP_Free (sink->rtmp);
    sink->rtmp = NULL;
  }
  if (sink->rtmp_uri) {
    g_free (sink->rtmp_uri);
    sink->rtmp_uri = NULL;
  }

  return TRUE;
}
示例#12
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;

  if (sink->first) {
    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
        GST_BUFFER_SIZE (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
        GST_BUFFER_SIZE (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_join (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
      GST_BUFFER_SIZE (buf));

  if (!RTMP_Write (sink->rtmp,
          (char *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf))) {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }

  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;
}
示例#13
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;
  GstMapInfo map;

  if (sink->first) {
    /* open the connection */
    if (!RTMP_IsConnected (sink->rtmp)) {
      if (!RTMP_Connect (sink->rtmp, NULL)
          || !RTMP_ConnectStream (sink->rtmp, 0)) {
        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
        RTMP_Free (sink->rtmp);
        sink->rtmp = NULL;
        g_free (sink->rtmp_uri);
        sink->rtmp_uri = NULL;
        return GST_FLOW_ERROR;
      }
      GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
    }

    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %" G_GSIZE_FORMAT
        " for concatenation", gst_buffer_get_size (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %" G_GSIZE_FORMAT
        " to cached buf", gst_buffer_get_size (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_append (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %" G_GSIZE_FORMAT " bytes to RTMP server",
      gst_buffer_get_size (buf));

  gst_buffer_map (buf, &map, GST_MAP_READ);

  if (RTMP_Write (sink->rtmp, (char *) map.data, map.size) <= 0)
    goto write_failed;

  gst_buffer_unmap (buf, &map);
  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;

  /* ERRORS */
write_failed:
  {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    gst_buffer_unmap (buf, &map);
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }
}