mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +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
15
ChangeLog
15
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.
|
||||
|
|
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]
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue