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