X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Frtp%2Fgstrtpjpegdepay.c;h=5cd54282847d20b37d82e0bfab3885759166b89a;hb=775ccdf9775bd7051929b257444b3be915e88ec6;hp=0ea3303a5c56f318454728b245ff622fdef7a196;hpb=e09ae5736d58df9fb6ea9ba6aebafee797f60919;p=platform%2Fupstream%2Fgst-plugins-good.git diff --git a/gst/rtp/gstrtpjpegdepay.c b/gst/rtp/gstrtpjpegdepay.c index 0ea3303..5cd5428 100644 --- a/gst/rtp/gstrtpjpegdepay.c +++ b/gst/rtp/gstrtpjpegdepay.c @@ -13,8 +13,8 @@ * * 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. */ #ifdef HAVE_CONFIG_H @@ -22,12 +22,14 @@ #endif #include +#include #include #include #include #include #include "gstrtpjpegdepay.h" +#include "gstrtputils.h" GST_DEBUG_CATEGORY_STATIC (rtpjpegdepay_debug); #define GST_CAT_DEFAULT (rtpjpegdepay_debug) @@ -45,7 +47,6 @@ static GstStaticPadTemplate gst_rtp_jpeg_depay_sink_template = 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) \"JPEG\"; " /* optional SDP attributes */ /* @@ -78,7 +79,7 @@ static GstStateChangeReturn gst_rtp_jpeg_depay_change_state (GstElement * static gboolean gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps); static GstBuffer *gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, - GstBuffer * buf); + GstRTPBuffer * rtp); static void gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass) @@ -93,10 +94,10 @@ gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass) gobject_class->finalize = gst_rtp_jpeg_depay_finalize; - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_jpeg_depay_src_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_rtp_jpeg_depay_sink_template)); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_jpeg_depay_src_template); + gst_element_class_add_static_pad_template (gstelement_class, + &gst_rtp_jpeg_depay_sink_template); gst_element_class_set_static_metadata (gstelement_class, "RTP JPEG depayloader", "Codec/Depayloader/Network/RTP", @@ -106,7 +107,7 @@ gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass) gstelement_class->change_state = gst_rtp_jpeg_depay_change_state; gstrtpbasedepayload_class->set_caps = gst_rtp_jpeg_depay_setcaps; - gstrtpbasedepayload_class->process = gst_rtp_jpeg_depay_process; + gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_jpeg_depay_process; GST_DEBUG_CATEGORY_INIT (rtpjpegdepay_debug, "rtpjpegdepay", 0, "JPEG Video RTP Depayloader"); @@ -154,6 +155,17 @@ gst_rtp_jpeg_depay_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static const int zigzag[] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + /* * Table K.1 from JPEG spec. */ @@ -198,8 +210,8 @@ MakeTables (GstRtpJPEGDepay * rtpjpegdepay, gint Q, guint8 qtable[128]) Q = 200 - factor * 2; for (i = 0; i < 64; i++) { - gint lq = (jpeg_luma_quantizer[i] * Q + 50) / 100; - gint cq = (jpeg_chroma_quantizer[i] * Q + 50) / 100; + gint lq = (jpeg_luma_quantizer[zigzag[i]] * Q + 50) / 100; + gint cq = (jpeg_chroma_quantizer[zigzag[i]] * Q + 50) / 100; /* Limit the quantizers to 1 <= q <= 255 */ qtable[i] = CLAMP (lq, 1, 255); @@ -406,7 +418,7 @@ MakeHeaders (guint8 * p, int type, int width, int height, guint8 * qt, *p++ = 0x11; /* huffman table 1 */ *p++ = 0; /* first DCT coeff */ *p++ = 63; /* last DCT coeff */ - *p++ = 0; /* sucessive approx. */ + *p++ = 0; /* successive approx. */ return (p - start); }; @@ -477,7 +489,7 @@ gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) } static GstBuffer * -gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) +gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp) { GstRtpJPEGDepay *rtpjpegdepay; GstBuffer *outbuf; @@ -488,22 +500,21 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) guint type, width, height; guint16 dri, precision, length; guint8 *qtable; - GstRTPBuffer rtp = { NULL }; rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload); - if (GST_BUFFER_IS_DISCONT (buf)) { + if (GST_BUFFER_IS_DISCONT (rtp->buffer)) { + GST_DEBUG_OBJECT (depayload, "DISCONT, reset adapter"); gst_adapter_clear (rtpjpegdepay->adapter); rtpjpegdepay->discont = TRUE; } - gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); - payload_len = gst_rtp_buffer_get_payload_len (&rtp); + payload_len = gst_rtp_buffer_get_payload_len (rtp); if (payload_len < 8) goto empty_packet; - payload = gst_rtp_buffer_get_payload (&rtp); + payload = gst_rtp_buffer_get_payload (rtp); header_len = 0; /* 0 1 2 3 @@ -520,6 +531,13 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) width = payload[6] * 8; height = payload[7] * 8; + /* saw a packet with fragment offset > 0 and we don't already have data queued + * up (most importantly, we don't have a header for this data) -- drop it + * XXX: maybe we can check if the jpeg is progressive and salvage the data? + * XXX: not implemented yet because jpegenc can't create progressive jpegs */ + if (frag_offset > 0 && gst_adapter_available (rtpjpegdepay->adapter) == 0) + goto no_header_packet; + /* allow frame dimensions > 2040, passed in SDP session or media attributes * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */ if (!width) @@ -609,9 +627,10 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) GstCaps *outcaps; outcaps = - gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION, - rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width", - G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE, + "framerate", GST_TYPE_FRACTION, rtpjpegdepay->frate_num, + rtpjpegdepay->frate_denom, "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, NULL); gst_pad_set_caps (depayload->srcpad, outcaps); gst_caps_unref (outcaps); @@ -643,6 +662,12 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) goto no_qtable; } } + + /* I think we can get here with a NULL qtable, so make sure we don't + go dereferencing it in MakeHeaders if we do */ + if (!qtable) + goto no_qtable; + /* max header length, should be big enough */ outbuf = gst_buffer_new_and_alloc (1000); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); @@ -657,11 +682,11 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) /* take JPEG data, push in the adapter */ GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len); - outbuf = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len, -1); + outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, -1); gst_adapter_push (rtpjpegdepay->adapter, outbuf); outbuf = NULL; - if (gst_rtp_buffer_get_marker (&rtp)) { + if (gst_rtp_buffer_get_marker (rtp)) { guint avail; guint8 end[2]; GstMapInfo map; @@ -670,6 +695,9 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) avail = gst_adapter_available (rtpjpegdepay->adapter); GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer"); + if (avail < 2) + goto invalid_packet; + /* take the last bytes of the jpeg data to see if there is an EOI * marker */ gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2); @@ -694,11 +722,11 @@ gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) rtpjpegdepay->discont = FALSE; } + gst_rtp_drop_non_video_meta (rtpjpegdepay, outbuf); + GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail); } - gst_rtp_buffer_unmap (&rtp); - return outbuf; /* ERRORS */ @@ -706,20 +734,30 @@ empty_packet: { GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE, ("Empty Payload."), (NULL)); - gst_rtp_buffer_unmap (&rtp); return NULL; } invalid_dimension: { GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT, ("Invalid Dimension %dx%d.", width, height), (NULL)); - gst_rtp_buffer_unmap (&rtp); return NULL; } no_qtable: { GST_WARNING_OBJECT (rtpjpegdepay, "no qtable"); - gst_rtp_buffer_unmap (&rtp); + return NULL; + } +invalid_packet: + { + GST_WARNING_OBJECT (rtpjpegdepay, "invalid packet"); + gst_adapter_flush (rtpjpegdepay->adapter, + gst_adapter_available (rtpjpegdepay->adapter)); + return NULL; + } +no_header_packet: + { + GST_WARNING_OBJECT (rtpjpegdepay, + "discarding data packets received when we have no header"); return NULL; } }