rtp: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpjpegdepay.c
index 0ea3303..5cd5428 100644 (file)
@@ -13,8 +13,8 @@
  *
  * 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.
  */
 
 #ifdef HAVE_CONFIG_H
 #endif
 
 #include <gst/rtp/gstrtpbuffer.h>
+#include <gst/video/video.h>
 
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "gstrtpjpegdepay.h"
+#include "gstrtputils.h"
 
 GST_DEBUG_CATEGORY_STATIC (rtpjpegdepay_debug);
 #define GST_CAT_DEFAULT (rtpjpegdepay_debug)
@@ -45,7 +47,6 @@ static GstStaticPadTemplate gst_rtp_jpeg_depay_sink_template =
     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) \"JPEG\"; "
         /* optional SDP attributes */
         /*
@@ -78,7 +79,7 @@ static GstStateChangeReturn gst_rtp_jpeg_depay_change_state (GstElement *
 static gboolean gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload,
     GstCaps * caps);
 static GstBuffer *gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload,
-    GstBuffer * buf);
+    GstRTPBuffer * rtp);
 
 static void
 gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass)
@@ -93,10 +94,10 @@ gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass)
 
   gobject_class->finalize = gst_rtp_jpeg_depay_finalize;
 
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_jpeg_depay_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_rtp_jpeg_depay_sink_template));
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_jpeg_depay_src_template);
+  gst_element_class_add_static_pad_template (gstelement_class,
+      &gst_rtp_jpeg_depay_sink_template);
 
   gst_element_class_set_static_metadata (gstelement_class,
       "RTP JPEG depayloader", "Codec/Depayloader/Network/RTP",
@@ -106,7 +107,7 @@ gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass)
   gstelement_class->change_state = gst_rtp_jpeg_depay_change_state;
 
   gstrtpbasedepayload_class->set_caps = gst_rtp_jpeg_depay_setcaps;
-  gstrtpbasedepayload_class->process = gst_rtp_jpeg_depay_process;
+  gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_jpeg_depay_process;
 
   GST_DEBUG_CATEGORY_INIT (rtpjpegdepay_debug, "rtpjpegdepay", 0,
       "JPEG Video RTP Depayloader");
@@ -154,6 +155,17 @@ gst_rtp_jpeg_depay_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static const int zigzag[] = {
+  0, 1, 8, 16, 9, 2, 3, 10,
+  17, 24, 32, 25, 18, 11, 4, 5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13, 6, 7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+
 /*
  * Table K.1 from JPEG spec.
  */
@@ -198,8 +210,8 @@ MakeTables (GstRtpJPEGDepay * rtpjpegdepay, gint Q, guint8 qtable[128])
     Q = 200 - factor * 2;
 
   for (i = 0; i < 64; i++) {
-    gint lq = (jpeg_luma_quantizer[i] * Q + 50) / 100;
-    gint cq = (jpeg_chroma_quantizer[i] * Q + 50) / 100;
+    gint lq = (jpeg_luma_quantizer[zigzag[i]] * Q + 50) / 100;
+    gint cq = (jpeg_chroma_quantizer[zigzag[i]] * Q + 50) / 100;
 
     /* Limit the quantizers to 1 <= q <= 255 */
     qtable[i] = CLAMP (lq, 1, 255);
@@ -406,7 +418,7 @@ MakeHeaders (guint8 * p, int type, int width, int height, guint8 * qt,
   *p++ = 0x11;                  /* huffman table 1 */
   *p++ = 0;                     /* first DCT coeff */
   *p++ = 63;                    /* last DCT coeff */
-  *p++ = 0;                     /* sucessive approx. */
+  *p++ = 0;                     /* successive approx. */
 
   return (p - start);
 };
@@ -477,7 +489,7 @@ gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
 }
 
 static GstBuffer *
-gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
+gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
 {
   GstRtpJPEGDepay *rtpjpegdepay;
   GstBuffer *outbuf;
@@ -488,22 +500,21 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
   guint type, width, height;
   guint16 dri, precision, length;
   guint8 *qtable;
-  GstRTPBuffer rtp = { NULL };
 
   rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
 
-  if (GST_BUFFER_IS_DISCONT (buf)) {
+  if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
+    GST_DEBUG_OBJECT (depayload, "DISCONT, reset adapter");
     gst_adapter_clear (rtpjpegdepay->adapter);
     rtpjpegdepay->discont = TRUE;
   }
 
-  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
-  payload_len = gst_rtp_buffer_get_payload_len (&rtp);
+  payload_len = gst_rtp_buffer_get_payload_len (rtp);
 
   if (payload_len < 8)
     goto empty_packet;
 
-  payload = gst_rtp_buffer_get_payload (&rtp);
+  payload = gst_rtp_buffer_get_payload (rtp);
   header_len = 0;
 
   /*  0                   1                   2                   3
@@ -520,6 +531,13 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
   width = payload[6] * 8;
   height = payload[7] * 8;
 
+  /* saw a packet with fragment offset > 0 and we don't already have data queued
+   * up (most importantly, we don't have a header for this data) -- drop it
+   * XXX: maybe we can check if the jpeg is progressive and salvage the data?
+   * XXX: not implemented yet because jpegenc can't create progressive jpegs */
+  if (frag_offset > 0 && gst_adapter_available (rtpjpegdepay->adapter) == 0)
+    goto no_header_packet;
+
   /* allow frame dimensions > 2040, passed in SDP session or media attributes
    * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
   if (!width)
@@ -609,9 +627,10 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
       GstCaps *outcaps;
 
       outcaps =
-          gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
-          rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
-          G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
+          gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
+          "framerate", GST_TYPE_FRACTION, rtpjpegdepay->frate_num,
+          rtpjpegdepay->frate_denom, "width", G_TYPE_INT, width,
+          "height", G_TYPE_INT, height, NULL);
       gst_pad_set_caps (depayload->srcpad, outcaps);
       gst_caps_unref (outcaps);
 
@@ -643,6 +662,12 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
           goto no_qtable;
       }
     }
+
+    /* I think we can get here with a NULL qtable, so make sure we don't
+       go dereferencing it in MakeHeaders if we do */
+    if (!qtable)
+      goto no_qtable;
+
     /* max header length, should be big enough */
     outbuf = gst_buffer_new_and_alloc (1000);
     gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
@@ -657,11 +682,11 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
 
   /* take JPEG data, push in the adapter */
   GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
-  outbuf = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len, -1);
+  outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, -1);
   gst_adapter_push (rtpjpegdepay->adapter, outbuf);
   outbuf = NULL;
 
-  if (gst_rtp_buffer_get_marker (&rtp)) {
+  if (gst_rtp_buffer_get_marker (rtp)) {
     guint avail;
     guint8 end[2];
     GstMapInfo map;
@@ -670,6 +695,9 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
     avail = gst_adapter_available (rtpjpegdepay->adapter);
     GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");
 
+    if (avail < 2)
+      goto invalid_packet;
+
     /* take the last bytes of the jpeg data to see if there is an EOI
      * marker */
     gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);
@@ -694,11 +722,11 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
       rtpjpegdepay->discont = FALSE;
     }
 
+    gst_rtp_drop_non_video_meta (rtpjpegdepay, outbuf);
+
     GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
   }
 
-  gst_rtp_buffer_unmap (&rtp);
-
   return outbuf;
 
   /* ERRORS */
@@ -706,20 +734,30 @@ empty_packet:
   {
     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
         ("Empty Payload."), (NULL));
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 invalid_dimension:
   {
     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
         ("Invalid Dimension %dx%d.", width, height), (NULL));
-    gst_rtp_buffer_unmap (&rtp);
     return NULL;
   }
 no_qtable:
   {
     GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
-    gst_rtp_buffer_unmap (&rtp);
+    return NULL;
+  }
+invalid_packet:
+  {
+    GST_WARNING_OBJECT (rtpjpegdepay, "invalid packet");
+    gst_adapter_flush (rtpjpegdepay->adapter,
+        gst_adapter_available (rtpjpegdepay->adapter));
+    return NULL;
+  }
+no_header_packet:
+  {
+    GST_WARNING_OBJECT (rtpjpegdepay,
+        "discarding data packets received when we have no header");
     return NULL;
   }
 }