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,3 +1,16 @@
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:

View 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
----
usage with UDP
--------------
- 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 )
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

View 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;
@ -328,13 +335,13 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
GValue v = { 0 };
#define MP4GCAPS \
"streamtype", G_TYPE_INT, rtpmp4gpay->streamtype, \
"profile-level-id", G_TYPE_INT, rtpmp4gpay->profile, \
"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_INT, 13, \
"indexlength", G_TYPE_INT, 3, \
"indexdeltalength", G_TYPE_INT, 3, \
"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);

View 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;
};