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