Commit e9de36e3 authored by Wim Taymans's avatar Wim Taymans

Ported tcp plugins to 0.9.

Original commit message from CVS:
* configure.ac:
* gst/tcp/Makefile.am:
* gst/tcp/README:
* gst/tcp/gstmultifdsink.c: (gst_multifdsink_get_type),
(gst_multifdsink_base_init), (gst_multifdsink_class_init),
(gst_multifdsink_init), (gst_multifdsink_remove_client_link),
(is_sync_frame), (gst_multifdsink_handle_client_write),
(gst_multifdsink_render), (gst_multifdsink_start),
(gst_multifdsink_stop), (gst_multifdsink_change_state):
* gst/tcp/gstmultifdsink.h:
* gst/tcp/gsttcp.c: (gst_tcp_host_to_ip),
(gst_tcp_gdp_read_buffer), (gst_tcp_gdp_read_caps),
(gst_tcp_gdp_write_buffer), (gst_tcp_gdp_write_caps):
* gst/tcp/gsttcp.h:
* gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_class_init),
(gst_tcpclientsink_init), (gst_tcpclientsink_setcaps),
(gst_tcpclientsink_render), (gst_tcpclientsink_start),
(gst_tcpclientsink_stop), (gst_tcpclientsink_change_state):
* gst/tcp/gsttcpclientsink.h:
* gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get_type),
(gst_tcpclientsrc_base_init), (gst_tcpclientsrc_class_init),
(gst_tcpclientsrc_init), (gst_tcpclientsrc_getcaps),
(gst_tcpclientsrc_create), (gst_tcpclientsrc_start),
(gst_tcpclientsrc_stop), (gst_tcpclientsrc_unlock):
* gst/tcp/gsttcpclientsrc.h:
* gst/tcp/gsttcpplugin.c: (plugin_init):
* gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init):
* gst/tcp/gsttcpserversink.h:
* gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_get_type),
(gst_tcpserversrc_base_init), (gst_tcpserversrc_class_init),
(gst_tcpserversrc_init), (gst_tcpserversrc_finalize),
(gst_tcpserversrc_create), (gst_tcpserversrc_start),
(gst_tcpserversrc_stop):
* gst/tcp/gsttcpserversrc.h:
* gst/tcp/gsttcpsink.c:
* gst/tcp/gsttcpsink.h:
* gst/tcp/gsttcpsrc.c:
* gst/tcp/gsttcpsrc.h:
Ported tcp plugins to 0.9.
parent 207c8ee7
2005-07-05 Wim Taymans <wim@fluendo.com>
* configure.ac:
* gst/tcp/Makefile.am:
* gst/tcp/README:
* gst/tcp/gstmultifdsink.c: (gst_multifdsink_get_type),
(gst_multifdsink_base_init), (gst_multifdsink_class_init),
(gst_multifdsink_init), (gst_multifdsink_remove_client_link),
(is_sync_frame), (gst_multifdsink_handle_client_write),
(gst_multifdsink_render), (gst_multifdsink_start),
(gst_multifdsink_stop), (gst_multifdsink_change_state):
* gst/tcp/gstmultifdsink.h:
* gst/tcp/gsttcp.c: (gst_tcp_host_to_ip),
(gst_tcp_gdp_read_buffer), (gst_tcp_gdp_read_caps),
(gst_tcp_gdp_write_buffer), (gst_tcp_gdp_write_caps):
* gst/tcp/gsttcp.h:
* gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_class_init),
(gst_tcpclientsink_init), (gst_tcpclientsink_setcaps),
(gst_tcpclientsink_render), (gst_tcpclientsink_start),
(gst_tcpclientsink_stop), (gst_tcpclientsink_change_state):
* gst/tcp/gsttcpclientsink.h:
* gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get_type),
(gst_tcpclientsrc_base_init), (gst_tcpclientsrc_class_init),
(gst_tcpclientsrc_init), (gst_tcpclientsrc_getcaps),
(gst_tcpclientsrc_create), (gst_tcpclientsrc_start),
(gst_tcpclientsrc_stop), (gst_tcpclientsrc_unlock):
* gst/tcp/gsttcpclientsrc.h:
* gst/tcp/gsttcpplugin.c: (plugin_init):
* gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init):
* gst/tcp/gsttcpserversink.h:
* gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_get_type),
(gst_tcpserversrc_base_init), (gst_tcpserversrc_class_init),
(gst_tcpserversrc_init), (gst_tcpserversrc_finalize),
(gst_tcpserversrc_create), (gst_tcpserversrc_start),
(gst_tcpserversrc_stop):
* gst/tcp/gsttcpserversrc.h:
* gst/tcp/gsttcpsink.c:
* gst/tcp/gsttcpsink.h:
* gst/tcp/gsttcpsrc.c:
* gst/tcp/gsttcpsrc.h:
Ported tcp plugins to 0.9.
2005-07-05 Andy Wingo <wingo@pobox.com>
* gst/playback/gstplaybasebin.c (fill_buffer):
......
......@@ -237,6 +237,16 @@ fi
AC_SUBST(GST_CONTROL_LIBS)
dnl check for gstreamer-dataprotocol; uninstalled is selected preferentially
PKG_CHECK_MODULES(GST_GDP, gstreamer-dataprotocol-$GST_MAJORMINOR >= $GST_REQ,
HAVE_GST_GDP="yes", HAVE_GST_GDP="no")
if test "x$HAVE_GST_GDP" = "xno"; then
AC_MSG_ERROR(no GStreamer Dataprotocol Libs found)
fi
AC_SUBST(GST_GDP_LIBS)
PKG_CHECK_MODULES(GST_BASE, gstreamer-base-$GST_MAJORMINOR >= $GST_REQ,
HAVE_GST_BASE="yes", HAVE_GST_BASE="no")
......@@ -375,6 +385,7 @@ GST_PLUGINS_ALL="\
playback \
sine \
subparse \
tcp \
typefind \
videotestsrc \
videorate \
......@@ -883,6 +894,7 @@ gst/ffmpegcolorspace/Makefile
gst/playback/Makefile
gst/sine/Makefile
gst/subparse/Makefile
gst/tcp/Makefile
gst/typefind/Makefile
gst/videotestsrc/Makefile
gst/videorate/Makefile
......
......@@ -14,7 +14,6 @@ BUILT_SOURCES = $(built_sources) $(built_headers)
libgsttcp_la_SOURCES = \
gsttcpplugin.c \
gsttcpsrc.c gsttcpsink.c \
gsttcp.c \
gstfdset.c \
gstmultifdsink.c \
......@@ -27,11 +26,10 @@ nodist_libgsttcp_la_SOURCES = \
# remove ENABLE_NEW when dataprotocol is stable
libgsttcp_la_CFLAGS = $(GST_CFLAGS) -DGST_ENABLE_NEW
libgsttcp_la_LIBADD =
libgsttcp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgsttcp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_GDP_LIBS)
noinst_HEADERS = \
gsttcpplugin.h \
gsttcpsrc.h gsttcpsink.h \
gsttcp.h \
gstfdset.h \
gstmultifdsink.h \
......
......@@ -4,8 +4,6 @@ This part of the documentation is for the new tcp elements:
- tcpserversrc
- tcpserversink
which are created to replace the old tcpsrc/tcpsink
TESTS
-----
Use these tests to test functionality of the various tcp plugins
......@@ -31,33 +29,3 @@ TODO
----
- implement DNS resolution
--------
This is the old documentation for the original tcpsrc/tcpsink elements.
* What is TCP src/sink?
solution, like icecast or realaudio or whatever.
But the future RTP plugins shall not do the actual transmission/reception
of packets on the network themselve but the Application developer would be
encouraged to use either the TCP or the UDP plugins for that. UDP would be
used mostly but there could be situations where TCP would be the only
available choice. For example streaming accross firewalls that do not
allow UDP.
* Shortcomings
Even given our modest ambitions, the current code doesn't handle
caps negotiation robustly.
* Todo
The caps nego should do bi-directional negotiation.
Perhaps this plugin can be the example of how to do caps negotiation
via a point-to-point protocol.
12 Sep 2001
Wim Taymans <wim.taymans@chello.be>
Joshua N Pritikin <vishnu@pobox.com>
Zeeshan Ali <zak147@yahoo.com>
......@@ -66,6 +66,11 @@ GST_ELEMENT_DETAILS ("MultiFd sink",
"Thomas Vander Stichele <thomas at apestaart dot org>, "
"Wim Taymans <wim@fluendo.com>");
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY (multifdsink_debug);
#define GST_CAT_DEFAULT (multifdsink_debug)
......@@ -215,7 +220,8 @@ static void gst_multifdsink_init (GstMultiFdSink * multifdsink);
static void gst_multifdsink_remove_client_link (GstMultiFdSink * sink,
GList * link);
static void gst_multifdsink_chain (GstPad * pad, GstData * _data);
static GstFlowReturn gst_multifdsink_render (GstBaseSink * bsink,
GstBuffer * buf);
static GstElementStateReturn gst_multifdsink_change_state (GstElement *
element);
......@@ -250,7 +256,7 @@ gst_multifdsink_get_type (void)
};
multifdsink_type =
g_type_register_static (GST_TYPE_ELEMENT, "GstMultiFdSink",
g_type_register_static (GST_TYPE_BASESINK, "GstMultiFdSink",
&multifdsink_info, 0);
}
return multifdsink_type;
......@@ -261,6 +267,9 @@ gst_multifdsink_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 (&sinktemplate));
gst_element_class_set_details (element_class, &gst_multifdsink_details);
}
......@@ -269,11 +278,16 @@ gst_multifdsink_class_init (GstMultiFdSinkClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSinkClass *gstbasesink_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_BASESINK);
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
gobject_class->set_property = gst_multifdsink_set_property;
gobject_class->get_property = gst_multifdsink_get_property;
g_object_class_install_property (gobject_class, ARG_PROTOCOL,
g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in",
......@@ -375,11 +389,10 @@ gst_multifdsink_class_init (GstMultiFdSinkClass * klass)
client_removed), NULL, NULL, gst_tcp_marshal_VOID__INT_BOXED,
G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS);
gobject_class->set_property = gst_multifdsink_set_property;
gobject_class->get_property = gst_multifdsink_get_property;
gstelement_class->change_state = gst_multifdsink_change_state;
gstbasesink_class->render = gst_multifdsink_render;
klass->add = gst_multifdsink_add;
klass->remove = gst_multifdsink_remove;
klass->clear = gst_multifdsink_clear;
......@@ -391,11 +404,6 @@ gst_multifdsink_class_init (GstMultiFdSinkClass * klass)
static void
gst_multifdsink_init (GstMultiFdSink * this)
{
/* create the sink pad */
this->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (this), this->sinkpad);
gst_pad_set_chain_function (this->sinkpad, gst_multifdsink_chain);
GST_FLAG_UNSET (this, GST_MULTIFDSINK_OPEN);
this->protocol = DEFAULT_PROTOCOL;
......@@ -636,7 +644,7 @@ gst_multifdsink_remove_client_link (GstMultiFdSink * sink, GList * link)
client->disconnect_time = GST_TIMEVAL_TO_TIME (now);
/* free client buffers */
g_slist_foreach (client->sending, (GFunc) gst_data_unref, NULL);
g_slist_foreach (client->sending, (GFunc) gst_mini_object_unref, NULL);
g_slist_free (client->sending);
client->sending = NULL;
......@@ -777,9 +785,9 @@ gst_multifdsink_client_queue_caps (GstMultiFdSink * sink, GstTCPClient * client,
static gboolean
is_sync_frame (GstMultiFdSink * sink, GstBuffer * buffer)
{
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DELTA_UNIT)) {
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
return FALSE;
} else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_IN_CAPS)) {
} else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) {
return TRUE;
}
return FALSE;
......@@ -934,7 +942,8 @@ gst_multifdsink_handle_client_write (GstMultiFdSink * sink,
/* when using GDP, first check if we have queued caps yet */
if (sink->protocol == GST_TCP_PROTOCOL_TYPE_GDP) {
if (!client->caps_sent) {
const GstCaps *caps = GST_PAD_CAPS (GST_PAD_PEER (sink->sinkpad));
const GstCaps *caps =
GST_PAD_CAPS (GST_PAD_PEER (GST_BASESINK_PAD (sink)));
/* queue caps for sending */
res = gst_multifdsink_client_queue_caps (sink, client, caps);
......@@ -1443,32 +1452,28 @@ gst_multifdsink_thread (GstMultiFdSink * sink)
return NULL;
}
static void
gst_multifdsink_chain (GstPad * pad, GstData * _data)
static GstFlowReturn
gst_multifdsink_render (GstBaseSink * bsink, GstBuffer * buf)
{
GstBuffer *buf = GST_BUFFER (_data);
GstMultiFdSink *sink;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
sink = GST_MULTIFDSINK (GST_OBJECT_PARENT (pad));
g_return_if_fail (GST_FLAG_IS_SET (sink, GST_MULTIFDSINK_OPEN));
sink = GST_MULTIFDSINK (bsink);
if (GST_IS_EVENT (buf)) {
g_warning ("FIXME: handle events");
return;
}
/* since we keep this buffer out of the scope of this method */
gst_buffer_ref (buf);
g_return_val_if_fail (GST_FLAG_IS_SET (sink, GST_MULTIFDSINK_OPEN),
GST_FLOW_ERROR);
GST_LOG_OBJECT (sink, "received buffer %p", buf);
/* if we get IN_CAPS buffers, but the previous buffer was not IN_CAPS,
* it means we're getting new streamheader buffers, and we should clear
* the old ones */
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_IN_CAPS) &&
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS) &&
sink->previous_buffer_in_caps == FALSE) {
GST_DEBUG_OBJECT (sink,
"receiving new IN_CAPS buffers, clearing old streamheader");
g_slist_foreach (sink->streamheader, (GFunc) gst_data_unref, NULL);
g_slist_foreach (sink->streamheader, (GFunc) gst_mini_object_unref, NULL);
g_slist_free (sink->streamheader);
sink->streamheader = NULL;
}
......@@ -1478,13 +1483,13 @@ gst_multifdsink_chain (GstPad * pad, GstData * _data)
* After that we return, since we only send these out when we get
* non IN_CAPS buffers so we properly keep track of clients that got
* streamheaders. */
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_IN_CAPS)) {
if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS)) {
sink->previous_buffer_in_caps = TRUE;
GST_DEBUG_OBJECT (sink,
"appending IN_CAPS buffer with length %d to streamheader",
GST_BUFFER_SIZE (buf));
sink->streamheader = g_slist_append (sink->streamheader, buf);
return;
return GST_FLOW_OK;
}
sink->previous_buffer_in_caps = FALSE;
......@@ -1492,6 +1497,8 @@ gst_multifdsink_chain (GstPad * pad, GstData * _data)
gst_multifdsink_queue_buffer (sink, buf);
sink->bytes_to_serve += GST_BUFFER_SIZE (buf);
return GST_FLOW_OK;
}
static void
......@@ -1617,21 +1624,24 @@ gst_multifdsink_get_property (GObject * object, guint prop_id, GValue * value,
/* create a socket for sending to remote machine */
static gboolean
gst_multifdsink_init_send (GstMultiFdSink * this)
gst_multifdsink_start (GstBaseSink * bsink)
{
GstMultiFdSinkClass *fclass;
int control_socket[2];
GstMultiFdSink *this;
if (GST_FLAG_IS_SET (bsink, GST_MULTIFDSINK_OPEN))
return TRUE;
this = GST_MULTIFDSINK (bsink);
fclass = GST_MULTIFDSINK_GET_CLASS (this);
GST_INFO_OBJECT (this, "starting in mode %d", this->mode);
this->fdset = gst_fdset_new (this->mode);
if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_socket) < 0) {
GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ_WRITE, (NULL),
GST_ERROR_SYSTEM);
return FALSE;
}
if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_socket) < 0)
goto socket_pair;
READ_SOCKET (this).fd = control_socket[0];
WRITE_SOCKET (this).fd = control_socket[1];
......@@ -1653,16 +1663,31 @@ gst_multifdsink_init_send (GstMultiFdSink * this)
this->thread = g_thread_create ((GThreadFunc) gst_multifdsink_thread,
this, TRUE, NULL);
GST_FLAG_SET (this, GST_MULTIFDSINK_OPEN);
return TRUE;
/* ERRORS */
socket_pair:
{
GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ_WRITE, (NULL),
GST_ERROR_SYSTEM);
return FALSE;
}
}
static void
gst_multifdsink_close (GstMultiFdSink * this)
static gboolean
gst_multifdsink_stop (GstBaseSink * bsink)
{
GstMultiFdSinkClass *fclass;
GstMultiFdSink *this;
this = GST_MULTIFDSINK (bsink);
fclass = GST_MULTIFDSINK_GET_CLASS (this);
if (!GST_FLAG_IS_SET (bsink, GST_MULTIFDSINK_OPEN))
return TRUE;
this->running = FALSE;
SEND_COMMAND (this, CONTROL_STOP);
......@@ -1678,7 +1703,7 @@ gst_multifdsink_close (GstMultiFdSink * this)
close (WRITE_SOCKET (this).fd);
if (this->streamheader) {
g_slist_foreach (this->streamheader, (GFunc) gst_data_unref, NULL);
g_slist_foreach (this->streamheader, (GFunc) gst_mini_object_unref, NULL);
g_slist_free (this->streamheader);
this->streamheader = NULL;
}
......@@ -1691,46 +1716,55 @@ gst_multifdsink_close (GstMultiFdSink * this)
gst_fdset_free (this->fdset);
this->fdset = NULL;
}
GST_FLAG_UNSET (this, GST_MULTIFDSINK_OPEN);
return TRUE;
}
static GstElementStateReturn
gst_multifdsink_change_state (GstElement * element)
{
GstMultiFdSink *sink;
gint transition;
GstElementStateReturn ret;
g_return_val_if_fail (GST_IS_MULTIFDSINK (element), GST_STATE_FAILURE);
sink = GST_MULTIFDSINK (element);
/* we disallow changing the state from the streaming thread */
if (g_thread_self () == sink->thread)
return GST_STATE_FAILURE;
switch (GST_STATE_TRANSITION (element)) {
transition = GST_STATE_TRANSITION (element);
switch (transition) {
case GST_STATE_NULL_TO_READY:
if (!GST_FLAG_IS_SET (sink, GST_MULTIFDSINK_OPEN)) {
if (!gst_multifdsink_init_send (sink))
return GST_STATE_FAILURE;
GST_FLAG_SET (sink, GST_MULTIFDSINK_OPEN);
}
if (!gst_multifdsink_start (GST_BASESINK (sink)))
goto start_failed;
break;
case GST_STATE_READY_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
switch (transition) {
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
if (GST_FLAG_IS_SET (sink, GST_MULTIFDSINK_OPEN)) {
gst_multifdsink_close (GST_MULTIFDSINK (element));
GST_FLAG_UNSET (sink, GST_MULTIFDSINK_OPEN);
}
gst_multifdsink_stop (GST_BASESINK (sink));
break;
}
return ret;
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
/* ERRORS */
start_failed:
{
return GST_STATE_FAILURE;
}
}
......@@ -22,12 +22,10 @@
#ifndef __GST_MULTIFDSINK_H__
#define __GST_MULTIFDSINK_H__
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
G_BEGIN_DECLS
#include "gsttcp.h"
#include "gstfdset.h"
......@@ -119,10 +117,7 @@ typedef struct {
} GstTCPClient;
struct _GstMultiFdSink {
GstElement element;
/* pad */
GstPad *sinkpad;
GstBaseSink element;
guint64 bytes_to_serve; /* how much bytes we must serve */
guint64 bytes_served; /* how much bytes have we served */
......@@ -161,7 +156,7 @@ struct _GstMultiFdSink {
};
struct _GstMultiFdSinkClass {
GstElementClass parent_class;
GstBaseSinkClass parent_class;
/* element methods */
void (*add) (GstMultiFdSink *sink, int fd);
......@@ -187,10 +182,6 @@ void gst_multifdsink_remove (GstMultiFdSink *sink, int fd);
void gst_multifdsink_clear (GstMultiFdSink *sink);
GValueArray* gst_multifdsink_get_stats (GstMultiFdSink *sink, int fd);
#ifdef __cplusplus
}
#endif /* __cplusplus */
G_END_DECLS
#endif /* __GST_MULTIFDSINK_H__ */
......@@ -56,35 +56,42 @@ gst_tcp_host_to_ip (GstElement * element, const gchar * host)
struct in_addr addr;
GST_DEBUG_OBJECT (element, "resolving host %s", host);
/* first check if it already is an IP address */
if (inet_aton (host, &addr)) {
ip = g_strdup (host);
goto beach;
}
/* FIXME: could do a localhost check here */
/* perform a name lookup */
hostinfo = gethostbyname (host);
if (!hostinfo) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("Could not find IP address for host \"%s\".", host));
return NULL;
}
if (!(hostinfo = gethostbyname (host)))
goto resolve_error;
if (hostinfo->h_addrtype != AF_INET) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("host \"%s\" is not an IP host", host));
return NULL;
}
if (hostinfo->h_addrtype != AF_INET)
goto not_ip;
addrs = hostinfo->h_addr_list;
/* There could be more than one IP address, but we just return the first */
ip = g_strdup (inet_ntoa (*(struct in_addr *) *addrs));
beach:
GST_DEBUG_OBJECT (element, "resolved to IP %s", ip);
return ip;
resolve_error:
{
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("Could not find IP address for host \"%s\".", host));
return NULL;
}
not_ip:
{
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL),
("host \"%s\" is not an IP host", host));
return NULL;
}
}
/* write buffer to given socket incrementally.
......@@ -149,15 +156,14 @@ gst_tcp_socket_close (int *socket)
*socket = -1;
}
/* read the gdp buffer header from the given socket
/* read a buffer from the given socket
* returns:
* - a GstData representing a GstBuffer in which data should be read
* - a GstData representing a GstEvent
* - a GstBuffer in which data should be read
* - NULL, indicating a connection close or an error, to be handled with
* EOS
*/
GstData *
gst_tcp_gdp_read_header (GstElement * this, int socket)
GstBuffer *
gst_tcp_gdp_read_buffer (GstElement * this, int socket)
{
size_t header_length = GST_DP_HEADER_LENGTH;
size_t readsize;
......@@ -169,36 +175,51 @@ gst_tcp_gdp_read_header (GstElement * this, int socket)
readsize = header_length;
GST_LOG_OBJECT (this, "Reading %d bytes for buffer packet header", readsize);
ret = gst_tcp_socket_read (socket, header, readsize);
/* if we read 0 bytes, and we're blocking, we hit eos */
if (ret == 0) {
GST_DEBUG ("blocking read returns 0, returning NULL");
g_free (header);
return NULL;
}
if (ret < 0) {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
g_free (header);
return NULL;
if ((ret = gst_tcp_socket_read (socket, header, readsize)) <= 0)
goto read_error;
if (ret != readsize)
goto short_read;
if (!gst_dp_validate_header (header_length, header))
goto validate_error;
GST_LOG_OBJECT (this, "validated buffer packet header");
buffer = gst_dp_buffer_from_header (header_length, header);
g_free (header);
GST_LOG_OBJECT (this, "created new buffer %p from packet header", buffer);
return buffer;
/* ERRORS */
read_error:
{
if (ret == 0) {
/* if we read 0 bytes, and we're blocking, we hit eos */
GST_DEBUG ("blocking read returns 0, returning NULL");
g_free (header);
return NULL;
} else {
GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
g_free (header);
return NULL;
}