From 8f1ae04ac5c444be42e9f98b8bdd7c74980fab7a Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Wed, 27 Nov 2019 15:37:45 +0100 Subject: [PATCH] rtmp2: Add single-value AMF0 parsing and serializing https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/merge_requests/878 --- gst/rtmp2/rtmp/amf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gst/rtmp2/rtmp/amf.h | 5 ++++ 2 files changed, 70 insertions(+) diff --git a/gst/rtmp2/rtmp/amf.c b/gst/rtmp2/rtmp/amf.c index 895570f..69c3768 100644 --- a/gst/rtmp2/rtmp/amf.c +++ b/gst/rtmp2/rtmp/amf.c @@ -886,6 +886,47 @@ parse_value (AmfParser * parser) return node; } +GstAmfNode * +gst_amf_node_parse (const guint8 * data, gsize size, guint8 ** endptr) +{ + AmfParser parser = { + .data = data, + .size = size, + }; + GstAmfNode *node; + + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (size, NULL); + + init_static (); + + GST_TRACE ("Starting parse with %" G_GSIZE_FORMAT " bytes", parser.size); + + node = parse_value (&parser); + if (gst_amf_node_get_type (node) == GST_AMF_TYPE_INVALID) { + GST_ERROR ("invalid value"); + goto out; + } + + if (G_UNLIKELY (GST_LEVEL_LOG <= _gst_debug_min) && + GST_LEVEL_LOG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) { + GString *string = g_string_new (NULL); + gst_amf_node_dump (node, -1, string); + GST_LOG ("Parsed value: %s", string->str); + g_string_free (string, TRUE); + } + + GST_TRACE ("Done parsing; consumed %" G_GSIZE_FORMAT " bytes and left %" + G_GSIZE_FORMAT " bytes", parser.offset, parser.size - parser.offset); + +out: + if (endptr) { + *endptr = (guint8 *) parser.data + parser.offset; + } + + return node; +} + GPtrArray * gst_amf_parse_command (const guint8 * data, gsize size, gdouble * transaction_id, gchar ** command_name) @@ -1094,6 +1135,30 @@ serialize_value (GByteArray * array, const GstAmfNode * node) } GBytes * +gst_amf_node_serialize (const GstAmfNode * node) +{ + GByteArray *array = g_byte_array_new (); + + g_return_val_if_fail (node, NULL); + + init_static (); + + if (G_UNLIKELY (GST_LEVEL_LOG <= _gst_debug_min) && + GST_LEVEL_LOG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) { + GString *string = g_string_new (NULL); + gst_amf_node_dump (node, -1, string); + GST_LOG ("Serializing value: %s", string->str); + g_string_free (string, TRUE); + } + + serialize_value (array, node); + + GST_TRACE ("Done serializing; produced %u bytes", array->len); + + return g_byte_array_free_to_bytes (array); +} + +GBytes * gst_amf_serialize_command (gdouble transaction_id, const gchar * command_name, const GstAmfNode * argument, ...) { diff --git a/gst/rtmp2/rtmp/amf.h b/gst/rtmp2/rtmp/amf.h index 639456e..6dfd966 100644 --- a/gst/rtmp2/rtmp/amf.h +++ b/gst/rtmp2/rtmp/amf.h @@ -100,9 +100,14 @@ void gst_amf_node_append_field_take_string (GstAmfNode * node, void gst_amf_node_dump (const GstAmfNode * node, gint indent, GString * string); +GstAmfNode * gst_amf_node_parse (const guint8 * data, gsize size, + guint8 ** endptr); + GPtrArray * gst_amf_parse_command (const guint8 * data, gsize size, gdouble * transaction_id, gchar ** command_name); +GBytes * gst_amf_node_serialize (const GstAmfNode * node); + GBytes * gst_amf_serialize_command (gdouble transaction_id, const gchar * command_name, const GstAmfNode * argument, ...) G_GNUC_NULL_TERMINATED; GBytes * gst_amf_serialize_command_valist (gdouble transaction_id, -- 2.7.4