mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
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:
parent
f1533c5504
commit
46d9a8a5e6
4 changed files with 148 additions and 51 deletions
13
ChangeLog
13
ChangeLog
|
@ -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>
|
2006-09-20 Philippe Kalaf <philippe.kalaf at collabora.co.uk>
|
||||||
|
|
||||||
* gst/rtp/gstrtph263pdepay.c:
|
* gst/rtp/gstrtph263pdepay.c:
|
||||||
|
|
103
gst/rtp/README
103
gst/rtp/README
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -328,13 +335,13 @@ gst_rtp_mp4g_pay_new_caps (GstRtpMP4GPay * rtpmp4gpay)
|
||||||
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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue