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