gst/rtp/gstrtpamrdec.c: Handle multiple AMr packets per payload. Handle CRC and parse...
authorWim Taymans <wim.taymans@gmail.com>
Wed, 21 Sep 2005 17:50:29 +0000 (17:50 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 21 Sep 2005 17:50:29 +0000 (17:50 +0000)
Original commit message from CVS:
* gst/rtp/gstrtpamrdec.c: (gst_rtpamrdec_sink_setcaps),
(gst_rtpamrdec_chain):
Handle multiple AMr packets per payload. Handle CRC and
parse ILL/ILP.

* gst/rtp/gstrtpamrenc.c: (gst_rtpamrenc_setcaps):
Make caps params strings for easy SDP mapping.

* gst/rtp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps):
Handle capsnego better.

* gst/rtp/gstrtpmp4vdec.c: (gst_rtpmp4vdec_setcaps):
* gst/rtp/gstrtpmp4venc.c: (gst_rtpmp4venc_new_caps):
Generate and parse config string in the caps.

ChangeLog
gst/rtp/gstrtpamrdec.c
gst/rtp/gstrtpamrdepay.c
gst/rtp/gstrtpamrenc.c
gst/rtp/gstrtpamrpay.c
gst/rtp/gstrtpdec.c
gst/rtp/gstrtpdepay.c
gst/rtp/gstrtpmp4vdec.c
gst/rtp/gstrtpmp4vdepay.c
gst/rtp/gstrtpmp4venc.c
gst/rtp/gstrtpmp4vpay.c

index 8743d98..53ff640 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2005-09-21  Wim Taymans  <wim@fluendo.com>
 
+       * gst/rtp/gstrtpamrdec.c: (gst_rtpamrdec_sink_setcaps),
+       (gst_rtpamrdec_chain):
+       Handle multiple AMr packets per payload. Handle CRC and
+       parse ILL/ILP.
+
+       * gst/rtp/gstrtpamrenc.c: (gst_rtpamrenc_setcaps):
+       Make caps params strings for easy SDP mapping.
+       
+       * gst/rtp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps):
+       Handle capsnego better.
+
+       * gst/rtp/gstrtpmp4vdec.c: (gst_rtpmp4vdec_setcaps):
+       * gst/rtp/gstrtpmp4venc.c: (gst_rtpmp4venc_new_caps):
+       Generate and parse config string in the caps.
+
+2005-09-21  Wim Taymans  <wim@fluendo.com>
+
        * gst/rtp/README:
        Update README
 
index f213662..216c3d5 100644 (file)
@@ -63,9 +63,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
         "clock-rate = (int) 8000, "
         "encoding-name = (string) \"AMR\", "
         "encoding-params = (string) \"1\", "
-        "octet-align = (string) 1, "
-        "crc = (string) 0, "
-        "robust-sorting = (string) 0, " "interleaving = (string) 0"
+        "octet-align = (string) \"1\", "
+        "crc = (string) { \"0\", \"1\" }, "
+        "robust-sorting = (string) \"0\", " "interleaving = (string) \"0\""
         /* following options are not needed for a decoder 
          *
          "mode-set = (int) [ 0, 7 ], "
@@ -238,8 +238,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
     return FALSE;
   if (rtpamrdec->octet_align != TRUE)
     return FALSE;
-  if (rtpamrdec->crc != FALSE)
-    return FALSE;
   if (rtpamrdec->robust_sorting != FALSE)
     return FALSE;
   if (rtpamrdec->interleaving != FALSE)
@@ -256,6 +254,12 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
   return TRUE;
 }
 
+/* -1 is invalid */
+static gint frame_size[16] = {
+  12, 13, 15, 17, 19, 20, 26, 31,
+  5, -1, -1, -1, -1, -1, -1, 0
+};
+
 static GstFlowReturn
 gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 {
@@ -275,9 +279,12 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
    * no robust sorting, no interleaving data is to be parsed */
   {
     gint payload_len;
-    guint8 *payload;
+    guint8 *payload, *p, *dp;
     guint32 timestamp;
-    guint8 CMR, F, FT, Q;
+    guint8 CMR;
+    gint i, num_packets, num_nonempty_packets;
+    gint amr_len;
+    gint ILL, ILP;
 
     payload_len = gst_rtpbuffer_get_payload_len (buf);
 
@@ -287,46 +294,111 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 
     payload = gst_rtpbuffer_get_payload (buf);
 
-    /* parse header 
-     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
-     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
-     * | CMR   |R|R|R|R|F|  FT   |Q|P|P|
-     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
+    /* parse CMR. The CMR is used by the sender to request
+     * a new encoding mode.
+     *
+     *  0 1 2 3 4 5 6 7 
+     * +-+-+-+-+-+-+-+-+
+     * | CMR   |R|R|R|R|
+     * +-+-+-+-+-+-+-+-+
      */
     CMR = (payload[0] & 0xf0) >> 4;
-    F = (payload[1] & 0x80) >> 7;
-    /* we only support 1 packet per RTP packet for now */
-    if (F != 0)
-      goto one_packet_only;
-
-    FT = (payload[1] & 0x78) >> 3;
-    Q = (payload[1] & 0x04) >> 2;
-
-    /* skip packet */
-    if (FT > 9 && FT < 15) {
-      ret = GST_FLOW_OK;
-      goto skip;
-    }
 
-    /* strip header now, leave FT in the data for the decoder */
+    /* strip CMR header now, pack FT and the data for the decoder */
     payload_len -= 1;
     payload += 1;
 
+    if (rtpamrdec->interleaving) {
+      ILL = (payload[0] & 0xf0) >> 4;
+      ILP = (payload[0] & 0x0f);
+
+      payload_len -= 1;
+      payload += 1;
+
+      if (ILP > ILL)
+        goto bad_packet;
+    }
+
+    /* 
+     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
+     * +-+-+-+-+-+-+-+-+..
+     * |F|  FT   |Q|P|P| more FT..
+     * +-+-+-+-+-+-+-+-+..
+     */
+    /* count number of packets by counting the FTs. Also
+     * count number of amr data bytes and number of non-empty
+     * packets (this is also the number of CRCs if present). */
+    amr_len = 0;
+    num_nonempty_packets = 0;
+    num_packets = 0;
+    for (i = 0; i < payload_len; i++) {
+      gint fr_size;
+      guint8 FT;
+
+      FT = (payload[i] & 0x78) >> 3;
+
+      fr_size = frame_size[FT];
+      if (fr_size == -1)
+        goto bad_packet;
+
+      if (fr_size > 0) {
+        amr_len += fr_size;
+        num_nonempty_packets++;
+      }
+      num_packets++;
+
+      if ((payload[i] & 0x80) == 0)
+        break;
+    }
+
+    /* this is impossible */
+    if (num_packets == payload_len)
+      goto bad_packet;
+
+    if (rtpamrdec->crc) {
+      /* data len + CRC len + header bytes should be smaller than payload_len */
+      if (num_packets + num_nonempty_packets + amr_len > payload_len)
+        goto bad_packet;
+    } else {
+      /* data len + header bytes should be smaller than payload_len */
+      if (num_packets + amr_len > payload_len)
+        goto bad_packet;
+    }
+
     timestamp = gst_rtpbuffer_get_timestamp (buf);
 
     outbuf = gst_buffer_new_and_alloc (payload_len);
-
     GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate;
 
-    memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
+    /* point to destination */
+    p = GST_BUFFER_DATA (outbuf);
+    /* point to first data packet */
+    dp = payload + num_packets;
+    if (rtpamrdec->crc) {
+      /* skip CRC if present */
+      dp += num_nonempty_packets;
+    }
+
+    for (i = 0; i < num_packets; i++) {
+      gint fr_size;
+
+      fr_size = frame_size[(payload[i] & 0x78) >> 3];
+      if (fr_size > 0) {
+        /* copy FT */
+        *p++ = payload[i];
+        /* copy data packet, FIXME, calc CRC here. */
+        memcpy (p, dp, fr_size);
 
+        p += fr_size;
+        dp += fr_size;
+      }
+    }
     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrdec->srcpad));
 
     GST_DEBUG ("gst_rtpamrdec_chain: pushing buffer of size %d",
         GST_BUFFER_SIZE (outbuf));
     ret = gst_pad_push (rtpamrdec->srcpad, outbuf);
 
-  skip:
     gst_buffer_unref (buf);
   }
 
@@ -334,21 +406,17 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 
 not_negotiated:
   {
-    GST_DEBUG ("not_negotiated");
+    GST_ELEMENT_ERROR (rtpamrdec, STREAM, NOT_IMPLEMENTED,
+        ("not negotiated"), (NULL));
     gst_buffer_unref (buf);
     return GST_FLOW_NOT_NEGOTIATED;
   }
 bad_packet:
   {
-    GST_DEBUG ("Packet did not validate");
-    gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
-  }
-one_packet_only:
-  {
-    GST_DEBUG ("One packet per RTP packet only");
+    GST_ELEMENT_WARNING (rtpamrdec, STREAM, DECODE,
+        ("amr packet did not validate"), (NULL));
     gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
+    return GST_FLOW_OK;
   }
 }
 
index f213662..216c3d5 100644 (file)
@@ -63,9 +63,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
         "clock-rate = (int) 8000, "
         "encoding-name = (string) \"AMR\", "
         "encoding-params = (string) \"1\", "
-        "octet-align = (string) 1, "
-        "crc = (string) 0, "
-        "robust-sorting = (string) 0, " "interleaving = (string) 0"
+        "octet-align = (string) \"1\", "
+        "crc = (string) { \"0\", \"1\" }, "
+        "robust-sorting = (string) \"0\", " "interleaving = (string) \"0\""
         /* following options are not needed for a decoder 
          *
          "mode-set = (int) [ 0, 7 ], "
@@ -238,8 +238,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
     return FALSE;
   if (rtpamrdec->octet_align != TRUE)
     return FALSE;
-  if (rtpamrdec->crc != FALSE)
-    return FALSE;
   if (rtpamrdec->robust_sorting != FALSE)
     return FALSE;
   if (rtpamrdec->interleaving != FALSE)
@@ -256,6 +254,12 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps)
   return TRUE;
 }
 
+/* -1 is invalid */
+static gint frame_size[16] = {
+  12, 13, 15, 17, 19, 20, 26, 31,
+  5, -1, -1, -1, -1, -1, -1, 0
+};
+
 static GstFlowReturn
 gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 {
@@ -275,9 +279,12 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
    * no robust sorting, no interleaving data is to be parsed */
   {
     gint payload_len;
-    guint8 *payload;
+    guint8 *payload, *p, *dp;
     guint32 timestamp;
-    guint8 CMR, F, FT, Q;
+    guint8 CMR;
+    gint i, num_packets, num_nonempty_packets;
+    gint amr_len;
+    gint ILL, ILP;
 
     payload_len = gst_rtpbuffer_get_payload_len (buf);
 
@@ -287,46 +294,111 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 
     payload = gst_rtpbuffer_get_payload (buf);
 
-    /* parse header 
-     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
-     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
-     * | CMR   |R|R|R|R|F|  FT   |Q|P|P|
-     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+..
+    /* parse CMR. The CMR is used by the sender to request
+     * a new encoding mode.
+     *
+     *  0 1 2 3 4 5 6 7 
+     * +-+-+-+-+-+-+-+-+
+     * | CMR   |R|R|R|R|
+     * +-+-+-+-+-+-+-+-+
      */
     CMR = (payload[0] & 0xf0) >> 4;
-    F = (payload[1] & 0x80) >> 7;
-    /* we only support 1 packet per RTP packet for now */
-    if (F != 0)
-      goto one_packet_only;
-
-    FT = (payload[1] & 0x78) >> 3;
-    Q = (payload[1] & 0x04) >> 2;
-
-    /* skip packet */
-    if (FT > 9 && FT < 15) {
-      ret = GST_FLOW_OK;
-      goto skip;
-    }
 
-    /* strip header now, leave FT in the data for the decoder */
+    /* strip CMR header now, pack FT and the data for the decoder */
     payload_len -= 1;
     payload += 1;
 
+    if (rtpamrdec->interleaving) {
+      ILL = (payload[0] & 0xf0) >> 4;
+      ILP = (payload[0] & 0x0f);
+
+      payload_len -= 1;
+      payload += 1;
+
+      if (ILP > ILL)
+        goto bad_packet;
+    }
+
+    /* 
+     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
+     * +-+-+-+-+-+-+-+-+..
+     * |F|  FT   |Q|P|P| more FT..
+     * +-+-+-+-+-+-+-+-+..
+     */
+    /* count number of packets by counting the FTs. Also
+     * count number of amr data bytes and number of non-empty
+     * packets (this is also the number of CRCs if present). */
+    amr_len = 0;
+    num_nonempty_packets = 0;
+    num_packets = 0;
+    for (i = 0; i < payload_len; i++) {
+      gint fr_size;
+      guint8 FT;
+
+      FT = (payload[i] & 0x78) >> 3;
+
+      fr_size = frame_size[FT];
+      if (fr_size == -1)
+        goto bad_packet;
+
+      if (fr_size > 0) {
+        amr_len += fr_size;
+        num_nonempty_packets++;
+      }
+      num_packets++;
+
+      if ((payload[i] & 0x80) == 0)
+        break;
+    }
+
+    /* this is impossible */
+    if (num_packets == payload_len)
+      goto bad_packet;
+
+    if (rtpamrdec->crc) {
+      /* data len + CRC len + header bytes should be smaller than payload_len */
+      if (num_packets + num_nonempty_packets + amr_len > payload_len)
+        goto bad_packet;
+    } else {
+      /* data len + header bytes should be smaller than payload_len */
+      if (num_packets + amr_len > payload_len)
+        goto bad_packet;
+    }
+
     timestamp = gst_rtpbuffer_get_timestamp (buf);
 
     outbuf = gst_buffer_new_and_alloc (payload_len);
-
     GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate;
 
-    memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
+    /* point to destination */
+    p = GST_BUFFER_DATA (outbuf);
+    /* point to first data packet */
+    dp = payload + num_packets;
+    if (rtpamrdec->crc) {
+      /* skip CRC if present */
+      dp += num_nonempty_packets;
+    }
+
+    for (i = 0; i < num_packets; i++) {
+      gint fr_size;
+
+      fr_size = frame_size[(payload[i] & 0x78) >> 3];
+      if (fr_size > 0) {
+        /* copy FT */
+        *p++ = payload[i];
+        /* copy data packet, FIXME, calc CRC here. */
+        memcpy (p, dp, fr_size);
 
+        p += fr_size;
+        dp += fr_size;
+      }
+    }
     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrdec->srcpad));
 
     GST_DEBUG ("gst_rtpamrdec_chain: pushing buffer of size %d",
         GST_BUFFER_SIZE (outbuf));
     ret = gst_pad_push (rtpamrdec->srcpad, outbuf);
 
-  skip:
     gst_buffer_unref (buf);
   }
 
@@ -334,21 +406,17 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
 
 not_negotiated:
   {
-    GST_DEBUG ("not_negotiated");
+    GST_ELEMENT_ERROR (rtpamrdec, STREAM, NOT_IMPLEMENTED,
+        ("not negotiated"), (NULL));
     gst_buffer_unref (buf);
     return GST_FLOW_NOT_NEGOTIATED;
   }
 bad_packet:
   {
-    GST_DEBUG ("Packet did not validate");
-    gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
-  }
-one_packet_only:
-  {
-    GST_DEBUG ("One packet per RTP packet only");
+    GST_ELEMENT_WARNING (rtpamrdec, STREAM, DECODE,
+        ("amr packet did not validate"), (NULL));
     gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
+    return GST_FLOW_OK;
   }
 }
 
index 37e5dd0..29cdb2b 100644 (file)
@@ -54,13 +54,13 @@ GST_STATIC_PAD_TEMPLATE ("src",
         "clock-rate = (int) 8000, "
         "encoding-name = (string) \"AMR\", "
         "encoding-params = (string) \"1\", "
-        "octet-align = (boolean) TRUE, "
-        "crc = (boolean) FALSE, "
-        "robust-sorting = (boolean) FALSE, "
-        "interleaving = (boolean) FALSE, "
+        "octet-align = (string) \"1\", "
+        "crc = (string) \"0\", "
+        "robust-sorting = (string) \"0\", "
+        "interleaving = (string) \"0\", "
         "mode-set = (int) [ 0, 7 ], "
         "mode-change-period = (int) [ 1, MAX ], "
-        "mode-change-neighbor = (boolean) { TRUE, FALSE }, "
+        "mode-change-neighbor = (string) { \"0\", \"1\" }, "
         "maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]")
     );
 
@@ -144,11 +144,14 @@ gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
 
   gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000);
   gst_basertppayload_set_outcaps (basepayload,
-      "encoding-params", G_TYPE_STRING, "1",
-      "octet-align", G_TYPE_BOOLEAN, TRUE,
-      "crc", G_TYPE_BOOLEAN, FALSE,
-      "robust-sorting", G_TYPE_BOOLEAN, FALSE,
-      "interleaving", G_TYPE_BOOLEAN, FALSE, NULL);
+      "encoding-params", G_TYPE_STRING, "1", "octet-align", G_TYPE_STRING, "1",
+      /* don't set the defaults 
+       * 
+       * "crc", G_TYPE_STRING, "0",
+       * "robust-sorting", G_TYPE_STRING, "0",
+       * "interleaving", G_TYPE_STRING, "0", 
+       */
+      NULL);
 
   return TRUE;
 }
index 37e5dd0..29cdb2b 100644 (file)
@@ -54,13 +54,13 @@ GST_STATIC_PAD_TEMPLATE ("src",
         "clock-rate = (int) 8000, "
         "encoding-name = (string) \"AMR\", "
         "encoding-params = (string) \"1\", "
-        "octet-align = (boolean) TRUE, "
-        "crc = (boolean) FALSE, "
-        "robust-sorting = (boolean) FALSE, "
-        "interleaving = (boolean) FALSE, "
+        "octet-align = (string) \"1\", "
+        "crc = (string) \"0\", "
+        "robust-sorting = (string) \"0\", "
+        "interleaving = (string) \"0\", "
         "mode-set = (int) [ 0, 7 ], "
         "mode-change-period = (int) [ 1, MAX ], "
-        "mode-change-neighbor = (boolean) { TRUE, FALSE }, "
+        "mode-change-neighbor = (string) { \"0\", \"1\" }, "
         "maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]")
     );
 
@@ -144,11 +144,14 @@ gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
 
   gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000);
   gst_basertppayload_set_outcaps (basepayload,
-      "encoding-params", G_TYPE_STRING, "1",
-      "octet-align", G_TYPE_BOOLEAN, TRUE,
-      "crc", G_TYPE_BOOLEAN, FALSE,
-      "robust-sorting", G_TYPE_BOOLEAN, FALSE,
-      "interleaving", G_TYPE_BOOLEAN, FALSE, NULL);
+      "encoding-params", G_TYPE_STRING, "1", "octet-align", G_TYPE_STRING, "1",
+      /* don't set the defaults 
+       * 
+       * "crc", G_TYPE_STRING, "0",
+       * "robust-sorting", G_TYPE_STRING, "0",
+       * "interleaving", G_TYPE_STRING, "0", 
+       */
+      NULL);
 
   return TRUE;
 }
index a7e7f6b..96089c4 100644 (file)
@@ -74,6 +74,7 @@ GST_STATIC_PAD_TEMPLATE ("sinkrtcp",
 static void gst_rtpdec_class_init (gpointer g_class);
 static void gst_rtpdec_init (GstRTPDec * rtpdec);
 
+static GstCaps *gst_rtpdec_getcaps (GstPad * pad);
 static GstFlowReturn gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer);
 static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer);
 
@@ -153,6 +154,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_rtpdec_sink_rtp_template), "sinkrtp");
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
+  gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
   gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
 
   /* the input rtcp pad */
@@ -166,6 +168,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
   rtpdec->src_rtp =
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_rtpdec_src_rtp_template), "srcrtp");
+  gst_pad_set_getcaps_function (rtpdec->src_rtp, gst_rtpdec_getcaps);
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtp);
 
   /* the output rtcp pad */
@@ -175,6 +178,19 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtcp);
 }
 
+static GstCaps *
+gst_rtpdec_getcaps (GstPad * pad)
+{
+  GstRTPDec *src;
+  GstPad *other;
+
+  src = GST_RTPDEC (GST_PAD_PARENT (pad));
+
+  other = pad == src->src_rtp ? src->sink_rtp : src->src_rtp;
+
+  return gst_pad_peer_get_caps (other);
+}
+
 static GstFlowReturn
 gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer)
 {
index a7e7f6b..96089c4 100644 (file)
@@ -74,6 +74,7 @@ GST_STATIC_PAD_TEMPLATE ("sinkrtcp",
 static void gst_rtpdec_class_init (gpointer g_class);
 static void gst_rtpdec_init (GstRTPDec * rtpdec);
 
+static GstCaps *gst_rtpdec_getcaps (GstPad * pad);
 static GstFlowReturn gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer);
 static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer);
 
@@ -153,6 +154,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_rtpdec_sink_rtp_template), "sinkrtp");
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
+  gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
   gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
 
   /* the input rtcp pad */
@@ -166,6 +168,7 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
   rtpdec->src_rtp =
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_rtpdec_src_rtp_template), "srcrtp");
+  gst_pad_set_getcaps_function (rtpdec->src_rtp, gst_rtpdec_getcaps);
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtp);
 
   /* the output rtcp pad */
@@ -175,6 +178,19 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
   gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->src_rtcp);
 }
 
+static GstCaps *
+gst_rtpdec_getcaps (GstPad * pad)
+{
+  GstRTPDec *src;
+  GstPad *other;
+
+  src = GST_RTPDEC (GST_PAD_PARENT (pad));
+
+  other = pad == src->src_rtp ? src->sink_rtp : src->src_rtp;
+
+  return gst_pad_peer_get_caps (other);
+}
+
 static GstFlowReturn
 gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer)
 {
index fba38d6..0b6ae40 100644 (file)
@@ -161,6 +161,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
   GstStructure *structure;
   GstRtpMP4VDec *rtpmp4vdec;
   GstCaps *srccaps;
+  const gchar *str;
 
   rtpmp4vdec = GST_RTP_MP4V_DEC (GST_OBJECT_PARENT (pad));
 
@@ -175,6 +176,29 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
   gst_pad_set_caps (rtpmp4vdec->srcpad, srccaps);
   gst_caps_unref (srccaps);
 
+  if ((str = gst_structure_get_string (structure, "config"))) {
+    GValue v = { 0 };
+
+    g_print ("config=%s\n", str);
+
+    g_value_init (&v, GST_TYPE_BUFFER);
+    if (gst_value_deserialize (&v, str)) {
+      GstBuffer *buffer;
+
+      buffer = gst_value_get_buffer (&v);
+      gst_buffer_ref (buffer);
+      g_value_unset (&v);
+
+      g_print ("buf=%p\n", buffer);
+
+      gst_buffer_set_caps (buffer, GST_PAD_CAPS (rtpmp4vdec->srcpad));
+
+      gst_pad_push (rtpmp4vdec->srcpad, buffer);
+    } else {
+      g_warning ("cannot convert config to buffer");
+    }
+  }
+
   return TRUE;
 }
 
index fba38d6..0b6ae40 100644 (file)
@@ -161,6 +161,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
   GstStructure *structure;
   GstRtpMP4VDec *rtpmp4vdec;
   GstCaps *srccaps;
+  const gchar *str;
 
   rtpmp4vdec = GST_RTP_MP4V_DEC (GST_OBJECT_PARENT (pad));
 
@@ -175,6 +176,29 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps)
   gst_pad_set_caps (rtpmp4vdec->srcpad, srccaps);
   gst_caps_unref (srccaps);
 
+  if ((str = gst_structure_get_string (structure, "config"))) {
+    GValue v = { 0 };
+
+    g_print ("config=%s\n", str);
+
+    g_value_init (&v, GST_TYPE_BUFFER);
+    if (gst_value_deserialize (&v, str)) {
+      GstBuffer *buffer;
+
+      buffer = gst_value_get_buffer (&v);
+      gst_buffer_ref (buffer);
+      g_value_unset (&v);
+
+      g_print ("buf=%p\n", buffer);
+
+      gst_buffer_set_caps (buffer, GST_PAD_CAPS (rtpmp4vdec->srcpad));
+
+      gst_pad_push (rtpmp4vdec->srcpad, buffer);
+    } else {
+      g_warning ("cannot convert config to buffer");
+    }
+  }
+
   return TRUE;
 }
 
index d9de14c..5a5de12 100644 (file)
@@ -45,11 +45,11 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS ("application/x-rtp, "
         "media = (string) \"video\", "
         "payload = (int) [ 96, 255 ], "
-        "clock-rate = (int) [1, MAX ], "
-        "encoding-name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]"
-        /* All optional parameters
+        "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"MP4V-ES\""
+        /* two string params
          *
-         * "config="
+         "profile-level-id = (string) [1,MAX]"
+         "config = (string) [1,MAX]"
          */
     )
     );
@@ -148,9 +148,22 @@ gst_rtpmp4venc_finalize (GObject * object)
 static void
 gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc)
 {
+  gchar *profile, *config;
+  GValue v = { 0 };
+
+  profile = g_strdup_printf ("%d", rtpmp4venc->profile);
+  g_value_init (&v, GST_TYPE_BUFFER);
+  gst_value_set_buffer (&v, rtpmp4venc->config);
+  config = gst_value_serialize (&v);
+
   gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc),
-      "profile-level-id", G_TYPE_INT, rtpmp4venc->profile,
-      "config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL);
+      "profile-level-id", G_TYPE_STRING, profile,
+      "config", G_TYPE_STRING, config, NULL);
+
+  g_value_unset (&v);
+
+  g_free (profile);
+  g_free (config);
 }
 
 static gboolean
index d9de14c..5a5de12 100644 (file)
@@ -45,11 +45,11 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS ("application/x-rtp, "
         "media = (string) \"video\", "
         "payload = (int) [ 96, 255 ], "
-        "clock-rate = (int) [1, MAX ], "
-        "encoding-name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]"
-        /* All optional parameters
+        "clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"MP4V-ES\""
+        /* two string params
          *
-         * "config="
+         "profile-level-id = (string) [1,MAX]"
+         "config = (string) [1,MAX]"
          */
     )
     );
@@ -148,9 +148,22 @@ gst_rtpmp4venc_finalize (GObject * object)
 static void
 gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc)
 {
+  gchar *profile, *config;
+  GValue v = { 0 };
+
+  profile = g_strdup_printf ("%d", rtpmp4venc->profile);
+  g_value_init (&v, GST_TYPE_BUFFER);
+  gst_value_set_buffer (&v, rtpmp4venc->config);
+  config = gst_value_serialize (&v);
+
   gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc),
-      "profile-level-id", G_TYPE_INT, rtpmp4venc->profile,
-      "config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL);
+      "profile-level-id", G_TYPE_STRING, profile,
+      "config", G_TYPE_STRING, config, NULL);
+
+  g_value_unset (&v);
+
+  g_free (profile);
+  g_free (config);
 }
 
 static gboolean