gst/rtp/README: Update README with some examples.
authorWim Taymans <wim.taymans@gmail.com>
Thu, 21 Sep 2006 09:35:13 +0000 (09:35 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 21 Sep 2006 09:35:13 +0000 (09:35 +0000)
Original commit message from CVS:
* gst/rtp/README:
Update README with some examples.
* gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_init),
(gst_rtp_mp4g_pay_finalize), (gst_rtp_mp4g_pay_parse_audio_config),
(gst_rtp_mp4g_pay_parse_video_config), (gst_rtp_mp4g_pay_new_caps),
(gst_rtp_mp4g_pay_setcaps):
* gst/rtp/gstrtpmp4gpay.h:
Make optional RTP parameters of type STRING, as required by the
application/x-rtp caps specification.

ChangeLog
gst/rtp/README
gst/rtp/gstrtpmp4gpay.c
gst/rtp/gstrtpmp4gpay.h

index 6116706..861bdeb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,19 @@
+2006-09-21  Wim Taymans  <wim@fluendo.com>
+
+       * gst/rtp/README:
+       Update README with some examples.
+
+       * gst/rtp/gstrtpmp4gpay.c: (gst_rtp_mp4g_pay_init),
+       (gst_rtp_mp4g_pay_finalize), (gst_rtp_mp4g_pay_parse_audio_config),
+       (gst_rtp_mp4g_pay_parse_video_config), (gst_rtp_mp4g_pay_new_caps),
+       (gst_rtp_mp4g_pay_setcaps):
+       * gst/rtp/gstrtpmp4gpay.h:
+       Make optional RTP parameters of type STRING, as required by the
+       application/x-rtp caps specification.
+
 2006-09-20  Philippe Kalaf  <philippe.kalaf at collabora.co.uk>
 
-  * gst/rtp/gstrtph263pdepay.c:
+       * gst/rtp/gstrtph263pdepay.c:
        * gst/rtp/gstrtph263ppay.c:
        Correctly calculate size of each H263+ RTP buffer taking into account MTU and
        RTP header.
index 146c55f..129efb9 100644 (file)
@@ -29,7 +29,7 @@ The following fields can or must (*) be specified in the structure:
    clock-base: (uint) [0 - MAXINT]
     The RTP time representing time 0
 
-   seqnum-base:
+   seqnum-base: (uint) [0 - MAXINT]
     The RTP sequence number representing the first rtp packet
 
    encoding-name: (String) ANY
@@ -76,19 +76,96 @@ The following fields can or must (*) be specified in the structure:
  possible.
 
 
-TODO
-----
-
-- implement packing up to the MTU.
-- discont events in the case of packet loss
-- figure out the clocking.
-- implement various RFCs dealing with different payload types. 
-  (as modules?)
-- Throw-out the the caps-nego & other session control things to the 
-  Application Developer( App ), by turning rtcp work into, signals 
-  in gstrtpsend & props/args in gstrtprecv.
-  The App would then be free to use any sort of session control 
-  protocal like RTSP.( done )
+usage with UDP
+--------------
+
+To correctly and completely use the RTP payloaders on the sender and the
+receiver you need to write an application. It is not possible to write a full
+blown RTP server with a single gst-launch line.
+
+That said, it is possible to do something functional with a few gst-launch
+lines. The biggest problem when constructing a correct gst-launch line lies on
+the receiver end. 
+
+The receiver needs to know about the type of the RTP data along with a set of
+RTP configuration parameters. This information is usually transmitted to the
+client using some sort of session description language (SDP) over some reliable
+channel (HTTP/RTSP/...).  
+
+All of the required parameters to connect and use the RTP session on the
+server can be found in the caps on the server end. The client receives this
+information in some way (caps are converted to and from SDP, as explained above,
+for example).
+
+Some gst-launch lines:
+
+  gst-launch-0.10 -v videotestsrc ! ffenc_h263p ! rtph263ppay ! udpsink
+
+   Setting pipeline to PAUSED ...
+   /pipeline0/videotestsrc0.src: caps = video/x-raw-yuv, format=(fourcc)I420,
+   width=(int)320, height=(int)240, framerate=(fraction)30/1
+   Pipeline is PREROLLING ...
+   ....
+   /pipeline0/udpsink0.sink: caps = application/x-rtp, media=(string)video,
+   payload=(int)96, clock-rate=(int)90000, encoding-name=(string)H263-1998,
+   ssrc=(guint)527842345, clock-base=(guint)1150776941, seqnum-base=(guint)30982
+   ....
+   Pipeline is PREROLLED ...
+   Setting pipeline to PLAYING ...
+   New clock: GstSystemClock
+
+ Write down the caps on the udpsink and set them as the caps of the UDP 
+ receiver:
+
+  gst-launch-0.10 -v udpsrc caps="application/x-rtp, media=(string)video,
+  payload=(int)96, clock-rate=(int)90000, encoding-name=(string)H263-1998,
+  ssrc=(guint)527842345, clock-base=(guint)1150776941, seqnum-base=(guint)30982"
+  ! rtph263pdepay ! ffdec_h263 ! xvimagesink sync=false
+
+ The receiver now displays an h263 image. Note that the sync parameter on
+ xvimagesink needs to be FALSE because we do not have an RTP session manager
+ that controls the synchronisation in this pipeline.
+
+ Stream a quicktime file with mpeg4 video and AAC audio on port 5000 and port
+ 5002.
+
+  gst-launch-0.10 -v filesrc location=~/data/sincity.mp4 ! qtdemux name=d ! queue ! rtpmp4vpay ! udpsink port=5000  
+                         d. ! queue ! rtpmp4gpay ! udpsink port=5002
+    ....
+    /pipeline0/udpsink0.sink: caps = application/x-rtp, media=(string)video,
+    payload=(int)96, clock-rate=(int)90000, encoding-name=(string)MP4V-ES,
+    ssrc=(guint)1162703703, clock-base=(guint)816135835, seqnum-base=(guint)9294,
+    profile-level-id=(string)3, config=(string)000001b003000001b50900000100000001200086c5d4c307d314043c1463000001b25876694430303334
+    /pipeline0/udpsink1.sink: caps = application/x-rtp, media=(string)audio,
+    payload=(int)96, clock-rate=(int)44100, encoding-name=(string)mpeg4-generic,
+    ssrc=(guint)3246149898, clock-base=(guint)4134514058, seqnum-base=(guint)57633,
+    encoding-params=(string)2, streamtype=(string)5, profile-level-id=(string)1,
+    mode=(string)AAC-hbr, config=(string)1210, sizelength=(string)13,
+    indexlength=(string)3, indexdeltalength=(string)3
+    ....
+
+ Again copy the caps on both sinks to the receiver launch line
+
+    gst-launch 
+     udpsrc port=5000 caps="application/x-rtp, media=(string)video, payload=(int)96,
+      clock-rate=(int)90000, encoding-name=(string)MP4V-ES, ssrc=(guint)1162703703,
+      clock-base=(guint)816135835, seqnum-base=(guint)9294, profile-level-id=(string)3,
+      config=(string)000001b003000001b50900000100000001200086c5d4c307d314043c1463000001b25876694430303334"
+      ! rtpmp4vdepay ! ffdec_mpeg4 ! xvimagesink sync=false 
+     udpsrc port=5002 caps="application/x-rtp, media=(string)audio, payload=(int)96,
+      clock-rate=(int)44100, encoding-name=(string)mpeg4-generic, ssrc=(guint)3246149898,
+      clock-base=(guint)4134514058, seqnum-base=(guint)57633, encoding-params=(string)2,
+      streamtype=(string)5, profile-level-id=(string)1, mode=(string)AAC-hbr,
+      config=(string)1210, sizelength=(string)13, indexlength=(string)3,
+      indexdeltalength=(string)3" 
+      ! rtpmp4gdepay ! faad ! alsasink sync=false
+
+ The caps on the udpsinks can be retrieved when the server pipeline prerolled to
+ PAUSED.
+
+ The caps on the receiver side can be set on the UDP source elements when the
+ pipeline went to PAUSED. In that state no data is received from the UDP sources
+ as they are live sources and only produce data in PLAYING.
 
 
 Relevant RFCs
index 3c8d804..42fae2e 100644 (file)
@@ -56,24 +56,25 @@ GST_STATIC_PAD_TEMPLATE ("src",
         "clock-rate = (int) [1, MAX ], "
         "encoding-name = (string) \"mpeg4-generic\", "
         /* required string params */
-        "streamtype = (int) { \"4\", \"5\" }, " /* 4 = video, 5 = audio */
-        "profile-level-id = (int) [1,MAX], "
+        "streamtype = (string) { \"4\", \"5\" }, "      /* 4 = video, 5 = audio */
+        /* "profile-level-id = (string) [1,MAX], " */
         /* "config = (string) [1,MAX]" */
-        "mode = (string) { \"generic\", \"CELP-cbr\", \"CELP-vbr\", \"AAC-lbr\", \"AAC-hbr\" }, "
+        "mode = (string) { \"generic\", \"CELP-cbr\", \"CELP-vbr\", \"AAC-lbr\", \"AAC-hbr\" } "
         /* Optional general parameters */
-        "objecttype = (int) [1,MAX], " "constantsize = (int) [1,MAX], " /* constant size of each AU */
-        "constantduration = (int) [1,MAX], "    /* constant duration of each AU */
-        "maxdisplacement = (int) [1,MAX], "
-        "de-interleavebuffersize = (int) [1,MAX], "
+        /* "objecttype = (string) [1,MAX], " */
+        /* "constantsize = (string) [1,MAX], " *//* constant size of each AU */
+        /* "constantduration = (string) [1,MAX], " *//* constant duration of each AU */
+        /* "maxdisplacement = (string) [1,MAX], " */
+        /* "de-interleavebuffersize = (string) [1,MAX], " */
         /* Optional configuration parameters */
-        "sizelength = (int) [1, 16], "  /* max 16 bits, should be enough... */
-        "indexlength = (int) [1, 8], "
-        "indexdeltalength = (int) [1, 8], "
-        "ctsdeltalength = (int) [1, 64], "
-        "dtsdeltalength = (int) [1, 64], "
-        "randomaccessindication = (int) {0, 1}, "
-        "streamstateindication = (int) [0, 64], "
-        "auxiliarydatasizelength = (int) [0, 64]")
+        /* "sizelength = (string) [1, 16], " *//* max 16 bits, should be enough... */
+        /* "indexlength = (string) [1, 8], " */
+        /* "indexdeltalength = (string) [1, 8], " */
+        /* "ctsdeltalength = (string) [1, 64], " */
+        /* "dtsdeltalength = (string) [1, 64], " */
+        /* "randomaccessindication = (string) {0, 1}, " */
+        /* "streamstateindication = (string) [0, 64], " */
+        /* "auxiliarydatasizelength = (string) [0, 64]" */ )
     );
 
 enum
@@ -167,7 +168,7 @@ gst_rtp_mp4g_pay_init (GstRtpMP4GPay * rtpmp4gpay)
 {
   rtpmp4gpay->adapter = gst_adapter_new ();
   rtpmp4gpay->rate = 90000;
-  rtpmp4gpay->profile = 1;
+  rtpmp4gpay->profile = g_strdup ("1");
   rtpmp4gpay->mode = "";
 }
 
@@ -180,6 +181,8 @@ gst_rtp_mp4g_pay_finalize (GObject * object)
 
   g_object_unref (rtpmp4gpay->adapter);
   rtpmp4gpay->adapter = NULL;
+  g_free (rtpmp4gpay->params);
+  rtpmp4gpay->params = NULL;
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -232,13 +235,15 @@ gst_rtp_mp4g_pay_parse_audio_config (GstRtpMP4GPay * rtpmp4gpay,
     rtpmp4gpay->rate = sampling_table[samplingIdx];
   }
   /* extra rtp params contain the number of channels */
-  rtpmp4gpay->params = channelCfg;
+  g_free (rtpmp4gpay->params);
+  rtpmp4gpay->params = g_strdup_printf ("%d", channelCfg);
   /* audio stream type */
-  rtpmp4gpay->streamtype = 5;
+  rtpmp4gpay->streamtype = "5";
   /* mode */
   rtpmp4gpay->mode = "AAC-hbr";
   /* profile (should be 1) */
-  rtpmp4gpay->profile = objectType - 1;
+  g_free (rtpmp4gpay->profile);
+  rtpmp4gpay->profile = g_strdup_printf ("%d", objectType - 1);
 
   GST_DEBUG_OBJECT (rtpmp4gpay,
       "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
@@ -290,25 +295,27 @@ gst_rtp_mp4g_pay_parse_video_config (GstRtpMP4GPay * rtpmp4gpay,
     goto too_short;
 
   code = GST_READ_UINT32_BE (data);
+
+  g_free (rtpmp4gpay->profile);
   if (code == VOS_STARTCODE) {
     /* get profile */
-    rtpmp4gpay->profile = data[4];
+    rtpmp4gpay->profile = g_strdup_printf ("%d", (gint) data[4]);
   } else {
     GST_ELEMENT_WARNING (rtpmp4gpay, STREAM, FORMAT,
-        (NULL), ("profile not found in config string"));
-    rtpmp4gpay->profile = 1;
+        (NULL), ("profile not found in config string, assuming \'1\'"));
+    rtpmp4gpay->profile = g_strdup ("1");
   }
 
   /* fixed rate */
   rtpmp4gpay->rate = 90000;
   /* video stream type */
-  rtpmp4gpay->streamtype = 4;
+  rtpmp4gpay->streamtype = "4";
   /* no params for video */
-  rtpmp4gpay->params = 0;
+  rtpmp4gpay->params = NULL;
   /* mode */
   rtpmp4gpay->mode = "generic";
 
-  GST_LOG_OBJECT (rtpmp4gpay, "profile %d", rtpmp4gpay->profile);
+  GST_LOG_OBJECT (rtpmp4gpay, "profile %s", rtpmp4gpay->profile);
 
   return TRUE;
 
@@ -327,14 +334,14 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
   gchar *config;
   GValue v = { 0 };
 
-#define MP4GCAPS                                       \
-  "streamtype", G_TYPE_INT, rtpmp4gpay->streamtype,    \
-  "profile-level-id", G_TYPE_INT, rtpmp4gpay->profile, \
-  "mode", G_TYPE_STRING, rtpmp4gpay->mode,             \
-  "config", G_TYPE_STRING, config,                     \
-  "sizelength", G_TYPE_INT, 13,                                \
-  "indexlength", G_TYPE_INT, 3,                                \
-  "indexdeltalength", G_TYPE_INT, 3,                   \
+#define MP4GCAPS                                               \
+  "streamtype", G_TYPE_STRING, rtpmp4gpay->streamtype,                 \
+  "profile-level-id", G_TYPE_STRING, rtpmp4gpay->profile,      \
+  "mode", G_TYPE_STRING, rtpmp4gpay->mode,                     \
+  "config", G_TYPE_STRING, config,                             \
+  "sizelength", G_TYPE_STRING, "13",                           \
+  "indexlength", G_TYPE_STRING, "3",                           \
+  "indexdeltalength", G_TYPE_STRING, "3",                      \
   NULL
 
   g_value_init (&v, GST_TYPE_BUFFER);
@@ -344,7 +351,7 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
   /* hmm, silly */
   if (rtpmp4gpay->params) {
     gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4gpay),
-        "encoding-params", G_TYPE_INT, rtpmp4gpay->params, MP4GCAPS);
+        "encoding-params", G_TYPE_STRING, rtpmp4gpay->params, MP4GCAPS);
   } else {
     gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4gpay),
         MP4GCAPS);
index bb0bb8f..b1557f5 100644 (file)
@@ -49,9 +49,9 @@ struct _GstRtpMP4GPay
   GstClockTime  duration;
 
   gint          rate;
-  gint         params;
-  gint          profile;
-  gint          streamtype;
+  gchar        *params;
+  gchar        *profile;
+  const gchar  *streamtype;
   const gchar  *mode;
   GstBuffer    *config;
 };