gst/rtp/README: Update README with some examples.

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.
This commit is contained in:
Wim Taymans 2006-09-21 09:35:13 +00:00
parent f1533c5504
commit 46d9a8a5e6
4 changed files with 148 additions and 51 deletions

View file

@ -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> 2006-09-20 Philippe Kalaf <philippe.kalaf at collabora.co.uk>
* gst/rtp/gstrtph263pdepay.c: * gst/rtp/gstrtph263pdepay.c:
* gst/rtp/gstrtph263ppay.c: * gst/rtp/gstrtph263ppay.c:
Correctly calculate size of each H263+ RTP buffer taking into account MTU and Correctly calculate size of each H263+ RTP buffer taking into account MTU and
RTP header. RTP header.

View file

@ -29,7 +29,7 @@ The following fields can or must (*) be specified in the structure:
clock-base: (uint) [0 - MAXINT] clock-base: (uint) [0 - MAXINT]
The RTP time representing time 0 The RTP time representing time 0
seqnum-base: seqnum-base: (uint) [0 - MAXINT]
The RTP sequence number representing the first rtp packet The RTP sequence number representing the first rtp packet
encoding-name: (String) ANY encoding-name: (String) ANY
@ -76,19 +76,96 @@ The following fields can or must (*) be specified in the structure:
possible. possible.
TODO usage with UDP
---- --------------
- implement packing up to the MTU. To correctly and completely use the RTP payloaders on the sender and the
- discont events in the case of packet loss receiver you need to write an application. It is not possible to write a full
- figure out the clocking. blown RTP server with a single gst-launch line.
- implement various RFCs dealing with different payload types.
(as modules?) That said, it is possible to do something functional with a few gst-launch
- Throw-out the the caps-nego & other session control things to the lines. The biggest problem when constructing a correct gst-launch line lies on
Application Developer( App ), by turning rtcp work into, signals the receiver end.
in gstrtpsend & props/args in gstrtprecv.
The App would then be free to use any sort of session control The receiver needs to know about the type of the RTP data along with a set of
protocal like RTSP.( done ) 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 Relevant RFCs

View file

@ -56,24 +56,25 @@ GST_STATIC_PAD_TEMPLATE ("src",
"clock-rate = (int) [1, MAX ], " "clock-rate = (int) [1, MAX ], "
"encoding-name = (string) \"mpeg4-generic\", " "encoding-name = (string) \"mpeg4-generic\", "
/* required string params */ /* required string params */
"streamtype = (int) { \"4\", \"5\" }, " /* 4 = video, 5 = audio */ "streamtype = (string) { \"4\", \"5\" }, " /* 4 = video, 5 = audio */
"profile-level-id = (int) [1,MAX], " /* "profile-level-id = (string) [1,MAX], " */
/* "config = (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 */ /* Optional general parameters */
"objecttype = (int) [1,MAX], " "constantsize = (int) [1,MAX], " /* constant size of each AU */ /* "objecttype = (string) [1,MAX], " */
"constantduration = (int) [1,MAX], " /* constant duration of each AU */ /* "constantsize = (string) [1,MAX], " *//* constant size of each AU */
"maxdisplacement = (int) [1,MAX], " /* "constantduration = (string) [1,MAX], " *//* constant duration of each AU */
"de-interleavebuffersize = (int) [1,MAX], " /* "maxdisplacement = (string) [1,MAX], " */
/* "de-interleavebuffersize = (string) [1,MAX], " */
/* Optional configuration parameters */ /* Optional configuration parameters */
"sizelength = (int) [1, 16], " /* max 16 bits, should be enough... */ /* "sizelength = (string) [1, 16], " *//* max 16 bits, should be enough... */
"indexlength = (int) [1, 8], " /* "indexlength = (string) [1, 8], " */
"indexdeltalength = (int) [1, 8], " /* "indexdeltalength = (string) [1, 8], " */
"ctsdeltalength = (int) [1, 64], " /* "ctsdeltalength = (string) [1, 64], " */
"dtsdeltalength = (int) [1, 64], " /* "dtsdeltalength = (string) [1, 64], " */
"randomaccessindication = (int) {0, 1}, " /* "randomaccessindication = (string) {0, 1}, " */
"streamstateindication = (int) [0, 64], " /* "streamstateindication = (string) [0, 64], " */
"auxiliarydatasizelength = (int) [0, 64]") /* "auxiliarydatasizelength = (string) [0, 64]" */ )
); );
enum enum
@ -167,7 +168,7 @@ gst_rtp_mp4g_pay_init (GstRtpMP4GPay * rtpmp4gpay)
{ {
rtpmp4gpay->adapter = gst_adapter_new (); rtpmp4gpay->adapter = gst_adapter_new ();
rtpmp4gpay->rate = 90000; rtpmp4gpay->rate = 90000;
rtpmp4gpay->profile = 1; rtpmp4gpay->profile = g_strdup ("1");
rtpmp4gpay->mode = ""; rtpmp4gpay->mode = "";
} }
@ -180,6 +181,8 @@ gst_rtp_mp4g_pay_finalize (GObject * object)
g_object_unref (rtpmp4gpay->adapter); g_object_unref (rtpmp4gpay->adapter);
rtpmp4gpay->adapter = NULL; rtpmp4gpay->adapter = NULL;
g_free (rtpmp4gpay->params);
rtpmp4gpay->params = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object); 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]; rtpmp4gpay->rate = sampling_table[samplingIdx];
} }
/* extra rtp params contain the number of channels */ /* 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 */ /* audio stream type */
rtpmp4gpay->streamtype = 5; rtpmp4gpay->streamtype = "5";
/* mode */ /* mode */
rtpmp4gpay->mode = "AAC-hbr"; rtpmp4gpay->mode = "AAC-hbr";
/* profile (should be 1) */ /* profile (should be 1) */
rtpmp4gpay->profile = objectType - 1; g_free (rtpmp4gpay->profile);
rtpmp4gpay->profile = g_strdup_printf ("%d", objectType - 1);
GST_DEBUG_OBJECT (rtpmp4gpay, GST_DEBUG_OBJECT (rtpmp4gpay,
"objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType, "objectType: %d, samplingIdx: %d (%d), channelCfg: %d", objectType,
@ -290,25 +295,27 @@ gst_rtp_mp4g_pay_parse_video_config (GstRtpMP4GPay * rtpmp4gpay,
goto too_short; goto too_short;
code = GST_READ_UINT32_BE (data); code = GST_READ_UINT32_BE (data);
g_free (rtpmp4gpay->profile);
if (code == VOS_STARTCODE) { if (code == VOS_STARTCODE) {
/* get profile */ /* get profile */
rtpmp4gpay->profile = data[4]; rtpmp4gpay->profile = g_strdup_printf ("%d", (gint) data[4]);
} else { } else {
GST_ELEMENT_WARNING (rtpmp4gpay, STREAM, FORMAT, GST_ELEMENT_WARNING (rtpmp4gpay, STREAM, FORMAT,
(NULL), ("profile not found in config string")); (NULL), ("profile not found in config string, assuming \'1\'"));
rtpmp4gpay->profile = 1; rtpmp4gpay->profile = g_strdup ("1");
} }
/* fixed rate */ /* fixed rate */
rtpmp4gpay->rate = 90000; rtpmp4gpay->rate = 90000;
/* video stream type */ /* video stream type */
rtpmp4gpay->streamtype = 4; rtpmp4gpay->streamtype = "4";
/* no params for video */ /* no params for video */
rtpmp4gpay->params = 0; rtpmp4gpay->params = NULL;
/* mode */ /* mode */
rtpmp4gpay->mode = "generic"; rtpmp4gpay->mode = "generic";
GST_LOG_OBJECT (rtpmp4gpay, "profile %d", rtpmp4gpay->profile); GST_LOG_OBJECT (rtpmp4gpay, "profile %s", rtpmp4gpay->profile);
return TRUE; return TRUE;
@ -327,14 +334,14 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
gchar *config; gchar *config;
GValue v = { 0 }; GValue v = { 0 };
#define MP4GCAPS \ #define MP4GCAPS \
"streamtype", G_TYPE_INT, rtpmp4gpay->streamtype, \ "streamtype", G_TYPE_STRING, rtpmp4gpay->streamtype, \
"profile-level-id", G_TYPE_INT, rtpmp4gpay->profile, \ "profile-level-id", G_TYPE_STRING, rtpmp4gpay->profile, \
"mode", G_TYPE_STRING, rtpmp4gpay->mode, \ "mode", G_TYPE_STRING, rtpmp4gpay->mode, \
"config", G_TYPE_STRING, config, \ "config", G_TYPE_STRING, config, \
"sizelength", G_TYPE_INT, 13, \ "sizelength", G_TYPE_STRING, "13", \
"indexlength", G_TYPE_INT, 3, \ "indexlength", G_TYPE_STRING, "3", \
"indexdeltalength", G_TYPE_INT, 3, \ "indexdeltalength", G_TYPE_STRING, "3", \
NULL NULL
g_value_init (&v, GST_TYPE_BUFFER); g_value_init (&v, GST_TYPE_BUFFER);
@ -344,7 +351,7 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
/* hmm, silly */ /* hmm, silly */
if (rtpmp4gpay->params) { if (rtpmp4gpay->params) {
gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4gpay), 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 { } else {
gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4gpay), gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4gpay),
MP4GCAPS); MP4GCAPS);

View file

@ -49,9 +49,9 @@ struct _GstRtpMP4GPay
GstClockTime duration; GstClockTime duration;
gint rate; gint rate;
gint params; gchar *params;
gint profile; gchar *profile;
gint streamtype; const gchar *streamtype;
const gchar *mode; const gchar *mode;
GstBuffer *config; GstBuffer *config;
}; };