rtp: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpj2kdepay.c
index c09c188..132bcf5 100644 (file)
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
+
+ /**
+ * SECTION:element-rtpj2kdepay
+ * @title: rtpj2kdepay
+ *
+ * Depayload an RTP-payloaded JPEG 2000 image into RTP packets according to RFC 5371
+ * and RFC 5372.
+ * For detailed information see: https://datatracker.ietf.org/doc/rfc5371/
+ * and https://datatracker.ietf.org/doc/rfc5372/
+ */
+
+
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
 #include <gst/rtp/gstrtpbuffer.h>
+#include <gst/video/video.h>
 
 #include <string.h>
+#include "gstrtpj2kcommon.h"
 #include "gstrtpj2kdepay.h"
+#include "gstrtputils.h"
 
 GST_DEBUG_CATEGORY_STATIC (rtpj2kdepay_debug);
 #define GST_CAT_DEFAULT (rtpj2kdepay_debug)
@@ -33,35 +48,27 @@ static GstStaticPadTemplate gst_rtp_j2k_depay_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("image/x-jpc")
+    GST_STATIC_CAPS ("image/x-jpc, "
+        "colorspace = (string) { sRGB, sYUV, GRAY }")
     );
 
 static GstStaticPadTemplate gst_rtp_j2k_depay_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("application/x-rtp, "
-        "media = (string) \"video\", "
-        "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
-        "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG2000\"")
+        "media = (string) \"video\", " "clock-rate = (int) 90000, "
+        GST_RTP_J2K_SAMPLING_LIST ","
+        "encoding-name = (string) \"JPEG2000\";"
+        "application/x-rtp, "
+        "media = (string) \"video\", " "clock-rate = (int) 90000, "
+        "colorspace = (string) { sRGB, sYUV, GRAY }, "
+        "encoding-name = (string) \"JPEG2000\";")
     );
 
-typedef enum
-{
-  J2K_MARKER = 0xFF,
-  J2K_MARKER_SOC = 0x4F,
-  J2K_MARKER_SOT = 0x90,
-  J2K_MARKER_SOP = 0x91,
-  J2K_MARKER_SOD = 0x93,
-  J2K_MARKER_EOC = 0xD9
-} RtpJ2KMarker;
-
-#define DEFAULT_BUFFER_LIST             TRUE
-
 enum
 {
   PROP_0,
-  PROP_BUFFER_LIST,
   PROP_LAST
 };
 
@@ -82,7 +89,7 @@ gst_rtp_j2k_depay_change_state (GstElement * element,
 static gboolean gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload,
     GstCaps * caps);
 static GstBuffer *gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload,
-    GstBuffer * buf);
+    GstRTPBuffer * rtp);
 
 static void
 gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass)
@@ -100,17 +107,12 @@ gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass)
   gobject_class->set_property = gst_rtp_j2k_depay_set_property;
   gobject_class->get_property = gst_rtp_j2k_depay_get_property;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST,
-      g_param_spec_boolean ("buffer-list", "Buffer List",
-          "Use Buffer Lists",
-          DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_j2k_depay_src_template);
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_j2k_depay_sink_template);
 
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_j2k_depay_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_j2k_depay_sink_template));
-
-  gst_element_class_set_details_simple (gstelement_class,
+  gst_element_class_set_static_metadata (gstelement_class,
       "RTP JPEG 2000 depayloader", "Codec/Depayloader/Network/RTP",
       "Extracts JPEG 2000 video from RTP packets (RFC 5371)",
       "Wim Taymans <wim.taymans@gmail.com>");
@@ -118,7 +120,7 @@ gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass)
   gstelement_class->change_state = gst_rtp_j2k_depay_change_state;
 
   gstrtpbasedepayload_class->set_caps = gst_rtp_j2k_depay_setcaps;
-  gstrtpbasedepayload_class->process = gst_rtp_j2k_depay_process;
+  gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_j2k_depay_process;
 
   GST_DEBUG_CATEGORY_INIT (rtpj2kdepay_debug, "rtpj2kdepay", 0,
       "J2K Video RTP Depayloader");
@@ -127,8 +129,6 @@ gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass)
 static void
 gst_rtp_j2k_depay_init (GstRtpJ2KDepay * rtpj2kdepay)
 {
-  rtpj2kdepay->buffer_list = DEFAULT_BUFFER_LIST;
-
   rtpj2kdepay->pu_adapter = gst_adapter_new ();
   rtpj2kdepay->t_adapter = gst_adapter_new ();
   rtpj2kdepay->f_adapter = gst_adapter_new ();
@@ -184,10 +184,12 @@ gst_rtp_j2k_depay_finalize (GObject * object)
 static gboolean
 gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
 {
-  GstStructure *structure;
+  GstStructure *structure = NULL;
   gint clock_rate;
-  GstCaps *outcaps;
-  gboolean res;
+  GstCaps *outcaps = NULL;
+  gboolean res = FALSE;
+  const gchar *colorspace = NULL;
+  const gchar *sampling = NULL;
 
   structure = gst_caps_get_structure (caps, 0);
 
@@ -195,10 +197,35 @@ gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
     clock_rate = 90000;
   depayload->clock_rate = clock_rate;
 
-  outcaps =
-      gst_caps_new_simple ("image/x-jpc", "framerate", GST_TYPE_FRACTION, 0, 1,
-      "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, "sYUV", NULL);
+  sampling = gst_structure_get_string (structure, "sampling");
+  if (sampling) {
+    if (!strcmp (sampling, GST_RTP_J2K_RGB) ||
+        !strcmp (sampling, GST_RTP_J2K_RGBA) ||
+        !strcmp (sampling, GST_RTP_J2K_BGR) ||
+        !strcmp (sampling, GST_RTP_J2K_BGRA))
+      colorspace = "sRGB";
+    else if (!strcmp (sampling, GST_RTP_J2K_GRAYSCALE))
+      colorspace = "GRAY";
+    else
+      colorspace = "sYUV";
+  } else {
+    GST_ELEMENT_WARNING (depayload, STREAM, DEMUX, NULL,
+        ("Non-compliant stream: sampling field missing. Frames my appear incorrect"));
+    colorspace = gst_structure_get_string (structure, "colorspace");
+    if (!strcmp (colorspace, "GRAY")) {
+      sampling = GST_RTP_J2K_GRAYSCALE;
+    }
+  }
+
+  outcaps = gst_caps_new_simple ("image/x-jpc",
+      "framerate", GST_TYPE_FRACTION, 0, 1,
+      "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, colorspace, NULL);
+
+  if (sampling)
+    gst_caps_set_simple (outcaps, "sampling", G_TYPE_STRING, sampling, NULL);
+
   res = gst_pad_set_caps (depayload->srcpad, outcaps);
+
   gst_caps_unref (outcaps);
 
   return res;
@@ -267,8 +294,7 @@ gst_rtp_j2k_depay_flush_tile (GstRTPBaseDepayload * depayload)
   GList *packets, *walk;
   guint8 end[2];
   GstFlowReturn ret = GST_FLOW_OK;
-  guint8 *data;
-  gsize size;
+  GstMapInfo map;
   GstBuffer *buf;
 
   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
@@ -307,32 +333,32 @@ gst_rtp_j2k_depay_flush_tile (GstRTPBaseDepayload * depayload)
 
     if (walk == packets) {
       /* first buffer should contain the SOT */
-      data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+      gst_buffer_map (buf, &map, GST_MAP_READ);
 
-      if (size < 12)
+      if (map.size < 12)
         goto invalid_tile;
 
-      if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) {
+      if (map.data[0] == GST_J2K_MARKER && map.data[1] == GST_J2K_MARKER_SOT) {
         guint Psot, nPsot;
 
-        if (end[0] == 0xff && end[1] == J2K_MARKER_EOC)
+        if (end[0] == GST_J2K_MARKER && end[1] == GST_J2K_MARKER_EOC)
           nPsot = avail - 2;
         else
           nPsot = avail;
 
-        Psot = GST_READ_UINT32_BE (&data[6]);
+        Psot = GST_READ_UINT32_BE (&map.data[6]);
         if (Psot != nPsot && Psot != 0) {
           /* Psot must match the size of the tile */
           GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot);
-          gst_buffer_unmap (buf, data, size);
+          gst_buffer_unmap (buf, &map);
 
           buf = gst_buffer_make_writable (buf);
 
-          data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
-          GST_WRITE_UINT32_BE (&data[6], nPsot);
+          gst_buffer_map (buf, &map, GST_MAP_WRITE);
+          GST_WRITE_UINT32_BE (&map.data[6], nPsot);
         }
       }
-      gst_buffer_unmap (buf, data, size);
+      gst_buffer_unmap (buf, &map);
     }
 
     GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %" G_GSIZE_FORMAT,
@@ -357,7 +383,7 @@ waiting_header:
 invalid_tile:
   {
     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL));
-    gst_buffer_unmap (buf, data, size);
+    gst_buffer_unmap (buf, &map);
     gst_adapter_clear (rtpj2kdepay->t_adapter);
     rtpj2kdepay->last_tile = -1;
     return ret;
@@ -390,9 +416,9 @@ gst_rtp_j2k_depay_flush_frame (GstRTPBaseDepayload * depayload)
      * marker */
     gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2);
 
-    if (end[0] != 0xff && end[1] != 0xd9) {
-      end[0] = 0xff;
-      end[1] = 0xd9;
+    if (end[0] != GST_J2K_MARKER && end[1] != GST_J2K_MARKER_EOC) {
+      end[0] = GST_J2K_MARKER;
+      end[1] = GST_J2K_MARKER_EOC;
 
       GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one");
 
@@ -403,29 +429,11 @@ gst_rtp_j2k_depay_flush_frame (GstRTPBaseDepayload * depayload)
       gst_adapter_push (rtpj2kdepay->f_adapter, outbuf);
       avail += 2;
     }
-#if 0
-    if (rtpj2kdepay->buffer_list) {
-      GList *list;
-      GstBufferList *buflist;
-      GstBufferListIterator *it;
-
-      GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail);
-      list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail);
-
-      buflist = gst_buffer_list_new ();
-      it = gst_buffer_list_iterate (buflist);
-      gst_buffer_list_iterator_add_group (it);
-      gst_buffer_list_iterator_add_list (it, list);
-      gst_buffer_list_iterator_free (it);
-
-      ret = gst_rtp_base_depayload_push_list (depayload, buflist);
-    } else
-#endif
-    {
-      GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail);
-      outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail);
-      ret = gst_rtp_base_depayload_push (depayload, outbuf);
-    }
+
+    GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail);
+    outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail);
+    gst_rtp_drop_non_video_meta (depayload, outbuf);
+    ret = gst_rtp_base_depayload_push (depayload, outbuf);
   } else {
     GST_WARNING_OBJECT (rtpj2kdepay, "empty packet");
     gst_adapter_clear (rtpj2kdepay->f_adapter);
@@ -446,27 +454,24 @@ done:
 }
 
 static GstBuffer *
-gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
+gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
 {
   GstRtpJ2KDepay *rtpj2kdepay;
   guint8 *payload;
   guint MHF, mh_id, frag_offset, tile, payload_len, j2klen;
   gint gap;
   guint32 rtptime;
-  GstRTPBuffer rtp = { NULL };
 
   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
 
-  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
-
-  payload = gst_rtp_buffer_get_payload (&rtp);
-  payload_len = gst_rtp_buffer_get_payload_len (&rtp);
+  payload = gst_rtp_buffer_get_payload (rtp);
+  payload_len = gst_rtp_buffer_get_payload_len (rtp);
 
   /* we need at least a header */
-  if (payload_len < 8)
+  if (payload_len < GST_RTP_J2K_HEADER_SIZE)
     goto empty_packet;
 
-  rtptime = gst_rtp_buffer_get_timestamp (&rtp);
+  rtptime = gst_rtp_buffer_get_timestamp (rtp);
 
   /* new timestamp marks new frame */
   if (rtpj2kdepay->last_rtptime != rtptime) {
@@ -494,7 +499,7 @@ gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
 
   tile = (payload[2] << 8) | payload[3];
   frag_offset = (payload[5] << 16) | (payload[6] << 8) | payload[7];
-  j2klen = payload_len - 8;
+  j2klen = payload_len - GST_RTP_J2K_HEADER_SIZE;
 
   GST_DEBUG_OBJECT (rtpj2kdepay, "MHF %u, tile %u, frag %u, expected %u", MHF,
       tile, frag_offset, rtpj2kdepay->next_frag);
@@ -511,19 +516,19 @@ gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
   }
 
   /* check for sync code */
-  if (j2klen > 2 && payload[8] == 0xff) {
-    guint marker = payload[9];
+  if (j2klen > 2 && payload[GST_RTP_J2K_HEADER_SIZE] == GST_J2K_MARKER) {
+    guint marker = payload[GST_RTP_J2K_HEADER_SIZE + 1];
 
     /* packets must start with SOC, SOT or SOP */
     switch (marker) {
-      case J2K_MARKER_SOC:
+      case GST_J2K_MARKER_SOC:
         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOC packet");
         /* flush the previous frame, should have happened when the timestamp
          * changed above. */
         gst_rtp_j2k_depay_flush_frame (depayload);
         rtpj2kdepay->have_sync = TRUE;
         break;
-      case J2K_MARKER_SOT:
+      case GST_J2K_MARKER_SOT:
         /* flush the previous tile */
         gst_rtp_j2k_depay_flush_tile (depayload);
         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOT packet");
@@ -531,7 +536,7 @@ gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
         /* we sync on the tile now */
         rtpj2kdepay->last_tile = tile;
         break;
-      case J2K_MARKER_SOP:
+      case GST_J2K_MARKER_SOP:
         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOP packet");
         /* flush the previous PU */
         gst_rtp_j2k_depay_flush_pu (depayload);
@@ -563,7 +568,7 @@ gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
     }
     /* and push in pu adapter */
     GST_DEBUG_OBJECT (rtpj2kdepay, "push pu of size %u in adapter", j2klen);
-    pu_frag = gst_rtp_buffer_get_payload_subbuffer (&rtp, 8, -1);
+    pu_frag = gst_rtp_buffer_get_payload_subbuffer (rtp, 8, -1);
     gst_adapter_push (rtpj2kdepay->pu_adapter, pu_frag);
 
     if (MHF & 2) {
@@ -576,12 +581,11 @@ gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
   }
 
   /* marker bit finishes the frame */
-  if (gst_rtp_buffer_get_marker (&rtp)) {
+  if (gst_rtp_buffer_get_marker (rtp)) {
     GST_DEBUG_OBJECT (rtpj2kdepay, "marker set, last buffer");
     /* then flush frame */
     gst_rtp_j2k_depay_flush_frame (depayload);
   }
-  gst_rtp_buffer_unmap (&rtp);
 
   return NULL;
 
@@ -590,7 +594,6 @@ empty_packet:
   {
     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
         ("Empty Payload."), (NULL));
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 wrong_mh_id:
@@ -599,7 +602,6 @@ wrong_mh_id:
         ("Invalid mh_id %u, expected %u", mh_id, rtpj2kdepay->last_mh_id),
         (NULL));
     gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 }
@@ -608,14 +610,7 @@ static void
 gst_rtp_j2k_depay_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstRtpJ2KDepay *rtpj2kdepay;
-
-  rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
-
   switch (prop_id) {
-    case PROP_BUFFER_LIST:
-      rtpj2kdepay->buffer_list = g_value_get_boolean (value);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -626,14 +621,7 @@ static void
 gst_rtp_j2k_depay_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
-  GstRtpJ2KDepay *rtpj2kdepay;
-
-  rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
-
   switch (prop_id) {
-    case PROP_BUFFER_LIST:
-      g_value_set_boolean (value, rtpj2kdepay->buffer_list);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;