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