rtmp2: Move FLV tag header parsing into rtmputils.c
authorJan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
Mon, 29 Jun 2020 17:46:53 +0000 (19:46 +0200)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 1 Jul 2020 18:33:42 +0000 (18:33 +0000)
To be shared with the AGGREGATE handling.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1384>

gst/rtmp2/gstrtmp2sink.c
gst/rtmp2/rtmp/rtmputils.c
gst/rtmp2/rtmp/rtmputils.h

index 7e67f86..a5ee7ac 100644 (file)
@@ -44,6 +44,7 @@
 #include "rtmp/amf.h"
 #include "rtmp/rtmpclient.h"
 #include "rtmp/rtmpmessage.h"
+#include "rtmp/rtmputils.h"
 
 #include <gst/gst.h>
 #include <gst/base/gstbasesink.h>
@@ -587,10 +588,9 @@ static gboolean
 buffer_to_message (GstRtmp2Sink * self, GstBuffer * buffer, GstBuffer ** outbuf)
 {
   GstBuffer *message;
-  gsize payload_offset, payload_size;
+  GstRtmpFlvTagHeader header;
   guint64 timestamp;
   guint32 cstream;
-  GstRtmpMessageType type;
 
   {
     GstMapInfo info;
@@ -611,21 +611,22 @@ buffer_to_message (GstRtmp2Sink * self, GstBuffer * buffer, GstBuffer ** outbuf)
       return TRUE;
     }
 
-    if (G_UNLIKELY (info.size < 11 + 4)) {
-      GST_ERROR_OBJECT (self, "too small: %" GST_PTR_FORMAT, buffer);
+    if (!gst_rtmp_flv_tag_parse_header (&header, info.data, info.size)) {
+      GST_ERROR_OBJECT (self, "too small for tag header: %" GST_PTR_FORMAT,
+          buffer);
       gst_buffer_unmap (buffer, &info);
       return FALSE;
     }
 
-    /* payload between 11 byte header and 4 byte size footer */
-    payload_offset = 11;
-    payload_size = info.size - 11 - 4;
-
-    type = GST_READ_UINT8 (info.data);
-    timestamp = GST_READ_UINT24_BE (info.data + 4);
-    timestamp |= (guint32) GST_READ_UINT8 (info.data + 7) << 24;
+    if (info.size < header.total_size) {
+      GST_ERROR_OBJECT (self, "too small for tag body: buffer %" G_GSIZE_FORMAT
+          ", tag %" G_GSIZE_FORMAT, info.size, header.total_size);
+      gst_buffer_unmap (buffer, &info);
+      return FALSE;
+    }
 
     /* flvmux timestamps roll over after about 49 days */
+    timestamp = header.timestamp;
     if (timestamp + self->base_ts + G_MAXINT32 < self->last_ts) {
       GST_WARNING_OBJECT (self, "Timestamp regression %" G_GUINT64_FORMAT
           " -> %" G_GUINT64_FORMAT "; assuming overflow", self->last_ts,
@@ -651,7 +652,7 @@ buffer_to_message (GstRtmp2Sink * self, GstBuffer * buffer, GstBuffer ** outbuf)
     gst_buffer_unmap (buffer, &info);
   }
 
-  switch (type) {
+  switch (header.type) {
     case GST_RTMP_MESSAGE_TYPE_DATA_AMF0:
       cstream = 4;
       break;
@@ -665,14 +666,14 @@ buffer_to_message (GstRtmp2Sink * self, GstBuffer * buffer, GstBuffer ** outbuf)
       break;
 
     default:
-      GST_ERROR_OBJECT (self, "unknown tag type %d", type);
+      GST_ERROR_OBJECT (self, "unknown tag type %d", header.type);
       return FALSE;
   }
 
   /* May not know stream ID yet; set later */
-  message = gst_rtmp_message_new (type, cstream, 0);
+  message = gst_rtmp_message_new (header.type, cstream, 0);
   message = gst_buffer_append_region (message, gst_buffer_ref (buffer),
-      payload_offset, payload_size);
+      GST_RTMP_FLV_TAG_HEADER_SIZE, header.payload_size);
 
   GST_BUFFER_DTS (message) = timestamp * GST_MSECOND;
 
index 5f64f27..f0f0cac 100644 (file)
@@ -347,3 +347,36 @@ gst_rtmp_string_print_escaped (GString * string, const gchar * data,
   g_string_append_c (string, '"');
 
 }
+
+gboolean
+gst_rtmp_flv_tag_parse_header (GstRtmpFlvTagHeader * header,
+    const guint8 * data, gsize size)
+{
+  g_return_val_if_fail (header, FALSE);
+  g_return_val_if_fail (data, FALSE);
+
+  /* Parse FLVTAG header as described in
+   * video_file_format_spec_v10.pdf page 5 (page 9 of the PDF) */
+
+  if (size < GST_RTMP_FLV_TAG_HEADER_SIZE) {
+    return FALSE;
+  }
+
+  /* TagType UI8 */
+  header->type = GST_READ_UINT8 (data);
+
+  /* DataSize UI24 */
+  header->payload_size = GST_READ_UINT24_BE (data + 1);
+
+  /* 4 bytes for the PreviousTagSize UI32 following every tag */
+  header->total_size = GST_RTMP_FLV_TAG_HEADER_SIZE + header->payload_size + 4;
+
+  /* Timestamp UI24 + TimestampExtended UI8 */
+  header->timestamp = GST_READ_UINT24_BE (data + 4);
+  header->timestamp |= (guint32) GST_READ_UINT8 (data + 7) << 24;
+
+  /* Skip StreamID UI24. It's "always 0" for FLV files and for aggregated RTMP
+   * messages we're supposed to use the Stream ID from the AGGREGATE. */
+
+  return TRUE;
+}
index 07c437f..f36116a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <gst/gst.h>
 #include <gio/gio.h>
+#include "rtmpmessage.h"
 
 G_BEGIN_DECLS
 
@@ -48,6 +49,17 @@ gboolean gst_rtmp_output_stream_write_all_buffer_finish (GOutputStream * stream,
 void gst_rtmp_string_print_escaped (GString * string, const gchar * data,
     gssize size);
 
+#define GST_RTMP_FLV_TAG_HEADER_SIZE 11
+
+typedef struct {
+  GstRtmpMessageType type;
+  gsize payload_size, total_size;
+  guint32 timestamp;
+} GstRtmpFlvTagHeader;
+
+gboolean gst_rtmp_flv_tag_parse_header (GstRtmpFlvTagHeader *header,
+    const guint8 * data, gsize size);
+
 G_END_DECLS
 
 #endif