X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Frtp%2Fgstrtpj2kdepay.c;h=132bcf5dfb1e7fbeeb6f56072cca2d9c94205ef8;hb=775ccdf9775bd7051929b257444b3be915e88ec6;hp=be6ba9758e17ae291326f63dc8be42543db5c666;hpb=22eb0d2300f1dd42ff6061bffbc6a08e38f4efa1;p=platform%2Fupstream%2Fgst-plugins-good.git diff --git a/gst/rtp/gstrtpj2kdepay.c b/gst/rtp/gstrtpj2kdepay.c index be6ba97..132bcf5 100644 --- a/gst/rtp/gstrtpj2kdepay.c +++ b/gst/rtp/gstrtpj2kdepay.c @@ -13,18 +13,33 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ + + /** + * SECTION:element-rtpj2kdepay + * @title: rtpj2kdepay + * + * Depayload an RTP-payloaded JPEG 2000 image into RTP packets according to RFC 5371 + * and RFC 5372. + * For detailed information see: https://datatracker.ietf.org/doc/rfc5371/ + * and https://datatracker.ietf.org/doc/rfc5372/ + */ + + #ifdef HAVE_CONFIG_H # include "config.h" #endif #include +#include #include +#include "gstrtpj2kcommon.h" #include "gstrtpj2kdepay.h" +#include "gstrtputils.h" GST_DEBUG_CATEGORY_STATIC (rtpj2kdepay_debug); #define GST_CAT_DEFAULT (rtpj2kdepay_debug) @@ -33,40 +48,32 @@ static GstStaticPadTemplate gst_rtp_j2k_depay_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("image/x-jpc") + GST_STATIC_CAPS ("image/x-jpc, " + "colorspace = (string) { sRGB, sYUV, GRAY }") ); static GstStaticPadTemplate gst_rtp_j2k_depay_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", + GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " - "media = (string) \"video\", " - "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " - "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG2000\"") + "media = (string) \"video\", " "clock-rate = (int) 90000, " + GST_RTP_J2K_SAMPLING_LIST "," + "encoding-name = (string) \"JPEG2000\";" + "application/x-rtp, " + "media = (string) \"video\", " "clock-rate = (int) 90000, " + "colorspace = (string) { sRGB, sYUV, GRAY }, " + "encoding-name = (string) \"JPEG2000\";") ); -typedef enum -{ - J2K_MARKER = 0xFF, - J2K_MARKER_SOC = 0x4F, - J2K_MARKER_SOT = 0x90, - J2K_MARKER_SOP = 0x91, - J2K_MARKER_SOD = 0x93, - J2K_MARKER_EOC = 0xD9 -} RtpJ2KMarker; - -#define DEFAULT_BUFFER_LIST TRUE - enum { PROP_0, - PROP_BUFFER_LIST, PROP_LAST }; #define gst_rtp_j2k_depay_parent_class parent_class -G_DEFINE_TYPE (GstRtpJ2KDepay, gst_rtp_j2k_depay, GST_TYPE_BASE_RTP_DEPAYLOAD); +G_DEFINE_TYPE (GstRtpJ2KDepay, gst_rtp_j2k_depay, GST_TYPE_RTP_BASE_DEPAYLOAD); static void gst_rtp_j2k_depay_finalize (GObject * object); @@ -79,46 +86,41 @@ static GstStateChangeReturn gst_rtp_j2k_depay_change_state (GstElement * element, GstStateChange transition); -static gboolean gst_rtp_j2k_depay_setcaps (GstBaseRTPDepayload * depayload, +static gboolean gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps); -static GstBuffer *gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, - GstBuffer * buf); +static GstBuffer *gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, + GstRTPBuffer * rtp); static void gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; - GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + GstRTPBaseDepayloadClass *gstrtpbasedepayload_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass; gobject_class->finalize = gst_rtp_j2k_depay_finalize; gobject_class->set_property = gst_rtp_j2k_depay_set_property; gobject_class->get_property = gst_rtp_j2k_depay_get_property; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST, - g_param_spec_boolean ("buffer-list", "Buffer List", - "Use Buffer Lists", - DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_j2k_depay_src_template); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_j2k_depay_sink_template); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_j2k_depay_src_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_j2k_depay_sink_template)); - - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "RTP JPEG 2000 depayloader", "Codec/Depayloader/Network/RTP", "Extracts JPEG 2000 video from RTP packets (RFC 5371)", "Wim Taymans "); gstelement_class->change_state = gst_rtp_j2k_depay_change_state; - gstbasertpdepayload_class->set_caps = gst_rtp_j2k_depay_setcaps; - gstbasertpdepayload_class->process = gst_rtp_j2k_depay_process; + gstrtpbasedepayload_class->set_caps = gst_rtp_j2k_depay_setcaps; + gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_j2k_depay_process; GST_DEBUG_CATEGORY_INIT (rtpj2kdepay_debug, "rtpj2kdepay", 0, "J2K Video RTP Depayloader"); @@ -127,8 +129,6 @@ gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass) static void gst_rtp_j2k_depay_init (GstRtpJ2KDepay * rtpj2kdepay) { - rtpj2kdepay->buffer_list = DEFAULT_BUFFER_LIST; - rtpj2kdepay->pu_adapter = gst_adapter_new (); rtpj2kdepay->t_adapter = gst_adapter_new (); rtpj2kdepay->f_adapter = gst_adapter_new (); @@ -182,12 +182,14 @@ gst_rtp_j2k_depay_finalize (GObject * object) } static gboolean -gst_rtp_j2k_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +gst_rtp_j2k_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { - GstStructure *structure; + GstStructure *structure = NULL; gint clock_rate; - GstCaps *outcaps; - gboolean res; + GstCaps *outcaps = NULL; + gboolean res = FALSE; + const gchar *colorspace = NULL; + const gchar *sampling = NULL; structure = gst_caps_get_structure (caps, 0); @@ -195,10 +197,35 @@ gst_rtp_j2k_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) clock_rate = 90000; depayload->clock_rate = clock_rate; - outcaps = - gst_caps_new_simple ("image/x-jpc", "framerate", GST_TYPE_FRACTION, 0, 1, - "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, "sYUV", NULL); + sampling = gst_structure_get_string (structure, "sampling"); + if (sampling) { + if (!strcmp (sampling, GST_RTP_J2K_RGB) || + !strcmp (sampling, GST_RTP_J2K_RGBA) || + !strcmp (sampling, GST_RTP_J2K_BGR) || + !strcmp (sampling, GST_RTP_J2K_BGRA)) + colorspace = "sRGB"; + else if (!strcmp (sampling, GST_RTP_J2K_GRAYSCALE)) + colorspace = "GRAY"; + else + colorspace = "sYUV"; + } else { + GST_ELEMENT_WARNING (depayload, STREAM, DEMUX, NULL, + ("Non-compliant stream: sampling field missing. Frames my appear incorrect")); + colorspace = gst_structure_get_string (structure, "colorspace"); + if (!strcmp (colorspace, "GRAY")) { + sampling = GST_RTP_J2K_GRAYSCALE; + } + } + + outcaps = gst_caps_new_simple ("image/x-jpc", + "framerate", GST_TYPE_FRACTION, 0, 1, + "fields", G_TYPE_INT, 1, "colorspace", G_TYPE_STRING, colorspace, NULL); + + if (sampling) + gst_caps_set_simple (outcaps, "sampling", G_TYPE_STRING, sampling, NULL); + res = gst_pad_set_caps (depayload->srcpad, outcaps); + gst_caps_unref (outcaps); return res; @@ -212,7 +239,7 @@ gst_rtp_j2k_depay_clear_pu (GstRtpJ2KDepay * rtpj2kdepay) } static GstFlowReturn -gst_rtp_j2k_depay_flush_pu (GstBaseRTPDepayload * depayload) +gst_rtp_j2k_depay_flush_pu (GstRTPBaseDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; GstBuffer *mheader; @@ -237,7 +264,8 @@ gst_rtp_j2k_depay_flush_pu (GstBaseRTPDepayload * depayload) /* append packets */ for (walk = packets; walk; walk = g_list_next (walk)) { GstBuffer *buf = GST_BUFFER_CAST (walk->data); - GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u", + GST_DEBUG_OBJECT (rtpj2kdepay, + "append pu packet of size %" G_GSIZE_FORMAT, gst_buffer_get_size (buf)); gst_adapter_push (rtpj2kdepay->t_adapter, buf); } @@ -259,15 +287,14 @@ done: } static GstFlowReturn -gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload) +gst_rtp_j2k_depay_flush_tile (GstRTPBaseDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint avail, mh_id; GList *packets, *walk; guint8 end[2]; GstFlowReturn ret = GST_FLOW_OK; - guint8 *data; - gsize size; + GstMapInfo map; GstBuffer *buf; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); @@ -306,35 +333,35 @@ gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload) if (walk == packets) { /* first buffer should contain the SOT */ - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + gst_buffer_map (buf, &map, GST_MAP_READ); - if (size < 12) + if (map.size < 12) goto invalid_tile; - if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) { + if (map.data[0] == GST_J2K_MARKER && map.data[1] == GST_J2K_MARKER_SOT) { guint Psot, nPsot; - if (end[0] == 0xff && end[1] == J2K_MARKER_EOC) + if (end[0] == GST_J2K_MARKER && end[1] == GST_J2K_MARKER_EOC) nPsot = avail - 2; else nPsot = avail; - Psot = GST_READ_UINT32_BE (&data[6]); + Psot = GST_READ_UINT32_BE (&map.data[6]); if (Psot != nPsot && Psot != 0) { /* Psot must match the size of the tile */ GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot); - gst_buffer_unmap (buf, data, size); + gst_buffer_unmap (buf, &map); buf = gst_buffer_make_writable (buf); - data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE); - GST_WRITE_UINT32_BE (&data[6], nPsot); + gst_buffer_map (buf, &map, GST_MAP_WRITE); + GST_WRITE_UINT32_BE (&map.data[6], nPsot); } } - gst_buffer_unmap (buf, data, size); + gst_buffer_unmap (buf, &map); } - GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u", + GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %" G_GSIZE_FORMAT, gst_buffer_get_size (buf)); gst_adapter_push (rtpj2kdepay->f_adapter, buf); } @@ -356,7 +383,7 @@ waiting_header: invalid_tile: { GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL)); - gst_buffer_unmap (buf, data, size); + gst_buffer_unmap (buf, &map); gst_adapter_clear (rtpj2kdepay->t_adapter); rtpj2kdepay->last_tile = -1; return ret; @@ -364,7 +391,7 @@ invalid_tile: } static GstFlowReturn -gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload) +gst_rtp_j2k_depay_flush_frame (GstRTPBaseDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint8 end[2]; @@ -389,9 +416,9 @@ gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload) * marker */ gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2); - if (end[0] != 0xff && end[1] != 0xd9) { - end[0] = 0xff; - end[1] = 0xd9; + if (end[0] != GST_J2K_MARKER && end[1] != GST_J2K_MARKER_EOC) { + end[0] = GST_J2K_MARKER; + end[1] = GST_J2K_MARKER_EOC; GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one"); @@ -402,29 +429,11 @@ gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload) gst_adapter_push (rtpj2kdepay->f_adapter, outbuf); avail += 2; } -#if 0 - if (rtpj2kdepay->buffer_list) { - GList *list; - GstBufferList *buflist; - GstBufferListIterator *it; - - GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail); - list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail); - - buflist = gst_buffer_list_new (); - it = gst_buffer_list_iterate (buflist); - gst_buffer_list_iterator_add_group (it); - gst_buffer_list_iterator_add_list (it, list); - gst_buffer_list_iterator_free (it); - - ret = gst_base_rtp_depayload_push_list (depayload, buflist); - } else -#endif - { - GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail); - outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail); - ret = gst_base_rtp_depayload_push (depayload, outbuf); - } + + GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail); + outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail); + gst_rtp_drop_non_video_meta (depayload, outbuf); + ret = gst_rtp_base_depayload_push (depayload, outbuf); } else { GST_WARNING_OBJECT (rtpj2kdepay, "empty packet"); gst_adapter_clear (rtpj2kdepay->f_adapter); @@ -445,27 +454,24 @@ done: } static GstBuffer * -gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +gst_rtp_j2k_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp) { GstRtpJ2KDepay *rtpj2kdepay; guint8 *payload; guint MHF, mh_id, frag_offset, tile, payload_len, j2klen; gint gap; guint32 rtptime; - GstRTPBuffer rtp = { NULL }; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); - gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); - - payload = gst_rtp_buffer_get_payload (&rtp); - payload_len = gst_rtp_buffer_get_payload_len (&rtp); + payload = gst_rtp_buffer_get_payload (rtp); + payload_len = gst_rtp_buffer_get_payload_len (rtp); /* we need at least a header */ - if (payload_len < 8) + if (payload_len < GST_RTP_J2K_HEADER_SIZE) goto empty_packet; - rtptime = gst_rtp_buffer_get_timestamp (&rtp); + rtptime = gst_rtp_buffer_get_timestamp (rtp); /* new timestamp marks new frame */ if (rtpj2kdepay->last_rtptime != rtptime) { @@ -493,7 +499,7 @@ gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) tile = (payload[2] << 8) | payload[3]; frag_offset = (payload[5] << 16) | (payload[6] << 8) | payload[7]; - j2klen = payload_len - 8; + j2klen = payload_len - GST_RTP_J2K_HEADER_SIZE; GST_DEBUG_OBJECT (rtpj2kdepay, "MHF %u, tile %u, frag %u, expected %u", MHF, tile, frag_offset, rtpj2kdepay->next_frag); @@ -510,19 +516,19 @@ gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } /* check for sync code */ - if (j2klen > 2 && payload[8] == 0xff) { - guint marker = payload[9]; + if (j2klen > 2 && payload[GST_RTP_J2K_HEADER_SIZE] == GST_J2K_MARKER) { + guint marker = payload[GST_RTP_J2K_HEADER_SIZE + 1]; /* packets must start with SOC, SOT or SOP */ switch (marker) { - case J2K_MARKER_SOC: + case GST_J2K_MARKER_SOC: GST_DEBUG_OBJECT (rtpj2kdepay, "found SOC packet"); /* flush the previous frame, should have happened when the timestamp * changed above. */ gst_rtp_j2k_depay_flush_frame (depayload); rtpj2kdepay->have_sync = TRUE; break; - case J2K_MARKER_SOT: + case GST_J2K_MARKER_SOT: /* flush the previous tile */ gst_rtp_j2k_depay_flush_tile (depayload); GST_DEBUG_OBJECT (rtpj2kdepay, "found SOT packet"); @@ -530,7 +536,7 @@ gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) /* we sync on the tile now */ rtpj2kdepay->last_tile = tile; break; - case J2K_MARKER_SOP: + case GST_J2K_MARKER_SOP: GST_DEBUG_OBJECT (rtpj2kdepay, "found SOP packet"); /* flush the previous PU */ gst_rtp_j2k_depay_flush_pu (depayload); @@ -562,7 +568,7 @@ gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } /* and push in pu adapter */ GST_DEBUG_OBJECT (rtpj2kdepay, "push pu of size %u in adapter", j2klen); - pu_frag = gst_rtp_buffer_get_payload_subbuffer (&rtp, 8, -1); + pu_frag = gst_rtp_buffer_get_payload_subbuffer (rtp, 8, -1); gst_adapter_push (rtpj2kdepay->pu_adapter, pu_frag); if (MHF & 2) { @@ -575,12 +581,11 @@ gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) } /* marker bit finishes the frame */ - if (gst_rtp_buffer_get_marker (&rtp)) { + if (gst_rtp_buffer_get_marker (rtp)) { GST_DEBUG_OBJECT (rtpj2kdepay, "marker set, last buffer"); /* then flush frame */ gst_rtp_j2k_depay_flush_frame (depayload); } - gst_rtp_buffer_unmap (&rtp); return NULL; @@ -589,7 +594,6 @@ empty_packet: { GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Empty Payload."), (NULL)); - gst_rtp_buffer_unmap (&rtp); return NULL; } wrong_mh_id: @@ -598,7 +602,6 @@ wrong_mh_id: ("Invalid mh_id %u, expected %u", mh_id, rtpj2kdepay->last_mh_id), (NULL)); gst_rtp_j2k_depay_clear_pu (rtpj2kdepay); - gst_rtp_buffer_unmap (&rtp); return NULL; } } @@ -607,14 +610,7 @@ static void gst_rtp_j2k_depay_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstRtpJ2KDepay *rtpj2kdepay; - - rtpj2kdepay = GST_RTP_J2K_DEPAY (object); - switch (prop_id) { - case PROP_BUFFER_LIST: - rtpj2kdepay->buffer_list = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -625,14 +621,7 @@ static void gst_rtp_j2k_depay_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstRtpJ2KDepay *rtpj2kdepay; - - rtpj2kdepay = GST_RTP_J2K_DEPAY (object); - switch (prop_id) { - case PROP_BUFFER_LIST: - g_value_set_boolean (value, rtpj2kdepay->buffer_list); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break;