mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
rtmp: port to 0.11
This commit is contained in:
parent
c16cc4698a
commit
9ddfdfe60c
2 changed files with 78 additions and 92 deletions
|
@ -75,63 +75,50 @@ static gboolean gst_rtmp_sink_stop (GstBaseSink * sink);
|
||||||
static gboolean gst_rtmp_sink_start (GstBaseSink * sink);
|
static gboolean gst_rtmp_sink_start (GstBaseSink * sink);
|
||||||
static GstFlowReturn gst_rtmp_sink_render (GstBaseSink * sink, GstBuffer * buf);
|
static GstFlowReturn gst_rtmp_sink_render (GstBaseSink * sink, GstBuffer * buf);
|
||||||
|
|
||||||
static void
|
#define gst_rtmp_sink_parent_class parent_class
|
||||||
_do_init (GType gtype)
|
G_DEFINE_TYPE_WITH_CODE (GstRTMPSink, gst_rtmp_sink, GST_TYPE_BASE_SINK,
|
||||||
{
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
|
||||||
static const GInterfaceInfo urihandler_info = {
|
gst_rtmp_sink_uri_handler_init));
|
||||||
gst_rtmp_sink_uri_handler_init,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
g_type_add_interface_static (gtype, GST_TYPE_URI_HANDLER, &urihandler_info);
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_rtmp_sink_debug, "rtmpsink", 0,
|
|
||||||
"RTMP server element");
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstRTMPSink, gst_rtmp_sink, GstBaseSink,
|
|
||||||
GST_TYPE_BASE_SINK, _do_init);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtmp_sink_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
|
||||||
"RTMP output sink",
|
|
||||||
"Sink/Network", "Sends FLV content to a server via RTMP",
|
|
||||||
"Jan Schmidt <thaytan@noraisin.net>");
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&sink_template));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the plugin's class */
|
/* initialize the plugin's class */
|
||||||
static void
|
static void
|
||||||
gst_rtmp_sink_class_init (GstRTMPSinkClass * klass)
|
gst_rtmp_sink_class_init (GstRTMPSinkClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass;
|
GstElementClass *gstelement_class;
|
||||||
|
GstBaseSinkClass *gstbasesink_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
gstbasesink_class = (GstBaseSinkClass *) klass;
|
||||||
|
|
||||||
gobject_class->set_property = gst_rtmp_sink_set_property;
|
gobject_class->set_property = gst_rtmp_sink_set_property;
|
||||||
gobject_class->get_property = gst_rtmp_sink_get_property;
|
gobject_class->get_property = gst_rtmp_sink_get_property;
|
||||||
|
|
||||||
|
gst_element_class_install_std_props (gstelement_class,
|
||||||
|
"location", PROP_LOCATION, G_PARAM_READWRITE, NULL);
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"RTMP output sink",
|
||||||
|
"Sink/Network", "Sends FLV content to a server via RTMP",
|
||||||
|
"Jan Schmidt <thaytan@noraisin.net>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
|
||||||
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_rtmp_sink_start);
|
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_rtmp_sink_start);
|
||||||
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_rtmp_sink_stop);
|
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_rtmp_sink_stop);
|
||||||
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_rtmp_sink_render);
|
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_rtmp_sink_render);
|
||||||
|
|
||||||
gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass),
|
GST_DEBUG_CATEGORY_INIT (gst_rtmp_sink_debug, "rtmpsink", 0,
|
||||||
"location", PROP_LOCATION, G_PARAM_READWRITE, NULL);
|
"RTMP server element");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the new element
|
/* initialize the new element
|
||||||
* initialize instance structure
|
* initialize instance structure
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gst_rtmp_sink_init (GstRTMPSink * sink, GstRTMPSinkClass * klass)
|
gst_rtmp_sink_init (GstRTMPSink * sink)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +181,8 @@ gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstRTMPSink *sink = GST_RTMP_SINK (bsink);
|
GstRTMPSink *sink = GST_RTMP_SINK (bsink);
|
||||||
GstBuffer *reffed_buf = NULL;
|
GstBuffer *reffed_buf = NULL;
|
||||||
|
guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
if (sink->first) {
|
if (sink->first) {
|
||||||
/* open the connection */
|
/* open the connection */
|
||||||
|
@ -214,7 +203,7 @@ gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
/* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
|
/* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
|
||||||
* of just assuming it's only the header */
|
* of just assuming it's only the header */
|
||||||
GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
|
GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
|
||||||
GST_BUFFER_SIZE (buf));
|
gst_buffer_get_size (buf));
|
||||||
gst_buffer_replace (&sink->cache, buf);
|
gst_buffer_replace (&sink->cache, buf);
|
||||||
sink->first = FALSE;
|
sink->first = FALSE;
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -222,40 +211,48 @@ gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
|
|
||||||
if (sink->cache) {
|
if (sink->cache) {
|
||||||
GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
|
GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
|
||||||
GST_BUFFER_SIZE (buf));
|
gst_buffer_get_size (buf));
|
||||||
gst_buffer_ref (buf);
|
gst_buffer_ref (buf);
|
||||||
reffed_buf = buf = gst_buffer_join (sink->cache, buf);
|
reffed_buf = buf = gst_buffer_join (sink->cache, buf);
|
||||||
sink->cache = NULL;
|
sink->cache = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
|
GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
|
||||||
GST_BUFFER_SIZE (buf));
|
gst_buffer_get_size (buf));
|
||||||
|
|
||||||
if (!RTMP_Write (sink->rtmp,
|
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||||
(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 (!RTMP_Write (sink->rtmp, (char *) data, size))
|
||||||
|
goto write_failed;
|
||||||
|
|
||||||
|
gst_buffer_unmap (buf, data, size);
|
||||||
if (reffed_buf)
|
if (reffed_buf)
|
||||||
gst_buffer_unref (reffed_buf);
|
gst_buffer_unref (reffed_buf);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
write_failed:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
|
||||||
|
gst_buffer_unmap (buf, data, size);
|
||||||
|
if (reffed_buf)
|
||||||
|
gst_buffer_unref (reffed_buf);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* URI interface support.
|
* URI interface support.
|
||||||
*/
|
*/
|
||||||
static GstURIType
|
static GstURIType
|
||||||
gst_rtmp_sink_uri_get_type (void)
|
gst_rtmp_sink_uri_get_type (GType type)
|
||||||
{
|
{
|
||||||
return GST_URI_SINK;
|
return GST_URI_SINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar **
|
static gchar **
|
||||||
gst_rtmp_sink_uri_get_protocols (void)
|
gst_rtmp_sink_uri_get_protocols (GType type)
|
||||||
{
|
{
|
||||||
static gchar *protocols[] =
|
static gchar *protocols[] =
|
||||||
{ (char *) "rtmp", (char *) "rtmpt", (char *) "rtmps", (char *) "rtmpe",
|
{ (char *) "rtmp", (char *) "rtmpt", (char *) "rtmps", (char *) "rtmpe",
|
||||||
|
|
|
@ -88,47 +88,21 @@ static GstFlowReturn gst_rtmp_src_create (GstPushSrc * pushsrc,
|
||||||
GstBuffer ** buffer);
|
GstBuffer ** buffer);
|
||||||
static gboolean gst_rtmp_src_query (GstBaseSrc * src, GstQuery * query);
|
static gboolean gst_rtmp_src_query (GstBaseSrc * src, GstQuery * query);
|
||||||
|
|
||||||
static void
|
#define gst_rtmp_src_parent_class parent_class
|
||||||
_do_init (GType gtype)
|
G_DEFINE_TYPE_WITH_CODE (GstRTMPSrc, gst_rtmp_src, GST_TYPE_PUSH_SRC,
|
||||||
{
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
|
||||||
static const GInterfaceInfo urihandler_info = {
|
gst_rtmp_src_uri_handler_init));
|
||||||
gst_rtmp_src_uri_handler_init,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
g_type_add_interface_static (gtype, GST_TYPE_URI_HANDLER, &urihandler_info);
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (rtmpsrc_debug, "rtmpsrc", 0, "RTMP Source");
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstRTMPSrc, gst_rtmp_src, GstPushSrc, GST_TYPE_PUSH_SRC,
|
|
||||||
_do_init);
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_rtmp_src_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&srctemplate));
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
|
||||||
"RTMP Source",
|
|
||||||
"Source/File",
|
|
||||||
"Read RTMP streams",
|
|
||||||
"Bastien Nocera <hadess@hadess.net>, "
|
|
||||||
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtmp_src_class_init (GstRTMPSrcClass * klass)
|
gst_rtmp_src_class_init (GstRTMPSrcClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
GstBaseSrcClass *gstbasesrc_class;
|
GstBaseSrcClass *gstbasesrc_class;
|
||||||
GstPushSrcClass *gstpushsrc_class;
|
GstPushSrcClass *gstpushsrc_class;
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS (klass);
|
gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||||
gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
|
gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
|
||||||
gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
|
gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
|
||||||
|
|
||||||
|
@ -137,9 +111,19 @@ gst_rtmp_src_class_init (GstRTMPSrcClass * klass)
|
||||||
gobject_class->get_property = gst_rtmp_src_get_property;
|
gobject_class->get_property = gst_rtmp_src_get_property;
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass),
|
gst_element_class_install_std_props (gstelement_class,
|
||||||
"location", PROP_LOCATION, G_PARAM_READWRITE, NULL);
|
"location", PROP_LOCATION, G_PARAM_READWRITE, NULL);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&srctemplate));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"RTMP Source",
|
||||||
|
"Source/File",
|
||||||
|
"Read RTMP streams",
|
||||||
|
"Bastien Nocera <hadess@hadess.net>, "
|
||||||
|
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||||
|
|
||||||
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_rtmp_src_start);
|
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_rtmp_src_start);
|
||||||
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rtmp_src_stop);
|
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rtmp_src_stop);
|
||||||
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_rtmp_src_is_seekable);
|
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_rtmp_src_is_seekable);
|
||||||
|
@ -148,10 +132,12 @@ gst_rtmp_src_class_init (GstRTMPSrcClass * klass)
|
||||||
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_rtmp_src_do_seek);
|
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_rtmp_src_do_seek);
|
||||||
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rtmp_src_create);
|
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rtmp_src_create);
|
||||||
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_rtmp_src_query);
|
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_rtmp_src_query);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (rtmpsrc_debug, "rtmpsrc", 0, "RTMP Source");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtmp_src_init (GstRTMPSrc * rtmpsrc, GstRTMPSrcClass * klass)
|
gst_rtmp_src_init (GstRTMPSrc * rtmpsrc)
|
||||||
{
|
{
|
||||||
rtmpsrc->cur_offset = 0;
|
rtmpsrc->cur_offset = 0;
|
||||||
rtmpsrc->last_timestamp = 0;
|
rtmpsrc->last_timestamp = 0;
|
||||||
|
@ -175,13 +161,13 @@ gst_rtmp_src_finalize (GObject * object)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static GstURIType
|
static GstURIType
|
||||||
gst_rtmp_src_uri_get_type (void)
|
gst_rtmp_src_uri_get_type (GType type)
|
||||||
{
|
{
|
||||||
return GST_URI_SRC;
|
return GST_URI_SRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar **
|
static gchar **
|
||||||
gst_rtmp_src_uri_get_protocols (void)
|
gst_rtmp_src_uri_get_protocols (GType type)
|
||||||
{
|
{
|
||||||
static gchar *protocols[] =
|
static gchar *protocols[] =
|
||||||
{ (char *) "rtmp", (char *) "rtmpt", (char *) "rtmps", (char *) "rtmpe",
|
{ (char *) "rtmp", (char *) "rtmpt", (char *) "rtmps", (char *) "rtmpe",
|
||||||
|
@ -286,8 +272,9 @@ gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
|
||||||
{
|
{
|
||||||
GstRTMPSrc *src;
|
GstRTMPSrc *src;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
guint8 *data;
|
guint8 *data, *bdata;
|
||||||
guint todo;
|
guint todo;
|
||||||
|
gsize bsize;
|
||||||
int read;
|
int read;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
|
@ -300,15 +287,15 @@ gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
|
||||||
GST_DEBUG ("reading from %" G_GUINT64_FORMAT
|
GST_DEBUG ("reading from %" G_GUINT64_FORMAT
|
||||||
", size %u", src->cur_offset, size);
|
", size %u", src->cur_offset, size);
|
||||||
|
|
||||||
buf = gst_buffer_try_new_and_alloc (size);
|
buf = gst_buffer_new_allocate (NULL, size, 0);
|
||||||
if (G_UNLIKELY (buf == NULL)) {
|
if (G_UNLIKELY (buf == NULL)) {
|
||||||
GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
|
GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo = size;
|
bsize = todo = size;
|
||||||
data = GST_BUFFER_DATA (buf);
|
bdata = data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||||
read = 0;
|
read = bsize = 0;
|
||||||
|
|
||||||
while (todo > 0) {
|
while (todo > 0) {
|
||||||
read = RTMP_Read (src->rtmp, (char *) data, todo);
|
read = RTMP_Read (src->rtmp, (char *) data, todo);
|
||||||
|
@ -316,7 +303,6 @@ gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
|
||||||
if (G_UNLIKELY (read == 0 && todo == size)) {
|
if (G_UNLIKELY (read == 0 && todo == size)) {
|
||||||
goto eos;
|
goto eos;
|
||||||
} else if (G_UNLIKELY (read == 0)) {
|
} else if (G_UNLIKELY (read == 0)) {
|
||||||
GST_BUFFER_SIZE (buf) -= todo;
|
|
||||||
todo = 0;
|
todo = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -325,13 +311,16 @@ gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
|
||||||
goto read_failed;
|
goto read_failed;
|
||||||
|
|
||||||
if (read < todo) {
|
if (read < todo) {
|
||||||
data = &data[read];
|
data += read;
|
||||||
todo -= read;
|
todo -= read;
|
||||||
|
bsize += read;
|
||||||
} else {
|
} else {
|
||||||
todo = 0;
|
todo = 0;
|
||||||
|
bsize += todo;
|
||||||
}
|
}
|
||||||
GST_LOG (" got size %d", read);
|
GST_LOG (" got size %d", read);
|
||||||
}
|
}
|
||||||
|
gst_buffer_unmap (buf, bdata, bsize);
|
||||||
|
|
||||||
if (src->discont) {
|
if (src->discont) {
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
@ -465,7 +454,7 @@ gst_rtmp_src_prepare_seek_segment (GstBaseSrc * basesrc, GstEvent * event,
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_segment_init (segment, GST_FORMAT_TIME);
|
gst_segment_init (segment, GST_FORMAT_TIME);
|
||||||
gst_segment_set_seek (segment, rate, format, flags, cur_type, cur, stop_type,
|
gst_segment_do_seek (segment, rate, format, flags, cur_type, cur, stop_type,
|
||||||
stop, NULL);
|
stop, NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in a new issue