rtpdepay: remove payload type restrictions
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpjpegdepay.c
1 /* GStreamer
2  * Copyright (C) <2008> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <gst/rtp/gstrtpbuffer.h>
25
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "gstrtpjpegdepay.h"
31
32 GST_DEBUG_CATEGORY_STATIC (rtpjpegdepay_debug);
33 #define GST_CAT_DEFAULT (rtpjpegdepay_debug)
34
35 static GstStaticPadTemplate gst_rtp_jpeg_depay_src_template =
36 GST_STATIC_PAD_TEMPLATE ("src",
37     GST_PAD_SRC,
38     GST_PAD_ALWAYS,
39     GST_STATIC_CAPS ("image/jpeg")
40     );
41
42 static GstStaticPadTemplate gst_rtp_jpeg_depay_sink_template =
43     GST_STATIC_PAD_TEMPLATE ("sink",
44     GST_PAD_SINK,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS ("application/x-rtp, "
47         "media = (string) \"video\", "
48         "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG\"; "
49         /* optional SDP attributes */
50         /*
51          * "a-framerate = (string) 0.00, "
52          * "x-framerate = (string) 0.00, "
53          * "x-dimensions = (string) \"1234,1234\", "
54          */
55         "application/x-rtp, "
56         "media = (string) \"video\", "
57         "payload = (int) " GST_RTP_PAYLOAD_JPEG_STRING ", "
58         "clock-rate = (int) 90000"
59         /* optional SDP attributes */
60         /*
61          * "a-framerate = (string) 0.00, "
62          * "x-framerate = (string) 0.00, "
63          * "x-dimensions = (string) \"1234,1234\""
64          */
65     )
66     );
67
68 #define gst_rtp_jpeg_depay_parent_class parent_class
69 G_DEFINE_TYPE (GstRtpJPEGDepay, gst_rtp_jpeg_depay,
70     GST_TYPE_RTP_BASE_DEPAYLOAD);
71
72 static void gst_rtp_jpeg_depay_finalize (GObject * object);
73
74 static GstStateChangeReturn gst_rtp_jpeg_depay_change_state (GstElement *
75     element, GstStateChange transition);
76
77 static gboolean gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload,
78     GstCaps * caps);
79 static GstBuffer *gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload,
80     GstBuffer * buf);
81
82 static void
83 gst_rtp_jpeg_depay_class_init (GstRtpJPEGDepayClass * klass)
84 {
85   GObjectClass *gobject_class;
86   GstElementClass *gstelement_class;
87   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
88
89   gobject_class = (GObjectClass *) klass;
90   gstelement_class = (GstElementClass *) klass;
91   gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
92
93   gobject_class->finalize = gst_rtp_jpeg_depay_finalize;
94
95   gst_element_class_add_pad_template (gstelement_class,
96       gst_static_pad_template_get (&gst_rtp_jpeg_depay_src_template));
97   gst_element_class_add_pad_template (gstelement_class,
98       gst_static_pad_template_get (&gst_rtp_jpeg_depay_sink_template));
99
100   gst_element_class_set_static_metadata (gstelement_class,
101       "RTP JPEG depayloader", "Codec/Depayloader/Network/RTP",
102       "Extracts JPEG video from RTP packets (RFC 2435)",
103       "Wim Taymans <wim.taymans@gmail.com>");
104
105   gstelement_class->change_state = gst_rtp_jpeg_depay_change_state;
106
107   gstrtpbasedepayload_class->set_caps = gst_rtp_jpeg_depay_setcaps;
108   gstrtpbasedepayload_class->process = gst_rtp_jpeg_depay_process;
109
110   GST_DEBUG_CATEGORY_INIT (rtpjpegdepay_debug, "rtpjpegdepay", 0,
111       "JPEG Video RTP Depayloader");
112 }
113
114 static void
115 gst_rtp_jpeg_depay_init (GstRtpJPEGDepay * rtpjpegdepay)
116 {
117   rtpjpegdepay->adapter = gst_adapter_new ();
118 }
119
120 static void
121 gst_rtp_jpeg_depay_reset (GstRtpJPEGDepay * depay)
122 {
123   gint i;
124
125   depay->width = 0;
126   depay->height = 0;
127   depay->media_width = 0;
128   depay->media_height = 0;
129   depay->frate_num = 0;
130   depay->frate_denom = 1;
131   depay->discont = TRUE;
132
133   for (i = 0; i < 255; i++) {
134     g_free (depay->qtables[i]);
135     depay->qtables[i] = NULL;
136   }
137
138   gst_adapter_clear (depay->adapter);
139 }
140
141 static void
142 gst_rtp_jpeg_depay_finalize (GObject * object)
143 {
144   GstRtpJPEGDepay *rtpjpegdepay;
145
146   rtpjpegdepay = GST_RTP_JPEG_DEPAY (object);
147
148   gst_rtp_jpeg_depay_reset (rtpjpegdepay);
149
150   g_object_unref (rtpjpegdepay->adapter);
151   rtpjpegdepay->adapter = NULL;
152
153   G_OBJECT_CLASS (parent_class)->finalize (object);
154 }
155
156 static const int zigzag[] = {
157   0, 1, 8, 16, 9, 2, 3, 10,
158   17, 24, 32, 25, 18, 11, 4, 5,
159   12, 19, 26, 33, 40, 48, 41, 34,
160   27, 20, 13, 6, 7, 14, 21, 28,
161   35, 42, 49, 56, 57, 50, 43, 36,
162   29, 22, 15, 23, 30, 37, 44, 51,
163   58, 59, 52, 45, 38, 31, 39, 46,
164   53, 60, 61, 54, 47, 55, 62, 63
165 };
166
167 /*
168  * Table K.1 from JPEG spec.
169  */
170 static const int jpeg_luma_quantizer[64] = {
171   16, 11, 10, 16, 24, 40, 51, 61,
172   12, 12, 14, 19, 26, 58, 60, 55,
173   14, 13, 16, 24, 40, 57, 69, 56,
174   14, 17, 22, 29, 51, 87, 80, 62,
175   18, 22, 37, 56, 68, 109, 103, 77,
176   24, 35, 55, 64, 81, 104, 113, 92,
177   49, 64, 78, 87, 103, 121, 120, 101,
178   72, 92, 95, 98, 112, 100, 103, 99
179 };
180
181 /*
182  * Table K.2 from JPEG spec.
183  */
184 static const int jpeg_chroma_quantizer[64] = {
185   17, 18, 24, 47, 99, 99, 99, 99,
186   18, 21, 26, 66, 99, 99, 99, 99,
187   24, 26, 56, 99, 99, 99, 99, 99,
188   47, 66, 99, 99, 99, 99, 99, 99,
189   99, 99, 99, 99, 99, 99, 99, 99,
190   99, 99, 99, 99, 99, 99, 99, 99,
191   99, 99, 99, 99, 99, 99, 99, 99,
192   99, 99, 99, 99, 99, 99, 99, 99
193 };
194
195 /* Call MakeTables with the Q factor and a guint8[128] return array
196  */
197 static void
198 MakeTables (GstRtpJPEGDepay * rtpjpegdepay, gint Q, guint8 qtable[128])
199 {
200   gint i;
201   guint factor;
202
203   factor = CLAMP (Q, 1, 99);
204
205   if (Q < 50)
206     Q = 5000 / factor;
207   else
208     Q = 200 - factor * 2;
209
210   for (i = 0; i < 64; i++) {
211     gint lq = (jpeg_luma_quantizer[zigzag[i]] * Q + 50) / 100;
212     gint cq = (jpeg_chroma_quantizer[zigzag[i]] * Q + 50) / 100;
213
214     /* Limit the quantizers to 1 <= q <= 255 */
215     qtable[i] = CLAMP (lq, 1, 255);
216     qtable[i + 64] = CLAMP (cq, 1, 255);
217   }
218 }
219
220 static const guint8 lum_dc_codelens[] = {
221   0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
222 };
223
224 static const guint8 lum_dc_symbols[] = {
225   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
226 };
227
228 static const guint8 lum_ac_codelens[] = {
229   0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
230 };
231
232 static const guint8 lum_ac_symbols[] = {
233   0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
234   0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
235   0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
236   0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
237   0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
238   0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
239   0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
240   0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
241   0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
242   0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
243   0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
244   0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
245   0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
246   0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
247   0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
248   0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
249   0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
250   0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
251   0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
252   0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
253   0xf9, 0xfa
254 };
255
256 static const guint8 chm_dc_codelens[] = {
257   0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
258 };
259
260 static const guint8 chm_dc_symbols[] = {
261   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
262 };
263
264 static const guint8 chm_ac_codelens[] = {
265   0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
266 };
267
268 static const guint8 chm_ac_symbols[] = {
269   0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
270   0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
271   0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
272   0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
273   0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
274   0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
275   0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
276   0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
277   0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
278   0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
279   0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
280   0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
281   0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
282   0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
283   0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
284   0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
285   0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
286   0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
287   0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
288   0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
289   0xf9, 0xfa
290 };
291
292 static guint8 *
293 MakeQuantHeader (guint8 * p, guint8 * qt, gint size, gint tableNo)
294 {
295   *p++ = 0xff;
296   *p++ = 0xdb;                  /* DQT */
297   *p++ = 0;                     /* length msb */
298   *p++ = size + 3;              /* length lsb */
299   *p++ = tableNo;
300   memcpy (p, qt, size);
301
302   return (p + size);
303 }
304
305 static guint8 *
306 MakeHuffmanHeader (guint8 * p, const guint8 * codelens, int ncodes,
307     const guint8 * symbols, int nsymbols, int tableNo, int tableClass)
308 {
309   *p++ = 0xff;
310   *p++ = 0xc4;                  /* DHT */
311   *p++ = 0;                     /* length msb */
312   *p++ = 3 + ncodes + nsymbols; /* length lsb */
313   *p++ = (tableClass << 4) | tableNo;
314   memcpy (p, codelens, ncodes);
315   p += ncodes;
316   memcpy (p, symbols, nsymbols);
317   p += nsymbols;
318
319   return (p);
320 }
321
322 static guint8 *
323 MakeDRIHeader (guint8 * p, guint16 dri)
324 {
325   *p++ = 0xff;
326   *p++ = 0xdd;                  /* DRI */
327   *p++ = 0x0;                   /* length msb */
328   *p++ = 4;                     /* length lsb */
329   *p++ = dri >> 8;              /* dri msb */
330   *p++ = dri & 0xff;            /* dri lsb */
331
332   return (p);
333 }
334
335 /*
336  *  Arguments:
337  *    type, width, height: as supplied in RTP/JPEG header
338  *    qt: quantization tables as either derived from
339  *        the Q field using MakeTables() or as specified
340  *        in section 4.2.
341  *    dri: restart interval in MCUs, or 0 if no restarts.
342  *
343  *    p: pointer to return area
344  *
345  *  Return value:
346  *    The length of the generated headers.
347  *
348  *    Generate a frame and scan headers that can be prepended to the
349  *    RTP/JPEG data payload to produce a JPEG compressed image in
350  *    interchange format (except for possible trailing garbage and
351  *    absence of an EOI marker to terminate the scan).
352  */
353 static guint
354 MakeHeaders (guint8 * p, int type, int width, int height, guint8 * qt,
355     guint precision, guint16 dri)
356 {
357   guint8 *start = p;
358   gint size;
359
360   *p++ = 0xff;
361   *p++ = 0xd8;                  /* SOI */
362
363   size = ((precision & 1) ? 128 : 64);
364   p = MakeQuantHeader (p, qt, size, 0);
365   qt += size;
366
367   size = ((precision & 2) ? 128 : 64);
368   p = MakeQuantHeader (p, qt, size, 1);
369   qt += size;
370
371   if (dri != 0)
372     p = MakeDRIHeader (p, dri);
373
374   *p++ = 0xff;
375   *p++ = 0xc0;                  /* SOF */
376   *p++ = 0;                     /* length msb */
377   *p++ = 17;                    /* length lsb */
378   *p++ = 8;                     /* 8-bit precision */
379   *p++ = height >> 8;           /* height msb */
380   *p++ = height;                /* height lsb */
381   *p++ = width >> 8;            /* width msb */
382   *p++ = width;                 /* width lsb */
383   *p++ = 3;                     /* number of components */
384   *p++ = 0;                     /* comp 0 */
385   if ((type & 0x3f) == 0)
386     *p++ = 0x21;                /* hsamp = 2, vsamp = 1 */
387   else
388     *p++ = 0x22;                /* hsamp = 2, vsamp = 2 */
389   *p++ = 0;                     /* quant table 0 */
390   *p++ = 1;                     /* comp 1 */
391   *p++ = 0x11;                  /* hsamp = 1, vsamp = 1 */
392   *p++ = 1;                     /* quant table 1 */
393   *p++ = 2;                     /* comp 2 */
394   *p++ = 0x11;                  /* hsamp = 1, vsamp = 1 */
395   *p++ = 1;                     /* quant table 1 */
396
397   p = MakeHuffmanHeader (p, lum_dc_codelens,
398       sizeof (lum_dc_codelens), lum_dc_symbols, sizeof (lum_dc_symbols), 0, 0);
399   p = MakeHuffmanHeader (p, lum_ac_codelens,
400       sizeof (lum_ac_codelens), lum_ac_symbols, sizeof (lum_ac_symbols), 0, 1);
401   p = MakeHuffmanHeader (p, chm_dc_codelens,
402       sizeof (chm_dc_codelens), chm_dc_symbols, sizeof (chm_dc_symbols), 1, 0);
403   p = MakeHuffmanHeader (p, chm_ac_codelens,
404       sizeof (chm_ac_codelens), chm_ac_symbols, sizeof (chm_ac_symbols), 1, 1);
405
406   *p++ = 0xff;
407   *p++ = 0xda;                  /* SOS */
408   *p++ = 0;                     /* length msb */
409   *p++ = 12;                    /* length lsb */
410   *p++ = 3;                     /* 3 components */
411   *p++ = 0;                     /* comp 0 */
412   *p++ = 0;                     /* huffman table 0 */
413   *p++ = 1;                     /* comp 1 */
414   *p++ = 0x11;                  /* huffman table 1 */
415   *p++ = 2;                     /* comp 2 */
416   *p++ = 0x11;                  /* huffman table 1 */
417   *p++ = 0;                     /* first DCT coeff */
418   *p++ = 63;                    /* last DCT coeff */
419   *p++ = 0;                     /* sucessive approx. */
420
421   return (p - start);
422 };
423
424 static gboolean
425 gst_rtp_jpeg_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
426 {
427   GstRtpJPEGDepay *rtpjpegdepay;
428   GstStructure *structure;
429   gint clock_rate;
430   const gchar *media_attr;
431
432   rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
433
434   structure = gst_caps_get_structure (caps, 0);
435   GST_DEBUG_OBJECT (rtpjpegdepay, "Caps set: %" GST_PTR_FORMAT, caps);
436
437   if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
438     clock_rate = 90000;
439   depayload->clock_rate = clock_rate;
440
441   /* reset defaults */
442   rtpjpegdepay->width = 0;
443   rtpjpegdepay->height = 0;
444   rtpjpegdepay->media_width = 0;
445   rtpjpegdepay->media_height = 0;
446   rtpjpegdepay->frate_num = 0;
447   rtpjpegdepay->frate_denom = 1;
448
449   /* check for optional SDP attributes */
450   if ((media_attr = gst_structure_get_string (structure, "x-dimensions"))) {
451     gint w, h;
452
453     if (sscanf (media_attr, "%d,%d", &w, &h) == 2) {
454       rtpjpegdepay->media_width = w;
455       rtpjpegdepay->media_height = h;
456     }
457   }
458
459   /* try to get a framerate */
460   media_attr = gst_structure_get_string (structure, "a-framerate");
461   if (!media_attr)
462     media_attr = gst_structure_get_string (structure, "x-framerate");
463
464   if (media_attr) {
465     GValue src = { 0 };
466     GValue dest = { 0 };
467     gchar *s;
468
469     /* canonicalise floating point string so we can handle framerate strings
470      * in the form "24.930" or "24,930" irrespective of the current locale */
471     s = g_strdup (media_attr);
472     g_strdelimit (s, ",", '.');
473
474     /* convert the float to a fraction */
475     g_value_init (&src, G_TYPE_DOUBLE);
476     g_value_set_double (&src, g_ascii_strtod (s, NULL));
477     g_value_init (&dest, GST_TYPE_FRACTION);
478     g_value_transform (&src, &dest);
479
480     rtpjpegdepay->frate_num = gst_value_get_fraction_numerator (&dest);
481     rtpjpegdepay->frate_denom = gst_value_get_fraction_denominator (&dest);
482
483     g_free (s);
484   }
485
486   return TRUE;
487 }
488
489 static GstBuffer *
490 gst_rtp_jpeg_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
491 {
492   GstRtpJPEGDepay *rtpjpegdepay;
493   GstBuffer *outbuf;
494   gint payload_len, header_len;
495   guint8 *payload;
496   guint frag_offset;
497   gint Q;
498   guint type, width, height;
499   guint16 dri, precision, length;
500   guint8 *qtable;
501   GstRTPBuffer rtp = { NULL };
502
503   rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
504
505   if (GST_BUFFER_IS_DISCONT (buf)) {
506     gst_adapter_clear (rtpjpegdepay->adapter);
507     rtpjpegdepay->discont = TRUE;
508   }
509
510   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
511   payload_len = gst_rtp_buffer_get_payload_len (&rtp);
512
513   if (payload_len < 8)
514     goto empty_packet;
515
516   payload = gst_rtp_buffer_get_payload (&rtp);
517   header_len = 0;
518
519   /*  0                   1                   2                   3
520    *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
521    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522    * | Type-specific |              Fragment Offset                  |
523    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
524    * |      Type     |       Q       |     Width     |     Height    |
525    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
526    */
527   frag_offset = (payload[1] << 16) | (payload[2] << 8) | payload[3];
528   type = payload[4];
529   Q = payload[5];
530   width = payload[6] * 8;
531   height = payload[7] * 8;
532
533   /* allow frame dimensions > 2040, passed in SDP session or media attributes
534    * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
535   if (!width)
536     width = rtpjpegdepay->media_width;
537
538   if (!height)
539     height = rtpjpegdepay->media_height;
540
541   if (width == 0 || height == 0)
542     goto invalid_dimension;
543
544   GST_DEBUG_OBJECT (rtpjpegdepay, "frag %u, type %u, Q %d, width %u, height %u",
545       frag_offset, type, Q, width, height);
546
547   header_len += 8;
548   payload += 8;
549   payload_len -= 8;
550
551   dri = 0;
552   if (type > 63) {
553     if (payload_len < 4)
554       goto empty_packet;
555
556     /*  0                   1                   2                   3
557      *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
558      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559      * |       Restart Interval        |F|L|       Restart Count       |
560      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561      */
562     dri = (payload[0] << 8) | payload[1];
563
564     GST_DEBUG_OBJECT (rtpjpegdepay, "DRI %" G_GUINT16_FORMAT, dri);
565
566     payload += 4;
567     header_len += 4;
568     payload_len -= 4;
569   }
570
571   if (Q >= 128 && frag_offset == 0) {
572     if (payload_len < 4)
573       goto empty_packet;
574
575     /*  0                   1                   2                   3
576      *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
577      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
578      * |      MBZ      |   Precision   |             Length            |
579      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
580      * |                    Quantization Table Data                    |
581      * |                              ...                              |
582      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583      */
584     precision = payload[1];
585     length = (payload[2] << 8) | payload[3];
586
587     GST_DEBUG_OBJECT (rtpjpegdepay, "precision %04x, length %" G_GUINT16_FORMAT,
588         precision, length);
589
590     if (Q == 255 && length == 0)
591       goto empty_packet;
592
593     payload += 4;
594     header_len += 4;
595     payload_len -= 4;
596
597     if (length > payload_len)
598       goto empty_packet;
599
600     if (length > 0)
601       qtable = payload;
602     else
603       qtable = rtpjpegdepay->qtables[Q];
604
605     payload += length;
606     header_len += length;
607     payload_len -= length;
608   } else {
609     length = 0;
610     qtable = NULL;
611     precision = 0;
612   }
613
614   if (frag_offset == 0) {
615     GstMapInfo map;
616     guint size;
617
618     if (rtpjpegdepay->width != width || rtpjpegdepay->height != height) {
619       GstCaps *outcaps;
620
621       outcaps =
622           gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
623           rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
624           G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
625       gst_pad_set_caps (depayload->srcpad, outcaps);
626       gst_caps_unref (outcaps);
627
628       rtpjpegdepay->width = width;
629       rtpjpegdepay->height = height;
630     }
631
632     GST_LOG_OBJECT (rtpjpegdepay, "first packet, length %" G_GUINT16_FORMAT,
633         length);
634
635     /* first packet */
636     if (length == 0) {
637       if (Q < 128) {
638         /* no quant table, see if we have one cached */
639         qtable = rtpjpegdepay->qtables[Q];
640         if (!qtable) {
641           GST_DEBUG_OBJECT (rtpjpegdepay, "making Q %d table", Q);
642           /* make and cache the table */
643           qtable = g_new (guint8, 128);
644           MakeTables (rtpjpegdepay, Q, qtable);
645           rtpjpegdepay->qtables[Q] = qtable;
646         } else {
647           GST_DEBUG_OBJECT (rtpjpegdepay, "using cached table for Q %d", Q);
648         }
649         /* all 8 bit quantizers */
650         precision = 0;
651       } else {
652         if (!qtable)
653           goto no_qtable;
654       }
655     }
656     /* max header length, should be big enough */
657     outbuf = gst_buffer_new_and_alloc (1000);
658     gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
659     size = MakeHeaders (map.data, type, width, height, qtable, precision, dri);
660     gst_buffer_unmap (outbuf, &map);
661     gst_buffer_resize (outbuf, 0, size);
662
663     GST_DEBUG_OBJECT (rtpjpegdepay, "pushing %u bytes of header", size);
664
665     gst_adapter_push (rtpjpegdepay->adapter, outbuf);
666   }
667
668   /* take JPEG data, push in the adapter */
669   GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
670   outbuf = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len, -1);
671   gst_adapter_push (rtpjpegdepay->adapter, outbuf);
672   outbuf = NULL;
673
674   if (gst_rtp_buffer_get_marker (&rtp)) {
675     guint avail;
676     guint8 end[2];
677     GstMapInfo map;
678
679     /* last buffer take all data out of the adapter */
680     avail = gst_adapter_available (rtpjpegdepay->adapter);
681     GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");
682
683     /* take the last bytes of the jpeg data to see if there is an EOI
684      * marker */
685     gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);
686
687     if (end[0] != 0xff && end[1] != 0xd9) {
688       GST_DEBUG_OBJECT (rtpjpegdepay, "no EOI marker, adding one");
689
690       /* no EOI marker, add one */
691       outbuf = gst_buffer_new_and_alloc (2);
692       gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
693       map.data[0] = 0xff;
694       map.data[1] = 0xd9;
695       gst_buffer_unmap (outbuf, &map);
696
697       gst_adapter_push (rtpjpegdepay->adapter, outbuf);
698       avail += 2;
699     }
700     outbuf = gst_adapter_take_buffer (rtpjpegdepay->adapter, avail);
701
702     if (rtpjpegdepay->discont) {
703       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
704       rtpjpegdepay->discont = FALSE;
705     }
706
707     GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
708   }
709
710   gst_rtp_buffer_unmap (&rtp);
711
712   return outbuf;
713
714   /* ERRORS */
715 empty_packet:
716   {
717     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
718         ("Empty Payload."), (NULL));
719     gst_rtp_buffer_unmap (&rtp);
720     return NULL;
721   }
722 invalid_dimension:
723   {
724     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
725         ("Invalid Dimension %dx%d.", width, height), (NULL));
726     gst_rtp_buffer_unmap (&rtp);
727     return NULL;
728   }
729 no_qtable:
730   {
731     GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
732     gst_rtp_buffer_unmap (&rtp);
733     return NULL;
734   }
735 }
736
737
738 static GstStateChangeReturn
739 gst_rtp_jpeg_depay_change_state (GstElement * element,
740     GstStateChange transition)
741 {
742   GstRtpJPEGDepay *rtpjpegdepay;
743   GstStateChangeReturn ret;
744
745   rtpjpegdepay = GST_RTP_JPEG_DEPAY (element);
746
747   switch (transition) {
748     case GST_STATE_CHANGE_READY_TO_PAUSED:
749       gst_rtp_jpeg_depay_reset (rtpjpegdepay);
750       break;
751     default:
752       break;
753   }
754
755   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
756
757   switch (transition) {
758     case GST_STATE_CHANGE_PAUSED_TO_READY:
759       break;
760     default:
761       break;
762   }
763   return ret;
764 }
765
766
767 gboolean
768 gst_rtp_jpeg_depay_plugin_init (GstPlugin * plugin)
769 {
770   return gst_element_register (plugin, "rtpjpegdepay",
771       GST_RANK_SECONDARY, GST_TYPE_RTP_JPEG_DEPAY);
772 }