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