From: <tho...@ke...> - 2006-06-06 14:24:16
|
CVS Root: /cvs/gstreamer Module: gstreamer Changes by: thomasvs Date: Tue Jun 06 2006 14:24:12 UTC Log message: * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_header_from_buffer_any), (gst_dp_packet_from_caps_any), (gst_dp_version_get_type), (gst_dp_init), (gst_dp_header_from_buffer), (gst_dp_header_from_buffer_1_0), (gst_dp_packet_from_caps), (gst_dp_packet_from_caps_1_0), (gst_dp_packet_from_event), (gst_dp_packet_from_event_1_0), (gst_dp_event_from_packet_0_2), (gst_dp_event_from_packet_1_0), (gst_dp_event_from_packet), (gst_dp_packetizer_new), (gst_dp_packetizer_free): * libs/gst/dataprotocol/dataprotocol.h: API: add a GstDPPacketizer object, and create/free functions API: add GstDPVersion enum Add 1.0 event function that uses the string serialization Serialize more useful buffer flags Fixes #343988 Modified files: . : ChangeLog libs/gst/dataprotocol: dataprotocol.c dataprotocol.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/ChangeLog.diff?r1=1.2575&r2=1.2576 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/libs/gst/dataprotocol/dataprotocol.c.diff?r1=1.27&r2=1.28 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/libs/gst/dataprotocol/dataprotocol.h.diff?r1=1.9&r2=1.10 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gstreamer/ChangeLog,v retrieving revision 1.2575 retrieving revision 1.2576 diff -u -d -r1.2575 -r1.2576 --- ChangeLog 6 Jun 2006 14:10:08 -0000 1.2575 +++ ChangeLog 6 Jun 2006 14:24:00 -0000 1.2576 @@ -1,5 +1,23 @@ 2006-06-06 Thomas Vander Stichele <thomas at apestaart dot org> + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer_any), (gst_dp_packet_from_caps_any), + (gst_dp_version_get_type), (gst_dp_init), + (gst_dp_header_from_buffer), (gst_dp_header_from_buffer_1_0), + (gst_dp_packet_from_caps), (gst_dp_packet_from_caps_1_0), + (gst_dp_packet_from_event), (gst_dp_packet_from_event_1_0), + (gst_dp_event_from_packet_0_2), (gst_dp_event_from_packet_1_0), + (gst_dp_event_from_packet), (gst_dp_packetizer_new), + (gst_dp_packetizer_free): + * libs/gst/dataprotocol/dataprotocol.h: + API: add a GstDPPacketizer object, and create/free functions + API: add GstDPVersion enum + Add 1.0 event function that uses the string serialization + Serialize more useful buffer flags + Fixes #343988 + +2006-06-06 Thomas Vander Stichele <thomas at apestaart dot org> * tests/check/Makefile.am: * tests/check/gst/gstabi.c: * tests/check/gst/struct_ppc64.h: Index: dataprotocol.c RCS file: /cvs/gstreamer/gstreamer/libs/gst/dataprotocol/dataprotocol.c,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- dataprotocol.c 2 Jun 2006 16:46:19 -0000 1.27 +++ dataprotocol.c 6 Jun 2006 14:24:00 -0000 1.28 @@ -20,6 +20,42 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:gstdataprotocol + * @short_description: Serialization of caps, buffers and events. + * @see_also: #GstCaps, #GstEvent, #GstBuffer + * + * This helper library provides serialization of GstBuffer, GstCaps and + * GstEvent structures. + * This serialization is useful when GStreamer needs to interface with + * the outside world to transport data between distinct GStreamer pipelines. + * The connections with the outside world generally don't have mechanisms + * to transport properties of these structures. + * For example, transporting buffers across named pipes or network connections + * doesn't maintain the buffer size and separation. + * This data protocol assumes a reliable connection-oriented transport, such as + * TCP, a pipe, or a file. The protocol does not serialize the caps for + * each buffer; instead, it transport the caps only when they change in the + * stream. This implies that there will always be a caps packet before any + * buffer packets. + * Version 0.2 serializes only a small subset of all events, with a custom + * payload for each type. Also, all GDP streams start with the initial caps + * packet. + * Version 1.0 serializes all events by taking the string representation of + * the event as the payload. In addition, GDP streams can now start with + * events as well, as required by the new data stream model in GStreamer 0.10. + * Converting buffers, caps and events to GDP buffers is done using a + * #GstDPPacketizer object and invoking its packetizer functions. + * For backwards-compatibility reasons, the old 0.2 methods are still + * available but deprecated. + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -37,8 +73,13 @@ /* helper macros */ /* write first 6 bytes of header, as well as ABI padding */ -#define GST_DP_INIT_HEADER(h, maj, min, flags, type) \ +#define GST_DP_INIT_HEADER(h, version, flags, type) \ G_STMT_START { \ + gint maj = 0, min = 0; \ + switch (version) { \ + case GST_DP_VERSION_0_2: maj = 0; min = 2; break; \ + case GST_DP_VERSION_1_0: maj = 1; min = 0; break; \ + } \ h[0] = (guint8) maj; \ h[1] = (guint8) min; \ h[2] = (guint8) flags; \ @@ -75,6 +116,89 @@ #define POLY 0x1021 #define CRC_INIT 0xFFFF +/*** HELPER FUNCTIONS ***/ +static gboolean +gst_dp_header_from_buffer_any (const GstBuffer * buffer, GstDPHeaderFlag flags, + guint * length, guint8 ** header, GstDPVersion version) +{ + guint8 *h; + guint16 flags_mask; + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (header, FALSE); + *length = GST_DP_HEADER_LENGTH; + h = g_malloc0 (GST_DP_HEADER_LENGTH); + /* version, flags, type */ + GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_BUFFER); + /* buffer properties */ + GST_WRITE_UINT32_BE (h + 6, GST_BUFFER_SIZE (buffer)); + GST_WRITE_UINT64_BE (h + 10, GST_BUFFER_TIMESTAMP (buffer)); + GST_WRITE_UINT64_BE (h + 18, GST_BUFFER_DURATION (buffer)); + GST_WRITE_UINT64_BE (h + 26, GST_BUFFER_OFFSET (buffer)); + GST_WRITE_UINT64_BE (h + 34, GST_BUFFER_OFFSET_END (buffer)); + /* data flags; eats two bytes from the ABI area */ + /* we copy everything but the read-only flags */ + flags_mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_DISCONT | + GST_BUFFER_FLAG_IN_CAPS | GST_BUFFER_FLAG_GAP | + GST_BUFFER_FLAG_DELTA_UNIT; + GST_WRITE_UINT16_BE (h + 42, GST_BUFFER_FLAGS (buffer) & flags_mask); + GST_DP_SET_CRC (h, flags, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + GST_LOG ("created header from buffer:"); + gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH); + *header = h; + return TRUE; +} +gst_dp_packet_from_caps_any (const GstCaps * caps, GstDPHeaderFlag flags, + guint * length, guint8 ** header, guint8 ** payload, GstDPVersion version) + guchar *string; + guint payload_length; + /* FIXME: GST_IS_CAPS doesn't work + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); */ + g_return_val_if_fail (caps, FALSE); + g_return_val_if_fail (payload, FALSE); + string = (guchar *) gst_caps_to_string (caps); + payload_length = strlen ((gchar *) string) + 1; /* include trailing 0 */ + GST_DP_INIT_HEADER (h, version, flags, GST_DP_PAYLOAD_CAPS); + GST_WRITE_UINT32_BE (h + 6, payload_length); + GST_WRITE_UINT64_BE (h + 10, (guint64) 0); + GST_WRITE_UINT64_BE (h + 18, (guint64) 0); + GST_WRITE_UINT64_BE (h + 26, (guint64) 0); + GST_WRITE_UINT64_BE (h + 34, (guint64) 0); + GST_DP_SET_CRC (h, flags, string, payload_length); + GST_LOG ("created header from caps:"); + *payload = string; +/*** PUBLIC FUNCTIONS ***/ /** * gst_dp_crc: * @@ -134,6 +258,23 @@ g_free (line); } +GType +gst_dp_version_get_type (void) + static GType gst_dp_version_type = 0; + static const GEnumValue gst_dp_version[] = { + {GST_DP_VERSION_0_2, "GDP Version 0.2", "0.2"}, + {GST_DP_VERSION_1_0, "GDP Version 1.0", "1.0"}, + {0, NULL, NULL}, + }; + if (!gst_dp_version_type) { + gst_dp_version_type = + g_enum_register_static ("GstDPVersion", gst_dp_version); + } + return gst_dp_version_type; +}; * gst_dp_init: @@ -152,12 +293,12 @@ _gst_dp_initialized = TRUE; + gst_dp_version_get_type (); GST_DEBUG_CATEGORY_INIT (data_protocol_debug, "gdp", 0, "GStreamer Data Protocol"); -/*** PUBLIC FUNCTIONS ***/ - * gst_dp_header_payload_length: * @header: the byte header of the packet array @@ -186,6 +327,8 @@ return GST_DP_HEADER_PAYLOAD_TYPE (header); +/*** PACKETIZER FUNCTIONS ***/ * gst_dp_header_from_buffer: * @buffer: a #GstBuffer to create a header for @@ -195,46 +338,24 @@ * Creates a GDP header from the given buffer. + * Deprecated: use a #GstDPPacketizer * Returns: %TRUE if the header was successfully created. gboolean gst_dp_header_from_buffer (const GstBuffer * buffer, GstDPHeaderFlag flags, guint * length, guint8 ** header) { - guint8 *h; - guint16 flags_mask; - g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); - g_return_val_if_fail (header, FALSE); - *length = GST_DP_HEADER_LENGTH; - h = g_malloc0 (GST_DP_HEADER_LENGTH); - /* version, flags, type */ - GST_DP_INIT_HEADER (h, GST_DP_VERSION_MAJOR, GST_DP_VERSION_MINOR, flags, - GST_DP_PAYLOAD_BUFFER); - /* buffer properties */ - GST_WRITE_UINT32_BE (h + 6, GST_BUFFER_SIZE (buffer)); - GST_WRITE_UINT64_BE (h + 10, GST_BUFFER_TIMESTAMP (buffer)); - GST_WRITE_UINT64_BE (h + 18, GST_BUFFER_DURATION (buffer)); - GST_WRITE_UINT64_BE (h + 26, GST_BUFFER_OFFSET (buffer)); - GST_WRITE_UINT64_BE (h + 34, GST_BUFFER_OFFSET_END (buffer)); - /* data flags; eats two bytes from the ABI area */ - /* we only copy KEY_UNIT,DELTA_UNIT and IN_CAPS flags */ - flags_mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | - GST_BUFFER_FLAG_DELTA_UNIT; - GST_WRITE_UINT16_BE (h + 42, GST_BUFFER_FLAGS (buffer) & flags_mask); - GST_DP_SET_CRC (h, flags, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + return gst_dp_header_from_buffer_any (buffer, flags, length, header, + GST_DP_VERSION_0_2); - GST_LOG ("created header from buffer:"); - gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH); - *header = h; - return TRUE; +gst_dp_header_from_buffer_1_0 (const GstBuffer * buffer, GstDPHeaderFlag flags, + guint * length, guint8 ** header) + GST_DP_VERSION_1_0); /** @@ -247,44 +368,24 @@ * Creates a GDP packet from the given caps. * Returns: %TRUE if the packet was successfully created. gst_dp_packet_from_caps (const GstCaps * caps, GstDPHeaderFlag flags, guint * length, guint8 ** header, guint8 ** payload) - guchar *string; - /* FIXME: GST_IS_CAPS doesn't work - g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); */ - g_return_val_if_fail (caps, FALSE); - g_return_val_if_fail (payload, FALSE); - string = (guchar *) gst_caps_to_string (caps); - GST_DP_PAYLOAD_CAPS); - GST_WRITE_UINT32_BE (h + 6, strlen ((gchar *) string) + 1); /* include trailing 0 */ - GST_WRITE_UINT64_BE (h + 10, (guint64) 0); - GST_WRITE_UINT64_BE (h + 18, (guint64) 0); - GST_WRITE_UINT64_BE (h + 26, (guint64) 0); - GST_WRITE_UINT64_BE (h + 34, (guint64) 0); - GST_DP_SET_CRC (h, flags, string, strlen ((gchar *) string) + 1); + return gst_dp_packet_from_caps_any (caps, flags, length, header, payload, - GST_LOG ("created header from caps:"); - *payload = string; +gboolean +gst_dp_packet_from_caps_1_0 (const GstCaps * caps, GstDPHeaderFlag flags, + guint * length, guint8 ** header, guint8 ** payload) @@ -297,6 +398,8 @@ * Creates a GDP packet from the given event. @@ -365,7 +468,7 @@ } /* version, flags, type */ + GST_DP_INIT_HEADER (h, GST_DP_VERSION_0_2, flags, GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event)); /* length */ @@ -381,6 +484,51 @@ return TRUE; +gst_dp_packet_from_event_1_0 (const GstEvent * event, GstDPHeaderFlag flags, + guint32 pl_length; /* length of payload */ + guchar *string = NULL; + g_return_val_if_fail (event, FALSE); + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + if (event->structure) { + string = (guchar *) gst_structure_to_string (event->structure); + GST_LOG ("event %p has structure, string %s", event, string); + pl_length = strlen ((gchar *) string) + 1; /* include trailing 0 */ + } else { + GST_LOG ("event %p has no structure"); + pl_length = 0; + GST_DP_INIT_HEADER (h, GST_DP_VERSION_1_0, flags, + GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event)); + /* length */ + GST_WRITE_UINT32_BE (h + 6, pl_length); + /* timestamp */ + GST_WRITE_UINT64_BE (h + 10, GST_EVENT_TIMESTAMP (event)); + GST_DP_SET_CRC (h, flags, *payload, pl_length); + GST_LOG ("created header from event:"); +/*** DEPACKETIZING FUNCTIONS ***/ * gst_dp_buffer_from_header: * @header_length: the length of the packet header @@ -441,27 +589,13 @@ return caps; -/** - * gst_dp_event_from_packet: - * @header_length: the length of the packet header - * @header: the byte array of the packet header - * @payload: the byte array of the packet payload - * - * Creates a newly allocated #GstEvent from the given packet. - * Returns: A #GstEvent if the event was successfully created, - * or NULL if an event could not be read from the payload. - */ -GstEvent * -gst_dp_event_from_packet (guint header_length, const guint8 * header, +static GstEvent * +gst_dp_event_from_packet_0_2 (guint header_length, const guint8 * header, const guint8 * payload) GstEvent *event = NULL; GstEventType type; - g_return_val_if_fail (header, NULL); - /* payload can be NULL, e.g. for an EOS event */ type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE; switch (type) { case GST_EVENT_UNKNOWN: @@ -509,6 +643,58 @@ return event; +gst_dp_event_from_packet_1_0 (guint header_length, const guint8 * header, + const guint8 * payload) + GstEvent *event = NULL; + GstEventType type; + gchar *string; + GstStructure *s; + type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE; + string = g_strndup ((gchar *) payload, GST_DP_HEADER_PAYLOAD_LENGTH (header)); + s = gst_structure_from_string (string, NULL); + g_free (string); + if (!s) + return NULL; + event = gst_event_new_custom (type, s); + return event; + * gst_dp_event_from_packet: + * @header_length: the length of the packet header + * @header: the byte array of the packet header + * @payload: the byte array of the packet payload + * Creates a newly allocated #GstEvent from the given packet. + * Returns: A #GstEvent if the event was successfully created, + * or NULL if an event could not be read from the payload. +GstEvent * +gst_dp_event_from_packet (guint header_length, const guint8 * header, + guint8 major, minor; + g_return_val_if_fail (header, NULL); + major = GST_DP_HEADER_MAJOR_VERSION (header); + minor = GST_DP_HEADER_MINOR_VERSION (header); + if (major == 0 && minor == 2) + return gst_dp_event_from_packet_0_2 (header_length, header, payload); + else if (major == 1 && minor == 0) + return gst_dp_event_from_packet_1_0 (header_length, header, payload); + else { + GST_ERROR ("Unknown GDP version %d.%d", major, minor); * gst_dp_validate_header: @@ -588,3 +774,51 @@ + * gst_dp_packetizer_new: + * @version: the #GstDPVersion of the protocol to packetize for. + * Creates a new packetizer. + * Returns: a newly allocated #GstDPPacketizer +GstDPPacketizer * +gst_dp_packetizer_new (GstDPVersion version) + GstDPPacketizer *ret; + ret = g_malloc0 (sizeof (GstDPPacketizer)); + ret->version = version; + switch (version) { + case GST_DP_VERSION_0_2: + ret->header_from_buffer = gst_dp_header_from_buffer; + ret->packet_from_caps = gst_dp_packet_from_caps; + ret->packet_from_event = gst_dp_packet_from_event; + break; + case GST_DP_VERSION_1_0: + ret->header_from_buffer = gst_dp_header_from_buffer_1_0; + ret->packet_from_caps = gst_dp_packet_from_caps_1_0; + ret->packet_from_event = gst_dp_packet_from_event_1_0; + default: + g_free (ret); + ret = NULL; + return ret; + * gst_dp_packetizer_free: + * @packetizer: the #GstDPPacketizer to free. + * Free the given packetizer. +void +gst_dp_packetizer_free (GstDPPacketizer * packetizer) + g_free (packetizer); Index: dataprotocol.h RCS file: /cvs/gstreamer/gstreamer/libs/gst/dataprotocol/dataprotocol.h,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- dataprotocol.h 2 Jun 2006 10:08:31 -0000 1.9 +++ dataprotocol.h 6 Jun 2006 14:24:00 -0000 1.10 @@ -1,6 +1,6 @@ /* GStreamer - * Copyright (C) <1999> Erik Walthinsen <om...@cs...> - * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org> + * Copyright (C) 1999 Erik Walthinsen <om...@cs...> + * Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org> * dataprotocol.h: Functions implementing the GStreamer Data Protocol @@ -30,6 +30,21 @@ G_BEGIN_DECLS + * GstDPVersion: + * @GST_DP_VERSION_0_2: protocol version 0.2 + * @GST_DP_VERSION_1_0: protocol version 1.0 + * The version of the GDP protocol being used. +typedef enum { + GST_DP_VERSION_0_2 = 1, + GST_DP_VERSION_1_0, +} GstDPVersion; +GType gst_dp_version_get_type (); +#define GST_TYPE_DP_VERSION (gst_dp_version_get_type ()) * GST_DP_VERSION_MAJOR: * The major version number of the GStreamer Data Protocol. @@ -62,7 +77,7 @@ GST_DP_HEADER_FLAG_NONE = 0, GST_DP_HEADER_FLAG_CRC_HEADER = (1 << 0), GST_DP_HEADER_FLAG_CRC_PAYLOAD = (1 << 1), - GST_DP_HEADER_FLAG_CRC = (1 << 1) | (1 <<0), + GST_DP_HEADER_FLAG_CRC = (1 << 1) | (1 << 0), } GstDPHeaderFlag; @@ -82,8 +97,39 @@ GST_DP_PAYLOAD_EVENT_NONE = 64, } GstDPPayloadType; +typedef gboolean (*GstDPHeaderFromBufferFunction) (const GstBuffer * buffer, + GstDPHeaderFlag flags, + guint * length, + guint8 ** header); +typedef gboolean (*GstDPPacketFromCapsFunction) (const GstCaps * caps, + guint8 ** header, + guint8 ** payload); +typedef gboolean (*GstDPPacketFromEventFunction) (const GstEvent * event, +typedef struct { + GstDPVersion version; + GstDPHeaderFromBufferFunction header_from_buffer; + GstDPPacketFromCapsFunction packet_from_caps; + GstDPPacketFromEventFunction packet_from_event; + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +} GstDPPacketizer; void gst_dp_init (void); +/* packetizer */ + gst_dp_packetizer_new (GstDPVersion version); +void gst_dp_packetizer_free (GstDPPacketizer *packetizer); /* crc checksum */ guint16 gst_dp_crc (const guint8 * buffer, guint length); @@ -109,7 +155,6 @@ guint8 ** header, guint8 ** payload); /* converting to GstBuffer/GstEvent/GstCaps */ GstBuffer * gst_dp_buffer_from_header (guint header_length, const guint8 * header); |