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