From fc158bc3c2739eabfb092f7a45f6656ac8c96e25 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 15 Sep 2005 13:57:56 +0000 Subject: [PATCH] Updates to payloader/depayloaders, make payloaders use the base classes. Original commit message from CVS: Updates to payloader/depayloaders, make payloaders use the base classes. Updated README with suggested RTP caps and how to convert to/from SDP. Added config descriptor in mp4v payloader. --- ChangeLog | 48 ++++++ common | 2 +- gst/rtp/Makefile.am | 2 + gst/rtp/README | 67 ++++++++ gst/rtp/gstrtp.c | 8 + gst/rtp/gstrtpamrdec.c | 39 ++--- gst/rtp/gstrtpamrdepay.c | 39 ++--- gst/rtp/gstrtpamrenc.c | 196 ++++------------------- gst/rtp/gstrtpamrenc.h | 14 +- gst/rtp/gstrtpamrpay.c | 196 ++++------------------- gst/rtp/gstrtpamrpay.h | 14 +- gst/rtp/gstrtpgsmdepay.c | 145 ++++++++--------- gst/rtp/gstrtpgsmdepay.h | 46 +++--- gst/rtp/gstrtpgsmenc.c | 236 +++++++--------------------- gst/rtp/gstrtpgsmenc.h | 52 ++----- gst/rtp/gstrtpgsmparse.c | 145 ++++++++--------- gst/rtp/gstrtpgsmparse.h | 46 +++--- gst/rtp/gstrtpgsmpay.c | 236 +++++++--------------------- gst/rtp/gstrtpgsmpay.h | 52 ++----- gst/rtp/gstrtph263pdec.c | 24 ++- gst/rtp/gstrtph263pdepay.c | 24 ++- gst/rtp/gstrtph263penc.c | 190 ++++++----------------- gst/rtp/gstrtph263penc.h | 14 +- gst/rtp/gstrtph263ppay.c | 190 ++++++----------------- gst/rtp/gstrtph263ppay.h | 14 +- gst/rtp/gstrtpmp4vdec.c | 9 +- gst/rtp/gstrtpmp4vdepay.c | 9 +- gst/rtp/gstrtpmp4venc.c | 309 ++++++++++++++++--------------------- gst/rtp/gstrtpmp4venc.h | 14 +- gst/rtp/gstrtpmp4vpay.c | 309 ++++++++++++++++--------------------- gst/rtp/gstrtpmp4vpay.h | 14 +- gst/rtp/gstrtpmpadec.c | 5 +- gst/rtp/gstrtpmpadepay.c | 5 +- gst/rtp/gstrtpmpaenc.c | 173 ++++++--------------- gst/rtp/gstrtpmpaenc.h | 11 +- gst/rtp/gstrtpmpapay.c | 173 ++++++--------------- gst/rtp/gstrtpmpapay.h | 11 +- 37 files changed, 1066 insertions(+), 2015 deletions(-) diff --git a/ChangeLog b/ChangeLog index f03aeb909d..9f600b7229 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +2005-09-15 Wim Taymans + + * gst/rtp/Makefile.am: + * gst/rtp/README: + * gst/rtp/gstrtp.c: (plugin_init): + * gst/rtp/gstrtpamrdec.c: (gst_rtpamrdec_init), + (gst_rtpamrdec_sink_setcaps), (gst_rtpamrdec_chain), + (gst_rtpamrdec_change_state): + * gst/rtp/gstrtpamrenc.c: (gst_rtpamrenc_get_type), + (gst_rtpamrenc_class_init), (gst_rtpamrenc_init), + (gst_rtpamrenc_setcaps), (gst_rtpamrenc_handle_buffer): + * gst/rtp/gstrtpamrenc.h: + * gst/rtp/gstrtpgsmenc.c: (gst_rtpgsmenc_get_type), + (gst_rtpgsmenc_class_init), (gst_rtpgsmenc_init), + (gst_rtpgsmenc_setcaps), (gst_rtpgsmenc_handle_buffer): + * gst/rtp/gstrtpgsmenc.h: + * gst/rtp/gstrtpgsmparse.c: (gst_rtpgsmparse_class_init), + (gst_rtpgsm_caps_nego), (gst_rtpgsmparse_chain), + (gst_rtpgsmparse_set_property), (gst_rtpgsmparse_get_property), + (gst_rtpgsmparse_change_state): + * gst/rtp/gstrtpgsmparse.h: + * gst/rtp/gstrtph263pdec.c: (gst_rtph263pdec_class_init), + (gst_rtph263pdec_finalize), (gst_rtph263pdec_change_state): + * gst/rtp/gstrtph263penc.c: (gst_rtph263penc_get_type), + (gst_rtph263penc_class_init), (gst_rtph263penc_init), + (gst_rtph263penc_finalize), (gst_rtph263penc_setcaps), + (gst_rtph263penc_flush), (gst_rtph263penc_handle_buffer): + * gst/rtp/gstrtph263penc.h: + * gst/rtp/gstrtpmp4vdec.c: (gst_rtpmp4vdec_setcaps), + (gst_rtpmp4vdec_chain), (gst_rtpmp4vdec_change_state): + * gst/rtp/gstrtpmp4venc.c: (gst_rtpmp4venc_get_type), + (gst_rtpmp4venc_class_init), (gst_rtpmp4venc_init), + (gst_rtpmp4venc_finalize), (gst_rtpmp4venc_new_caps), + (gst_rtpmp4venc_setcaps), (gst_rtpmp4venc_flush), + (gst_rtpmp4venc_parse_data), (gst_rtpmp4venc_handle_buffer): + * gst/rtp/gstrtpmp4venc.h: + * gst/rtp/gstrtpmpadec.c: + * gst/rtp/gstrtpmpaenc.c: (gst_rtpmpaenc_get_type), + (gst_rtpmpaenc_class_init), (gst_rtpmpaenc_init), + (gst_rtpmpaenc_finalize), (gst_rtpmpaenc_setcaps), + (gst_rtpmpaenc_flush), (gst_rtpmpaenc_handle_buffer): + * gst/rtp/gstrtpmpaenc.h: + Updates to payloader/depayloaders, make payloaders use + the base classes. + Updated README with suggested RTP caps and how to convert + to/from SDP. + Added config descriptor in mp4v payloader. + 2005-09-15 Andy Wingo * gst/autodetect/gstautoaudiosink.c (gst_auto_audio_sink_find_best): diff --git a/common b/common index 97fbc2dd78..9a5025a2d2 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 97fbc2dd78ea0cc2225b63ff383802b7c376d9b7 +Subproject commit 9a5025a2d276796d8d21243ef598e679ff7477bc diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am index 073e1145e4..151b3ef16f 100644 --- a/gst/rtp/Makefile.am +++ b/gst/rtp/Makefile.am @@ -4,6 +4,8 @@ libgstrtp_la_SOURCES = gstrtp.c \ gstrtpdec.c \ gstrtpmpadec.c \ gstrtpmpaenc.c \ + gstrtpgsmenc.c \ + gstrtpgsmparse.c \ gstrtpamrdec.c \ gstrtpamrenc.c \ gstrtph263pdec.c \ diff --git a/gst/rtp/README b/gst/rtp/README index 6a9b01bd82..b809df8a04 100644 --- a/gst/rtp/README +++ b/gst/rtp/README @@ -1,3 +1,70 @@ +The application/x-rtp mime type +------------------------------- + +For valid RTP packets encapsulated in GstBuffers, we use the caps with +mime type application/x-rtp. + +The following fields can or must (*) be specified in the structure: + + * media: (String) [ "audio", "video", "application", "data", "control" ] + Defined in RFC 2327 in the SDP media announcement field. + + * payload: (int) [0, 255] + For audio and video, these will normally be a media payload type as + defined in the RTP Audio/Video Profile. For dynamicaly allocated + payload types, this value will be >= 96 and the encoding_name must be + set. + + * clock_rate: (int) [0 - MAXINT] + the RTP clock rate + + ssrc: (uint) [0 - MAXINT] + The ssrc value currently in use. + + clock_base: (uint) [0 - MAXINT] + The RTP time representing time 0 + + seqnum_base: + The RTP sequence number representing the first rtp packet + + encoding_name: (String) ANY + typically second part of the mime type. ex. MP4V-ES. only required if + payload type >= 96 + + encoding_params: (String) ANY + extra encoding parameters (as in the SDP a=rtpmap: field). only required + if different from the default of the encoding_name. + + Optional parameters as key/value pairs, media type specific. + + Example: + + "application/x-rtp", + "media", G_TYPE_STRING, "audio", -] + "payload", G_TYPE_INT, 96, ] - required + "clock_rate", G_TYPE_INT, 8000, -] + "encoding_name", G_TYPE_STRING, "AMR", -] - required since payload >= 96 + "encoding_params", G_TYPE_STRING, "1", -] - optional param for AMR + "octet-align", G_TYPE_BOOLEAN, TRUE, -] + "crc", G_TYPE_BOOLEAN, FALSE, ] + "robust-sorting", G_TYPE_BOOLEAN, FALSE, ] AMR specific params. + "interleaving", G_TYPE_BOOLEAN, FALSE, -] + + Mapping of caps to and from SDP fields: + + m= RTP/AVP -] media and payload from caps + a=rtpmap: /[/] + -> when >= 96 + a=fmtp: =;... + + For above caps: + + m=audio RTP/AVP 96 + a=rtpmap:96 AMR/8000/1 + a=fmtp:96 octet-align=1;crc=0;robust-sorting=0;interleaving=0 + + in RTSP, the SSRC is also sent. + TODO ---- diff --git a/gst/rtp/gstrtp.c b/gst/rtp/gstrtp.c index d571b11997..6c6523cc92 100644 --- a/gst/rtp/gstrtp.c +++ b/gst/rtp/gstrtp.c @@ -22,6 +22,8 @@ #endif #include "gstrtpdec.h" +#include "gstrtpgsmenc.h" +#include "gstrtpgsmparse.h" #include "gstrtpamrenc.h" #include "gstrtpamrdec.h" #include "gstrtpmpaenc.h" @@ -37,6 +39,12 @@ plugin_init (GstPlugin * plugin) if (!gst_rtpdec_plugin_init (plugin)) return FALSE; + if (!gst_rtpgsmparse_plugin_init (plugin)) + return FALSE; + + if (!gst_rtpgsmenc_plugin_init (plugin)) + return FALSE; + if (!gst_rtpamrdec_plugin_init (plugin)) return FALSE; diff --git a/gst/rtp/gstrtpamrdec.c b/gst/rtp/gstrtpamrdec.c index c242a79cb9..a576e6fd8c 100644 --- a/gst/rtp/gstrtpamrdec.c +++ b/gst/rtp/gstrtpamrdec.c @@ -32,7 +32,7 @@ static GstElementDetails gst_rtp_amrdec_details = { "RTP packet parser", "Codec/Parser/Network", - "Extracts MPEG audio from RTP packets", + "Extracts AMR audio from RTP packets (RFC 3267)", "Wim Taymans " }; @@ -58,11 +58,14 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " + "encoding_name = (string) \"AMR\", " + "encoding_params = (string) \"1\", " "octet-align = (boolean) TRUE, " "crc = (boolean) FALSE, " - "robust-sorting = (boolean) FALSE, " - "interleaving = (boolean) FALSE, " - "channels = (int) 1, " "rate = (int) 8000" + "robust-sorting = (boolean) FALSE, " "interleaving = (boolean) FALSE" /* following options are not needed for a decoder * "mode-set = (int) [ 0, 7 ], " @@ -156,18 +159,10 @@ gst_rtpamrdec_class_init (GstRtpAMRDecClass * klass) static void gst_rtpamrdec_init (GstRtpAMRDec * rtpamrdec) { - GstCaps *srccaps; - rtpamrdec->srcpad = gst_pad_new_from_template (gst_static_pad_template_get (&gst_rtpamrdec_src_template), "src"); - /* FIXME */ - srccaps = gst_caps_new_simple ("audio/AMR", - "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL); - gst_pad_set_caps (rtpamrdec->srcpad, srccaps); - gst_caps_unref (srccaps); - gst_element_add_pad (GST_ELEMENT (rtpamrdec), rtpamrdec->srcpad); rtpamrdec->sinkpad = @@ -184,6 +179,7 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) GstStructure *structure; GstCaps *srccaps; GstRtpAMRDec *rtpamrdec; + const gchar *params; rtpamrdec = GST_RTP_AMR_DEC (GST_OBJECT_PARENT (pad)); @@ -193,10 +189,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) &rtpamrdec->octet_align)) rtpamrdec->octet_align = FALSE; - /* FIXME, force octect align for now until all elements negotiate - * correctly*/ - rtpamrdec->octet_align = TRUE; - if (!gst_structure_get_boolean (structure, "crc", &rtpamrdec->crc)) rtpamrdec->crc = FALSE; @@ -223,9 +215,13 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) rtpamrdec->octet_align = TRUE; } - if (!gst_structure_get_int (structure, "channels", &rtpamrdec->channels)) + if (!(params = gst_structure_get_string (structure, "encoding_params"))) rtpamrdec->channels = 1; - if (!gst_structure_get_int (structure, "rate", &rtpamrdec->rate)) + else { + rtpamrdec->channels = atoi (params); + } + + if (!gst_structure_get_int (structure, "clock_rate", &rtpamrdec->rate)) rtpamrdec->rate = 8000; /* we require 1 channel, 8000 Hz, octet aligned, no CRC, @@ -288,7 +284,7 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf) /* parse header * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.. - * | CMR=6 |R|R|R|R|0|FT#1=5 |Q|P|P| + * | CMR |R|R|R|R|F| FT |Q|P|P| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.. */ CMR = (payload[0] & 0xf0) >> 4; @@ -314,7 +310,7 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf) outbuf = gst_buffer_new_and_alloc (payload_len); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 8000; + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate; memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); @@ -392,9 +388,6 @@ gst_rtpamrdec_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: - /* FIXME, don't require negotiation until all elements - * do */ - rtpamrdec->negotiated = TRUE; break; default: break; diff --git a/gst/rtp/gstrtpamrdepay.c b/gst/rtp/gstrtpamrdepay.c index c242a79cb9..a576e6fd8c 100644 --- a/gst/rtp/gstrtpamrdepay.c +++ b/gst/rtp/gstrtpamrdepay.c @@ -32,7 +32,7 @@ static GstElementDetails gst_rtp_amrdec_details = { "RTP packet parser", "Codec/Parser/Network", - "Extracts MPEG audio from RTP packets", + "Extracts AMR audio from RTP packets (RFC 3267)", "Wim Taymans " }; @@ -58,11 +58,14 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " + "encoding_name = (string) \"AMR\", " + "encoding_params = (string) \"1\", " "octet-align = (boolean) TRUE, " "crc = (boolean) FALSE, " - "robust-sorting = (boolean) FALSE, " - "interleaving = (boolean) FALSE, " - "channels = (int) 1, " "rate = (int) 8000" + "robust-sorting = (boolean) FALSE, " "interleaving = (boolean) FALSE" /* following options are not needed for a decoder * "mode-set = (int) [ 0, 7 ], " @@ -156,18 +159,10 @@ gst_rtpamrdec_class_init (GstRtpAMRDecClass * klass) static void gst_rtpamrdec_init (GstRtpAMRDec * rtpamrdec) { - GstCaps *srccaps; - rtpamrdec->srcpad = gst_pad_new_from_template (gst_static_pad_template_get (&gst_rtpamrdec_src_template), "src"); - /* FIXME */ - srccaps = gst_caps_new_simple ("audio/AMR", - "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL); - gst_pad_set_caps (rtpamrdec->srcpad, srccaps); - gst_caps_unref (srccaps); - gst_element_add_pad (GST_ELEMENT (rtpamrdec), rtpamrdec->srcpad); rtpamrdec->sinkpad = @@ -184,6 +179,7 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) GstStructure *structure; GstCaps *srccaps; GstRtpAMRDec *rtpamrdec; + const gchar *params; rtpamrdec = GST_RTP_AMR_DEC (GST_OBJECT_PARENT (pad)); @@ -193,10 +189,6 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) &rtpamrdec->octet_align)) rtpamrdec->octet_align = FALSE; - /* FIXME, force octect align for now until all elements negotiate - * correctly*/ - rtpamrdec->octet_align = TRUE; - if (!gst_structure_get_boolean (structure, "crc", &rtpamrdec->crc)) rtpamrdec->crc = FALSE; @@ -223,9 +215,13 @@ gst_rtpamrdec_sink_setcaps (GstPad * pad, GstCaps * caps) rtpamrdec->octet_align = TRUE; } - if (!gst_structure_get_int (structure, "channels", &rtpamrdec->channels)) + if (!(params = gst_structure_get_string (structure, "encoding_params"))) rtpamrdec->channels = 1; - if (!gst_structure_get_int (structure, "rate", &rtpamrdec->rate)) + else { + rtpamrdec->channels = atoi (params); + } + + if (!gst_structure_get_int (structure, "clock_rate", &rtpamrdec->rate)) rtpamrdec->rate = 8000; /* we require 1 channel, 8000 Hz, octet aligned, no CRC, @@ -288,7 +284,7 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf) /* parse header * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.. - * | CMR=6 |R|R|R|R|0|FT#1=5 |Q|P|P| + * | CMR |R|R|R|R|F| FT |Q|P|P| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.. */ CMR = (payload[0] & 0xf0) >> 4; @@ -314,7 +310,7 @@ gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf) outbuf = gst_buffer_new_and_alloc (payload_len); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 8000; + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / rtpamrdec->rate; memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); @@ -392,9 +388,6 @@ gst_rtpamrdec_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: - /* FIXME, don't require negotiation until all elements - * do */ - rtpamrdec->negotiated = TRUE; break; default: break; diff --git a/gst/rtp/gstrtpamrenc.c b/gst/rtp/gstrtpamrenc.c index a60648d780..9b867cfe05 100644 --- a/gst/rtp/gstrtpamrenc.c +++ b/gst/rtp/gstrtpamrenc.c @@ -33,29 +33,10 @@ static GstElementDetails gst_rtp_amrenc_details = { "RTP packet parser", "Codec/Parser/Network", - "Encode AMR audio into RTP packets", + "Encode AMR audio into RTP packets (RFC 3267)", "Wim Taymans " }; -/* RtpAMREnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtpamrenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -68,34 +49,31 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " + "encoding_name = (string) \"AMR\", " + "encoding_params = (string) \"1\", " "octet-align = (boolean) TRUE, " "crc = (boolean) FALSE, " "robust-sorting = (boolean) FALSE, " "interleaving = (boolean) FALSE, " - "channels = (int) 1, " - "rate = (int) 8000, " "mode-set = (int) [ 0, 7 ], " "mode-change-period = (int) [ 1, MAX ], " "mode-change-neighbor = (boolean) { TRUE, FALSE }, " "maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]") ); - static void gst_rtpamrenc_class_init (GstRtpAMREncClass * klass); static void gst_rtpamrenc_base_init (GstRtpAMREncClass * klass); static void gst_rtpamrenc_init (GstRtpAMREnc * rtpamrenc); -static GstFlowReturn gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, + GstCaps * caps); +static GstFlowReturn gst_rtpamrenc_handle_buffer (GstBaseRTPPayload * pad, + GstBuffer * buffer); -static void gst_rtpamrenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpamrenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpamrenc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpamrenc_get_type (void) @@ -116,7 +94,7 @@ gst_rtpamrenc_get_type (void) }; rtpamrenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpAMREnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpAMREnc", &rtpamrenc_info, 0); } return rtpamrenc_type; @@ -140,64 +118,44 @@ gst_rtpamrenc_class_init (GstRtpAMREncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpamrenc_set_property; - gobject_class->get_property = gst_rtpamrenc_get_property; - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpamrenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpamrenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpamrenc_handle_buffer; } static void gst_rtpamrenc_init (GstRtpAMREnc * rtpamrenc) { - GstCaps *caps; +} - rtpamrenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpamrenc_src_template), "src"); +static gboolean +gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) +{ + GstRtpAMREnc *rtpamrenc; - caps = gst_caps_new_simple ("application/x-rtp", + rtpamrenc = GST_RTP_AMR_ENC (basepayload); + + gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000); + gst_basertppayload_set_outcaps (basepayload, + "encoding_params", G_TYPE_STRING, "1", "octet-align", G_TYPE_BOOLEAN, TRUE, "crc", G_TYPE_BOOLEAN, FALSE, "robust-sorting", G_TYPE_BOOLEAN, FALSE, - "interleaving", G_TYPE_BOOLEAN, FALSE, - "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL); + "interleaving", G_TYPE_BOOLEAN, FALSE, NULL); - gst_pad_set_caps (rtpamrenc->srcpad, caps); - gst_caps_unref (caps); - gst_element_add_pad (GST_ELEMENT (rtpamrenc), rtpamrenc->srcpad); - - rtpamrenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpamrenc_sink_template), "sink"); - gst_pad_set_chain_function (rtpamrenc->sinkpad, gst_rtpamrenc_chain); - gst_element_add_pad (GST_ELEMENT (rtpamrenc), rtpamrenc->sinkpad); - - rtpamrenc->mtu = DEFAULT_MTU; - rtpamrenc->pt = DEFAULT_PT; - rtpamrenc->ssrc = DEFAULT_SSRC; + return TRUE; } static GstFlowReturn -gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpamrenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpAMREnc *rtpamrenc; GstFlowReturn ret; @@ -206,7 +164,7 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) guint8 *payload, *data; GstClockTime timestamp; - rtpamrenc = GST_RTP_AMR_ENC (gst_pad_get_parent (pad)); + rtpamrenc = GST_RTP_AMR_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); @@ -221,12 +179,7 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); /* FIXME, assert for now */ - g_assert (GST_BUFFER_SIZE (outbuf) < rtpamrenc->mtu); - - gst_rtpbuffer_set_payload_type (outbuf, rtpamrenc->pt); - gst_rtpbuffer_set_ssrc (outbuf, rtpamrenc->ssrc); - gst_rtpbuffer_set_seq (outbuf, rtpamrenc->seqnum++); - gst_rtpbuffer_set_timestamp (outbuf, timestamp * 8000 / GST_SECOND); + g_assert (GST_BUFFER_SIZE (outbuf) < GST_BASE_RTP_PAYLOAD_MTU (rtpamrenc)); /* copy timestamp */ GST_BUFFER_TIMESTAMP (outbuf) = timestamp; @@ -256,89 +209,8 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrenc->srcpad)); + ret = gst_basertppayload_push (basepayload, outbuf); - ret = gst_pad_push (rtpamrenc->srcpad, outbuf); - - gst_object_unref (rtpamrenc); - - return ret; -} - -static void -gst_rtpamrenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpAMREnc *rtpamrenc; - - rtpamrenc = GST_RTP_AMR_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpamrenc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtpamrenc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtpamrenc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpamrenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpAMREnc *rtpamrenc; - - rtpamrenc = GST_RTP_AMR_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpamrenc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtpamrenc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtpamrenc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpamrenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpAMREnc *rtpamrenc; - GstStateChangeReturn ret; - - rtpamrenc = GST_RTP_AMR_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpamrenc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } return ret; } diff --git a/gst/rtp/gstrtpamrenc.h b/gst/rtp/gstrtpamrenc.h index 7d9e06fe15..719cffa3dd 100644 --- a/gst/rtp/gstrtpamrenc.h +++ b/gst/rtp/gstrtpamrenc.h @@ -21,6 +21,7 @@ #define __GST_RTP_AMR_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,21 +42,12 @@ typedef struct _GstRtpAMREncClass GstRtpAMREncClass; struct _GstRtpAMREnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint16 seqnum; - guint pt; - guint ssrc; - - guint mtu; + GstBaseRTPPayload payload; }; struct _GstRtpAMREncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpamrenc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpamrpay.c b/gst/rtp/gstrtpamrpay.c index a60648d780..9b867cfe05 100644 --- a/gst/rtp/gstrtpamrpay.c +++ b/gst/rtp/gstrtpamrpay.c @@ -33,29 +33,10 @@ static GstElementDetails gst_rtp_amrenc_details = { "RTP packet parser", "Codec/Parser/Network", - "Encode AMR audio into RTP packets", + "Encode AMR audio into RTP packets (RFC 3267)", "Wim Taymans " }; -/* RtpAMREnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtpamrenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -68,34 +49,31 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " + "encoding_name = (string) \"AMR\", " + "encoding_params = (string) \"1\", " "octet-align = (boolean) TRUE, " "crc = (boolean) FALSE, " "robust-sorting = (boolean) FALSE, " "interleaving = (boolean) FALSE, " - "channels = (int) 1, " - "rate = (int) 8000, " "mode-set = (int) [ 0, 7 ], " "mode-change-period = (int) [ 1, MAX ], " "mode-change-neighbor = (boolean) { TRUE, FALSE }, " "maxptime = (int) [ 20, MAX ], " "ptime = (int) [ 20, MAX ]") ); - static void gst_rtpamrenc_class_init (GstRtpAMREncClass * klass); static void gst_rtpamrenc_base_init (GstRtpAMREncClass * klass); static void gst_rtpamrenc_init (GstRtpAMREnc * rtpamrenc); -static GstFlowReturn gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, + GstCaps * caps); +static GstFlowReturn gst_rtpamrenc_handle_buffer (GstBaseRTPPayload * pad, + GstBuffer * buffer); -static void gst_rtpamrenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpamrenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpamrenc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpamrenc_get_type (void) @@ -116,7 +94,7 @@ gst_rtpamrenc_get_type (void) }; rtpamrenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpAMREnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpAMREnc", &rtpamrenc_info, 0); } return rtpamrenc_type; @@ -140,64 +118,44 @@ gst_rtpamrenc_class_init (GstRtpAMREncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpamrenc_set_property; - gobject_class->get_property = gst_rtpamrenc_get_property; - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpamrenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpamrenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpamrenc_handle_buffer; } static void gst_rtpamrenc_init (GstRtpAMREnc * rtpamrenc) { - GstCaps *caps; +} - rtpamrenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpamrenc_src_template), "src"); +static gboolean +gst_rtpamrenc_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) +{ + GstRtpAMREnc *rtpamrenc; - caps = gst_caps_new_simple ("application/x-rtp", + rtpamrenc = GST_RTP_AMR_ENC (basepayload); + + gst_basertppayload_set_options (basepayload, "audio", TRUE, "AMR", 8000); + gst_basertppayload_set_outcaps (basepayload, + "encoding_params", G_TYPE_STRING, "1", "octet-align", G_TYPE_BOOLEAN, TRUE, "crc", G_TYPE_BOOLEAN, FALSE, "robust-sorting", G_TYPE_BOOLEAN, FALSE, - "interleaving", G_TYPE_BOOLEAN, FALSE, - "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 8000, NULL); + "interleaving", G_TYPE_BOOLEAN, FALSE, NULL); - gst_pad_set_caps (rtpamrenc->srcpad, caps); - gst_caps_unref (caps); - gst_element_add_pad (GST_ELEMENT (rtpamrenc), rtpamrenc->srcpad); - - rtpamrenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpamrenc_sink_template), "sink"); - gst_pad_set_chain_function (rtpamrenc->sinkpad, gst_rtpamrenc_chain); - gst_element_add_pad (GST_ELEMENT (rtpamrenc), rtpamrenc->sinkpad); - - rtpamrenc->mtu = DEFAULT_MTU; - rtpamrenc->pt = DEFAULT_PT; - rtpamrenc->ssrc = DEFAULT_SSRC; + return TRUE; } static GstFlowReturn -gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpamrenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpAMREnc *rtpamrenc; GstFlowReturn ret; @@ -206,7 +164,7 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) guint8 *payload, *data; GstClockTime timestamp; - rtpamrenc = GST_RTP_AMR_ENC (gst_pad_get_parent (pad)); + rtpamrenc = GST_RTP_AMR_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); @@ -221,12 +179,7 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); /* FIXME, assert for now */ - g_assert (GST_BUFFER_SIZE (outbuf) < rtpamrenc->mtu); - - gst_rtpbuffer_set_payload_type (outbuf, rtpamrenc->pt); - gst_rtpbuffer_set_ssrc (outbuf, rtpamrenc->ssrc); - gst_rtpbuffer_set_seq (outbuf, rtpamrenc->seqnum++); - gst_rtpbuffer_set_timestamp (outbuf, timestamp * 8000 / GST_SECOND); + g_assert (GST_BUFFER_SIZE (outbuf) < GST_BASE_RTP_PAYLOAD_MTU (rtpamrenc)); /* copy timestamp */ GST_BUFFER_TIMESTAMP (outbuf) = timestamp; @@ -256,89 +209,8 @@ gst_rtpamrenc_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpamrenc->srcpad)); + ret = gst_basertppayload_push (basepayload, outbuf); - ret = gst_pad_push (rtpamrenc->srcpad, outbuf); - - gst_object_unref (rtpamrenc); - - return ret; -} - -static void -gst_rtpamrenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpAMREnc *rtpamrenc; - - rtpamrenc = GST_RTP_AMR_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpamrenc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtpamrenc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtpamrenc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpamrenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpAMREnc *rtpamrenc; - - rtpamrenc = GST_RTP_AMR_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpamrenc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtpamrenc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtpamrenc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpamrenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpAMREnc *rtpamrenc; - GstStateChangeReturn ret; - - rtpamrenc = GST_RTP_AMR_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpamrenc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } return ret; } diff --git a/gst/rtp/gstrtpamrpay.h b/gst/rtp/gstrtpamrpay.h index 7d9e06fe15..719cffa3dd 100644 --- a/gst/rtp/gstrtpamrpay.h +++ b/gst/rtp/gstrtpamrpay.h @@ -21,6 +21,7 @@ #define __GST_RTP_AMR_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,21 +42,12 @@ typedef struct _GstRtpAMREncClass GstRtpAMREncClass; struct _GstRtpAMREnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint16 seqnum; - guint pt; - guint ssrc; - - guint mtu; + GstBaseRTPPayload payload; }; struct _GstRtpAMREncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpamrenc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpgsmdepay.c b/gst/rtp/gstrtpgsmdepay.c index 78171cbfcd..97b43420f8 100644 --- a/gst/rtp/gstrtpgsmdepay.c +++ b/gst/rtp/gstrtpgsmdepay.c @@ -17,8 +17,8 @@ #endif #include +#include #include "gstrtpgsmparse.h" -#include "gstrtp-common.h" /* elementfactory information */ static GstElementDetails gst_rtp_gsmparse_details = { @@ -60,13 +60,15 @@ static void gst_rtpgsmparse_class_init (GstRtpGSMParseClass * klass); static void gst_rtpgsmparse_base_init (GstRtpGSMParseClass * klass); static void gst_rtpgsmparse_init (GstRtpGSMParse * rtpgsmparse); -static void gst_rtpgsmparse_chain (GstPad * pad, GstData * _data); +static GstFlowReturn gst_rtpgsmparse_chain (GstPad * pad, GstBuffer * buffer); static void gst_rtpgsmparse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_rtpgsmparse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element); + +static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element, + GstStateChange transition); static GstElementClass *parent_class = NULL; @@ -118,13 +120,13 @@ gst_rtpgsmparse_class_init (GstRtpGSMParseClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = gst_rtpgsmparse_set_property; + gobject_class->get_property = gst_rtpgsmparse_get_property; + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREQUENCY, g_param_spec_int ("frequency", "frequency", "frequency", G_MININT, G_MAXINT, 8000, G_PARAM_READWRITE)); - gobject_class->set_property = gst_rtpgsmparse_set_property; - gobject_class->get_property = gst_rtpgsmparse_get_property; - gstelement_class->change_state = gst_rtpgsmparse_change_state; } @@ -144,21 +146,7 @@ gst_rtpgsmparse_init (GstRtpGSMParse * rtpgsmparse) rtpgsmparse->frequency = 8000; } -void -gst_rtpgsmparse_ntohs (GstBuffer * buf) -{ - gint16 *i, *len; - - /* FIXME: is this code correct or even sane at all? */ - i = (gint16 *) GST_BUFFER_DATA (buf); - len = i + GST_BUFFER_SIZE (buf) / sizeof (gint16 *); - - for (; i < len; i++) { - *i = g_ntohs (*i); - } -} - -void +static void gst_rtpgsm_caps_nego (GstRtpGSMParse * rtpgsmparse) { GstCaps *caps; @@ -166,72 +154,67 @@ gst_rtpgsm_caps_nego (GstRtpGSMParse * rtpgsmparse) caps = gst_caps_new_simple ("audio/x-gsm", "rate", G_TYPE_INT, rtpgsmparse->frequency, NULL); - gst_pad_try_set_caps (rtpgsmparse->srcpad, caps); + gst_pad_set_caps (rtpgsmparse->srcpad, caps); + gst_caps_unref (caps); } -static void -gst_rtpgsmparse_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_rtpgsmparse_chain (GstPad * pad, GstBuffer * buf) { - GstBuffer *buf = GST_BUFFER (_data); GstRtpGSMParse *rtpgsmparse; GstBuffer *outbuf; - Rtp_Packet packet; - rtp_payload_t pt; + GstFlowReturn ret; + guint8 pt; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - rtpgsmparse = GST_RTP_GSM_PARSE (GST_OBJECT_PARENT (pad)); - - g_return_if_fail (rtpgsmparse != NULL); - g_return_if_fail (GST_IS_RTP_GSM_PARSE (rtpgsmparse)); - - if (GST_IS_EVENT (buf)) { - GstEvent *event = GST_EVENT (buf); - - gst_pad_event_default (pad, event); - - return; - } + rtpgsmparse = GST_RTP_GSM_PARSE (gst_pad_get_parent (pad)); if (GST_PAD_CAPS (rtpgsmparse->srcpad) == NULL) { gst_rtpgsm_caps_nego (rtpgsmparse); } - packet = - rtp_packet_new_copy_data (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; - pt = rtp_packet_get_payload_type (packet); + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != GST_RTP_PAYLOAD_GSM) + goto bad_payload; + + { + gint payload_len; + guint8 *payload; + guint32 timestamp; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 8000; + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + GST_DEBUG ("pushing buffer of size %d", GST_BUFFER_SIZE (outbuf)); - if (pt != PAYLOAD_GSM) { - g_warning ("Unexpected paload type %u\n", pt); - rtp_packet_free (packet); gst_buffer_unref (buf); - return; + + ret = gst_pad_push (rtpgsmparse->srcpad, outbuf); } - outbuf = gst_buffer_new (); - GST_BUFFER_SIZE (outbuf) = rtp_packet_get_payload_len (packet); - GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf)); - GST_BUFFER_TIMESTAMP (outbuf) = - g_ntohl (rtp_packet_get_timestamp (packet)) * GST_SECOND; + return ret; - memcpy (GST_BUFFER_DATA (outbuf), rtp_packet_get_payload (packet), - GST_BUFFER_SIZE (outbuf)); - - GST_DEBUG ("gst_rtpgsmparse_chain: pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); - -/* FIXME: According to RFC 1890, this is required, right? */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - gst_rtpgsmparse_ntohs (outbuf); -#endif - - gst_pad_push (rtpgsmparse->srcpad, GST_DATA (outbuf)); - - rtp_packet_free (packet); - gst_buffer_unref (buf); +bad_packet: + { + GST_DEBUG ("Packet did not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } } static void @@ -240,7 +223,6 @@ gst_rtpgsmparse_set_property (GObject * object, guint prop_id, { GstRtpGSMParse *rtpgsmparse; - g_return_if_fail (GST_IS_RTP_GSM_PARSE (object)); rtpgsmparse = GST_RTP_GSM_PARSE (object); switch (prop_id) { @@ -258,7 +240,6 @@ gst_rtpgsmparse_get_property (GObject * object, guint prop_id, GValue * value, { GstRtpGSMParse *rtpgsmparse; - g_return_if_fail (GST_IS_RTP_GSM_PARSE (object)); rtpgsmparse = GST_RTP_GSM_PARSE (object); switch (prop_id) { @@ -275,28 +256,26 @@ static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element, GstStateChange transition) { GstRtpGSMParse *rtpgsmparse; - - g_return_val_if_fail (GST_IS_RTP_GSM_PARSE (element), - GST_STATE_CHANGE_FAILURE); + GstStateChangeReturn ret; rtpgsmparse = GST_RTP_GSM_PARSE (element); - GST_DEBUG ("state pending %d\n", GST_STATE_PENDING (element)); - switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; default: break; } - /* if we haven't failed already, give the parent class a chance to ;-) */ - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - return GST_STATE_CHANGE_SUCCESS; + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + return ret; } gboolean diff --git a/gst/rtp/gstrtpgsmdepay.h b/gst/rtp/gstrtpgsmdepay.h index 0a006e70fe..19bd5b28ff 100644 --- a/gst/rtp/gstrtpgsmdepay.h +++ b/gst/rtp/gstrtpgsmdepay.h @@ -21,34 +21,12 @@ #define __GST_RTP_GSM_PARSE_H__ #include -#include "rtp-packet.h" -#include "gstrtp-common.h" -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS -/* Definition of structure storing data for this element. */ typedef struct _GstRtpGSMParse GstRtpGSMParse; -struct _GstRtpGSMParse -{ - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint frequency; -}; - -/* Standard definition defining a class for this element. */ typedef struct _GstRtpGSMParseClass GstRtpGSMParseClass; -struct _GstRtpGSMParseClass -{ - GstElementClass parent_class; -}; -/* Standard macros for defining types for this element. */ #define GST_TYPE_RTP_GSM_PARSE \ (gst_rtpgsmparse_get_type()) #define GST_RTP_GSM_PARSE(obj) \ @@ -60,11 +38,23 @@ struct _GstRtpGSMParseClass #define GST_IS_RTP_GSM_PARSE_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_GSM_PARSE)) +struct _GstRtpGSMParse +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + guint frequency; +}; + +struct _GstRtpGSMParseClass +{ + GstElementClass parent_class; +}; + gboolean gst_rtpgsmparse_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS - -#endif /* __GST_RTP_GSM_PARSE_H__ */ +#endif /* __GST_RTP_GSM_PARSE_H__ */ diff --git a/gst/rtp/gstrtpgsmenc.c b/gst/rtp/gstrtpgsmenc.c index 47daa43064..19930ac321 100644 --- a/gst/rtp/gstrtpgsmenc.c +++ b/gst/rtp/gstrtpgsmenc.c @@ -23,6 +23,8 @@ #include #include +#include + #include "gstrtpgsmenc.h" /* elementfactory information */ @@ -33,19 +35,6 @@ static GstElementDetails gst_rtpgsmenc_details = { "Zeeshan Ali " }; -/* RtpGSMEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - /* FILL ME */ - ARG_0 -}; - static GstStaticPadTemplate gst_rtpgsmenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -57,24 +46,23 @@ static GstStaticPadTemplate gst_rtpgsmenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " "encoding_name = (string) \"GSM\"") ); static void gst_rtpgsmenc_class_init (GstRtpGSMEncClass * klass); static void gst_rtpgsmenc_base_init (GstRtpGSMEncClass * klass); static void gst_rtpgsmenc_init (GstRtpGSMEnc * rtpgsmenc); -static void gst_rtpgsmenc_chain (GstPad * pad, GstData * _data); -static void gst_rtpgsmenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpgsmenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static GstPadLinkReturn gst_rtpgsmenc_sinkconnect (GstPad * pad, - const GstCaps * caps); -static GstStateChangeReturn gst_rtpgsmenc_change_state (GstElement * element, - GstStateChange transition); -static GstElementClass *parent_class = NULL; +static gboolean gst_rtpgsmenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpgsmenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); + +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpgsmenc_get_type (void) @@ -95,7 +83,7 @@ gst_rtpgsmenc_get_type (void) }; rtpgsmenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpGSMEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpGSMEnc", &rtpgsmenc_info, 0); } return rtpgsmenc_type; @@ -118,209 +106,91 @@ gst_rtpgsmenc_class_init (GstRtpGSMEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpgsmenc_set_property; - gobject_class->get_property = gst_rtpgsmenc_get_property; - - gstelement_class->change_state = gst_rtpgsmenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpgsmenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpgsmenc_handle_buffer; } static void gst_rtpgsmenc_init (GstRtpGSMEnc * rtpgsmenc) { - rtpgsmenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpgsmenc_sink_template), "sink"); - rtpgsmenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpgsmenc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpgsmenc), rtpgsmenc->sinkpad); - gst_element_add_pad (GST_ELEMENT (rtpgsmenc), rtpgsmenc->srcpad); - gst_pad_set_chain_function (rtpgsmenc->sinkpad, gst_rtpgsmenc_chain); - gst_pad_set_link_function (rtpgsmenc->sinkpad, gst_rtpgsmenc_sinkconnect); - rtpgsmenc->frequency = 8000; - - rtpgsmenc->next_time = 0; - rtpgsmenc->time_interval = 0; - - rtpgsmenc->seq = 0; - rtpgsmenc->ssrc = random (); } -static GstPadLinkReturn -gst_rtpgsmenc_sinkconnect (GstPad * pad, const GstCaps * caps) +static gboolean +gst_rtpgsmenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { GstRtpGSMEnc *rtpgsmenc; GstStructure *structure; gboolean ret; + GstCaps *srccaps; - rtpgsmenc = GST_RTP_GSM_ENC (gst_pad_get_parent (pad)); + rtpgsmenc = GST_RTP_GSM_ENC (payload); structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "rate", &rtpgsmenc->frequency); if (!ret) - return GST_PAD_LINK_REFUSED; + return FALSE; - /* Pre-calculate what we can */ - rtpgsmenc->time_interval = GST_SECOND / (2 * rtpgsmenc->frequency); + srccaps = gst_caps_new_simple ("application/x-rtp", NULL); + gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (rtpgsmenc), srccaps); + gst_caps_unref (srccaps); - return GST_PAD_LINK_OK; + return TRUE; } - -void -gst_rtpgsmenc_htons (GstBuffer * buf) +static GstFlowReturn +gst_rtpgsmenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { - gint16 *i, *len; - - /* FIXME: is this code correct or even sane at all? */ - i = (gint16 *) GST_BUFFER_DATA (buf); - len = i + GST_BUFFER_SIZE (buf) / sizeof (gint16 *); - - for (; i < len; i++) { - *i = g_htons (*i); - } -} - -static void -gst_rtpgsmenc_chain (GstPad * pad, GstData * _data) -{ - GstBuffer *buf = GST_BUFFER (_data); GstRtpGSMEnc *rtpgsmenc; + guint size, payload_len; GstBuffer *outbuf; - Rtp_Packet packet; + guint8 *payload, *data; + GstClockTime timestamp; + GstFlowReturn ret; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); + rtpgsmenc = GST_RTP_GSM_ENC (basepayload); - rtpgsmenc = GST_RTP_GSM_ENC (GST_OBJECT_PARENT (pad)); + size = GST_BUFFER_SIZE (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); - g_return_if_fail (rtpgsmenc != NULL); - g_return_if_fail (GST_IS_RTP_GSM_ENC (rtpgsmenc)); + /* FIXME, only one GSM frame per RTP packet for now */ + payload_len = size; - if (GST_IS_EVENT (buf)) { - GstEvent *event = GST_EVENT (buf); + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + /* FIXME, assert for now */ + g_assert (GST_BUFFER_SIZE (outbuf) < GST_BASE_RTP_PAYLOAD_MTU (rtpgsmenc)); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_DISCONTINUOUS: - GST_DEBUG ("discont"); - rtpgsmenc->next_time = 0; - gst_pad_event_default (pad, event); - return; - default: - gst_pad_event_default (pad, event); - return; - } - } + gst_rtpbuffer_set_timestamp (outbuf, timestamp * 8000 / GST_SECOND); - /* We only need the header */ - packet = rtp_packet_new_allocate (0, 0, 0); + /* copy timestamp */ + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - rtp_packet_set_csrc_count (packet, 0); - rtp_packet_set_extension (packet, 0); - rtp_packet_set_padding (packet, 0); - rtp_packet_set_version (packet, RTP_VERSION); - rtp_packet_set_marker (packet, 0); - rtp_packet_set_ssrc (packet, g_htonl (rtpgsmenc->ssrc)); - rtp_packet_set_seq (packet, g_htons (rtpgsmenc->seq)); - rtp_packet_set_timestamp (packet, - g_htonl ((guint32) rtpgsmenc->next_time / GST_SECOND)); - rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_GSM); + /* get payload */ + payload = gst_rtpbuffer_get_payload (outbuf); - /* FIXME: According to RFC 1890, this is required, right? */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - gst_rtpgsmenc_htons (buf); -#endif + data = GST_BUFFER_DATA (buffer); - outbuf = gst_buffer_new (); - GST_BUFFER_SIZE (outbuf) = - rtp_packet_get_packet_len (packet) + GST_BUFFER_SIZE (buf); - GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf)); - GST_BUFFER_TIMESTAMP (outbuf) = rtpgsmenc->next_time; + /* copy data in payload */ + memcpy (&payload[0], data, size); - memcpy (GST_BUFFER_DATA (outbuf), packet->data, - rtp_packet_get_packet_len (packet)); - memcpy (GST_BUFFER_DATA (outbuf) + rtp_packet_get_packet_len (packet), - GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buffer); GST_DEBUG ("gst_rtpgsmenc_chain: pushing buffer of size %d", GST_BUFFER_SIZE (outbuf)); - gst_pad_push (rtpgsmenc->srcpad, GST_DATA (outbuf)); - ++rtpgsmenc->seq; - rtpgsmenc->next_time += rtpgsmenc->time_interval * GST_BUFFER_SIZE (buf); + ret = gst_basertppayload_push (basepayload, outbuf); - rtp_packet_free (packet); - gst_buffer_unref (buf); -} - -static void -gst_rtpgsmenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_if_fail (GST_IS_RTP_GSM_ENC (object)); - rtpgsmenc = GST_RTP_GSM_ENC (object); - - switch (prop_id) { - default: - break; - } -} - -static void -gst_rtpgsmenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_if_fail (GST_IS_RTP_GSM_ENC (object)); - rtpgsmenc = GST_RTP_GSM_ENC (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpgsmenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_val_if_fail (GST_IS_RTP_GSM_ENC (element), GST_STATE_CHANGE_FAILURE); - - rtpgsmenc = GST_RTP_GSM_ENC (element); - - GST_DEBUG ("state pending %d\n", GST_STATE_PENDING (element)); - - /* if going down into NULL state, close the file if it's open */ - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - - case GST_STATE_CHANGE_READY_TO_NULL: - break; - - default: - break; - } - - /* if we haven't failed already, give the parent class a chance to ;-) */ - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - return GST_STATE_CHANGE_SUCCESS; + return ret; } gboolean diff --git a/gst/rtp/gstrtpgsmenc.h b/gst/rtp/gstrtpgsmenc.h index 1220d4029d..46fab46aab 100644 --- a/gst/rtp/gstrtpgsmenc.h +++ b/gst/rtp/gstrtpgsmenc.h @@ -22,42 +22,13 @@ #define __GST_RTP_GSM_ENC_H__ #include -#include "rtp-packet.h" -#include "gstrtp-common.h" +#include -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS -/* Definition of structure storing data for this element. */ typedef struct _GstRtpGSMEnc GstRtpGSMEnc; -struct _GstRtpGSMEnc -{ - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint frequency; - - /* the timestamp of the next frame */ - guint64 next_time; - /* the interval between frames */ - guint64 time_interval; - - guint32 ssrc; - guint16 seq; -}; - -/* Standard definition defining a class for this element. */ typedef struct _GstRtpGSMEncClass GstRtpGSMEncClass; -struct _GstRtpGSMEncClass -{ - GstElementClass parent_class; -}; -/* Standard macros for defining types for this element. */ #define GST_TYPE_RTP_GSM_ENC \ (gst_rtpgsmenc_get_type()) #define GST_RTP_GSM_ENC(obj) \ @@ -69,11 +40,20 @@ struct _GstRtpGSMEncClass #define GST_IS_RTP_GSM_ENC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_GSM_ENC)) +struct _GstRtpGSMEnc +{ + GstBaseRTPPayload payload; + + gint frequency; +}; + +struct _GstRtpGSMEncClass +{ + GstBaseRTPPayloadClass parent_class; +}; + gboolean gst_rtpgsmenc_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS - -#endif /* __GST_RTP_GSM_ENC_H__ */ +#endif /* __GST_RTP_GSM_ENC_H__ */ diff --git a/gst/rtp/gstrtpgsmparse.c b/gst/rtp/gstrtpgsmparse.c index 78171cbfcd..97b43420f8 100644 --- a/gst/rtp/gstrtpgsmparse.c +++ b/gst/rtp/gstrtpgsmparse.c @@ -17,8 +17,8 @@ #endif #include +#include #include "gstrtpgsmparse.h" -#include "gstrtp-common.h" /* elementfactory information */ static GstElementDetails gst_rtp_gsmparse_details = { @@ -60,13 +60,15 @@ static void gst_rtpgsmparse_class_init (GstRtpGSMParseClass * klass); static void gst_rtpgsmparse_base_init (GstRtpGSMParseClass * klass); static void gst_rtpgsmparse_init (GstRtpGSMParse * rtpgsmparse); -static void gst_rtpgsmparse_chain (GstPad * pad, GstData * _data); +static GstFlowReturn gst_rtpgsmparse_chain (GstPad * pad, GstBuffer * buffer); static void gst_rtpgsmparse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_rtpgsmparse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element); + +static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element, + GstStateChange transition); static GstElementClass *parent_class = NULL; @@ -118,13 +120,13 @@ gst_rtpgsmparse_class_init (GstRtpGSMParseClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = gst_rtpgsmparse_set_property; + gobject_class->get_property = gst_rtpgsmparse_get_property; + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREQUENCY, g_param_spec_int ("frequency", "frequency", "frequency", G_MININT, G_MAXINT, 8000, G_PARAM_READWRITE)); - gobject_class->set_property = gst_rtpgsmparse_set_property; - gobject_class->get_property = gst_rtpgsmparse_get_property; - gstelement_class->change_state = gst_rtpgsmparse_change_state; } @@ -144,21 +146,7 @@ gst_rtpgsmparse_init (GstRtpGSMParse * rtpgsmparse) rtpgsmparse->frequency = 8000; } -void -gst_rtpgsmparse_ntohs (GstBuffer * buf) -{ - gint16 *i, *len; - - /* FIXME: is this code correct or even sane at all? */ - i = (gint16 *) GST_BUFFER_DATA (buf); - len = i + GST_BUFFER_SIZE (buf) / sizeof (gint16 *); - - for (; i < len; i++) { - *i = g_ntohs (*i); - } -} - -void +static void gst_rtpgsm_caps_nego (GstRtpGSMParse * rtpgsmparse) { GstCaps *caps; @@ -166,72 +154,67 @@ gst_rtpgsm_caps_nego (GstRtpGSMParse * rtpgsmparse) caps = gst_caps_new_simple ("audio/x-gsm", "rate", G_TYPE_INT, rtpgsmparse->frequency, NULL); - gst_pad_try_set_caps (rtpgsmparse->srcpad, caps); + gst_pad_set_caps (rtpgsmparse->srcpad, caps); + gst_caps_unref (caps); } -static void -gst_rtpgsmparse_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_rtpgsmparse_chain (GstPad * pad, GstBuffer * buf) { - GstBuffer *buf = GST_BUFFER (_data); GstRtpGSMParse *rtpgsmparse; GstBuffer *outbuf; - Rtp_Packet packet; - rtp_payload_t pt; + GstFlowReturn ret; + guint8 pt; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - rtpgsmparse = GST_RTP_GSM_PARSE (GST_OBJECT_PARENT (pad)); - - g_return_if_fail (rtpgsmparse != NULL); - g_return_if_fail (GST_IS_RTP_GSM_PARSE (rtpgsmparse)); - - if (GST_IS_EVENT (buf)) { - GstEvent *event = GST_EVENT (buf); - - gst_pad_event_default (pad, event); - - return; - } + rtpgsmparse = GST_RTP_GSM_PARSE (gst_pad_get_parent (pad)); if (GST_PAD_CAPS (rtpgsmparse->srcpad) == NULL) { gst_rtpgsm_caps_nego (rtpgsmparse); } - packet = - rtp_packet_new_copy_data (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; - pt = rtp_packet_get_payload_type (packet); + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != GST_RTP_PAYLOAD_GSM) + goto bad_payload; + + { + gint payload_len; + guint8 *payload; + guint32 timestamp; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 8000; + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + GST_DEBUG ("pushing buffer of size %d", GST_BUFFER_SIZE (outbuf)); - if (pt != PAYLOAD_GSM) { - g_warning ("Unexpected paload type %u\n", pt); - rtp_packet_free (packet); gst_buffer_unref (buf); - return; + + ret = gst_pad_push (rtpgsmparse->srcpad, outbuf); } - outbuf = gst_buffer_new (); - GST_BUFFER_SIZE (outbuf) = rtp_packet_get_payload_len (packet); - GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf)); - GST_BUFFER_TIMESTAMP (outbuf) = - g_ntohl (rtp_packet_get_timestamp (packet)) * GST_SECOND; + return ret; - memcpy (GST_BUFFER_DATA (outbuf), rtp_packet_get_payload (packet), - GST_BUFFER_SIZE (outbuf)); - - GST_DEBUG ("gst_rtpgsmparse_chain: pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); - -/* FIXME: According to RFC 1890, this is required, right? */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - gst_rtpgsmparse_ntohs (outbuf); -#endif - - gst_pad_push (rtpgsmparse->srcpad, GST_DATA (outbuf)); - - rtp_packet_free (packet); - gst_buffer_unref (buf); +bad_packet: + { + GST_DEBUG ("Packet did not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } } static void @@ -240,7 +223,6 @@ gst_rtpgsmparse_set_property (GObject * object, guint prop_id, { GstRtpGSMParse *rtpgsmparse; - g_return_if_fail (GST_IS_RTP_GSM_PARSE (object)); rtpgsmparse = GST_RTP_GSM_PARSE (object); switch (prop_id) { @@ -258,7 +240,6 @@ gst_rtpgsmparse_get_property (GObject * object, guint prop_id, GValue * value, { GstRtpGSMParse *rtpgsmparse; - g_return_if_fail (GST_IS_RTP_GSM_PARSE (object)); rtpgsmparse = GST_RTP_GSM_PARSE (object); switch (prop_id) { @@ -275,28 +256,26 @@ static GstStateChangeReturn gst_rtpgsmparse_change_state (GstElement * element, GstStateChange transition) { GstRtpGSMParse *rtpgsmparse; - - g_return_val_if_fail (GST_IS_RTP_GSM_PARSE (element), - GST_STATE_CHANGE_FAILURE); + GstStateChangeReturn ret; rtpgsmparse = GST_RTP_GSM_PARSE (element); - GST_DEBUG ("state pending %d\n", GST_STATE_PENDING (element)); - switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; default: break; } - /* if we haven't failed already, give the parent class a chance to ;-) */ - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - return GST_STATE_CHANGE_SUCCESS; + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + return ret; } gboolean diff --git a/gst/rtp/gstrtpgsmparse.h b/gst/rtp/gstrtpgsmparse.h index 0a006e70fe..19bd5b28ff 100644 --- a/gst/rtp/gstrtpgsmparse.h +++ b/gst/rtp/gstrtpgsmparse.h @@ -21,34 +21,12 @@ #define __GST_RTP_GSM_PARSE_H__ #include -#include "rtp-packet.h" -#include "gstrtp-common.h" -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS -/* Definition of structure storing data for this element. */ typedef struct _GstRtpGSMParse GstRtpGSMParse; -struct _GstRtpGSMParse -{ - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint frequency; -}; - -/* Standard definition defining a class for this element. */ typedef struct _GstRtpGSMParseClass GstRtpGSMParseClass; -struct _GstRtpGSMParseClass -{ - GstElementClass parent_class; -}; -/* Standard macros for defining types for this element. */ #define GST_TYPE_RTP_GSM_PARSE \ (gst_rtpgsmparse_get_type()) #define GST_RTP_GSM_PARSE(obj) \ @@ -60,11 +38,23 @@ struct _GstRtpGSMParseClass #define GST_IS_RTP_GSM_PARSE_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_GSM_PARSE)) +struct _GstRtpGSMParse +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + guint frequency; +}; + +struct _GstRtpGSMParseClass +{ + GstElementClass parent_class; +}; + gboolean gst_rtpgsmparse_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS - -#endif /* __GST_RTP_GSM_PARSE_H__ */ +#endif /* __GST_RTP_GSM_PARSE_H__ */ diff --git a/gst/rtp/gstrtpgsmpay.c b/gst/rtp/gstrtpgsmpay.c index 47daa43064..19930ac321 100644 --- a/gst/rtp/gstrtpgsmpay.c +++ b/gst/rtp/gstrtpgsmpay.c @@ -23,6 +23,8 @@ #include #include +#include + #include "gstrtpgsmenc.h" /* elementfactory information */ @@ -33,19 +35,6 @@ static GstElementDetails gst_rtpgsmenc_details = { "Zeeshan Ali " }; -/* RtpGSMEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - /* FILL ME */ - ARG_0 -}; - static GstStaticPadTemplate gst_rtpgsmenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -57,24 +46,23 @@ static GstStaticPadTemplate gst_rtpgsmenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 8000, " "encoding_name = (string) \"GSM\"") ); static void gst_rtpgsmenc_class_init (GstRtpGSMEncClass * klass); static void gst_rtpgsmenc_base_init (GstRtpGSMEncClass * klass); static void gst_rtpgsmenc_init (GstRtpGSMEnc * rtpgsmenc); -static void gst_rtpgsmenc_chain (GstPad * pad, GstData * _data); -static void gst_rtpgsmenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpgsmenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static GstPadLinkReturn gst_rtpgsmenc_sinkconnect (GstPad * pad, - const GstCaps * caps); -static GstStateChangeReturn gst_rtpgsmenc_change_state (GstElement * element, - GstStateChange transition); -static GstElementClass *parent_class = NULL; +static gboolean gst_rtpgsmenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpgsmenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); + +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpgsmenc_get_type (void) @@ -95,7 +83,7 @@ gst_rtpgsmenc_get_type (void) }; rtpgsmenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpGSMEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpGSMEnc", &rtpgsmenc_info, 0); } return rtpgsmenc_type; @@ -118,209 +106,91 @@ gst_rtpgsmenc_class_init (GstRtpGSMEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpgsmenc_set_property; - gobject_class->get_property = gst_rtpgsmenc_get_property; - - gstelement_class->change_state = gst_rtpgsmenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpgsmenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpgsmenc_handle_buffer; } static void gst_rtpgsmenc_init (GstRtpGSMEnc * rtpgsmenc) { - rtpgsmenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpgsmenc_sink_template), "sink"); - rtpgsmenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpgsmenc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpgsmenc), rtpgsmenc->sinkpad); - gst_element_add_pad (GST_ELEMENT (rtpgsmenc), rtpgsmenc->srcpad); - gst_pad_set_chain_function (rtpgsmenc->sinkpad, gst_rtpgsmenc_chain); - gst_pad_set_link_function (rtpgsmenc->sinkpad, gst_rtpgsmenc_sinkconnect); - rtpgsmenc->frequency = 8000; - - rtpgsmenc->next_time = 0; - rtpgsmenc->time_interval = 0; - - rtpgsmenc->seq = 0; - rtpgsmenc->ssrc = random (); } -static GstPadLinkReturn -gst_rtpgsmenc_sinkconnect (GstPad * pad, const GstCaps * caps) +static gboolean +gst_rtpgsmenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { GstRtpGSMEnc *rtpgsmenc; GstStructure *structure; gboolean ret; + GstCaps *srccaps; - rtpgsmenc = GST_RTP_GSM_ENC (gst_pad_get_parent (pad)); + rtpgsmenc = GST_RTP_GSM_ENC (payload); structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "rate", &rtpgsmenc->frequency); if (!ret) - return GST_PAD_LINK_REFUSED; + return FALSE; - /* Pre-calculate what we can */ - rtpgsmenc->time_interval = GST_SECOND / (2 * rtpgsmenc->frequency); + srccaps = gst_caps_new_simple ("application/x-rtp", NULL); + gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (rtpgsmenc), srccaps); + gst_caps_unref (srccaps); - return GST_PAD_LINK_OK; + return TRUE; } - -void -gst_rtpgsmenc_htons (GstBuffer * buf) +static GstFlowReturn +gst_rtpgsmenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { - gint16 *i, *len; - - /* FIXME: is this code correct or even sane at all? */ - i = (gint16 *) GST_BUFFER_DATA (buf); - len = i + GST_BUFFER_SIZE (buf) / sizeof (gint16 *); - - for (; i < len; i++) { - *i = g_htons (*i); - } -} - -static void -gst_rtpgsmenc_chain (GstPad * pad, GstData * _data) -{ - GstBuffer *buf = GST_BUFFER (_data); GstRtpGSMEnc *rtpgsmenc; + guint size, payload_len; GstBuffer *outbuf; - Rtp_Packet packet; + guint8 *payload, *data; + GstClockTime timestamp; + GstFlowReturn ret; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); + rtpgsmenc = GST_RTP_GSM_ENC (basepayload); - rtpgsmenc = GST_RTP_GSM_ENC (GST_OBJECT_PARENT (pad)); + size = GST_BUFFER_SIZE (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); - g_return_if_fail (rtpgsmenc != NULL); - g_return_if_fail (GST_IS_RTP_GSM_ENC (rtpgsmenc)); + /* FIXME, only one GSM frame per RTP packet for now */ + payload_len = size; - if (GST_IS_EVENT (buf)) { - GstEvent *event = GST_EVENT (buf); + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + /* FIXME, assert for now */ + g_assert (GST_BUFFER_SIZE (outbuf) < GST_BASE_RTP_PAYLOAD_MTU (rtpgsmenc)); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_DISCONTINUOUS: - GST_DEBUG ("discont"); - rtpgsmenc->next_time = 0; - gst_pad_event_default (pad, event); - return; - default: - gst_pad_event_default (pad, event); - return; - } - } + gst_rtpbuffer_set_timestamp (outbuf, timestamp * 8000 / GST_SECOND); - /* We only need the header */ - packet = rtp_packet_new_allocate (0, 0, 0); + /* copy timestamp */ + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - rtp_packet_set_csrc_count (packet, 0); - rtp_packet_set_extension (packet, 0); - rtp_packet_set_padding (packet, 0); - rtp_packet_set_version (packet, RTP_VERSION); - rtp_packet_set_marker (packet, 0); - rtp_packet_set_ssrc (packet, g_htonl (rtpgsmenc->ssrc)); - rtp_packet_set_seq (packet, g_htons (rtpgsmenc->seq)); - rtp_packet_set_timestamp (packet, - g_htonl ((guint32) rtpgsmenc->next_time / GST_SECOND)); - rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_GSM); + /* get payload */ + payload = gst_rtpbuffer_get_payload (outbuf); - /* FIXME: According to RFC 1890, this is required, right? */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - gst_rtpgsmenc_htons (buf); -#endif + data = GST_BUFFER_DATA (buffer); - outbuf = gst_buffer_new (); - GST_BUFFER_SIZE (outbuf) = - rtp_packet_get_packet_len (packet) + GST_BUFFER_SIZE (buf); - GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf)); - GST_BUFFER_TIMESTAMP (outbuf) = rtpgsmenc->next_time; + /* copy data in payload */ + memcpy (&payload[0], data, size); - memcpy (GST_BUFFER_DATA (outbuf), packet->data, - rtp_packet_get_packet_len (packet)); - memcpy (GST_BUFFER_DATA (outbuf) + rtp_packet_get_packet_len (packet), - GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buffer); GST_DEBUG ("gst_rtpgsmenc_chain: pushing buffer of size %d", GST_BUFFER_SIZE (outbuf)); - gst_pad_push (rtpgsmenc->srcpad, GST_DATA (outbuf)); - ++rtpgsmenc->seq; - rtpgsmenc->next_time += rtpgsmenc->time_interval * GST_BUFFER_SIZE (buf); + ret = gst_basertppayload_push (basepayload, outbuf); - rtp_packet_free (packet); - gst_buffer_unref (buf); -} - -static void -gst_rtpgsmenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_if_fail (GST_IS_RTP_GSM_ENC (object)); - rtpgsmenc = GST_RTP_GSM_ENC (object); - - switch (prop_id) { - default: - break; - } -} - -static void -gst_rtpgsmenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_if_fail (GST_IS_RTP_GSM_ENC (object)); - rtpgsmenc = GST_RTP_GSM_ENC (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpgsmenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpGSMEnc *rtpgsmenc; - - g_return_val_if_fail (GST_IS_RTP_GSM_ENC (element), GST_STATE_CHANGE_FAILURE); - - rtpgsmenc = GST_RTP_GSM_ENC (element); - - GST_DEBUG ("state pending %d\n", GST_STATE_PENDING (element)); - - /* if going down into NULL state, close the file if it's open */ - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - - case GST_STATE_CHANGE_READY_TO_NULL: - break; - - default: - break; - } - - /* if we haven't failed already, give the parent class a chance to ;-) */ - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - return GST_STATE_CHANGE_SUCCESS; + return ret; } gboolean diff --git a/gst/rtp/gstrtpgsmpay.h b/gst/rtp/gstrtpgsmpay.h index 1220d4029d..46fab46aab 100644 --- a/gst/rtp/gstrtpgsmpay.h +++ b/gst/rtp/gstrtpgsmpay.h @@ -22,42 +22,13 @@ #define __GST_RTP_GSM_ENC_H__ #include -#include "rtp-packet.h" -#include "gstrtp-common.h" +#include -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS -/* Definition of structure storing data for this element. */ typedef struct _GstRtpGSMEnc GstRtpGSMEnc; -struct _GstRtpGSMEnc -{ - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint frequency; - - /* the timestamp of the next frame */ - guint64 next_time; - /* the interval between frames */ - guint64 time_interval; - - guint32 ssrc; - guint16 seq; -}; - -/* Standard definition defining a class for this element. */ typedef struct _GstRtpGSMEncClass GstRtpGSMEncClass; -struct _GstRtpGSMEncClass -{ - GstElementClass parent_class; -}; -/* Standard macros for defining types for this element. */ #define GST_TYPE_RTP_GSM_ENC \ (gst_rtpgsmenc_get_type()) #define GST_RTP_GSM_ENC(obj) \ @@ -69,11 +40,20 @@ struct _GstRtpGSMEncClass #define GST_IS_RTP_GSM_ENC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_GSM_ENC)) +struct _GstRtpGSMEnc +{ + GstBaseRTPPayload payload; + + gint frequency; +}; + +struct _GstRtpGSMEncClass +{ + GstBaseRTPPayloadClass parent_class; +}; + gboolean gst_rtpgsmenc_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS - -#endif /* __GST_RTP_GSM_ENC_H__ */ +#endif /* __GST_RTP_GSM_ENC_H__ */ diff --git a/gst/rtp/gstrtph263pdec.c b/gst/rtp/gstrtph263pdec.c index 62c2d61c35..16fd8be58c 100644 --- a/gst/rtp/gstrtph263pdec.c +++ b/gst/rtp/gstrtph263pdec.c @@ -53,13 +53,17 @@ static GstStaticPadTemplate gst_rtph263pdec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"H263-1998\"") ); static void gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass); static void gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass); static void gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec); +static void gst_rtph263pdec_finalize (GObject * object); static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buffer); @@ -122,6 +126,8 @@ gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->finalize = gst_rtph263pdec_finalize; + gobject_class->set_property = gst_rtph263pdec_set_property; gobject_class->get_property = gst_rtph263pdec_get_property; @@ -145,6 +151,19 @@ gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec) rtph263pdec->adapter = gst_adapter_new (); } +static void +gst_rtph263pdec_finalize (GObject * object) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + g_object_unref (rtph263pdec->adapter); + rtph263pdec->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buf) { @@ -292,6 +311,9 @@ gst_rtph263pdec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_adapter_clear (rtph263pdec->adapter); + break; default: break; } diff --git a/gst/rtp/gstrtph263pdepay.c b/gst/rtp/gstrtph263pdepay.c index 62c2d61c35..16fd8be58c 100644 --- a/gst/rtp/gstrtph263pdepay.c +++ b/gst/rtp/gstrtph263pdepay.c @@ -53,13 +53,17 @@ static GstStaticPadTemplate gst_rtph263pdec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"H263-1998\"") ); static void gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass); static void gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass); static void gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec); +static void gst_rtph263pdec_finalize (GObject * object); static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buffer); @@ -122,6 +126,8 @@ gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->finalize = gst_rtph263pdec_finalize; + gobject_class->set_property = gst_rtph263pdec_set_property; gobject_class->get_property = gst_rtph263pdec_get_property; @@ -145,6 +151,19 @@ gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec) rtph263pdec->adapter = gst_adapter_new (); } +static void +gst_rtph263pdec_finalize (GObject * object) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + g_object_unref (rtph263pdec->adapter); + rtph263pdec->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buf) { @@ -292,6 +311,9 @@ gst_rtph263pdec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_adapter_clear (rtph263pdec->adapter); + break; default: break; } diff --git a/gst/rtp/gstrtph263penc.c b/gst/rtp/gstrtph263penc.c index 192466d5c6..c1fb93fa2b 100644 --- a/gst/rtp/gstrtph263penc.c +++ b/gst/rtp/gstrtph263penc.c @@ -26,29 +26,10 @@ static GstElementDetails gst_rtp_h263penc_details = { "RTP packet parser", "Codec/Parser/Network", - "Extracts H263+ video from RTP packets", + "Encodes H263+ video in RTP packets (RFC 2429)", "Wim Taymans " }; -/* RtpH263PEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtph263penc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -60,25 +41,23 @@ static GstStaticPadTemplate gst_rtph263penc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"H263-1998\"") ); - static void gst_rtph263penc_class_init (GstRtpH263PEncClass * klass); static void gst_rtph263penc_base_init (GstRtpH263PEncClass * klass); static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc); +static void gst_rtph263penc_finalize (GObject * object); -static GstFlowReturn gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtph263penc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtph263penc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtph263penc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtph263penc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtph263penc_change_state (GstElement * - element, GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtph263penc_get_type (void) @@ -99,7 +78,7 @@ gst_rtph263penc_get_type (void) }; rtph263penc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpH263PEnc", &rtph263penc_info, 0); } return rtph263penc_type; @@ -123,49 +102,49 @@ gst_rtph263penc_class_init (GstRtpH263PEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtph263penc_set_property; - gobject_class->get_property = gst_rtph263penc_get_property; + gobject_class->finalize = gst_rtph263penc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtph263penc_change_state; + gstbasertppayload_class->set_caps = gst_rtph263penc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtph263penc_handle_buffer; } static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc) { - rtph263penc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtph263penc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->srcpad); - - rtph263penc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtph263penc_sink_template), "sink"); - gst_pad_set_chain_function (rtph263penc->sinkpad, gst_rtph263penc_chain); - gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->sinkpad); - rtph263penc->adapter = gst_adapter_new (); - rtph263penc->mtu = DEFAULT_MTU; } +static void +gst_rtph263penc_finalize (GObject * object) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + g_object_unref (rtph263penc->adapter); + rtph263penc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_rtph263penc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "video", TRUE, "H263-1998", 90000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; +} + + static GstFlowReturn gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) { @@ -189,7 +168,7 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) /* FIXME, do better mtu packing, header len etc should be * included in this calculation. */ - towrite = MIN (avail, rtph263penc->mtu); + towrite = MIN (avail, GST_BASE_RTP_PAYLOAD_MTU (rtph263penc)); /* for fragmented frames we need 2 bytes header, for other * frames we must reuse the first 2 bytes of the data as the * header */ @@ -197,11 +176,6 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) payload_len = header_len + towrite; outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - gst_rtpbuffer_set_timestamp (outbuf, - rtph263penc->first_ts * 90000 / GST_SECOND); - gst_rtpbuffer_set_payload_type (outbuf, rtph263penc->pt); - gst_rtpbuffer_set_ssrc (outbuf, rtph263penc->ssrc); - gst_rtpbuffer_set_seq (outbuf, rtph263penc->seqnum++); /* last fragment gets the marker bit set */ gst_rtpbuffer_set_marker (outbuf, avail > towrite ? 0 : 1); @@ -222,7 +196,7 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) GST_BUFFER_TIMESTAMP (outbuf) = rtph263penc->first_ts; gst_adapter_flush (rtph263penc->adapter, towrite); - ret = gst_pad_push (rtph263penc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtph263penc), outbuf); avail -= towrite; fragmented = TRUE; @@ -232,13 +206,13 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) } static GstFlowReturn -gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtph263penc_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer) { GstRtpH263PEnc *rtph263penc; GstFlowReturn ret; guint size; - rtph263penc = GST_RTP_H263P_ENC (GST_OBJECT_PARENT (pad)); + rtph263penc = GST_RTP_H263P_ENC (payload); size = GST_BUFFER_SIZE (buffer); rtph263penc->first_ts = GST_BUFFER_TIMESTAMP (buffer); @@ -250,80 +224,6 @@ gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) return ret; } -static void -gst_rtph263penc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpH263PEnc *rtph263penc; - - rtph263penc = GST_RTP_H263P_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtph263penc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtph263penc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtph263penc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtph263penc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpH263PEnc *rtph263penc; - - rtph263penc = GST_RTP_H263P_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtph263penc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtph263penc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtph263penc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtph263penc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpH263PEnc *rtph263penc; - GstStateChangeReturn ret; - - rtph263penc = GST_RTP_H263P_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin) { diff --git a/gst/rtp/gstrtph263penc.h b/gst/rtp/gstrtph263penc.h index 316ae037e4..409e2ebdaf 100644 --- a/gst/rtp/gstrtph263penc.h +++ b/gst/rtp/gstrtph263penc.h @@ -21,6 +21,7 @@ #define __GST_RTP_H263P_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,24 +42,15 @@ typedef struct _GstRtpH263PEncClass GstRtpH263PEncClass; struct _GstRtpH263PEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - - guint16 seqnum; - guint pt; - guint ssrc; - - guint mtu; }; struct _GstRtpH263PEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtph263ppay.c b/gst/rtp/gstrtph263ppay.c index 192466d5c6..c1fb93fa2b 100644 --- a/gst/rtp/gstrtph263ppay.c +++ b/gst/rtp/gstrtph263ppay.c @@ -26,29 +26,10 @@ static GstElementDetails gst_rtp_h263penc_details = { "RTP packet parser", "Codec/Parser/Network", - "Extracts H263+ video from RTP packets", + "Encodes H263+ video in RTP packets (RFC 2429)", "Wim Taymans " }; -/* RtpH263PEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtph263penc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -60,25 +41,23 @@ static GstStaticPadTemplate gst_rtph263penc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"H263-1998\"") ); - static void gst_rtph263penc_class_init (GstRtpH263PEncClass * klass); static void gst_rtph263penc_base_init (GstRtpH263PEncClass * klass); static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc); +static void gst_rtph263penc_finalize (GObject * object); -static GstFlowReturn gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtph263penc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtph263penc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtph263penc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtph263penc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtph263penc_change_state (GstElement * - element, GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtph263penc_get_type (void) @@ -99,7 +78,7 @@ gst_rtph263penc_get_type (void) }; rtph263penc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpH263PEnc", &rtph263penc_info, 0); } return rtph263penc_type; @@ -123,49 +102,49 @@ gst_rtph263penc_class_init (GstRtpH263PEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtph263penc_set_property; - gobject_class->get_property = gst_rtph263penc_get_property; + gobject_class->finalize = gst_rtph263penc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtph263penc_change_state; + gstbasertppayload_class->set_caps = gst_rtph263penc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtph263penc_handle_buffer; } static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc) { - rtph263penc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtph263penc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->srcpad); - - rtph263penc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtph263penc_sink_template), "sink"); - gst_pad_set_chain_function (rtph263penc->sinkpad, gst_rtph263penc_chain); - gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->sinkpad); - rtph263penc->adapter = gst_adapter_new (); - rtph263penc->mtu = DEFAULT_MTU; } +static void +gst_rtph263penc_finalize (GObject * object) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + g_object_unref (rtph263penc->adapter); + rtph263penc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_rtph263penc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "video", TRUE, "H263-1998", 90000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; +} + + static GstFlowReturn gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) { @@ -189,7 +168,7 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) /* FIXME, do better mtu packing, header len etc should be * included in this calculation. */ - towrite = MIN (avail, rtph263penc->mtu); + towrite = MIN (avail, GST_BASE_RTP_PAYLOAD_MTU (rtph263penc)); /* for fragmented frames we need 2 bytes header, for other * frames we must reuse the first 2 bytes of the data as the * header */ @@ -197,11 +176,6 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) payload_len = header_len + towrite; outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - gst_rtpbuffer_set_timestamp (outbuf, - rtph263penc->first_ts * 90000 / GST_SECOND); - gst_rtpbuffer_set_payload_type (outbuf, rtph263penc->pt); - gst_rtpbuffer_set_ssrc (outbuf, rtph263penc->ssrc); - gst_rtpbuffer_set_seq (outbuf, rtph263penc->seqnum++); /* last fragment gets the marker bit set */ gst_rtpbuffer_set_marker (outbuf, avail > towrite ? 0 : 1); @@ -222,7 +196,7 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) GST_BUFFER_TIMESTAMP (outbuf) = rtph263penc->first_ts; gst_adapter_flush (rtph263penc->adapter, towrite); - ret = gst_pad_push (rtph263penc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtph263penc), outbuf); avail -= towrite; fragmented = TRUE; @@ -232,13 +206,13 @@ gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) } static GstFlowReturn -gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtph263penc_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer) { GstRtpH263PEnc *rtph263penc; GstFlowReturn ret; guint size; - rtph263penc = GST_RTP_H263P_ENC (GST_OBJECT_PARENT (pad)); + rtph263penc = GST_RTP_H263P_ENC (payload); size = GST_BUFFER_SIZE (buffer); rtph263penc->first_ts = GST_BUFFER_TIMESTAMP (buffer); @@ -250,80 +224,6 @@ gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) return ret; } -static void -gst_rtph263penc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpH263PEnc *rtph263penc; - - rtph263penc = GST_RTP_H263P_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtph263penc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtph263penc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtph263penc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtph263penc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpH263PEnc *rtph263penc; - - rtph263penc = GST_RTP_H263P_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtph263penc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtph263penc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtph263penc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtph263penc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpH263PEnc *rtph263penc; - GstStateChangeReturn ret; - - rtph263penc = GST_RTP_H263P_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin) { diff --git a/gst/rtp/gstrtph263ppay.h b/gst/rtp/gstrtph263ppay.h index 316ae037e4..409e2ebdaf 100644 --- a/gst/rtp/gstrtph263ppay.h +++ b/gst/rtp/gstrtph263ppay.h @@ -21,6 +21,7 @@ #define __GST_RTP_H263P_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,24 +42,15 @@ typedef struct _GstRtpH263PEncClass GstRtpH263PEncClass; struct _GstRtpH263PEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - - guint16 seqnum; - guint pt; - guint ssrc; - - guint mtu; }; struct _GstRtpH263PEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpmp4vdec.c b/gst/rtp/gstrtpmp4vdec.c index 39ab5df955..4250e77be6 100644 --- a/gst/rtp/gstrtpmp4vdec.c +++ b/gst/rtp/gstrtpmp4vdec.c @@ -54,10 +54,12 @@ static GstStaticPadTemplate gst_rtpmp4vdec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp" + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) [1, MAX ], " "encoding_name = (string) \"MP4V-ES\"" /* All optional parameters * - * "rate=(int) [1, MAX]," * "profile-level-id=[1,MAX]" * "config=" */ @@ -164,7 +166,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (structure, "rate", &rtpmp4vdec->rate)) + if (!gst_structure_get_int (structure, "clock_rate", &rtpmp4vdec->rate)) rtpmp4vdec->rate = 90000; srccaps = gst_caps_new_simple ("video/mpeg", @@ -282,7 +284,6 @@ gst_rtpmp4vdec_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_adapter_clear (rtpmp4vdec->adapter); - rtpmp4vdec->rate = 90000; break; default: break; diff --git a/gst/rtp/gstrtpmp4vdepay.c b/gst/rtp/gstrtpmp4vdepay.c index 39ab5df955..4250e77be6 100644 --- a/gst/rtp/gstrtpmp4vdepay.c +++ b/gst/rtp/gstrtpmp4vdepay.c @@ -54,10 +54,12 @@ static GstStaticPadTemplate gst_rtpmp4vdec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp" + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) [1, MAX ], " "encoding_name = (string) \"MP4V-ES\"" /* All optional parameters * - * "rate=(int) [1, MAX]," * "profile-level-id=[1,MAX]" * "config=" */ @@ -164,7 +166,7 @@ gst_rtpmp4vdec_setcaps (GstPad * pad, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (structure, "rate", &rtpmp4vdec->rate)) + if (!gst_structure_get_int (structure, "clock_rate", &rtpmp4vdec->rate)) rtpmp4vdec->rate = 90000; srccaps = gst_caps_new_simple ("video/mpeg", @@ -282,7 +284,6 @@ gst_rtpmp4vdec_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_adapter_clear (rtpmp4vdec->adapter); - rtpmp4vdec->rate = 90000; break; default: break; diff --git a/gst/rtp/gstrtpmp4venc.c b/gst/rtp/gstrtpmp4venc.c index 13b1e33d51..bba139a020 100644 --- a/gst/rtp/gstrtpmp4venc.c +++ b/gst/rtp/gstrtpmp4venc.c @@ -30,25 +30,6 @@ static GstElementDetails gst_rtp_mp4venc_details = { "Wim Taymans " }; -/* RtpMP4VEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtpmp4venc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -61,9 +42,15 @@ static GstStaticPadTemplate gst_rtpmp4venc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp," - "rate=(int) [1, MAX]," "profile-level-id=[1,MAX]" - /* "config=" */ + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) [1, MAX ], " + "encoding_name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]" + /* All optional parameters + * + * "config=" + */ ) ); @@ -71,19 +58,14 @@ GST_STATIC_PAD_TEMPLATE ("src", static void gst_rtpmp4venc_class_init (GstRtpMP4VEncClass * klass); static void gst_rtpmp4venc_base_init (GstRtpMP4VEncClass * klass); static void gst_rtpmp4venc_init (GstRtpMP4VEnc * rtpmp4venc); +static void gst_rtpmp4venc_finalize (GObject * object); -static gboolean gst_rtpmp4venc_setcaps (GstPad * pad, GstCaps * caps); -static GstFlowReturn gst_rtpmp4venc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpmp4venc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpmp4venc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtpmp4venc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpmp4venc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpmp4venc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpmp4venc_get_type (void) @@ -104,7 +86,7 @@ gst_rtpmp4venc_get_type (void) }; rtpmp4venc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMP4VEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpMP4VEnc", &rtpmp4venc_info, 0); } return rtpmp4venc_type; @@ -128,69 +110,58 @@ gst_rtpmp4venc_class_init (GstRtpMP4VEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpmp4venc_set_property; - gobject_class->get_property = gst_rtpmp4venc_get_property; + gobject_class->finalize = gst_rtpmp4venc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpmp4venc_change_state; + gstbasertppayload_class->set_caps = gst_rtpmp4venc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpmp4venc_handle_buffer; } static void gst_rtpmp4venc_init (GstRtpMP4VEnc * rtpmp4venc) { - rtpmp4venc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmp4venc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpmp4venc), rtpmp4venc->srcpad); - - rtpmp4venc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmp4venc_sink_template), "sink"); - gst_pad_set_setcaps_function (rtpmp4venc->sinkpad, gst_rtpmp4venc_setcaps); - gst_pad_set_chain_function (rtpmp4venc->sinkpad, gst_rtpmp4venc_chain); - gst_element_add_pad (GST_ELEMENT (rtpmp4venc), rtpmp4venc->sinkpad); - rtpmp4venc->adapter = gst_adapter_new (); - rtpmp4venc->mtu = DEFAULT_MTU; - rtpmp4venc->pt = DEFAULT_PT; - rtpmp4venc->ssrc = DEFAULT_SSRC; rtpmp4venc->rate = 90000; rtpmp4venc->profile = 1; } -static gboolean -gst_rtpmp4venc_setcaps (GstPad * pad, GstCaps * caps) +static void +gst_rtpmp4venc_finalize (GObject * object) { GstRtpMP4VEnc *rtpmp4venc; - GstCaps *srccaps; - rtpmp4venc = GST_RTP_MP4V_ENC (gst_pad_get_parent (pad)); + rtpmp4venc = GST_RTP_MP4V_ENC (object); - srccaps = gst_caps_new_simple ("application/x-rtp", - "rate", G_TYPE_INT, rtpmp4venc->rate, - "profile-level-id", G_TYPE_INT, rtpmp4venc->profile, NULL); - gst_pad_set_caps (rtpmp4venc->srcpad, srccaps); - gst_caps_unref (srccaps); + g_object_unref (rtpmp4venc->adapter); + rtpmp4venc->adapter = NULL; - gst_object_unref (rtpmp4venc); + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc) +{ + gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc), + "profile-level-id", G_TYPE_INT, rtpmp4venc->profile, + "config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL); +} + +static gboolean +gst_rtpmp4venc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + GstRtpMP4VEnc *rtpmp4venc; + + rtpmp4venc = GST_RTP_MP4V_ENC (payload); + + gst_basertppayload_set_options (payload, "video", TRUE, "MP4V-ES", + rtpmp4venc->rate); return TRUE; } @@ -201,7 +172,6 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) guint avail; GstBuffer *outbuf; GstFlowReturn ret; - guint16 frag_offset; /* the data available in the adapter is either smaller * than the MTU or bigger. In the case it is smaller, the complete @@ -212,7 +182,6 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) ret = GST_FLOW_OK; - frag_offset = 0; while (avail > 0) { guint towrite; guint8 *payload; @@ -224,159 +193,149 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) packet_len = gst_rtpbuffer_calc_packet_len (avail, 0, 0); /* fill one MTU or all available bytes */ - towrite = MIN (packet_len, rtpmp4venc->mtu); + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpmp4venc)); /* this is the payload length */ payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); /* create buffer to hold the payload */ outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpmp4venc->srcpad)); - - /* set timestamp */ - if (GST_CLOCK_TIME_IS_VALID (rtpmp4venc->first_ts)) { - gst_rtpbuffer_set_timestamp (outbuf, - rtpmp4venc->first_ts * 90000 / GST_SECOND); - } - gst_rtpbuffer_set_payload_type (outbuf, rtpmp4venc->pt); - gst_rtpbuffer_set_seq (outbuf, rtpmp4venc->seqnum++); + /* copy payload */ payload = gst_rtpbuffer_get_payload (outbuf); - data = (guint8 *) gst_adapter_peek (rtpmp4venc->adapter, payload_len); memcpy (payload, data, payload_len); + gst_adapter_flush (rtpmp4venc->adapter, payload_len); avail -= payload_len; - frag_offset += payload_len; gst_rtpbuffer_set_marker (outbuf, avail == 0); GST_BUFFER_TIMESTAMP (outbuf) = rtpmp4venc->first_ts; - ret = gst_pad_push (rtpmp4venc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4venc), outbuf); } return ret; } +#define VOS_STARTCODE 0x000001B0 +#define VOS_ENDCODE 0x000001B1 +#define USER_DATA_STARTCODE 0x000001B2 +#define GOP_STARTCODE 0x000001B3 +#define VISUAL_OBJECT_STARTCODE 0x000001B5 +#define VOP_STARTCODE 0x000001B6 + +static gboolean +gst_rtpmp4venc_parse_data (GstRtpMP4VEnc * enc, guint8 * data, guint size) +{ + guint32 code; + gboolean result; + + if (size < 5) + return FALSE; + + code = GST_READ_UINT32_BE (data); + + switch (code) { + case VOS_STARTCODE: + { + gint i; + guint8 profile; + gboolean newprofile = FALSE; + gboolean equal; + + /* profile_and_level_indication */ + profile = data[4]; + + if (profile != enc->profile) { + newprofile = TRUE; + enc->profile = profile; + } + + /* up to the next GOP_STARTCODE or VOP_STARTCODE is + * the config information */ + code = 0xffffffff; + for (i = 5; i < size - 4; i++) { + code = (code << 8) | data[i]; + if (code == GOP_STARTCODE || code == VOP_STARTCODE) + break; + } + i -= 3; + /* see if config changed */ + equal = FALSE; + if (enc->config) { + if (GST_BUFFER_SIZE (enc->config) == i) { + equal = memcmp (GST_BUFFER_DATA (enc->config), data, i) == 0; + } + } + /* if config string changed or new profile, make new caps */ + if (!equal || newprofile) { + if (enc->config) + gst_buffer_unref (enc->config); + enc->config = gst_buffer_new_and_alloc (i); + memcpy (GST_BUFFER_DATA (enc->config), data, i); + gst_rtpmp4venc_new_caps (enc); + } + result = TRUE; + break; + } + case VOP_STARTCODE: + result = FALSE; + break; + default: + result = TRUE; + break; + } + return result; +} + /* we expect buffers starting on startcodes. - * - * FIXME, need to flush the adapter if we receive non VOP - * packets. */ static GstFlowReturn -gst_rtpmp4venc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpmp4venc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpMP4VEnc *rtpmp4venc; GstFlowReturn ret; guint size, avail; guint packet_len; + guint8 *data; + gboolean flush; - rtpmp4venc = GST_RTP_MP4V_ENC (gst_pad_get_parent (pad)); + rtpmp4venc = GST_RTP_MP4V_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); avail = gst_adapter_available (rtpmp4venc->adapter); + /* parse incomming data and see if we need to start a new RTP + * packet */ + flush = gst_rtpmp4venc_parse_data (rtpmp4venc, data, size); + /* get packet length of previous data and this new data */ packet_len = gst_rtpbuffer_calc_packet_len (avail + size, 0, 0); /* if this buffer is going to overflow the packet, flush what we * have. */ - if (packet_len > rtpmp4venc->mtu) { + if (flush || packet_len > GST_BASE_RTP_PAYLOAD_MTU (rtpmp4venc)) { ret = gst_rtpmp4venc_flush (rtpmp4venc); avail = 0; } gst_adapter_push (rtpmp4venc->adapter, buffer); + if (avail == 0) { rtpmp4venc->first_ts = GST_BUFFER_TIMESTAMP (buffer); } - gst_object_unref (rtpmp4venc); ret = GST_FLOW_OK; return ret; } -static void -gst_rtpmp4venc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpMP4VEnc *rtpmp4venc; - - rtpmp4venc = GST_RTP_MP4V_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpmp4venc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtpmp4venc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtpmp4venc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpmp4venc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpMP4VEnc *rtpmp4venc; - - rtpmp4venc = GST_RTP_MP4V_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpmp4venc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtpmp4venc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtpmp4venc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpmp4venc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpMP4VEnc *rtpmp4venc; - GstStateChangeReturn ret; - - rtpmp4venc = GST_RTP_MP4V_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpmp4venc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - gboolean gst_rtpmp4venc_plugin_init (GstPlugin * plugin) { diff --git a/gst/rtp/gstrtpmp4venc.h b/gst/rtp/gstrtpmp4venc.h index b694903983..2edd0171a0 100644 --- a/gst/rtp/gstrtpmp4venc.h +++ b/gst/rtp/gstrtpmp4venc.h @@ -21,6 +21,7 @@ #define __GST_RTP_MP4V_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,26 +42,19 @@ typedef struct _GstRtpMP4VEncClass GstRtpMP4VEncClass; struct _GstRtpMP4VEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - guint16 seqnum; gint rate; gint profile; - - guint mtu; - guint pt; - guint ssrc; + GstBuffer *config; }; struct _GstRtpMP4VEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpmp4venc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpmp4vpay.c b/gst/rtp/gstrtpmp4vpay.c index 13b1e33d51..bba139a020 100644 --- a/gst/rtp/gstrtpmp4vpay.c +++ b/gst/rtp/gstrtpmp4vpay.c @@ -30,25 +30,6 @@ static GstElementDetails gst_rtp_mp4venc_details = { "Wim Taymans " }; -/* RtpMP4VEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 -#define DEFAULT_PT 96 -#define DEFAULT_SSRC 0 - -enum -{ - PROP_0, - PROP_MTU, - PROP_PT, - PROP_SSRC -}; - static GstStaticPadTemplate gst_rtpmp4venc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -61,9 +42,15 @@ static GstStaticPadTemplate gst_rtpmp4venc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp," - "rate=(int) [1, MAX]," "profile-level-id=[1,MAX]" - /* "config=" */ + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"video\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) [1, MAX ], " + "encoding_name = (string) \"MP4V-ES\", " "profile-level-id=[1,MAX]" + /* All optional parameters + * + * "config=" + */ ) ); @@ -71,19 +58,14 @@ GST_STATIC_PAD_TEMPLATE ("src", static void gst_rtpmp4venc_class_init (GstRtpMP4VEncClass * klass); static void gst_rtpmp4venc_base_init (GstRtpMP4VEncClass * klass); static void gst_rtpmp4venc_init (GstRtpMP4VEnc * rtpmp4venc); +static void gst_rtpmp4venc_finalize (GObject * object); -static gboolean gst_rtpmp4venc_setcaps (GstPad * pad, GstCaps * caps); -static GstFlowReturn gst_rtpmp4venc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpmp4venc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpmp4venc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtpmp4venc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpmp4venc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpmp4venc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpmp4venc_get_type (void) @@ -104,7 +86,7 @@ gst_rtpmp4venc_get_type (void) }; rtpmp4venc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMP4VEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpMP4VEnc", &rtpmp4venc_info, 0); } return rtpmp4venc_type; @@ -128,69 +110,58 @@ gst_rtpmp4venc_class_init (GstRtpMP4VEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpmp4venc_set_property; - gobject_class->get_property = gst_rtpmp4venc_get_property; + gobject_class->finalize = gst_rtpmp4venc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, - g_param_spec_uint ("pt", "payload type", - "The payload type of the packets", - 0, 0x80, DEFAULT_PT, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, - g_param_spec_uint ("ssrc", "SSRC", - "The SSRC of the packets", - 0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpmp4venc_change_state; + gstbasertppayload_class->set_caps = gst_rtpmp4venc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpmp4venc_handle_buffer; } static void gst_rtpmp4venc_init (GstRtpMP4VEnc * rtpmp4venc) { - rtpmp4venc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmp4venc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpmp4venc), rtpmp4venc->srcpad); - - rtpmp4venc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmp4venc_sink_template), "sink"); - gst_pad_set_setcaps_function (rtpmp4venc->sinkpad, gst_rtpmp4venc_setcaps); - gst_pad_set_chain_function (rtpmp4venc->sinkpad, gst_rtpmp4venc_chain); - gst_element_add_pad (GST_ELEMENT (rtpmp4venc), rtpmp4venc->sinkpad); - rtpmp4venc->adapter = gst_adapter_new (); - rtpmp4venc->mtu = DEFAULT_MTU; - rtpmp4venc->pt = DEFAULT_PT; - rtpmp4venc->ssrc = DEFAULT_SSRC; rtpmp4venc->rate = 90000; rtpmp4venc->profile = 1; } -static gboolean -gst_rtpmp4venc_setcaps (GstPad * pad, GstCaps * caps) +static void +gst_rtpmp4venc_finalize (GObject * object) { GstRtpMP4VEnc *rtpmp4venc; - GstCaps *srccaps; - rtpmp4venc = GST_RTP_MP4V_ENC (gst_pad_get_parent (pad)); + rtpmp4venc = GST_RTP_MP4V_ENC (object); - srccaps = gst_caps_new_simple ("application/x-rtp", - "rate", G_TYPE_INT, rtpmp4venc->rate, - "profile-level-id", G_TYPE_INT, rtpmp4venc->profile, NULL); - gst_pad_set_caps (rtpmp4venc->srcpad, srccaps); - gst_caps_unref (srccaps); + g_object_unref (rtpmp4venc->adapter); + rtpmp4venc->adapter = NULL; - gst_object_unref (rtpmp4venc); + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_rtpmp4venc_new_caps (GstRtpMP4VEnc * rtpmp4venc) +{ + gst_basertppayload_set_outcaps (GST_BASE_RTP_PAYLOAD (rtpmp4venc), + "profile-level-id", G_TYPE_INT, rtpmp4venc->profile, + "config", GST_TYPE_BUFFER, rtpmp4venc->config, NULL); +} + +static gboolean +gst_rtpmp4venc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + GstRtpMP4VEnc *rtpmp4venc; + + rtpmp4venc = GST_RTP_MP4V_ENC (payload); + + gst_basertppayload_set_options (payload, "video", TRUE, "MP4V-ES", + rtpmp4venc->rate); return TRUE; } @@ -201,7 +172,6 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) guint avail; GstBuffer *outbuf; GstFlowReturn ret; - guint16 frag_offset; /* the data available in the adapter is either smaller * than the MTU or bigger. In the case it is smaller, the complete @@ -212,7 +182,6 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) ret = GST_FLOW_OK; - frag_offset = 0; while (avail > 0) { guint towrite; guint8 *payload; @@ -224,159 +193,149 @@ gst_rtpmp4venc_flush (GstRtpMP4VEnc * rtpmp4venc) packet_len = gst_rtpbuffer_calc_packet_len (avail, 0, 0); /* fill one MTU or all available bytes */ - towrite = MIN (packet_len, rtpmp4venc->mtu); + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpmp4venc)); /* this is the payload length */ payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); /* create buffer to hold the payload */ outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (rtpmp4venc->srcpad)); - - /* set timestamp */ - if (GST_CLOCK_TIME_IS_VALID (rtpmp4venc->first_ts)) { - gst_rtpbuffer_set_timestamp (outbuf, - rtpmp4venc->first_ts * 90000 / GST_SECOND); - } - gst_rtpbuffer_set_payload_type (outbuf, rtpmp4venc->pt); - gst_rtpbuffer_set_seq (outbuf, rtpmp4venc->seqnum++); + /* copy payload */ payload = gst_rtpbuffer_get_payload (outbuf); - data = (guint8 *) gst_adapter_peek (rtpmp4venc->adapter, payload_len); memcpy (payload, data, payload_len); + gst_adapter_flush (rtpmp4venc->adapter, payload_len); avail -= payload_len; - frag_offset += payload_len; gst_rtpbuffer_set_marker (outbuf, avail == 0); GST_BUFFER_TIMESTAMP (outbuf) = rtpmp4venc->first_ts; - ret = gst_pad_push (rtpmp4venc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmp4venc), outbuf); } return ret; } +#define VOS_STARTCODE 0x000001B0 +#define VOS_ENDCODE 0x000001B1 +#define USER_DATA_STARTCODE 0x000001B2 +#define GOP_STARTCODE 0x000001B3 +#define VISUAL_OBJECT_STARTCODE 0x000001B5 +#define VOP_STARTCODE 0x000001B6 + +static gboolean +gst_rtpmp4venc_parse_data (GstRtpMP4VEnc * enc, guint8 * data, guint size) +{ + guint32 code; + gboolean result; + + if (size < 5) + return FALSE; + + code = GST_READ_UINT32_BE (data); + + switch (code) { + case VOS_STARTCODE: + { + gint i; + guint8 profile; + gboolean newprofile = FALSE; + gboolean equal; + + /* profile_and_level_indication */ + profile = data[4]; + + if (profile != enc->profile) { + newprofile = TRUE; + enc->profile = profile; + } + + /* up to the next GOP_STARTCODE or VOP_STARTCODE is + * the config information */ + code = 0xffffffff; + for (i = 5; i < size - 4; i++) { + code = (code << 8) | data[i]; + if (code == GOP_STARTCODE || code == VOP_STARTCODE) + break; + } + i -= 3; + /* see if config changed */ + equal = FALSE; + if (enc->config) { + if (GST_BUFFER_SIZE (enc->config) == i) { + equal = memcmp (GST_BUFFER_DATA (enc->config), data, i) == 0; + } + } + /* if config string changed or new profile, make new caps */ + if (!equal || newprofile) { + if (enc->config) + gst_buffer_unref (enc->config); + enc->config = gst_buffer_new_and_alloc (i); + memcpy (GST_BUFFER_DATA (enc->config), data, i); + gst_rtpmp4venc_new_caps (enc); + } + result = TRUE; + break; + } + case VOP_STARTCODE: + result = FALSE; + break; + default: + result = TRUE; + break; + } + return result; +} + /* we expect buffers starting on startcodes. - * - * FIXME, need to flush the adapter if we receive non VOP - * packets. */ static GstFlowReturn -gst_rtpmp4venc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpmp4venc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpMP4VEnc *rtpmp4venc; GstFlowReturn ret; guint size, avail; guint packet_len; + guint8 *data; + gboolean flush; - rtpmp4venc = GST_RTP_MP4V_ENC (gst_pad_get_parent (pad)); + rtpmp4venc = GST_RTP_MP4V_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); avail = gst_adapter_available (rtpmp4venc->adapter); + /* parse incomming data and see if we need to start a new RTP + * packet */ + flush = gst_rtpmp4venc_parse_data (rtpmp4venc, data, size); + /* get packet length of previous data and this new data */ packet_len = gst_rtpbuffer_calc_packet_len (avail + size, 0, 0); /* if this buffer is going to overflow the packet, flush what we * have. */ - if (packet_len > rtpmp4venc->mtu) { + if (flush || packet_len > GST_BASE_RTP_PAYLOAD_MTU (rtpmp4venc)) { ret = gst_rtpmp4venc_flush (rtpmp4venc); avail = 0; } gst_adapter_push (rtpmp4venc->adapter, buffer); + if (avail == 0) { rtpmp4venc->first_ts = GST_BUFFER_TIMESTAMP (buffer); } - gst_object_unref (rtpmp4venc); ret = GST_FLOW_OK; return ret; } -static void -gst_rtpmp4venc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpMP4VEnc *rtpmp4venc; - - rtpmp4venc = GST_RTP_MP4V_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpmp4venc->mtu = g_value_get_uint (value); - break; - case PROP_PT: - rtpmp4venc->pt = g_value_get_uint (value); - break; - case PROP_SSRC: - rtpmp4venc->ssrc = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpmp4venc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpMP4VEnc *rtpmp4venc; - - rtpmp4venc = GST_RTP_MP4V_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpmp4venc->mtu); - break; - case PROP_PT: - g_value_set_uint (value, rtpmp4venc->pt); - break; - case PROP_SSRC: - g_value_set_uint (value, rtpmp4venc->ssrc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpmp4venc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpMP4VEnc *rtpmp4venc; - GstStateChangeReturn ret; - - rtpmp4venc = GST_RTP_MP4V_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpmp4venc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - gboolean gst_rtpmp4venc_plugin_init (GstPlugin * plugin) { diff --git a/gst/rtp/gstrtpmp4vpay.h b/gst/rtp/gstrtpmp4vpay.h index b694903983..2edd0171a0 100644 --- a/gst/rtp/gstrtpmp4vpay.h +++ b/gst/rtp/gstrtpmp4vpay.h @@ -21,6 +21,7 @@ #define __GST_RTP_MP4V_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,26 +42,19 @@ typedef struct _GstRtpMP4VEncClass GstRtpMP4VEncClass; struct _GstRtpMP4VEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - guint16 seqnum; gint rate; gint profile; - - guint mtu; - guint pt; - guint ssrc; + GstBuffer *config; }; struct _GstRtpMP4VEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpmp4venc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpmpadec.c b/gst/rtp/gstrtpmpadec.c index 50576a3bf2..f2adc4ba80 100644 --- a/gst/rtp/gstrtpmpadec.c +++ b/gst/rtp/gstrtpmpadec.c @@ -53,7 +53,10 @@ static GstStaticPadTemplate gst_rtpmpadec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"MPA\"") ); diff --git a/gst/rtp/gstrtpmpadepay.c b/gst/rtp/gstrtpmpadepay.c index 50576a3bf2..f2adc4ba80 100644 --- a/gst/rtp/gstrtpmpadepay.c +++ b/gst/rtp/gstrtpmpadepay.c @@ -53,7 +53,10 @@ static GstStaticPadTemplate gst_rtpmpadec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"MPA\"") ); diff --git a/gst/rtp/gstrtpmpaenc.c b/gst/rtp/gstrtpmpaenc.c index 6ad805c406..691e556af3 100644 --- a/gst/rtp/gstrtpmpaenc.c +++ b/gst/rtp/gstrtpmpaenc.c @@ -30,21 +30,6 @@ static GstElementDetails gst_rtp_mpaenc_details = { "Wim Taymans " }; -/* RtpMPAEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 - -enum -{ - PROP_0, - PROP_MTU -}; - static GstStaticPadTemplate gst_rtpmpaenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -56,25 +41,23 @@ static GstStaticPadTemplate gst_rtpmpaenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"MPA\"") ); - static void gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass); static void gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass); static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc); +static void gst_rtpmpaenc_finalize (GObject * object); -static GstFlowReturn gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpmpaenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpmpaenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtpmpaenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpmpaenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpmpaenc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpmpaenc_get_type (void) @@ -95,7 +78,7 @@ gst_rtpmpaenc_get_type (void) }; rtpmpaenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPAEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpMPAEnc", &rtpmpaenc_info, 0); } return rtpmpaenc_type; @@ -119,39 +102,46 @@ gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpmpaenc_set_property; - gobject_class->get_property = gst_rtpmpaenc_get_property; + gobject_class->finalize = gst_rtpmpaenc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpmpaenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpmpaenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpmpaenc_handle_buffer; } static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc) { - rtpmpaenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmpaenc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->srcpad); - - rtpmpaenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmpaenc_sink_template), "sink"); - gst_pad_set_chain_function (rtpmpaenc->sinkpad, gst_rtpmpaenc_chain); - gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->sinkpad); - rtpmpaenc->adapter = gst_adapter_new (); - rtpmpaenc->mtu = DEFAULT_MTU; +} + +static void +gst_rtpmpaenc_finalize (GObject * object) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + g_object_unref (rtpmpaenc->adapter); + rtpmpaenc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_rtpmpaenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "audio", TRUE, "MPA", 90000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; } static GstFlowReturn @@ -184,7 +174,7 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) packet_len = gst_rtpbuffer_calc_packet_len (4 + avail, 0, 0); /* fill one MTU or all available bytes */ - towrite = MIN (packet_len, rtpmpaenc->mtu); + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpmpaenc)); /* this is the payload length */ payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); @@ -194,11 +184,7 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) payload_len -= 4; - /* set timestamp */ - gst_rtpbuffer_set_timestamp (outbuf, - rtpmpaenc->first_ts * 90000 / GST_SECOND); gst_rtpbuffer_set_payload_type (outbuf, GST_RTP_PAYLOAD_MPA); - gst_rtpbuffer_set_seq (outbuf, rtpmpaenc->seqnum++); /* * 0 1 2 3 @@ -225,21 +211,22 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) GST_BUFFER_TIMESTAMP (outbuf) = rtpmpaenc->first_ts; - ret = gst_pad_push (rtpmpaenc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmpaenc), outbuf); } return ret; } static GstFlowReturn -gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpmpaenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpMPAEnc *rtpmpaenc; GstFlowReturn ret; guint size, avail; guint packet_len; - rtpmpaenc = GST_RTP_MPA_ENC (gst_pad_get_parent (pad)); + rtpmpaenc = GST_RTP_MPA_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); avail = gst_adapter_available (rtpmpaenc->adapter); @@ -250,9 +237,11 @@ gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) /* if this buffer is going to overflow the packet, flush what we * have. */ - if (packet_len > rtpmpaenc->mtu) { + if (packet_len > GST_BASE_RTP_PAYLOAD_MTU (rtpmpaenc)) { ret = gst_rtpmpaenc_flush (rtpmpaenc); avail = 0; + } else { + ret = GST_FLOW_OK; } gst_adapter_push (rtpmpaenc->adapter, buffer); @@ -260,75 +249,7 @@ gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) if (avail == 0) { rtpmpaenc->first_ts = GST_BUFFER_TIMESTAMP (buffer); } - gst_object_unref (rtpmpaenc); - ret = GST_FLOW_OK; - - return ret; -} - -static void -gst_rtpmpaenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpMPAEnc *rtpmpaenc; - - rtpmpaenc = GST_RTP_MPA_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpmpaenc->mtu = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpmpaenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpMPAEnc *rtpmpaenc; - - rtpmpaenc = GST_RTP_MPA_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpmpaenc->mtu); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpmpaenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpMPAEnc *rtpmpaenc; - GstStateChangeReturn ret; - - rtpmpaenc = GST_RTP_MPA_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpmpaenc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } return ret; } diff --git a/gst/rtp/gstrtpmpaenc.h b/gst/rtp/gstrtpmpaenc.h index 5a03c7cb4d..6079f83e8e 100644 --- a/gst/rtp/gstrtpmpaenc.h +++ b/gst/rtp/gstrtpmpaenc.h @@ -21,6 +21,7 @@ #define __GST_RTP_MPA_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,21 +42,15 @@ typedef struct _GstRtpMPAEncClass GstRtpMPAEncClass; struct _GstRtpMPAEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - guint16 seqnum; - - guint mtu; }; struct _GstRtpMPAEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpmpaenc_plugin_init (GstPlugin * plugin); diff --git a/gst/rtp/gstrtpmpapay.c b/gst/rtp/gstrtpmpapay.c index 6ad805c406..691e556af3 100644 --- a/gst/rtp/gstrtpmpapay.c +++ b/gst/rtp/gstrtpmpapay.c @@ -30,21 +30,6 @@ static GstElementDetails gst_rtp_mpaenc_details = { "Wim Taymans " }; -/* RtpMPAEnc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_MTU 1024 - -enum -{ - PROP_0, - PROP_MTU -}; - static GstStaticPadTemplate gst_rtpmpaenc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -56,25 +41,23 @@ static GstStaticPadTemplate gst_rtpmpaenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-rtp") + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 255 ], " + "clock_rate = (int) 90000, " "encoding_name = (string) \"MPA\"") ); - static void gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass); static void gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass); static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc); +static void gst_rtpmpaenc_finalize (GObject * object); -static GstFlowReturn gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_rtpmpaenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpmpaenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); -static void gst_rtpmpaenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_rtpmpaenc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_rtpmpaenc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; +static GstBaseRTPPayloadClass *parent_class = NULL; static GType gst_rtpmpaenc_get_type (void) @@ -95,7 +78,7 @@ gst_rtpmpaenc_get_type (void) }; rtpmpaenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPAEnc", + g_type_register_static (GST_TYPE_BASE_RTP_PAYLOAD, "GstRtpMPAEnc", &rtpmpaenc_info, 0); } return rtpmpaenc_type; @@ -119,39 +102,46 @@ gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); - gobject_class->set_property = gst_rtpmpaenc_set_property; - gobject_class->get_property = gst_rtpmpaenc_get_property; + gobject_class->finalize = gst_rtpmpaenc_finalize; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, - g_param_spec_uint ("mtu", "MTU", - "Maximum size of one packet", - 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); - - gstelement_class->change_state = gst_rtpmpaenc_change_state; + gstbasertppayload_class->set_caps = gst_rtpmpaenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpmpaenc_handle_buffer; } static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc) { - rtpmpaenc->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmpaenc_src_template), "src"); - gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->srcpad); - - rtpmpaenc->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_rtpmpaenc_sink_template), "sink"); - gst_pad_set_chain_function (rtpmpaenc->sinkpad, gst_rtpmpaenc_chain); - gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->sinkpad); - rtpmpaenc->adapter = gst_adapter_new (); - rtpmpaenc->mtu = DEFAULT_MTU; +} + +static void +gst_rtpmpaenc_finalize (GObject * object) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + g_object_unref (rtpmpaenc->adapter); + rtpmpaenc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_rtpmpaenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "audio", TRUE, "MPA", 90000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; } static GstFlowReturn @@ -184,7 +174,7 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) packet_len = gst_rtpbuffer_calc_packet_len (4 + avail, 0, 0); /* fill one MTU or all available bytes */ - towrite = MIN (packet_len, rtpmpaenc->mtu); + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpmpaenc)); /* this is the payload length */ payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); @@ -194,11 +184,7 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) payload_len -= 4; - /* set timestamp */ - gst_rtpbuffer_set_timestamp (outbuf, - rtpmpaenc->first_ts * 90000 / GST_SECOND); gst_rtpbuffer_set_payload_type (outbuf, GST_RTP_PAYLOAD_MPA); - gst_rtpbuffer_set_seq (outbuf, rtpmpaenc->seqnum++); /* * 0 1 2 3 @@ -225,21 +211,22 @@ gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) GST_BUFFER_TIMESTAMP (outbuf) = rtpmpaenc->first_ts; - ret = gst_pad_push (rtpmpaenc->srcpad, outbuf); + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpmpaenc), outbuf); } return ret; } static GstFlowReturn -gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) +gst_rtpmpaenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) { GstRtpMPAEnc *rtpmpaenc; GstFlowReturn ret; guint size, avail; guint packet_len; - rtpmpaenc = GST_RTP_MPA_ENC (gst_pad_get_parent (pad)); + rtpmpaenc = GST_RTP_MPA_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); avail = gst_adapter_available (rtpmpaenc->adapter); @@ -250,9 +237,11 @@ gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) /* if this buffer is going to overflow the packet, flush what we * have. */ - if (packet_len > rtpmpaenc->mtu) { + if (packet_len > GST_BASE_RTP_PAYLOAD_MTU (rtpmpaenc)) { ret = gst_rtpmpaenc_flush (rtpmpaenc); avail = 0; + } else { + ret = GST_FLOW_OK; } gst_adapter_push (rtpmpaenc->adapter, buffer); @@ -260,75 +249,7 @@ gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) if (avail == 0) { rtpmpaenc->first_ts = GST_BUFFER_TIMESTAMP (buffer); } - gst_object_unref (rtpmpaenc); - ret = GST_FLOW_OK; - - return ret; -} - -static void -gst_rtpmpaenc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstRtpMPAEnc *rtpmpaenc; - - rtpmpaenc = GST_RTP_MPA_ENC (object); - - switch (prop_id) { - case PROP_MTU: - rtpmpaenc->mtu = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_rtpmpaenc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstRtpMPAEnc *rtpmpaenc; - - rtpmpaenc = GST_RTP_MPA_ENC (object); - - switch (prop_id) { - case PROP_MTU: - g_value_set_uint (value, rtpmpaenc->mtu); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_rtpmpaenc_change_state (GstElement * element, GstStateChange transition) -{ - GstRtpMPAEnc *rtpmpaenc; - GstStateChangeReturn ret; - - rtpmpaenc = GST_RTP_MPA_ENC (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - rtpmpaenc->seqnum = 0; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } return ret; } diff --git a/gst/rtp/gstrtpmpapay.h b/gst/rtp/gstrtpmpapay.h index 5a03c7cb4d..6079f83e8e 100644 --- a/gst/rtp/gstrtpmpapay.h +++ b/gst/rtp/gstrtpmpapay.h @@ -21,6 +21,7 @@ #define __GST_RTP_MPA_ENC_H__ #include +#include #include G_BEGIN_DECLS @@ -41,21 +42,15 @@ typedef struct _GstRtpMPAEncClass GstRtpMPAEncClass; struct _GstRtpMPAEnc { - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; + GstBaseRTPPayload payload; GstAdapter *adapter; GstClockTime first_ts; - guint16 seqnum; - - guint mtu; }; struct _GstRtpMPAEncClass { - GstElementClass parent_class; + GstBaseRTPPayloadClass parent_class; }; gboolean gst_rtpmpaenc_plugin_init (GstPlugin * plugin);