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