Merge branch 'plugin-move-rtp-opus'
[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_pad_template (gstelement_class,
98       gst_static_pad_template_get (&gst_rtp_jpeg_depay_src_template));
99   gst_element_class_add_pad_template (gstelement_class,
100       gst_static_pad_template_get (&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;                     /* sucessive 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   /* allow frame dimensions > 2040, passed in SDP session or media attributes
535    * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
536   if (!width)
537     width = rtpjpegdepay->media_width;
538
539   if (!height)
540     height = rtpjpegdepay->media_height;
541
542   if (width == 0 || height == 0)
543     goto invalid_dimension;
544
545   GST_DEBUG_OBJECT (rtpjpegdepay, "frag %u, type %u, Q %d, width %u, height %u",
546       frag_offset, type, Q, width, height);
547
548   header_len += 8;
549   payload += 8;
550   payload_len -= 8;
551
552   dri = 0;
553   if (type > 63) {
554     if (payload_len < 4)
555       goto empty_packet;
556
557     /*  0                   1                   2                   3
558      *  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
559      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
560      * |       Restart Interval        |F|L|       Restart Count       |
561      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
562      */
563     dri = (payload[0] << 8) | payload[1];
564
565     GST_DEBUG_OBJECT (rtpjpegdepay, "DRI %" G_GUINT16_FORMAT, dri);
566
567     payload += 4;
568     header_len += 4;
569     payload_len -= 4;
570   }
571
572   if (Q >= 128 && frag_offset == 0) {
573     if (payload_len < 4)
574       goto empty_packet;
575
576     /*  0                   1                   2                   3
577      *  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
578      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
579      * |      MBZ      |   Precision   |             Length            |
580      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581      * |                    Quantization Table Data                    |
582      * |                              ...                              |
583      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
584      */
585     precision = payload[1];
586     length = (payload[2] << 8) | payload[3];
587
588     GST_DEBUG_OBJECT (rtpjpegdepay, "precision %04x, length %" G_GUINT16_FORMAT,
589         precision, length);
590
591     if (Q == 255 && length == 0)
592       goto empty_packet;
593
594     payload += 4;
595     header_len += 4;
596     payload_len -= 4;
597
598     if (length > payload_len)
599       goto empty_packet;
600
601     if (length > 0)
602       qtable = payload;
603     else
604       qtable = rtpjpegdepay->qtables[Q];
605
606     payload += length;
607     header_len += length;
608     payload_len -= length;
609   } else {
610     length = 0;
611     qtable = NULL;
612     precision = 0;
613   }
614
615   if (frag_offset == 0) {
616     GstMapInfo map;
617     guint size;
618
619     if (rtpjpegdepay->width != width || rtpjpegdepay->height != height) {
620       GstCaps *outcaps;
621
622       outcaps =
623           gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
624           rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
625           G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
626       gst_pad_set_caps (depayload->srcpad, outcaps);
627       gst_caps_unref (outcaps);
628
629       rtpjpegdepay->width = width;
630       rtpjpegdepay->height = height;
631     }
632
633     GST_LOG_OBJECT (rtpjpegdepay, "first packet, length %" G_GUINT16_FORMAT,
634         length);
635
636     /* first packet */
637     if (length == 0) {
638       if (Q < 128) {
639         /* no quant table, see if we have one cached */
640         qtable = rtpjpegdepay->qtables[Q];
641         if (!qtable) {
642           GST_DEBUG_OBJECT (rtpjpegdepay, "making Q %d table", Q);
643           /* make and cache the table */
644           qtable = g_new (guint8, 128);
645           MakeTables (rtpjpegdepay, Q, qtable);
646           rtpjpegdepay->qtables[Q] = qtable;
647         } else {
648           GST_DEBUG_OBJECT (rtpjpegdepay, "using cached table for Q %d", Q);
649         }
650         /* all 8 bit quantizers */
651         precision = 0;
652       } else {
653         if (!qtable)
654           goto no_qtable;
655       }
656     }
657
658     /* I think we can get here with a NULL qtable, so make sure we don't
659        go dereferencing it in MakeHeaders if we do */
660     if (!qtable)
661       goto no_qtable;
662
663     /* max header length, should be big enough */
664     outbuf = gst_buffer_new_and_alloc (1000);
665     gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
666     size = MakeHeaders (map.data, type, width, height, qtable, precision, dri);
667     gst_buffer_unmap (outbuf, &map);
668     gst_buffer_resize (outbuf, 0, size);
669
670     GST_DEBUG_OBJECT (rtpjpegdepay, "pushing %u bytes of header", size);
671
672     gst_adapter_push (rtpjpegdepay->adapter, outbuf);
673   }
674
675   /* take JPEG data, push in the adapter */
676   GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
677   outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, header_len, -1);
678   gst_adapter_push (rtpjpegdepay->adapter, outbuf);
679   outbuf = NULL;
680
681   if (gst_rtp_buffer_get_marker (rtp)) {
682     guint avail;
683     guint8 end[2];
684     GstMapInfo map;
685
686     /* last buffer take all data out of the adapter */
687     avail = gst_adapter_available (rtpjpegdepay->adapter);
688     GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");
689
690     if (avail < 2)
691       goto invalid_packet;
692
693     /* take the last bytes of the jpeg data to see if there is an EOI
694      * marker */
695     gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);
696
697     if (end[0] != 0xff && end[1] != 0xd9) {
698       GST_DEBUG_OBJECT (rtpjpegdepay, "no EOI marker, adding one");
699
700       /* no EOI marker, add one */
701       outbuf = gst_buffer_new_and_alloc (2);
702       gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
703       map.data[0] = 0xff;
704       map.data[1] = 0xd9;
705       gst_buffer_unmap (outbuf, &map);
706
707       gst_adapter_push (rtpjpegdepay->adapter, outbuf);
708       avail += 2;
709     }
710     outbuf = gst_adapter_take_buffer (rtpjpegdepay->adapter, avail);
711
712     if (rtpjpegdepay->discont) {
713       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
714       rtpjpegdepay->discont = FALSE;
715     }
716
717     gst_rtp_drop_meta (GST_ELEMENT_CAST (rtpjpegdepay), outbuf,
718         g_quark_from_static_string (GST_META_TAG_VIDEO_STR));
719
720     GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
721   }
722
723   return outbuf;
724
725   /* ERRORS */
726 empty_packet:
727   {
728     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
729         ("Empty Payload."), (NULL));
730     return NULL;
731   }
732 invalid_dimension:
733   {
734     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
735         ("Invalid Dimension %dx%d.", width, height), (NULL));
736     return NULL;
737   }
738 no_qtable:
739   {
740     GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
741     return NULL;
742   }
743 invalid_packet:
744   {
745     GST_WARNING_OBJECT (rtpjpegdepay, "invalid packet");
746     gst_adapter_flush (rtpjpegdepay->adapter,
747         gst_adapter_available (rtpjpegdepay->adapter));
748     return NULL;
749   }
750 }
751
752
753 static GstStateChangeReturn
754 gst_rtp_jpeg_depay_change_state (GstElement * element,
755     GstStateChange transition)
756 {
757   GstRtpJPEGDepay *rtpjpegdepay;
758   GstStateChangeReturn ret;
759
760   rtpjpegdepay = GST_RTP_JPEG_DEPAY (element);
761
762   switch (transition) {
763     case GST_STATE_CHANGE_READY_TO_PAUSED:
764       gst_rtp_jpeg_depay_reset (rtpjpegdepay);
765       break;
766     default:
767       break;
768   }
769
770   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
771
772   switch (transition) {
773     case GST_STATE_CHANGE_PAUSED_TO_READY:
774       break;
775     default:
776       break;
777   }
778   return ret;
779 }
780
781
782 gboolean
783 gst_rtp_jpeg_depay_plugin_init (GstPlugin * plugin)
784 {
785   return gst_element_register (plugin, "rtpjpegdepay",
786       GST_RANK_SECONDARY, GST_TYPE_RTP_JPEG_DEPAY);
787 }