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