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