📄 dataprotocol.c
字号:
g_return_val_if_fail (length, FALSE); g_return_val_if_fail (header, FALSE); g_return_val_if_fail (payload, FALSE); /* first construct payload, since we need the length */ switch (GST_EVENT_TYPE (event)) { case GST_EVENT_UNKNOWN: GST_WARNING ("Unknown event, ignoring"); return FALSE; case GST_EVENT_EOS: case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_STOP: case GST_EVENT_NEWSEGMENT: pl_length = 0; *payload = NULL; break; case GST_EVENT_SEEK: { gdouble rate; GstFormat format; GstSeekFlags flags; GstSeekType cur_type, stop_type; gint64 cur, stop; gst_event_parse_seek ((GstEvent *) event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); pl_length = 4 + 4 + 4 + 8 + 4 + 8; *payload = g_malloc0 (pl_length); /* FIXME write rate */ GST_WRITE_UINT32_BE (*payload, (guint32) format); GST_WRITE_UINT32_BE (*payload + 4, (guint32) flags); GST_WRITE_UINT32_BE (*payload + 8, (guint32) cur_type); GST_WRITE_UINT64_BE (*payload + 12, (guint64) cur); GST_WRITE_UINT32_BE (*payload + 20, (guint32) stop_type); GST_WRITE_UINT64_BE (*payload + 24, (guint64) stop); break; } case GST_EVENT_QOS: case GST_EVENT_NAVIGATION: case GST_EVENT_TAG: GST_WARNING ("Unhandled event type %d, ignoring", GST_EVENT_TYPE (event)); return FALSE; default: GST_WARNING ("Unknown event type %d, ignoring", GST_EVENT_TYPE (event)); return FALSE; } /* now we can create and fill the header */ h = g_malloc0 (GST_DP_HEADER_LENGTH); *length = GST_DP_HEADER_LENGTH; /* version, flags, type */ GST_DP_INIT_HEADER (h, GST_DP_VERSION_0_2, flags, GST_DP_PAYLOAD_EVENT_NONE + GST_EVENT_TYPE (event)); /* length */ GST_WRITE_UINT32_BE (h + 6, (guint32) 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:"); gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH); *header = h; return TRUE;}#endifstatic gbooleangst_dp_packet_from_event_1_0 (const GstEvent * event, GstDPHeaderFlag flags, guint * length, guint8 ** header, guint8 ** payload){ guint8 *h; guint32 pl_length; /* length of payload */ guchar *string = NULL; g_return_val_if_fail (GST_IS_EVENT (event), FALSE); g_return_val_if_fail (length, FALSE); g_return_val_if_fail (header, FALSE); g_return_val_if_fail (payload, FALSE); *length = GST_DP_HEADER_LENGTH; h = g_malloc0 (GST_DP_HEADER_LENGTH); 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", event); pl_length = 0; } /* version, flags, type */ 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:"); gst_dp_dump_byte_array (h, GST_DP_HEADER_LENGTH); *header = h; *payload = string; return TRUE;}/*** DEPACKETIZING FUNCTIONS ***//** * gst_dp_buffer_from_header: * @header_length: the length of the packet header * @header: the byte array of the packet header * * Creates a newly allocated #GstBuffer from the given header. * The buffer data needs to be copied into it before validating. * * Use this function if you want to pre-allocate a buffer based on the * packet header to read the packet payload in to. * * This function does not check the header passed to it, use * gst_dp_validate_header() first if the header data is unchecked. * * Returns: A #GstBuffer if the buffer was successfully created, or NULL. */GstBuffer *gst_dp_buffer_from_header (guint header_length, const guint8 * header){ GstBuffer *buffer; g_return_val_if_fail (header != NULL, NULL); g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, NULL); g_return_val_if_fail (GST_DP_HEADER_PAYLOAD_TYPE (header) == GST_DP_PAYLOAD_BUFFER, NULL); buffer = gst_buffer_new_and_alloc ((guint) GST_DP_HEADER_PAYLOAD_LENGTH (header)); GST_BUFFER_TIMESTAMP (buffer) = GST_DP_HEADER_TIMESTAMP (header); GST_BUFFER_DURATION (buffer) = GST_DP_HEADER_DURATION (header); GST_BUFFER_OFFSET (buffer) = GST_DP_HEADER_OFFSET (header); GST_BUFFER_OFFSET_END (buffer) = GST_DP_HEADER_OFFSET_END (header); GST_BUFFER_FLAGS (buffer) = GST_DP_HEADER_BUFFER_FLAGS (header); return buffer;}/** * gst_dp_caps_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 #GstCaps from the given packet. * * This function does not check the arguments passed to it, use * gst_dp_validate_packet() first if the header and payload data are * unchecked. * * Returns: A #GstCaps containing the caps represented in the packet, * or NULL if the packet could not be converted. */GstCaps *gst_dp_caps_from_packet (guint header_length, const guint8 * header, const guint8 * payload){ GstCaps *caps; gchar *string; g_return_val_if_fail (header, NULL); g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, NULL); g_return_val_if_fail (GST_DP_HEADER_PAYLOAD_TYPE (header) == GST_DP_PAYLOAD_CAPS, NULL); g_return_val_if_fail (payload, NULL); /* 0 sized payload length will work create NULL string */ string = g_strndup ((gchar *) payload, GST_DP_HEADER_PAYLOAD_LENGTH (header)); caps = gst_caps_from_string (string); g_free (string); return caps;}static GstEvent *gst_dp_event_from_packet_0_2 (guint header_length, const guint8 * header, const guint8 * payload){ GstEvent *event = NULL; GstEventType type; type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE; switch (type) { case GST_EVENT_UNKNOWN: GST_WARNING ("Unknown event, ignoring"); return FALSE; case GST_EVENT_EOS: case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_STOP: case GST_EVENT_NEWSEGMENT: event = gst_event_new_custom (type, NULL); GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header); break; case GST_EVENT_SEEK: { gdouble rate; GstFormat format; GstSeekFlags flags; GstSeekType cur_type, stop_type; gint64 cur, stop; g_return_val_if_fail (payload != NULL, NULL); /* FIXME, read rate */ rate = 1.0; format = (GstFormat) GST_READ_UINT32_BE (payload); flags = (GstSeekFlags) GST_READ_UINT32_BE (payload + 4); cur_type = (GstSeekType) GST_READ_UINT32_BE (payload + 8); cur = (gint64) GST_READ_UINT64_BE (payload + 12); stop_type = (GstSeekType) GST_READ_UINT32_BE (payload + 20); stop = (gint64) GST_READ_UINT64_BE (payload + 24); event = gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop); GST_EVENT_TIMESTAMP (event) = GST_DP_HEADER_TIMESTAMP (header); break; } case GST_EVENT_QOS: case GST_EVENT_NAVIGATION: case GST_EVENT_TAG: GST_WARNING ("Unhandled event type %d, ignoring", type); return FALSE; default: GST_WARNING ("Unknown event type %d, ignoring", type); return FALSE; } return event;}static GstEvent *gst_dp_event_from_packet_1_0 (guint header_length, const guint8 * header, const guint8 * payload){ GstEvent *event = NULL; GstEventType type; gchar *string = NULL; GstStructure *s = NULL; type = GST_DP_HEADER_PAYLOAD_TYPE (header) - GST_DP_PAYLOAD_EVENT_NONE; if (payload) { string = g_strndup ((gchar *) payload, GST_DP_HEADER_PAYLOAD_LENGTH (header)); s = gst_structure_from_string (string, NULL); g_free (string); } 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. * * This function does not check the arguments passed to it, use * gst_dp_validate_packet() first if the header and payload data are * unchecked. * * 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, const guint8 * payload){ guint8 major, minor; g_return_val_if_fail (header, NULL); g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, 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); return NULL; }}/** * gst_dp_validate_header: * @header_length: the length of the packet header * @header: the byte array of the packet header * * Validates the given packet header by checking the CRC checksum. * * Returns: %TRUE if the CRC matches, or no CRC checksum is present. */gbooleangst_dp_validate_header (guint header_length, const guint8 * header){ guint16 crc_read, crc_calculated; g_return_val_if_fail (header != NULL, FALSE); g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, FALSE); if (!(GST_DP_HEADER_FLAGS (header) & GST_DP_HEADER_FLAG_CRC_HEADER)) return TRUE; crc_read = GST_DP_HEADER_CRC_HEADER (header); /* don't include the last two crc fields for the crc check */ crc_calculated = gst_dp_crc (header, header_length - 4); if (crc_read != crc_calculated) goto crc_error; GST_LOG ("header crc validation: %02x", crc_read); return TRUE; /* ERRORS */crc_error: { GST_WARNING ("header crc mismatch: read %02x, calculated %02x", crc_read, crc_calculated); return FALSE; }}/** * gst_dp_validate_payload: * @header_length: the length of the packet header * @header: the byte array of the packet header * @payload: the byte array of the packet payload * * Validates the given packet payload using the given packet header * by checking the CRC checksum. * * Returns: %TRUE if the CRC matches, or no CRC checksum is present. */gbooleangst_dp_validate_payload (guint header_length, const guint8 * header, const guint8 * payload){ guint16 crc_read, crc_calculated; g_return_val_if_fail (header != NULL, FALSE); g_return_val_if_fail (header_length >= GST_DP_HEADER_LENGTH, FALSE); if (!(GST_DP_HEADER_FLAGS (header) & GST_DP_HEADER_FLAG_CRC_PAYLOAD)) return TRUE; crc_read = GST_DP_HEADER_CRC_PAYLOAD (header); crc_calculated = gst_dp_crc (payload, GST_DP_HEADER_PAYLOAD_LENGTH (header)); if (crc_read != crc_calculated) goto crc_error; GST_LOG ("payload crc validation: %02x", crc_read); return TRUE; /* ERRORS */crc_error: { GST_WARNING ("payload crc mismatch: read %02x, calculated %02x", crc_read, crc_calculated); return FALSE; }}/** * gst_dp_validate_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 * * Validates the given packet by checking version information and checksums. * * Returns: %TRUE if the packet validates. */gbooleangst_dp_validate_packet (guint header_length, const guint8 * header, const guint8 * payload){ if (!gst_dp_validate_header (header_length, header)) return FALSE; if (!gst_dp_validate_payload (header_length, header, payload)) return FALSE; return TRUE;}/** * 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) {#ifndef GST_REMOVE_DEPRECATED 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;#endif 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; break; default: g_free (ret); ret = NULL; break; } return ret;}/** * gst_dp_packetizer_free: * @packetizer: the #GstDPPacketizer to free. * * Free the given packetizer. */voidgst_dp_packetizer_free (GstDPPacketizer * packetizer){ g_free (packetizer);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -