Merge commit '38516ad367128d83f9e156529018adb4433cd328' 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_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_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   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 /*
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 (GstRTPBaseDepayload * 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 (GstRTPBaseDepayload * 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   GstRTPBuffer rtp = { NULL };
492
493   rtpjpegdepay = GST_RTP_JPEG_DEPAY (depayload);
494
495   if (GST_BUFFER_IS_DISCONT (buf)) {
496     gst_adapter_clear (rtpjpegdepay->adapter);
497     rtpjpegdepay->discont = TRUE;
498   }
499
500   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
501   payload_len = gst_rtp_buffer_get_payload_len (&rtp);
502
503   if (payload_len < 8)
504     goto empty_packet;
505
506   payload = gst_rtp_buffer_get_payload (&rtp);
507   header_len = 0;
508
509   /*  0                   1                   2                   3
510    *  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
511    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
512    * | Type-specific |              Fragment Offset                  |
513    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514    * |      Type     |       Q       |     Width     |     Height    |
515    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516    */
517   frag_offset = (payload[1] << 16) | (payload[2] << 8) | payload[3];
518   type = payload[4];
519   Q = payload[5];
520   width = payload[6] * 8;
521   height = payload[7] * 8;
522
523   /* allow frame dimensions > 2040, passed in SDP session or media attributes
524    * from gstrtspsrc.c (gst_rtspsrc_sdp_attributes_to_caps), or in caps */
525   if (!width)
526     width = rtpjpegdepay->media_width;
527
528   if (!height)
529     height = rtpjpegdepay->media_height;
530
531   if (width == 0 || height == 0)
532     goto invalid_dimension;
533
534   GST_DEBUG_OBJECT (rtpjpegdepay, "frag %u, type %u, Q %d, width %u, height %u",
535       frag_offset, type, Q, width, height);
536
537   header_len += 8;
538   payload += 8;
539   payload_len -= 8;
540
541   dri = 0;
542   if (type > 63) {
543     if (payload_len < 4)
544       goto empty_packet;
545
546     /*  0                   1                   2                   3
547      *  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
548      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
549      * |       Restart Interval        |F|L|       Restart Count       |
550      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
551      */
552     dri = (payload[0] << 8) | payload[1];
553
554     GST_DEBUG_OBJECT (rtpjpegdepay, "DRI %" G_GUINT16_FORMAT, dri);
555
556     payload += 4;
557     header_len += 4;
558     payload_len -= 4;
559   }
560
561   if (Q >= 128 && frag_offset == 0) {
562     if (payload_len < 4)
563       goto empty_packet;
564
565     /*  0                   1                   2                   3
566      *  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
567      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
568      * |      MBZ      |   Precision   |             Length            |
569      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570      * |                    Quantization Table Data                    |
571      * |                              ...                              |
572      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573      */
574     precision = payload[1];
575     length = (payload[2] << 8) | payload[3];
576
577     GST_DEBUG_OBJECT (rtpjpegdepay, "precision %04x, length %" G_GUINT16_FORMAT,
578         precision, length);
579
580     if (Q == 255 && length == 0)
581       goto empty_packet;
582
583     payload += 4;
584     header_len += 4;
585     payload_len -= 4;
586
587     if (length > payload_len)
588       goto empty_packet;
589
590     if (length > 0)
591       qtable = payload;
592     else
593       qtable = rtpjpegdepay->qtables[Q];
594
595     payload += length;
596     header_len += length;
597     payload_len -= length;
598   } else {
599     length = 0;
600     qtable = NULL;
601     precision = 0;
602   }
603
604   if (frag_offset == 0) {
605     GstMapInfo map;
606     guint size;
607
608     if (rtpjpegdepay->width != width || rtpjpegdepay->height != height) {
609       GstCaps *outcaps;
610
611       outcaps =
612           gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION,
613           rtpjpegdepay->frate_num, rtpjpegdepay->frate_denom, "width",
614           G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
615       gst_pad_set_caps (depayload->srcpad, outcaps);
616       gst_caps_unref (outcaps);
617
618       rtpjpegdepay->width = width;
619       rtpjpegdepay->height = height;
620     }
621
622     GST_LOG_OBJECT (rtpjpegdepay, "first packet, length %" G_GUINT16_FORMAT,
623         length);
624
625     /* first packet */
626     if (length == 0) {
627       if (Q < 128) {
628         /* no quant table, see if we have one cached */
629         qtable = rtpjpegdepay->qtables[Q];
630         if (!qtable) {
631           GST_DEBUG_OBJECT (rtpjpegdepay, "making Q %d table", Q);
632           /* make and cache the table */
633           qtable = g_new (guint8, 128);
634           MakeTables (rtpjpegdepay, Q, qtable);
635           rtpjpegdepay->qtables[Q] = qtable;
636         } else {
637           GST_DEBUG_OBJECT (rtpjpegdepay, "using cached table for Q %d", Q);
638         }
639         /* all 8 bit quantizers */
640         precision = 0;
641       } else {
642         if (!qtable)
643           goto no_qtable;
644       }
645     }
646     /* max header length, should be big enough */
647     outbuf = gst_buffer_new_and_alloc (1000);
648     gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
649     size = MakeHeaders (map.data, type, width, height, qtable, precision, dri);
650     gst_buffer_unmap (outbuf, &map);
651     gst_buffer_resize (outbuf, 0, size);
652
653     GST_DEBUG_OBJECT (rtpjpegdepay, "pushing %u bytes of header", size);
654
655     gst_adapter_push (rtpjpegdepay->adapter, outbuf);
656   }
657
658   /* take JPEG data, push in the adapter */
659   GST_DEBUG_OBJECT (rtpjpegdepay, "pushing data at offset %d", header_len);
660   outbuf = gst_rtp_buffer_get_payload_subbuffer (&rtp, header_len, -1);
661   gst_adapter_push (rtpjpegdepay->adapter, outbuf);
662   outbuf = NULL;
663
664   if (gst_rtp_buffer_get_marker (&rtp)) {
665     guint avail;
666     guint8 end[2];
667     GstMapInfo map;
668
669     /* last buffer take all data out of the adapter */
670     avail = gst_adapter_available (rtpjpegdepay->adapter);
671     GST_DEBUG_OBJECT (rtpjpegdepay, "marker set, last buffer");
672
673     /* take the last bytes of the jpeg data to see if there is an EOI
674      * marker */
675     gst_adapter_copy (rtpjpegdepay->adapter, end, avail - 2, 2);
676
677     if (end[0] != 0xff && end[1] != 0xd9) {
678       GST_DEBUG_OBJECT (rtpjpegdepay, "no EOI marker, adding one");
679
680       /* no EOI marker, add one */
681       outbuf = gst_buffer_new_and_alloc (2);
682       gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
683       map.data[0] = 0xff;
684       map.data[1] = 0xd9;
685       gst_buffer_unmap (outbuf, &map);
686
687       gst_adapter_push (rtpjpegdepay->adapter, outbuf);
688       avail += 2;
689     }
690     outbuf = gst_adapter_take_buffer (rtpjpegdepay->adapter, avail);
691
692     if (rtpjpegdepay->discont) {
693       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
694       rtpjpegdepay->discont = FALSE;
695     }
696
697     GST_DEBUG_OBJECT (rtpjpegdepay, "returning %u bytes", avail);
698   }
699
700   gst_rtp_buffer_unmap (&rtp);
701
702   return outbuf;
703
704   /* ERRORS */
705 empty_packet:
706   {
707     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, DECODE,
708         ("Empty Payload."), (NULL));
709     gst_rtp_buffer_unmap (&rtp);
710     return NULL;
711   }
712 invalid_dimension:
713   {
714     GST_ELEMENT_WARNING (rtpjpegdepay, STREAM, FORMAT,
715         ("Invalid Dimension %dx%d.", width, height), (NULL));
716     gst_rtp_buffer_unmap (&rtp);
717     return NULL;
718   }
719 no_qtable:
720   {
721     GST_WARNING_OBJECT (rtpjpegdepay, "no qtable");
722     gst_rtp_buffer_unmap (&rtp);
723     return NULL;
724   }
725 }
726
727
728 static GstStateChangeReturn
729 gst_rtp_jpeg_depay_change_state (GstElement * element,
730     GstStateChange transition)
731 {
732   GstRtpJPEGDepay *rtpjpegdepay;
733   GstStateChangeReturn ret;
734
735   rtpjpegdepay = GST_RTP_JPEG_DEPAY (element);
736
737   switch (transition) {
738     case GST_STATE_CHANGE_READY_TO_PAUSED:
739       gst_rtp_jpeg_depay_reset (rtpjpegdepay);
740       break;
741     default:
742       break;
743   }
744
745   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
746
747   switch (transition) {
748     case GST_STATE_CHANGE_PAUSED_TO_READY:
749       break;
750     default:
751       break;
752   }
753   return ret;
754 }
755
756
757 gboolean
758 gst_rtp_jpeg_depay_plugin_init (GstPlugin * plugin)
759 {
760   return gst_element_register (plugin, "rtpjpegdepay",
761       GST_RANK_SECONDARY, GST_TYPE_RTP_JPEG_DEPAY);
762 }