typefinding: fix AC-3 typefinding so that it actually checks for a second frame
[platform/upstream/gstreamer.git] / gst / typefind / gsttypefindfunctions.c
1 /* GStreamer
2  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  * Copyright (C) 2005-2009 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  *
6  * gsttypefindfunctions.c: collection of various typefind functions
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <glib.h>
29 #include <glib/gprintf.h>
30
31 /* don't want to add gio xdgmime typefinder if gio was disabled via configure */
32 #ifdef HAVE_GIO
33 #include <gio/gio.h>
34 #define USE_GIO
35 #endif
36
37 #include <gst/gsttypefind.h>
38 #include <gst/gstelement.h>
39 #include <gst/gstversion.h>
40 #include <gst/gstinfo.h>
41 #include <gst/gstutils.h>
42
43 #include <stdio.h>
44 #include <string.h>
45 #include <ctype.h>
46
47 #include "gstaacutil.h"
48
49 GST_DEBUG_CATEGORY_STATIC (type_find_debug);
50 #define GST_CAT_DEFAULT type_find_debug
51
52 /* DataScanCtx: helper for typefind functions that scan through data
53  * step-by-step, to avoid doing a peek at each and every offset */
54
55 #define DATA_SCAN_CTX_CHUNK_SIZE 4096
56
57 typedef struct
58 {
59   guint64 offset;
60   const guint8 *data;
61   gint size;
62 } DataScanCtx;
63
64 static inline void
65 data_scan_ctx_advance (GstTypeFind * tf, DataScanCtx * c, guint bytes_to_skip)
66 {
67   c->offset += bytes_to_skip;
68   if (G_LIKELY (c->size > bytes_to_skip)) {
69     c->size -= bytes_to_skip;
70     c->data += bytes_to_skip;
71   } else {
72     c->data += c->size;
73     c->size = 0;
74   }
75 }
76
77 static inline gboolean
78 data_scan_ctx_ensure_data (GstTypeFind * tf, DataScanCtx * c, gint min_len)
79 {
80   const guint8 *data;
81   guint64 len;
82   guint chunk_len = MAX (DATA_SCAN_CTX_CHUNK_SIZE, min_len);
83
84   if (G_LIKELY (c->size >= min_len))
85     return TRUE;
86
87   data = gst_type_find_peek (tf, c->offset, chunk_len);
88   if (G_LIKELY (data != NULL)) {
89     c->data = data;
90     c->size = chunk_len;
91     return TRUE;
92   }
93
94   /* if there's less than our chunk size, try to get as much as we can, but
95    * always at least min_len bytes (we might be typefinding the first buffer
96    * of the stream and not have as much data available as we'd like) */
97   len = gst_type_find_get_length (tf);
98   if (len > 0) {
99     len = CLAMP (len - c->offset, min_len, chunk_len);
100   } else {
101     len = min_len;
102   }
103
104   data = gst_type_find_peek (tf, c->offset, len);
105   if (data != NULL) {
106     c->data = data;
107     c->size = len;
108     return TRUE;
109   }
110
111   return FALSE;
112 }
113
114 /*** text/plain ***/
115 static gboolean xml_check_first_element (GstTypeFind * tf,
116     const gchar * element, guint elen, gboolean strict);
117 static gboolean sdp_check_header (GstTypeFind * tf);
118
119 static GstStaticCaps utf8_caps = GST_STATIC_CAPS ("text/plain");
120
121 #define UTF8_CAPS gst_static_caps_get(&utf8_caps)
122
123 static gboolean
124 utf8_type_find_have_valid_utf8_at_offset (GstTypeFind * tf, guint64 offset,
125     GstTypeFindProbability * prob)
126 {
127   guint8 *data;
128
129   /* randomly decided values */
130   guint min_size = 16;          /* minimum size  */
131   guint size = 32 * 1024;       /* starting size */
132   guint probability = 95;       /* starting probability */
133   guint step = 10;              /* how much we reduce probability in each
134                                  * iteration */
135
136   while (probability > step && size > min_size) {
137     data = gst_type_find_peek (tf, offset, size);
138     if (data) {
139       gchar *end;
140       gchar *start = (gchar *) data;
141
142       if (g_utf8_validate (start, size, (const gchar **) &end) || (end - start + 4 > size)) {   /* allow last char to be cut off */
143         *prob = probability;
144         return TRUE;
145       }
146       *prob = 0;
147       return FALSE;
148     }
149     size /= 2;
150     probability -= step;
151   }
152   *prob = 0;
153   return FALSE;
154 }
155
156 static void
157 utf8_type_find (GstTypeFind * tf, gpointer unused)
158 {
159   GstTypeFindProbability start_prob, mid_prob;
160   guint64 length;
161
162   /* leave xml to the xml typefinders */
163   if (xml_check_first_element (tf, "", 0, TRUE))
164     return;
165
166   /* leave sdp to the sdp typefinders */
167   if (sdp_check_header (tf))
168     return;
169
170   /* check beginning of stream */
171   if (!utf8_type_find_have_valid_utf8_at_offset (tf, 0, &start_prob))
172     return;
173
174   GST_LOG ("start is plain text with probability of %u", start_prob);
175
176   /* POSSIBLE is the highest probability we ever return if we can't
177    * probe into the middle of the file and don't know its length */
178
179   length = gst_type_find_get_length (tf);
180   if (length == 0 || length == (guint64) - 1) {
181     gst_type_find_suggest (tf, MIN (start_prob, GST_TYPE_FIND_POSSIBLE),
182         UTF8_CAPS);
183     return;
184   }
185
186   if (length < 64 * 1024) {
187     gst_type_find_suggest (tf, start_prob, UTF8_CAPS);
188     return;
189   }
190
191   /* check middle of stream */
192   if (!utf8_type_find_have_valid_utf8_at_offset (tf, length / 2, &mid_prob))
193     return;
194
195   GST_LOG ("middle is plain text with probability of %u", mid_prob);
196   gst_type_find_suggest (tf, (start_prob + mid_prob) / 2, UTF8_CAPS);
197 }
198
199 /*** text/uri-list ***/
200
201 static GstStaticCaps uri_caps = GST_STATIC_CAPS ("text/uri-list");
202
203 #define URI_CAPS (gst_static_caps_get(&uri_caps))
204 #define BUFFER_SIZE 16          /* If the string is < 16 bytes we're screwed */
205 #define INC_BUFFER {                                                    \
206   pos++;                                                                \
207   if (pos == BUFFER_SIZE) {                                             \
208     pos = 0;                                                            \
209     offset += BUFFER_SIZE;                                              \
210     data = gst_type_find_peek (tf, offset, BUFFER_SIZE);                \
211     if (data == NULL) return;                                           \
212   } else {                                                              \
213     data++;                                                             \
214   }                                                                     \
215 }
216 static void
217 uri_type_find (GstTypeFind * tf, gpointer unused)
218 {
219   guint8 *data = gst_type_find_peek (tf, 0, BUFFER_SIZE);
220   guint pos = 0;
221   guint offset = 0;
222
223   if (data) {
224     /* Search for # comment lines */
225     while (*data == '#') {
226       /* Goto end of line */
227       while (*data != '\n') {
228         INC_BUFFER;
229       }
230
231       INC_BUFFER;
232     }
233
234     if (!g_ascii_isalpha (*data)) {
235       /* Had a non alpha char - can't be uri-list */
236       return;
237     }
238
239     INC_BUFFER;
240
241     while (g_ascii_isalnum (*data)) {
242       INC_BUFFER;
243     }
244
245     if (*data != ':') {
246       /* First non alpha char is not a : */
247       return;
248     }
249
250     /* Get the next 2 bytes as well */
251     data = gst_type_find_peek (tf, offset + pos, 3);
252     if (data == NULL)
253       return;
254
255     if (data[1] != '/' && data[2] != '/') {
256       return;
257     }
258
259     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, URI_CAPS);
260   }
261 }
262
263
264 /*** application/xml **********************************************************/
265
266 #define XML_BUFFER_SIZE 16
267 #define XML_INC_BUFFER {                                                \
268   pos++;                                                                \
269   if (pos == XML_BUFFER_SIZE) {                                         \
270     pos = 0;                                                            \
271     offset += XML_BUFFER_SIZE;                                          \
272     data = gst_type_find_peek (tf, offset, XML_BUFFER_SIZE);            \
273     if (data == NULL) return FALSE;                                     \
274   } else {                                                              \
275     data++;                                                             \
276   }                                                                     \
277 }
278
279 static gboolean
280 xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen,
281     gboolean strict)
282 {
283   gboolean got_xmldec;
284   guint8 *data;
285   guint offset = 0;
286   guint pos = 0;
287
288   data = gst_type_find_peek (tf, 0, XML_BUFFER_SIZE);
289   if (!data)
290     return FALSE;
291
292   /* look for the XMLDec
293    * see XML spec 2.8, Prolog and Document Type Declaration
294    * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */
295   got_xmldec = (memcmp (data, "<?xml", 5) == 0);
296
297   if (strict && !got_xmldec)
298     return FALSE;
299
300   /* skip XMLDec in any case if we've got one */
301   if (got_xmldec) {
302     pos += 5;
303     data += 5;
304   }
305
306   /* look for the first element, it has to be the requested element. Bail
307    * out if it is not within the first 4kB. */
308   while (data && (offset + pos) < 4096) {
309     while (*data != '<' && (offset + pos) < 4096) {
310       XML_INC_BUFFER;
311     }
312
313     XML_INC_BUFFER;
314     if (!g_ascii_isalpha (*data)) {
315       /* if not alphabetic, it's a PI or an element / attribute declaration
316        * like <?xxx or <!xxx */
317       XML_INC_BUFFER;
318       continue;
319     }
320
321     /* the first normal element, check if it's the one asked for */
322     data = gst_type_find_peek (tf, offset + pos, elen + 1);
323     return (data && element && strncmp ((char *) data, element, elen) == 0);
324   }
325
326   return FALSE;
327 }
328
329 static GstStaticCaps generic_xml_caps = GST_STATIC_CAPS ("application/xml");
330
331 #define GENERIC_XML_CAPS (gst_static_caps_get(&generic_xml_caps))
332 static void
333 xml_type_find (GstTypeFind * tf, gpointer unused)
334 {
335   if (xml_check_first_element (tf, "", 0, TRUE)) {
336     gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, GENERIC_XML_CAPS);
337   }
338 }
339
340 /*** application/sdp *********************************************************/
341
342 static GstStaticCaps sdp_caps = GST_STATIC_CAPS ("application/sdp");
343
344 #define SDP_CAPS (gst_static_caps_get(&sdp_caps))
345 static gboolean
346 sdp_check_header (GstTypeFind * tf)
347 {
348   guint8 *data;
349
350   data = gst_type_find_peek (tf, 0, 5);
351   if (!data)
352     return FALSE;
353
354   /* sdp must start with v=0[\r]\n */
355   if (memcmp (data, "v=0", 3))
356     return FALSE;
357
358   if (data[3] == '\r' && data[4] == '\n')
359     return TRUE;
360   if (data[3] == '\n')
361     return TRUE;
362
363   return FALSE;
364 }
365
366 static void
367 sdp_type_find (GstTypeFind * tf, gpointer unused)
368 {
369   if (sdp_check_header (tf))
370     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SDP_CAPS);
371 }
372
373 /*** application/smil *********************************************************/
374
375 static GstStaticCaps smil_caps = GST_STATIC_CAPS ("application/smil");
376
377 #define SMIL_CAPS (gst_static_caps_get(&smil_caps))
378 static void
379 smil_type_find (GstTypeFind * tf, gpointer unused)
380 {
381   if (xml_check_first_element (tf, "smil", 4, FALSE)) {
382     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SMIL_CAPS);
383   }
384 }
385
386 /*** text/html ***/
387
388 static GstStaticCaps html_caps = GST_STATIC_CAPS ("text/html");
389
390 #define HTML_CAPS gst_static_caps_get (&html_caps)
391
392 static void
393 html_type_find (GstTypeFind * tf, gpointer unused)
394 {
395   gchar *d, *data;
396
397   data = (gchar *) gst_type_find_peek (tf, 0, 16);
398   if (!data)
399     return;
400
401   if (!g_ascii_strncasecmp (data, "<!DOCTYPE HTML", 14)) {
402     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
403   } else if (xml_check_first_element (tf, "html", 4, FALSE)) {
404     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
405   } else if ((d = memchr (data, '<', 16))) {
406     data = (gchar *) gst_type_find_peek (tf, d - data, 6);
407     if (data && g_ascii_strncasecmp (data, "<html>", 6) == 0) {
408       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
409     }
410   }
411 }
412
413 /*** audio/midi ***/
414
415 static GstStaticCaps mid_caps = GST_STATIC_CAPS ("audio/midi");
416
417 #define MID_CAPS gst_static_caps_get(&mid_caps)
418 static void
419 mid_type_find (GstTypeFind * tf, gpointer unused)
420 {
421   guint8 *data = gst_type_find_peek (tf, 0, 4);
422
423   /* http://jedi.ks.uiuc.edu/~johns/links/music/midifile.html */
424   if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h'
425       && data[3] == 'd')
426     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS);
427 }
428
429 /*** audio/mobile-xmf ***/
430
431 static GstStaticCaps mxmf_caps = GST_STATIC_CAPS ("audio/mobile-xmf");
432
433 #define MXMF_CAPS gst_static_caps_get(&mxmf_caps)
434 static void
435 mxmf_type_find (GstTypeFind * tf, gpointer unused)
436 {
437   guint8 *data = NULL;
438
439   /* Search FileId "XMF_" 4 bytes */
440   data = gst_type_find_peek (tf, 0, 4);
441   if (data && data[0] == 'X' && data[1] == 'M' && data[2] == 'F'
442       && data[3] == '_') {
443     /* Search Format version "2.00" 4 bytes */
444     data = gst_type_find_peek (tf, 4, 4);
445     if (data && data[0] == '2' && data[1] == '.' && data[2] == '0'
446         && data[3] == '0') {
447       /* Search TypeId 2     1 byte */
448       data = gst_type_find_peek (tf, 11, 1);
449       if (data && data[0] == 2) {
450         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXMF_CAPS);
451       }
452     }
453   }
454 }
455
456
457 /*** video/x-fli ***/
458
459 static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli");
460
461 #define FLX_CAPS gst_static_caps_get(&flx_caps)
462 static void
463 flx_type_find (GstTypeFind * tf, gpointer unused)
464 {
465   guint8 *data = gst_type_find_peek (tf, 0, 134);
466
467   if (data) {
468     /* check magic and the frame type of the first frame */
469     if ((data[4] == 0x11 || data[4] == 0x12 ||
470             data[4] == 0x30 || data[4] == 0x44) &&
471         data[5] == 0xaf &&
472         ((data[132] == 0x00 || data[132] == 0xfa) && data[133] == 0xf1)) {
473       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLX_CAPS);
474     }
475     return;
476   }
477   data = gst_type_find_peek (tf, 0, 6);
478   if (data) {
479     /* check magic only */
480     if ((data[4] == 0x11 || data[4] == 0x12 ||
481             data[4] == 0x30 || data[4] == 0x44) && data[5] == 0xaf) {
482       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, FLX_CAPS);
483     }
484     return;
485   }
486 }
487
488 /*** application/x-id3 ***/
489
490 static GstStaticCaps id3_caps = GST_STATIC_CAPS ("application/x-id3");
491
492 #define ID3_CAPS gst_static_caps_get(&id3_caps)
493 static void
494 id3v2_type_find (GstTypeFind * tf, gpointer unused)
495 {
496   guint8 *data = gst_type_find_peek (tf, 0, 10);
497
498   if (data && memcmp (data, "ID3", 3) == 0 &&
499       data[3] != 0xFF && data[4] != 0xFF &&
500       (data[6] & 0x80) == 0 && (data[7] & 0x80) == 0 &&
501       (data[8] & 0x80) == 0 && (data[9] & 0x80) == 0) {
502     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS);
503   }
504 }
505
506 static void
507 id3v1_type_find (GstTypeFind * tf, gpointer unused)
508 {
509   guint8 *data = gst_type_find_peek (tf, -128, 3);
510
511   if (data && memcmp (data, "TAG", 3) == 0) {
512     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS);
513   }
514 }
515
516 /*** application/x-ape ***/
517
518 static GstStaticCaps apetag_caps = GST_STATIC_CAPS ("application/x-apetag");
519
520 #define APETAG_CAPS gst_static_caps_get(&apetag_caps)
521 static void
522 apetag_type_find (GstTypeFind * tf, gpointer unused)
523 {
524   guint8 *data;
525
526   /* APEv1/2 at start of file */
527   data = gst_type_find_peek (tf, 0, 8);
528   if (data && !memcmp (data, "APETAGEX", 8)) {
529     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS);
530     return;
531   }
532
533   /* APEv1/2 at end of file */
534   data = gst_type_find_peek (tf, -32, 8);
535   if (data && !memcmp (data, "APETAGEX", 8)) {
536     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS);
537     return;
538   }
539 }
540
541 /*** audio/x-ttafile ***/
542
543 static GstStaticCaps tta_caps = GST_STATIC_CAPS ("audio/x-ttafile");
544
545 #define TTA_CAPS gst_static_caps_get(&tta_caps)
546 static void
547 tta_type_find (GstTypeFind * tf, gpointer unused)
548 {
549   guint8 *data = gst_type_find_peek (tf, 0, 3);
550
551   if (data) {
552     if (memcmp (data, "TTA", 3) == 0) {
553       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TTA_CAPS);
554       return;
555     }
556   }
557 }
558
559 /*** audio/x-flac ***/
560 static GstStaticCaps flac_caps = GST_STATIC_CAPS ("audio/x-flac");
561
562 #define FLAC_CAPS (gst_static_caps_get(&flac_caps))
563
564 static void
565 flac_type_find (GstTypeFind * tf, gpointer unused)
566 {
567   DataScanCtx c = { 0, NULL, 0 };
568
569   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
570     return;
571
572   /* standard flac (also old/broken flac-in-ogg with an initial 4-byte marker
573    * packet and without the usual packet framing) */
574   if (memcmp (c.data, "fLaC", 4) == 0) {
575     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
576     return;
577   }
578
579   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
580     return;
581
582   /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
583   if (memcmp (c.data, "\177FLAC\001", 6) == 0) {
584     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
585     return;
586   }
587
588 /* disabled because it happily typefinds /dev/urandom as audio/x-flac, and
589  * because I yet have to see header-less flac in the wild */
590 #if 0
591   /* flac without headers (subset format) */
592   /* 64K should be enough */
593   while (c.offset < (64 * 1024)) {
594     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
595       break;
596
597     /* look for frame header,
598      * http://flac.sourceforge.net/format.html#frame_header
599      */
600     if (c.data[0] == 0xff && (c.data[1] >> 2) == 0x3e) {
601       /* bit 15 in the header must be 0 */
602       if (((c.data[1] >> 1) & 0x01) == 0x01)
603         goto advance;
604
605       /* blocksize must be != 0x00 */
606       if ((c.data[2] >> 4) == 0x00)
607         goto advance;
608
609       /* samplerate must be != 0x0f */
610       if ((c.data[2] & 0x0f) == 0x0f)
611         goto advance;
612       /* also 0 is invalid, as it means get the info from the header and we
613        * don't have headers if we are here */
614       if ((c.data[2] & 0x0f) == 0x00)
615         goto advance;
616
617       /* channel assignment must be < 11 */
618       if ((c.data[3] >> 4) >= 11)
619         goto advance;
620
621       /* sample size must be != 0x07 and != 0x05 */
622       if (((c.data[3] >> 1) & 0x07) == 0x07)
623         goto advance;
624       if (((c.data[3] >> 1) & 0x07) == 0x05)
625         goto advance;
626       /* also 0 is invalid, as it means get the info from the header and we
627        * don't have headers if we are here */
628       if (((c.data[3] >> 1) & 0x07) == 0x00)
629         goto advance;
630
631       /* next bit must be 0 */
632       if ((c.data[3] & 0x01) == 0x01)
633         goto advance;
634
635       /* FIXME: shouldn't we include the crc check ? */
636
637       GST_DEBUG ("Found flac without headers at %d", (gint) c.offset);
638       gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, FLAC_CAPS);
639       return;
640     }
641   advance:
642     data_scan_ctx_advance (tf, &c, 1);
643   }
644 #endif
645 }
646
647 /*** audio/mpeg version 2, 4 ***/
648
649 static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, "
650     "mpegversion = (int) { 2, 4 }, framed = (bool) false");
651 #define AAC_CAPS (gst_static_caps_get(&aac_caps))
652 #define AAC_AMOUNT (4096)
653 static void
654 aac_type_find (GstTypeFind * tf, gpointer unused)
655 {
656   /* LUT to convert the AudioObjectType from the ADTS header to a string */
657   static const gchar profile_to_string[][5] = { "main", "lc", "ssr", "ltp" };
658   static const guint sample_freq[] = { 96000, 88200, 64000, 48000, 44100,
659     32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350
660   };
661   DataScanCtx c = { 0, NULL, 0 };
662
663   while (c.offset < AAC_AMOUNT) {
664     guint snc, len;
665
666     /* detect adts header or adif header.
667      * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
668      * the other hand, is 14 bits only, so we require one valid frame with
669      * again a valid syncpoint on the next one (28 bits) for certainty. We
670      * require 4 kB, which is quite a lot, since frames are generally 200-400
671      * bytes.
672      */
673     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
674       break;
675
676     snc = GST_READ_UINT16_BE (c.data);
677     if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) {
678       /* ADTS header - find frame length */
679       GST_DEBUG ("Found one ADTS syncpoint at offset 0x%" G_GINT64_MODIFIER
680           "x, tracing next...", c.offset);
681       len = ((c.data[3] & 0x03) << 11) |
682           (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
683
684       if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
685         GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
686         goto next;
687       }
688
689       /* check if there's a second ADTS frame */
690       snc = GST_READ_UINT16_BE (c.data + len);
691       if ((snc & 0xfff6) == 0xfff0) {
692         GstCaps *caps;
693         guint mpegversion, sample_freq_idx, channel_config, profile, rate;
694         gint level;
695
696         mpegversion = (c.data[1] & 0x08) ? 2 : 4;
697         profile = c.data[2] >> 6;
698         sample_freq_idx = ((c.data[2] & 0x3c) >> 2);
699         channel_config = ((c.data[2] & 0x01) << 2) + (c.data[3] >> 6);
700
701         GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%"
702             G_GINT64_MODIFIER "x, framelen %u", mpegversion, c.offset, len);
703
704         /* 0xd and 0xe are reserved. 0xf means the sample frequency is directly
705          * specified in the header, but that's not allowed for ADTS */
706         if (sample_freq_idx > 0xc) {
707           GST_DEBUG ("Unexpected sample frequency index %d or wrong sync",
708               sample_freq_idx);
709           goto next;
710         }
711
712         rate = sample_freq[sample_freq_idx];
713         GST_LOG ("ADTS: profile=%u, rate=%u", profile, rate);
714
715         /* ADTS counts profiles from 0 instead of 1 to save bits */
716         level = gst_aac_level_from_header (profile + 1, rate, channel_config);
717
718         caps = gst_caps_new_simple ("audio/mpeg",
719             "framed", G_TYPE_BOOLEAN, FALSE,
720             "mpegversion", G_TYPE_INT, mpegversion,
721             "stream-type", G_TYPE_STRING, "adts",
722             "base-profile", G_TYPE_STRING, profile_to_string[profile],
723             "profile", G_TYPE_STRING, profile_to_string[profile], NULL);
724
725         if (level != -1) {
726           gchar level_str[16];
727
728           /* we use a string here because h.264 levels are also strings and
729            * there aren't a lot of levels, so it's not too awkward to not use
730            * and integer here and keep the field type consistent with h.264 */
731           g_snprintf (level_str, sizeof (level_str), "%d", level);
732           gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_str, NULL);
733         }
734
735         /* add rate and number of channels if we can */
736         if (channel_config != 0 && channel_config <= 7) {
737           const guint channels_map[] = { 0, 1, 2, 3, 4, 5, 6, 8 };
738
739           gst_caps_set_simple (caps, "channels", G_TYPE_INT,
740               channels_map[channel_config], "rate", G_TYPE_INT, rate, NULL);
741         }
742
743         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
744         gst_caps_unref (caps);
745         break;
746       }
747
748       GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
749     } else if (!memcmp (c.data, "ADIF", 4)) {
750       /* ADIF header */
751       gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
752           "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4,
753           "stream-format", G_TYPE_STRING, "adif", NULL);
754       break;
755     }
756
757   next:
758
759     data_scan_ctx_advance (tf, &c, 1);
760   }
761 }
762
763 /*** audio/mpeg version 1 ***/
764
765 /*
766  * The chance that random data is identified as a valid mp3 header is 63 / 2^18
767  * (0.024%) per try. This makes the function for calculating false positives
768  *   1 - (1 - ((63 / 2 ^18) ^ GST_MP3_TYPEFIND_MIN_HEADERS)) ^ buffersize)
769  * This has the following probabilities of false positives:
770  * datasize               MIN_HEADERS
771  * (bytes)      1       2       3       4
772  * 4096         62.6%    0.02%   0%      0%
773  * 16384        98%      0.09%   0%      0%
774  * 1 MiB       100%      5.88%   0%      0%
775  * 1 GiB       100%    100%      1.44%   0%
776  * 1 TiB       100%    100%    100%      0.35%
777  * This means that the current choice (3 headers by most of the time 4096 byte
778  * buffers is pretty safe for now.
779  *
780  * The max. size of each frame is 1440 bytes, which means that for N frames to
781  * be detected, we need 1440 * GST_MP3_TYPEFIND_MIN_HEADERS + 3 bytes of data.
782  * Assuming we step into the stream right after the frame header, this
783  * means we need 1440 * (GST_MP3_TYPEFIND_MIN_HEADERS + 1) - 1 + 3 bytes
784  * of data (5762) to always detect any mp3.
785  */
786
787 static const guint mp3types_bitrates[2][3][16] =
788     { {{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
789     {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
790     {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}},
791 {{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
792     {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
793     {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}},
794 };
795
796 static const guint mp3types_freqs[3][3] = { {11025, 12000, 8000},
797 {22050, 24000, 16000},
798 {44100, 48000, 32000}
799 };
800
801 static inline guint
802 mp3_type_frame_length_from_header (guint32 header, guint * put_layer,
803     guint * put_channels, guint * put_bitrate, guint * put_samplerate,
804     gboolean * may_be_free_format, gint possible_free_framelen)
805 {
806   guint bitrate, layer, length, mode, samplerate, version, channels;
807
808   if ((header & 0xffe00000) != 0xffe00000)
809     return 0;
810
811   /* we don't need extension, copyright, original or
812    * emphasis for the frame length */
813   header >>= 6;
814
815   /* mode */
816   mode = header & 0x3;
817   header >>= 3;
818
819   /* padding */
820   length = header & 0x1;
821   header >>= 1;
822
823   /* sampling frequency */
824   samplerate = header & 0x3;
825   if (samplerate == 3)
826     return 0;
827   header >>= 2;
828
829   /* bitrate index */
830   bitrate = header & 0xF;
831   if (bitrate == 0 && possible_free_framelen == -1) {
832     GST_LOG ("Possibly a free format mp3 - signalling");
833     *may_be_free_format = TRUE;
834   }
835   if (bitrate == 15 || (bitrate == 0 && possible_free_framelen == -1))
836     return 0;
837
838   /* ignore error correction, too */
839   header >>= 5;
840
841   /* layer */
842   layer = 4 - (header & 0x3);
843   if (layer == 4)
844     return 0;
845   header >>= 2;
846
847   /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */
848   version = header & 0x3;
849   if (version == 1)
850     return 0;
851
852   /* lookup */
853   channels = (mode == 3) ? 1 : 2;
854   samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate];
855   if (bitrate == 0) {
856     if (layer == 1) {
857       length *= 4;
858       length += possible_free_framelen;
859       bitrate = length * samplerate / 48000;
860     } else {
861       length += possible_free_framelen;
862       bitrate = length * samplerate /
863           ((layer == 3 && version != 3) ? 72000 : 144000);
864     }
865   } else {
866     /* calculating */
867     bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate];
868     if (layer == 1) {
869       length = ((12000 * bitrate / samplerate) + length) * 4;
870     } else {
871       length += ((layer == 3
872               && version != 3) ? 72000 : 144000) * bitrate / samplerate;
873     }
874   }
875
876   GST_LOG ("mp3typefind: calculated mp3 frame length of %u bytes", length);
877   GST_LOG
878       ("mp3typefind: samplerate = %u - bitrate = %u - layer = %u - version = %u"
879       " - channels = %u", samplerate, bitrate, layer, version, channels);
880
881   if (put_layer)
882     *put_layer = layer;
883   if (put_channels)
884     *put_channels = channels;
885   if (put_bitrate)
886     *put_bitrate = bitrate;
887   if (put_samplerate)
888     *put_samplerate = samplerate;
889
890   return length;
891 }
892
893
894 static GstStaticCaps mp3_caps = GST_STATIC_CAPS ("audio/mpeg, "
895     "mpegversion = (int) 1, layer = (int) [ 1, 3 ]");
896 #define MP3_CAPS (gst_static_caps_get(&mp3_caps))
897 /*
898  * random values for typefinding
899  * if no more data is available, we will return a probability of
900  * (found_headers/TRY_HEADERS) * (MAXIMUM * (TRY_SYNC - bytes_skipped)
901  *        / TRY_SYNC)
902  * if found_headers >= MIN_HEADERS
903  */
904 #define GST_MP3_TYPEFIND_MIN_HEADERS (2)
905 #define GST_MP3_TYPEFIND_TRY_HEADERS (5)
906 #define GST_MP3_TYPEFIND_TRY_SYNC (GST_TYPE_FIND_MAXIMUM * 100) /* 10kB */
907 #define GST_MP3_TYPEFIND_SYNC_SIZE (2048)
908 #define GST_MP3_WRONG_HEADER (10)
909
910 static void
911 mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off,
912     guint * found_layer, GstTypeFindProbability * found_prob)
913 {
914   guint8 *data = NULL;
915   guint8 *data_end = NULL;
916   guint size;
917   guint64 skipped;
918   gint last_free_offset = -1;
919   gint last_free_framelen = -1;
920   gboolean headerstart = TRUE;
921
922   *found_layer = 0;
923   *found_prob = 0;
924
925   size = 0;
926   skipped = 0;
927   while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) {
928     if (size <= 0) {
929       size = GST_MP3_TYPEFIND_SYNC_SIZE * 2;
930       do {
931         size /= 2;
932         data = gst_type_find_peek (tf, skipped + start_off, size);
933       } while (size > 10 && !data);
934       if (!data)
935         break;
936       data_end = data + size;
937     }
938     if (*data == 0xFF) {
939       guint8 *head_data = NULL;
940       guint layer = 0, bitrate, samplerate, channels;
941       guint found = 0;          /* number of valid headers found */
942       guint64 offset = skipped;
943
944       while (found < GST_MP3_TYPEFIND_TRY_HEADERS) {
945         guint32 head;
946         guint length;
947         guint prev_layer = 0, prev_bitrate = 0;
948         guint prev_channels = 0, prev_samplerate = 0;
949         gboolean free = FALSE;
950
951         if ((gint64) (offset - skipped + 4) >= 0 &&
952             data + offset - skipped + 4 < data_end) {
953           head_data = data + offset - skipped;
954         } else {
955           head_data = gst_type_find_peek (tf, offset + start_off, 4);
956         }
957         if (!head_data)
958           break;
959         head = GST_READ_UINT32_BE (head_data);
960         if (!(length = mp3_type_frame_length_from_header (head, &layer,
961                     &channels, &bitrate, &samplerate, &free,
962                     last_free_framelen))) {
963           if (free) {
964             if (last_free_offset == -1)
965               last_free_offset = offset;
966             else {
967               last_free_framelen = offset - last_free_offset;
968               offset = last_free_offset;
969               continue;
970             }
971           } else {
972             last_free_framelen = -1;
973           }
974
975           /* Mark the fact that we didn't find a valid header at the beginning */
976           if (found == 0)
977             headerstart = FALSE;
978
979           GST_LOG ("%d. header at offset %" G_GUINT64_FORMAT
980               " (0x%" G_GINT64_MODIFIER "x) was not an mp3 header "
981               "(possibly-free: %s)", found + 1, start_off + offset,
982               start_off + offset, free ? "yes" : "no");
983           break;
984         }
985         if ((prev_layer && prev_layer != layer) ||
986             /* (prev_bitrate && prev_bitrate != bitrate) || <-- VBR */
987             (prev_samplerate && prev_samplerate != samplerate) ||
988             (prev_channels && prev_channels != channels)) {
989           /* this means an invalid property, or a change, which might mean
990            * that this is not a mp3 but just a random bytestream. It could
991            * be a freaking funky encoded mp3 though. We'll just not count
992            * this header*/
993           prev_layer = layer;
994           prev_bitrate = bitrate;
995           prev_channels = channels;
996           prev_samplerate = samplerate;
997         } else {
998           found++;
999           GST_LOG ("found %d. header at offset %" G_GUINT64_FORMAT " (0x%"
1000               G_GINT64_MODIFIER "X)", found, start_off + offset,
1001               start_off + offset);
1002         }
1003         offset += length;
1004       }
1005       g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
1006       if (head_data == NULL &&
1007           gst_type_find_peek (tf, offset + start_off - 1, 1) == NULL)
1008         /* Incomplete last frame - don't count it. */
1009         found--;
1010       if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
1011           (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
1012         /* we can make a valid guess */
1013         guint probability = found * GST_TYPE_FIND_MAXIMUM *
1014             (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
1015             GST_MP3_TYPEFIND_TRY_HEADERS / GST_MP3_TYPEFIND_TRY_SYNC;
1016
1017         if (!headerstart
1018             && probability > (GST_TYPE_FIND_MINIMUM + GST_MP3_WRONG_HEADER))
1019           probability -= GST_MP3_WRONG_HEADER;
1020         if (probability < GST_TYPE_FIND_MINIMUM)
1021           probability = GST_TYPE_FIND_MINIMUM;
1022         if (start_off > 0)
1023           probability /= 2;
1024
1025         GST_INFO
1026             ("audio/mpeg calculated %u  =  %u  *  %u / %u  *  (%u - %"
1027             G_GUINT64_FORMAT ") / %u", probability, GST_TYPE_FIND_MAXIMUM,
1028             found, GST_MP3_TYPEFIND_TRY_HEADERS, GST_MP3_TYPEFIND_TRY_SYNC,
1029             (guint64) skipped, GST_MP3_TYPEFIND_TRY_SYNC);
1030         /* make sure we're not id3 tagged */
1031         head_data = gst_type_find_peek (tf, -128, 3);
1032         if (head_data && (memcmp (head_data, "TAG", 3) == 0)) {
1033           probability = 0;
1034         }
1035         g_assert (probability <= GST_TYPE_FIND_MAXIMUM);
1036
1037         *found_prob = probability;
1038         if (probability > 0)
1039           *found_layer = layer;
1040         return;
1041       }
1042     }
1043     data++;
1044     skipped++;
1045     size--;
1046   }
1047 }
1048
1049 static void
1050 mp3_type_find (GstTypeFind * tf, gpointer unused)
1051 {
1052   GstTypeFindProbability prob, mid_prob;
1053   guint8 *data;
1054   guint layer, mid_layer;
1055   guint64 length;
1056
1057   mp3_type_find_at_offset (tf, 0, &layer, &prob);
1058   length = gst_type_find_get_length (tf);
1059
1060   if (length == 0 || length == (guint64) - 1) {
1061     if (prob != 0)
1062       goto suggest;
1063     return;
1064   }
1065
1066   /* if we're pretty certain already, skip the additional check */
1067   if (prob >= GST_TYPE_FIND_LIKELY)
1068     goto suggest;
1069
1070   mp3_type_find_at_offset (tf, length / 2, &mid_layer, &mid_prob);
1071
1072   if (mid_prob > 0) {
1073     if (prob == 0) {
1074       GST_LOG ("detected audio/mpeg only in the middle (p=%u)", mid_prob);
1075       layer = mid_layer;
1076       prob = mid_prob;
1077       goto suggest;
1078     }
1079
1080     if (layer != mid_layer) {
1081       GST_WARNING ("audio/mpeg layer discrepancy: %u vs. %u", layer, mid_layer);
1082       return;                   /* FIXME: or should we just go with the one in the middle? */
1083     }
1084
1085     /* detected mpeg audio both in middle of the file and at the start */
1086     prob = (prob + mid_prob) / 2;
1087     goto suggest;
1088   }
1089
1090   /* let's see if there's a valid header right at the start */
1091   data = gst_type_find_peek (tf, 0, 4); /* use min. frame size? */
1092   if (data && mp3_type_frame_length_from_header (GST_READ_UINT32_BE (data),
1093           &layer, NULL, NULL, NULL, NULL, 0) != 0) {
1094     if (prob == 0)
1095       prob = GST_TYPE_FIND_POSSIBLE - 10;
1096     else
1097       prob = MAX (GST_TYPE_FIND_POSSIBLE - 10, prob + 10);
1098   }
1099
1100   if (prob > 0)
1101     goto suggest;
1102
1103   return;
1104
1105 suggest:
1106   {
1107     g_return_if_fail (layer >= 1 && layer <= 3);
1108
1109     gst_type_find_suggest_simple (tf, prob, "audio/mpeg",
1110         "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
1111   }
1112 }
1113
1114 /*** audio/x-musepack ***/
1115
1116 static GstStaticCaps musepack_caps =
1117 GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }");
1118
1119 #define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps))
1120 static void
1121 musepack_type_find (GstTypeFind * tf, gpointer unused)
1122 {
1123   guint8 *data = gst_type_find_peek (tf, 0, 4);
1124   GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM;
1125   gint streamversion = -1;
1126
1127   if (data && memcmp (data, "MP+", 3) == 0) {
1128     streamversion = 7;
1129     if ((data[3] & 0x7f) == 7) {
1130       prop = GST_TYPE_FIND_MAXIMUM;
1131     } else {
1132       prop = GST_TYPE_FIND_LIKELY + 10;
1133     }
1134   } else if (data && memcmp (data, "MPCK", 4) == 0) {
1135     streamversion = 8;
1136     prop = GST_TYPE_FIND_MAXIMUM;
1137   }
1138
1139   if (streamversion != -1) {
1140     gst_type_find_suggest_simple (tf, prop, "audio/x-musepack",
1141         "streamversion", G_TYPE_INT, streamversion, NULL);
1142   }
1143 }
1144
1145 /*** audio/x-ac3 ***/
1146 /* FIXME 0.11: should be audio/ac3, but isn't for backwards compatibility */
1147 static GstStaticCaps ac3_caps = GST_STATIC_CAPS ("audio/x-ac3");
1148
1149 #define AC3_CAPS (gst_static_caps_get(&ac3_caps))
1150
1151 struct ac3_frmsize
1152 {
1153   unsigned short bit_rate;
1154   unsigned short frm_size[3];
1155 };
1156
1157 static const struct ac3_frmsize ac3_frmsizecod_tbl[] = {
1158   {32, {64, 69, 96}},
1159   {32, {64, 70, 96}},
1160   {40, {80, 87, 120}},
1161   {40, {80, 88, 120}},
1162   {48, {96, 104, 144}},
1163   {48, {96, 105, 144}},
1164   {56, {112, 121, 168}},
1165   {56, {112, 122, 168}},
1166   {64, {128, 139, 192}},
1167   {64, {128, 140, 192}},
1168   {80, {160, 174, 240}},
1169   {80, {160, 175, 240}},
1170   {96, {192, 208, 288}},
1171   {96, {192, 209, 288}},
1172   {112, {224, 243, 336}},
1173   {112, {224, 244, 336}},
1174   {128, {256, 278, 384}},
1175   {128, {256, 279, 384}},
1176   {160, {320, 348, 480}},
1177   {160, {320, 349, 480}},
1178   {192, {384, 417, 576}},
1179   {192, {384, 418, 576}},
1180   {224, {448, 487, 672}},
1181   {224, {448, 488, 672}},
1182   {256, {512, 557, 768}},
1183   {256, {512, 558, 768}},
1184   {320, {640, 696, 960}},
1185   {320, {640, 697, 960}},
1186   {384, {768, 835, 1152}},
1187   {384, {768, 836, 1152}},
1188   {448, {896, 975, 1344}},
1189   {448, {896, 976, 1344}},
1190   {512, {1024, 1114, 1536}},
1191   {512, {1024, 1115, 1536}},
1192   {576, {1152, 1253, 1728}},
1193   {576, {1152, 1254, 1728}},
1194   {640, {1280, 1393, 1920}},
1195   {640, {1280, 1394, 1920}}
1196 };
1197
1198 static void
1199 ac3_type_find (GstTypeFind * tf, gpointer unused)
1200 {
1201   DataScanCtx c = { 0, NULL, 0 };
1202
1203   /* Search for an ac3 frame; not neccesarily right at the start, but give it
1204    * a lower probability if not found right at the start. Check that the
1205    * frame is followed by a second frame at the expected offset.
1206    * We could also check the two ac3 CRCs, but we don't do that right now */
1207   while (c.offset < 1024) {
1208     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 5)))
1209       break;
1210
1211     if (c.data[0] == 0x0b && c.data[1] == 0x77) {
1212       guint fscod = (c.data[4] >> 6) & 0x03;
1213       guint frmsizecod = c.data[4] & 0x3f;
1214
1215       if (fscod < 3 && frmsizecod < 38) {
1216         DataScanCtx c_next = c;
1217         guint frame_size;
1218
1219         frame_size = ac3_frmsizecod_tbl[frmsizecod].frm_size[fscod];
1220         GST_LOG ("possible frame sync at offset %" G_GUINT64_FORMAT ", size=%u",
1221             c.offset, frame_size);
1222         if (data_scan_ctx_ensure_data (tf, &c_next, (frame_size * 2) + 5)) {
1223           data_scan_ctx_advance (tf, &c_next, frame_size * 2);
1224
1225           if (c_next.data[0] == 0x0b && c_next.data[1] == 0x77) {
1226             guint fscod2 = (c_next.data[4] >> 6) & 0x03;
1227             guint frmsizecod2 = c_next.data[4] & 0x3f;
1228
1229             if (fscod == fscod2 && frmsizecod == frmsizecod2) {
1230               GstTypeFindProbability prob;
1231
1232               GST_LOG ("found second frame, looks good");
1233               if (c.offset == 0)
1234                 prob = GST_TYPE_FIND_MAXIMUM;
1235               else
1236                 prob = GST_TYPE_FIND_NEARLY_CERTAIN;
1237
1238               gst_type_find_suggest (tf, prob, AC3_CAPS);
1239               return;
1240             }
1241           } else {
1242             GST_LOG ("no second frame found, false sync");
1243           }
1244         }
1245       }
1246     }
1247     data_scan_ctx_advance (tf, &c, 1);
1248   }
1249 }
1250
1251 /*** gsm ***/
1252
1253 /* can only be detected by using the extension, in which case we use the default
1254  * GSM properties */
1255 static GstStaticCaps gsm_caps =
1256 GST_STATIC_CAPS ("audio/x-gsm, rate=8000, channels=1");
1257
1258 #define GSM_CAPS (gst_static_caps_get(&gsm_caps))
1259
1260 /*** wavpack ***/
1261
1262 static GstStaticCaps wavpack_caps =
1263 GST_STATIC_CAPS ("audio/x-wavpack, framed = (boolean) false");
1264
1265 #define WAVPACK_CAPS (gst_static_caps_get(&wavpack_caps))
1266
1267 static GstStaticCaps wavpack_correction_caps =
1268 GST_STATIC_CAPS ("audio/x-wavpack-correction, framed = (boolean) false");
1269
1270 #define WAVPACK_CORRECTION_CAPS (gst_static_caps_get(&wavpack_correction_caps))
1271
1272 static void
1273 wavpack_type_find (GstTypeFind * tf, gpointer unused)
1274 {
1275   guint64 offset;
1276   guint32 blocksize;
1277   guint8 *data;
1278
1279   data = gst_type_find_peek (tf, 0, 32);
1280   if (!data)
1281     return;
1282
1283   if (data[0] != 'w' || data[1] != 'v' || data[2] != 'p' || data[3] != 'k')
1284     return;
1285
1286   /* Note: wavpack blocks can be fairly large (easily 60-110k), possibly
1287    * larger than the max. limits imposed by certain typefinding elements
1288    * like id3demux or apedemux, so typefinding is most likely only going to
1289    * work in pull-mode */
1290   blocksize = GST_READ_UINT32_LE (data + 4);
1291   GST_LOG ("wavpack header, blocksize=0x%04x", blocksize);
1292   offset = 32;
1293   while (offset < 32 + blocksize) {
1294     guint32 sublen;
1295
1296     /* get chunk header */
1297     GST_LOG ("peeking at chunk at offset 0x%04x", (guint) offset);
1298     data = gst_type_find_peek (tf, offset, 4);
1299     if (data == NULL)
1300       break;
1301     sublen = ((guint32) data[1]) << 1;
1302     if (data[0] & 0x80) {
1303       sublen |= (((guint32) data[2]) << 9) | (((guint32) data[3]) << 17);
1304       sublen += 1 + 3;          /* id + length */
1305     } else {
1306       sublen += 1 + 1;          /* id + length */
1307     }
1308     if (sublen > blocksize - offset + 32) {
1309       GST_LOG ("chunk length too big (%u > %" G_GUINT64_FORMAT ")", sublen,
1310           blocksize - offset);
1311       break;
1312     }
1313     if ((data[0] & 0x20) == 0) {
1314       switch (data[0] & 0x0f) {
1315         case 0xa:              /* ID_WV_BITSTREAM  */
1316         case 0xc:              /* ID_WVX_BITSTREAM */
1317           gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, WAVPACK_CAPS);
1318           return;
1319         case 0xb:              /* ID_WVC_BITSTREAM */
1320           gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY,
1321               WAVPACK_CORRECTION_CAPS);
1322           return;
1323         default:
1324           break;
1325       }
1326     }
1327     offset += sublen;
1328   }
1329 }
1330
1331 /*** application/postscrip ***/
1332 static GstStaticCaps postscript_caps =
1333 GST_STATIC_CAPS ("application/postscript");
1334
1335 #define POSTSCRIPT_CAPS (gst_static_caps_get(&postscript_caps))
1336
1337 static void
1338 postscript_type_find (GstTypeFind * tf, gpointer unused)
1339 {
1340   guint8 *data = gst_type_find_peek (tf, 0, 3);
1341   if (!data)
1342     return;
1343
1344   if (data[0] == 0x04)
1345     data++;
1346   if (data[0] == '%' && data[1] == '!')
1347     gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, POSTSCRIPT_CAPS);
1348
1349 }
1350
1351 /*** image/svg+xml ***/
1352 static GstStaticCaps svg_caps = GST_STATIC_CAPS ("image/svg+xml");
1353
1354 #define SVG_CAPS (gst_static_caps_get(&svg_caps))
1355
1356 static void
1357 svg_type_find (GstTypeFind * tf, gpointer unused)
1358 {
1359   static const gchar svg_doctype[] = "!DOCTYPE svg";
1360   static const gchar svg_tag[] = "<svg";
1361   DataScanCtx c = { 0, NULL, 0 };
1362
1363   while (c.offset <= 1024) {
1364     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 12)))
1365       break;
1366
1367     if (memcmp (svg_doctype, c.data, 12) == 0) {
1368       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SVG_CAPS);
1369       return;
1370     } else if (memcmp (svg_tag, c.data, 4) == 0) {
1371       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, SVG_CAPS);
1372       return;
1373     }
1374     data_scan_ctx_advance (tf, &c, 1);
1375   }
1376 }
1377
1378 /*** multipart/x-mixed-replace mimestream ***/
1379
1380 static GstStaticCaps multipart_caps =
1381 GST_STATIC_CAPS ("multipart/x-mixed-replace");
1382 #define MULTIPART_CAPS gst_static_caps_get(&multipart_caps)
1383
1384 /* multipart/x-mixed replace is: 
1385  *   <maybe some whitespace>--<some ascii chars>[\r]\n
1386  *   <more ascii chars>[\r]\nContent-type:<more ascii>[\r]\n */
1387 static void
1388 multipart_type_find (GstTypeFind * tf, gpointer unused)
1389 {
1390   guint8 *data;
1391   guint8 *x;
1392
1393 #define MULTIPART_MAX_BOUNDARY_OFFSET 16
1394   data = gst_type_find_peek (tf, 0, MULTIPART_MAX_BOUNDARY_OFFSET);
1395   if (!data)
1396     return;
1397
1398   for (x = data;
1399       x - data < MULTIPART_MAX_BOUNDARY_OFFSET - 2 && g_ascii_isspace (*x);
1400       x++);
1401   if (x[0] != '-' || x[1] != '-')
1402     return;
1403
1404   /* Could be okay, peek what should be enough for a complete header */
1405 #define MULTIPART_MAX_HEADER_SIZE 256
1406   data = gst_type_find_peek (tf, 0, MULTIPART_MAX_HEADER_SIZE);
1407   if (!data)
1408     return;
1409
1410   for (x = data; x - data < MULTIPART_MAX_HEADER_SIZE - 14; x++) {
1411     if (!isascii (*x)) {
1412       return;
1413     }
1414     if (*x == '\n' &&
1415         !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) {
1416       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MULTIPART_CAPS);
1417       return;
1418     }
1419   }
1420 }
1421
1422 /*** video/mpeg systemstream ***/
1423 static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
1424     "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]");
1425
1426 #define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps)
1427 #define IS_MPEG_HEADER(data) (G_UNLIKELY((((guint8 *)(data))[0] == 0x00) &&  \
1428                                          (((guint8 *)(data))[1] == 0x00) &&  \
1429                                          (((guint8 *)(data))[2] == 0x01)))
1430
1431 #define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
1432 #define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
1433 #define IS_MPEG_PACK_HEADER(data)       (IS_MPEG_HEADER (data) &&            \
1434                                          IS_MPEG_PACK_CODE (((guint8 *)(data))[3]))
1435
1436 #define IS_MPEG_PES_CODE(b) (((b) & 0xF0) == 0xE0 || ((b) & 0xF0) == 0xC0 || \
1437                              (b) >= 0xBD)
1438 #define IS_MPEG_PES_HEADER(data)        (IS_MPEG_HEADER (data) &&            \
1439                                          IS_MPEG_PES_CODE (((guint8 *)(data))[3]))
1440
1441 #define MPEG2_MAX_PROBE_LENGTH (128 * 1024)     /* 128kB should be 64 packs of the 
1442                                                  * most common 2kB pack size. */
1443
1444 #define MPEG2_MIN_SYS_HEADERS 2
1445 #define MPEG2_MAX_SYS_HEADERS 5
1446
1447 static gboolean
1448 mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len,
1449     guint * pack_size)
1450 {
1451   /* Check the pack header @ offset for validity, assuming that the 4 byte header
1452    * itself has already been checked. */
1453   guint8 stuff_len;
1454
1455   if (len < 12)
1456     return FALSE;
1457
1458   /* Check marker bits */
1459   if ((data[4] & 0xC4) == 0x44) {
1460     /* MPEG-2 PACK */
1461     if (len < 14)
1462       return FALSE;
1463
1464     if ((data[6] & 0x04) != 0x04 ||
1465         (data[8] & 0x04) != 0x04 ||
1466         (data[9] & 0x01) != 0x01 || (data[12] & 0x03) != 0x03)
1467       return FALSE;
1468
1469     stuff_len = data[13] & 0x07;
1470
1471     /* Check the following header bytes, if we can */
1472     if ((14 + stuff_len + 4) <= len) {
1473       if (!IS_MPEG_HEADER (data + 14 + stuff_len))
1474         return FALSE;
1475     }
1476     if (pack_size)
1477       *pack_size = 14 + stuff_len;
1478     return TRUE;
1479   } else if ((data[4] & 0xF1) == 0x21) {
1480     /* MPEG-1 PACK */
1481     if ((data[6] & 0x01) != 0x01 ||
1482         (data[8] & 0x01) != 0x01 ||
1483         (data[9] & 0x80) != 0x80 || (data[11] & 0x01) != 0x01)
1484       return FALSE;
1485
1486     /* Check the following header bytes, if we can */
1487     if ((12 + 4) <= len) {
1488       if (!IS_MPEG_HEADER (data + 12))
1489         return FALSE;
1490     }
1491     if (pack_size)
1492       *pack_size = 12;
1493     return TRUE;
1494   }
1495
1496   return FALSE;
1497 }
1498
1499 static gboolean
1500 mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len,
1501     guint * pack_size)
1502 {
1503   guint pes_packet_len;
1504
1505   /* Check the PES header at the given position, assuming the header code itself
1506    * was already checked */
1507   if (len < 6)
1508     return FALSE;
1509
1510   /* For MPEG Program streams, unbounded PES is not allowed, so we must have a
1511    * valid length present */
1512   pes_packet_len = GST_READ_UINT16_BE (data + 4);
1513   if (pes_packet_len == 0)
1514     return FALSE;
1515
1516   /* Check the following header, if we can */
1517   if (6 + pes_packet_len + 4 <= len) {
1518     if (!IS_MPEG_HEADER (data + 6 + pes_packet_len))
1519       return FALSE;
1520   }
1521
1522   if (pack_size)
1523     *pack_size = 6 + pes_packet_len;
1524   return TRUE;
1525 }
1526
1527 static gboolean
1528 mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len,
1529     guint * pack_size)
1530 {
1531   guint sys_hdr_len;
1532
1533   /* Check the System header at the given position, assuming the header code itself
1534    * was already checked */
1535   if (len < 6)
1536     return FALSE;
1537   sys_hdr_len = GST_READ_UINT16_BE (data + 4);
1538   if (sys_hdr_len < 6)
1539     return FALSE;
1540
1541   /* Check the following header, if we can */
1542   if (6 + sys_hdr_len + 4 <= len) {
1543     if (!IS_MPEG_HEADER (data + 6 + sys_hdr_len))
1544       return FALSE;
1545   }
1546
1547   if (pack_size)
1548     *pack_size = 6 + sys_hdr_len;
1549
1550   return TRUE;
1551 }
1552
1553 /* calculation of possibility to identify random data as mpeg systemstream:
1554  * bits that must match in header detection:            32 (or more)
1555  * chance that random data is identifed:                1/2^32
1556  * chance that MPEG2_MIN_PACK_HEADERS headers are identified:
1557  *       1/2^(32*MPEG2_MIN_PACK_HEADERS)
1558  * chance that this happens in MPEG2_MAX_PROBE_LENGTH bytes:
1559  *       1-(1+1/2^(32*MPEG2_MIN_PACK_HEADERS)^MPEG2_MAX_PROBE_LENGTH)
1560  * for current values:
1561  *       1-(1+1/2^(32*4)^101024)
1562  *       = <some_number>
1563  * Since we also check marker bits and pes packet lengths, this probability is a
1564  * very coarse upper bound.
1565  */
1566 static void
1567 mpeg_sys_type_find (GstTypeFind * tf, gpointer unused)
1568 {
1569   guint8 *data, *data0, *first_sync, *end;
1570   gint mpegversion = 0;
1571   guint pack_headers = 0;
1572   guint pes_headers = 0;
1573   guint pack_size;
1574   guint since_last_sync = 0;
1575   guint32 sync_word = 0xffffffff;
1576
1577   G_STMT_START {
1578     gint len;
1579
1580     len = MPEG2_MAX_PROBE_LENGTH;
1581     do {
1582       len = len / 2;
1583       data = gst_type_find_peek (tf, 0, 5 + len);
1584     } while (data == NULL && len >= 32);
1585
1586     if (!data)
1587       return;
1588
1589     end = data + len;
1590   }
1591   G_STMT_END;
1592
1593   data0 = data;
1594   first_sync = NULL;
1595
1596   while (data < end) {
1597     sync_word <<= 8;
1598     if (sync_word == 0x00000100) {
1599       /* Found potential sync word */
1600       if (first_sync == NULL)
1601         first_sync = data - 3;
1602
1603       if (since_last_sync > 4) {
1604         /* If more than 4 bytes since the last sync word, reset our counters,
1605          * as we're only interested in counting contiguous packets */
1606         pes_headers = pack_headers = 0;
1607       }
1608       pack_size = 0;
1609
1610       if (IS_MPEG_PACK_CODE (data[0])) {
1611         if ((data[1] & 0xC0) == 0x40) {
1612           /* MPEG-2 */
1613           mpegversion = 2;
1614         } else if ((data[1] & 0xF0) == 0x20) {
1615           mpegversion = 1;
1616         }
1617         if (mpegversion != 0 &&
1618             mpeg_sys_is_valid_pack (tf, data - 3, end - data + 3, &pack_size)) {
1619           pack_headers++;
1620         }
1621       } else if (IS_MPEG_PES_CODE (data[0])) {
1622         /* PES stream */
1623         if (mpeg_sys_is_valid_pes (tf, data - 3, end - data + 3, &pack_size)) {
1624           pes_headers++;
1625           if (mpegversion == 0)
1626             mpegversion = 2;
1627         }
1628       } else if (IS_MPEG_SYS_CODE (data[0])) {
1629         if (mpeg_sys_is_valid_sys (tf, data - 3, end - data + 3, &pack_size)) {
1630           pack_headers++;
1631         }
1632       }
1633
1634       /* If we found a packet with a known size, skip the bytes in it and loop
1635        * around to check the next packet. */
1636       if (pack_size != 0) {
1637         data += pack_size - 3;
1638         sync_word = 0xffffffff;
1639         since_last_sync = 0;
1640         continue;
1641       }
1642     }
1643
1644     sync_word |= data[0];
1645     since_last_sync++;
1646     data++;
1647
1648     /* If we have found MAX headers, and *some* were pes headers (pack headers
1649      * are optional in an mpeg system stream) then return our high-probability
1650      * result */
1651     if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MAX_SYS_HEADERS)
1652       goto suggest;
1653   }
1654
1655   /* If we at least saw MIN headers, and *some* were pes headers (pack headers
1656    * are optional in an mpeg system stream) then return a lower-probability 
1657    * result */
1658   if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS)
1659     goto suggest;
1660
1661   return;
1662 suggest:
1663   {
1664     guint prob;
1665
1666     prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
1667     prob = MIN (prob, GST_TYPE_FIND_MAXIMUM);
1668
1669     /* lower probability if the first packet wasn't right at the start */
1670     if (data0 != first_sync && prob >= 10)
1671       prob -= 10;
1672
1673     GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
1674         mpegversion, pack_headers, pes_headers, prob);
1675
1676     gst_type_find_suggest_simple (tf, prob, "video/mpeg",
1677         "systemstream", G_TYPE_BOOLEAN, TRUE,
1678         "mpegversion", G_TYPE_INT, mpegversion, NULL);
1679   }
1680 };
1681
1682 /*** video/mpegts Transport Stream ***/
1683 static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
1684     "systemstream = (boolean) true, packetsize = (int) [ 188, 208 ]");
1685 #define MPEGTS_CAPS gst_static_caps_get(&mpegts_caps)
1686
1687 #define GST_MPEGTS_TYPEFIND_MIN_HEADERS 4
1688 #define GST_MPEGTS_TYPEFIND_MAX_HEADERS 10
1689 #define GST_MPEGTS_MAX_PACKET_SIZE 208
1690 #define GST_MPEGTS_TYPEFIND_SYNC_SIZE \
1691             (GST_MPEGTS_TYPEFIND_MIN_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
1692 #define GST_MPEGTS_TYPEFIND_MAX_SYNC \
1693             (GST_MPEGTS_TYPEFIND_MAX_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
1694
1695 #define MPEGTS_HDR_SIZE 4
1696 /* Check for sync byte, error_indicator == 0 and packet has payload */
1697 #define IS_MPEGTS_HEADER(data) (((data)[0] == 0x47) && \
1698                                 (((data)[1] & 0x80) == 0x00) && \
1699                                 (((data)[3] & 0x10) == 0x10))
1700
1701 /* Helper function to search ahead at intervals of packet_size for mpegts
1702  * headers */
1703 static gint
1704 mpeg_ts_probe_headers (GstTypeFind * tf, guint64 offset, gint packet_size)
1705 {
1706   /* We always enter this function having found at least one header already */
1707   gint found = 1;
1708   guint8 *data = NULL;
1709
1710   while (found < GST_MPEGTS_TYPEFIND_MAX_HEADERS) {
1711     offset += packet_size;
1712
1713     data = gst_type_find_peek (tf, offset, MPEGTS_HDR_SIZE);
1714     if (data == NULL || !IS_MPEGTS_HEADER (data))
1715       return found;
1716
1717     found++;
1718   }
1719
1720   return found;
1721 }
1722
1723 /* Try and detect at least 4 packets in at most 10 packets worth of
1724  * data. Need to try several possible packet sizes */
1725 static void
1726 mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
1727 {
1728   /* TS packet sizes to test: normal, DVHS packet size and 
1729    * FEC with 16 or 20 byte codes packet size. */
1730   const gint pack_sizes[] = { 188, 192, 204, 208 };
1731   const gint n_pack_sizes = sizeof (pack_sizes) / sizeof (gint);
1732
1733   guint8 *data = NULL;
1734   guint size = 0;
1735   guint64 skipped = 0;
1736
1737   while (skipped < GST_MPEGTS_TYPEFIND_MAX_SYNC) {
1738     if (size < MPEGTS_HDR_SIZE) {
1739       data = gst_type_find_peek (tf, skipped, GST_MPEGTS_TYPEFIND_SYNC_SIZE);
1740       if (!data)
1741         break;
1742       size = GST_MPEGTS_TYPEFIND_SYNC_SIZE;
1743     }
1744
1745     /* Have at least MPEGTS_HDR_SIZE bytes at this point */
1746     if (IS_MPEGTS_HEADER (data)) {
1747       gint p;
1748
1749       for (p = 0; p < n_pack_sizes; p++) {
1750         gint found;
1751
1752         /* Probe ahead at size pack_sizes[p] */
1753         found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]);
1754         if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
1755           gint probability;
1756
1757           /* found at least 4 headers. 10 headers = MAXIMUM probability. 
1758            * Arbitrarily, I assigned 10% probability for each header we
1759            * found, 40% -> 100% */
1760           probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
1761
1762           gst_type_find_suggest_simple (tf, probability, "video/mpegts",
1763               "systemstream", G_TYPE_BOOLEAN, TRUE,
1764               "packetsize", G_TYPE_INT, pack_sizes[p], NULL);
1765           return;
1766         }
1767       }
1768     }
1769     data++;
1770     skipped++;
1771     size--;
1772   }
1773 }
1774
1775 #define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6
1776 #define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024)      /* 100 kB */
1777
1778 /* Scan ahead a maximum of max_extra_offset bytes until the next IS_MPEG_HEADER
1779  * offset.  After the call, offset will be after the 0x000001, i.e. at the 4th
1780  * byte of the MPEG header.  Returns TRUE if a header was found, FALSE if not.
1781  */
1782 static gboolean
1783 mpeg_find_next_header (GstTypeFind * tf, DataScanCtx * c,
1784     guint64 max_extra_offset)
1785 {
1786   guint64 extra_offset;
1787
1788   for (extra_offset = 0; extra_offset <= max_extra_offset; ++extra_offset) {
1789     if (!data_scan_ctx_ensure_data (tf, c, 4))
1790       return FALSE;
1791     if (IS_MPEG_HEADER (c->data)) {
1792       data_scan_ctx_advance (tf, c, 3);
1793       return TRUE;
1794     }
1795     data_scan_ctx_advance (tf, c, 1);
1796   }
1797   return FALSE;
1798 }
1799
1800 /*** video/mpeg MPEG-4 elementary video stream ***/
1801
1802 static GstStaticCaps mpeg4_video_caps = GST_STATIC_CAPS ("video/mpeg, "
1803     "systemstream=(boolean)false, mpegversion=4, parsed=(boolean)false");
1804 #define MPEG4_VIDEO_CAPS gst_static_caps_get(&mpeg4_video_caps)
1805
1806 /*
1807  * This typefind is based on the elementary video header defined in
1808  * http://xhelmboyx.tripod.com/formats/mpeg-layout.txt
1809  * In addition, it allows the visual object sequence header to be
1810  * absent, and even the VOS header to be absent.  In the latter case,
1811  * a number of VOPs have to be present.
1812  */
1813 static void
1814 mpeg4_video_type_find (GstTypeFind * tf, gpointer unused)
1815 {
1816   DataScanCtx c = { 0, NULL, 0 };
1817   gboolean seen_vios_at_0 = FALSE;
1818   gboolean seen_vios = FALSE;
1819   gboolean seen_vos = FALSE;
1820   gboolean seen_vol = FALSE;
1821   guint num_vop_headers = 0;
1822   guint8 sc;
1823
1824   while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) {
1825     if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
1826       break;
1827
1828     if (!mpeg_find_next_header (tf, &c,
1829             GST_MPEGVID_TYPEFIND_TRY_SYNC - c.offset))
1830       break;
1831
1832     sc = c.data[0];
1833
1834     /* visual_object_sequence_start_code */
1835     if (sc == 0xB0) {
1836       if (seen_vios)
1837         break;                  /* Terminate at second vios */
1838       if (c.offset == 0)
1839         seen_vios_at_0 = TRUE;
1840       seen_vios = TRUE;
1841       data_scan_ctx_advance (tf, &c, 2);
1842       if (!mpeg_find_next_header (tf, &c, 0))
1843         break;
1844
1845       sc = c.data[0];
1846
1847       /* Optional metadata */
1848       if (sc == 0xB2)
1849         if (!mpeg_find_next_header (tf, &c, 24))
1850           break;
1851     }
1852
1853     /* visual_object_start_code (consider it optional) */
1854     if (sc == 0xB5) {
1855       data_scan_ctx_advance (tf, &c, 2);
1856       /* may contain ID marker and YUV clamping */
1857       if (!mpeg_find_next_header (tf, &c, 7))
1858         break;
1859
1860       sc = c.data[0];
1861     }
1862
1863     /* video_object_start_code */
1864     if (sc <= 0x1F) {
1865       if (seen_vos)
1866         break;                  /* Terminate at second vos */
1867       seen_vos = TRUE;
1868       data_scan_ctx_advance (tf, &c, 2);
1869       continue;
1870     }
1871
1872     /* video_object_layer_start_code */
1873     if (sc >= 0x20 && sc <= 0x2F) {
1874       seen_vol = TRUE;
1875       data_scan_ctx_advance (tf, &c, 5);
1876       continue;
1877     }
1878
1879     /* video_object_plane_start_code */
1880     if (sc == 0xB6) {
1881       num_vop_headers++;
1882       data_scan_ctx_advance (tf, &c, 2);
1883       continue;
1884     }
1885
1886     /* Unknown start code. */
1887   }
1888
1889   if (num_vop_headers > 0 || seen_vol) {
1890     GstTypeFindProbability probability = 0;
1891
1892     GST_LOG ("Found %d pictures, vios: %d, vos:%d, vol:%d", num_vop_headers,
1893         seen_vios, seen_vos, seen_vol);
1894
1895     if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vios_at_0
1896         && seen_vos && seen_vol)
1897       probability = GST_TYPE_FIND_MAXIMUM - 1;
1898     else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vios
1899         && seen_vos && seen_vol)
1900       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1;
1901     else if (seen_vios_at_0 && seen_vos && seen_vol)
1902       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 6;
1903     else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vos
1904         && seen_vol)
1905       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 6;
1906     else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vol)
1907       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9;
1908     else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
1909       probability = GST_TYPE_FIND_LIKELY - 1;
1910     else if (num_vop_headers > 2 && seen_vios && seen_vos && seen_vol)
1911       probability = GST_TYPE_FIND_LIKELY - 9;
1912     else if (seen_vios && seen_vos && seen_vol)
1913       probability = GST_TYPE_FIND_LIKELY - 20;
1914     else if (num_vop_headers > 0 && seen_vos && seen_vol)
1915       probability = GST_TYPE_FIND_POSSIBLE;
1916     else if (num_vop_headers > 0)
1917       probability = GST_TYPE_FIND_POSSIBLE - 10;
1918     else if (seen_vos && seen_vol)
1919       probability = GST_TYPE_FIND_POSSIBLE - 20;
1920
1921     gst_type_find_suggest (tf, probability, MPEG4_VIDEO_CAPS);
1922   }
1923 }
1924
1925 /*** video/x-h264 H264 elementary video stream ***/
1926
1927 static GstStaticCaps h264_video_caps = GST_STATIC_CAPS ("video/x-h264");
1928
1929 #define H264_VIDEO_CAPS gst_static_caps_get(&h264_video_caps)
1930
1931 #define H264_MAX_PROBE_LENGTH (128 * 1024)      /* 128kB for HD should be enough. */
1932
1933 static void
1934 h264_video_type_find (GstTypeFind * tf, gpointer unused)
1935 {
1936   DataScanCtx c = { 0, NULL, 0 };
1937
1938   /* Stream consists of: a series of sync codes (00 00 00 01) followed 
1939    * by NALs
1940    */
1941   int nut, ref;
1942   int good = 0;
1943   int bad = 0;
1944
1945   while (c.offset < H264_MAX_PROBE_LENGTH) {
1946     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
1947       break;
1948
1949     if (IS_MPEG_HEADER (c.data)) {
1950       nut = c.data[3] & 0x9f;   /* forbiden_zero_bit | nal_unit_type */
1951       ref = c.data[3] & 0x60;   /* nal_ref_idc */
1952
1953       /* if forbiden bit is different to 0 won't be h264 */
1954       if (nut > 0x1f) {
1955         bad++;
1956         break;
1957       }
1958
1959       /* collect statistics about the NAL types */
1960       if ((nut >= 1 && nut <= 13) || nut == 19) {
1961         if ((nut == 5 && ref == 0) ||
1962             ((nut == 6 || (nut >= 9 && nut <= 12)) && ref != 0)) {
1963           bad++;
1964         } else {
1965           good++;
1966         }
1967       } else if (nut >= 14 && nut <= 33) {
1968         /* reserved */
1969         /* Theoretically these are good, since if they exist in the
1970            stream it merely means that a newer backwards-compatible
1971            h.264 stream.  But we should be identifying that separately. */
1972         bad++;
1973       } else {
1974         /* unspecified, application specific */
1975         /* don't consider these bad */
1976       }
1977
1978       GST_DEBUG ("good %d bad %d", good, bad);
1979
1980       if (good >= 10 && bad < 4) {
1981         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
1982         return;
1983       }
1984
1985       data_scan_ctx_advance (tf, &c, 4);
1986     }
1987     data_scan_ctx_advance (tf, &c, 1);
1988   }
1989
1990   if (good >= 2 && bad < 1) {
1991     gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H264_VIDEO_CAPS);
1992     return;
1993   }
1994 }
1995
1996 /*** video/mpeg video stream ***/
1997
1998 static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
1999     "systemstream = (boolean) false");
2000 #define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps)
2001
2002 /*
2003  * Idea is the same as MPEG system stream typefinding: We check each
2004  * byte of the stream to see if - from that point on - the stream
2005  * matches a predefined set of marker bits as defined in the MPEG
2006  * video specs.
2007  *
2008  * I'm sure someone will do a chance calculation here too.
2009  */
2010
2011 static void
2012 mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
2013 {
2014   DataScanCtx c = { 0, NULL, 0 };
2015   gboolean seen_seq_at_0 = FALSE;
2016   gboolean seen_seq = FALSE;
2017   gboolean seen_gop = FALSE;
2018   guint64 last_pic_offset = 0;
2019   guint num_pic_headers = 0;
2020   gint found = 0;
2021
2022   while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) {
2023     if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
2024       break;
2025
2026     if (!data_scan_ctx_ensure_data (tf, &c, 5))
2027       break;
2028
2029     if (!IS_MPEG_HEADER (c.data))
2030       goto next;
2031
2032     /* a pack header indicates that this isn't an elementary stream */
2033     if (c.data[3] == 0xBA && mpeg_sys_is_valid_pack (tf, c.data, c.size, NULL))
2034       return;
2035
2036     /* do we have a sequence header? */
2037     if (c.data[3] == 0xB3) {
2038       seen_seq_at_0 = seen_seq_at_0 || (c.offset == 0);
2039       seen_seq = TRUE;
2040       data_scan_ctx_advance (tf, &c, 4 + 8);
2041       continue;
2042     }
2043
2044     /* or a GOP header */
2045     if (c.data[3] == 0xB8) {
2046       seen_gop = TRUE;
2047       data_scan_ctx_advance (tf, &c, 8);
2048       continue;
2049     }
2050
2051     /* but what we'd really like to see is a picture header */
2052     if (c.data[3] == 0x00) {
2053       ++num_pic_headers;
2054       last_pic_offset = c.offset;
2055       data_scan_ctx_advance (tf, &c, 8);
2056       continue;
2057     }
2058
2059     /* ... each followed by a slice header with slice_vertical_pos=1 that's
2060      * not too far away from the previously seen picture header. */
2061     if (c.data[3] == 0x01 && num_pic_headers > found &&
2062         (c.offset - last_pic_offset) >= 4 &&
2063         (c.offset - last_pic_offset) <= 64) {
2064       data_scan_ctx_advance (tf, &c, 4);
2065       found += 1;
2066       continue;
2067     }
2068
2069   next:
2070
2071     data_scan_ctx_advance (tf, &c, 1);
2072   }
2073
2074   if (found > 0 || seen_seq) {
2075     GstTypeFindProbability probability = 0;
2076
2077     GST_LOG ("Found %d pictures, seq:%d, gop:%d", found, seen_seq, seen_gop);
2078
2079     if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq && seen_gop)
2080       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1;
2081     else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq)
2082       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9;
2083     else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
2084       probability = GST_TYPE_FIND_LIKELY;
2085     else if (seen_seq_at_0 && seen_gop && found > 2)
2086       probability = GST_TYPE_FIND_LIKELY - 10;
2087     else if (seen_seq && seen_gop && found > 2)
2088       probability = GST_TYPE_FIND_LIKELY - 20;
2089     else if (seen_seq_at_0 && found > 0)
2090       probability = GST_TYPE_FIND_POSSIBLE;
2091     else if (seen_seq && found > 0)
2092       probability = GST_TYPE_FIND_POSSIBLE - 5;
2093     else if (found > 0)
2094       probability = GST_TYPE_FIND_POSSIBLE - 10;
2095     else if (seen_seq)
2096       probability = GST_TYPE_FIND_POSSIBLE - 20;
2097
2098     gst_type_find_suggest_simple (tf, probability, "video/mpeg",
2099         "systemstream", G_TYPE_BOOLEAN, FALSE,
2100         "mpegversion", G_TYPE_INT, 1, NULL);
2101   }
2102 }
2103
2104 /*** audio/x-aiff ***/
2105
2106 static GstStaticCaps aiff_caps = GST_STATIC_CAPS ("audio/x-aiff");
2107
2108 #define AIFF_CAPS gst_static_caps_get(&aiff_caps)
2109 static void
2110 aiff_type_find (GstTypeFind * tf, gpointer unused)
2111 {
2112   guint8 *data = gst_type_find_peek (tf, 0, 4);
2113
2114   if (data && memcmp (data, "FORM", 4) == 0) {
2115     data += 8;
2116     if (memcmp (data, "AIFF", 4) == 0 || memcmp (data, "AIFC", 4) == 0)
2117       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AIFF_CAPS);
2118   }
2119 }
2120
2121 /*** audio/x-svx ***/
2122
2123 static GstStaticCaps svx_caps = GST_STATIC_CAPS ("audio/x-svx");
2124
2125 #define SVX_CAPS gst_static_caps_get(&svx_caps)
2126 static void
2127 svx_type_find (GstTypeFind * tf, gpointer unused)
2128 {
2129   guint8 *data = gst_type_find_peek (tf, 0, 4);
2130
2131   if (data && memcmp (data, "FORM", 4) == 0) {
2132     data += 8;
2133     if (memcmp (data, "8SVX", 4) == 0 || memcmp (data, "16SV", 4) == 0)
2134       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SVX_CAPS);
2135   }
2136 }
2137
2138 /*** audio/x-shorten ***/
2139
2140 static GstStaticCaps shn_caps = GST_STATIC_CAPS ("audio/x-shorten");
2141
2142 #define SHN_CAPS gst_static_caps_get(&shn_caps)
2143 static void
2144 shn_type_find (GstTypeFind * tf, gpointer unused)
2145 {
2146   guint8 *data = gst_type_find_peek (tf, 0, 4);
2147
2148   if (data && memcmp (data, "ajkg", 4) == 0) {
2149     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS);
2150   }
2151   data = gst_type_find_peek (tf, -8, 8);
2152   if (data && memcmp (data, "SHNAMPSK", 8) == 0) {
2153     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS);
2154   }
2155 }
2156
2157 /*** application/x-ape ***/
2158
2159 static GstStaticCaps ape_caps = GST_STATIC_CAPS ("application/x-ape");
2160
2161 #define APE_CAPS gst_static_caps_get(&ape_caps)
2162 static void
2163 ape_type_find (GstTypeFind * tf, gpointer unused)
2164 {
2165   guint8 *data = gst_type_find_peek (tf, 0, 4);
2166
2167   if (data && memcmp (data, "MAC ", 4) == 0) {
2168     gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, APE_CAPS);
2169   }
2170 }
2171
2172 /*** ISO FORMATS ***/
2173
2174 /*** audio/x-m4a ***/
2175
2176 static GstStaticCaps m4a_caps = GST_STATIC_CAPS ("audio/x-m4a");
2177
2178 #define M4A_CAPS (gst_static_caps_get(&m4a_caps))
2179 static void
2180 m4a_type_find (GstTypeFind * tf, gpointer unused)
2181 {
2182   guint8 *data = gst_type_find_peek (tf, 4, 8);
2183
2184   if (data &&
2185       (memcmp (data, "ftypM4A ", 8) == 0 ||
2186           memcmp (data, "ftypmp42", 8) == 0)) {
2187     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M4A_CAPS);
2188   }
2189 }
2190
2191 /*** application/x-3gp ***/
2192
2193 /* The Q is there because variables can't start with a number. */
2194
2195
2196 static GstStaticCaps q3gp_caps = GST_STATIC_CAPS ("application/x-3gp");
2197
2198 #define Q3GP_CAPS (gst_static_caps_get(&q3gp_caps))
2199 static void
2200 q3gp_type_find (GstTypeFind * tf, gpointer unused)
2201 {
2202
2203   guint32 ftyp_size = 0;
2204   gint offset = 0;
2205   guint8 *data = NULL;
2206
2207   if ((data = gst_type_find_peek (tf, 0, 12)) == NULL) {
2208     return;
2209   }
2210
2211   data += 4;
2212   if (memcmp (data, "ftyp", 4) != 0) {
2213     return;
2214   }
2215
2216   /* check major brand */
2217   data += 4;
2218   if (memcmp (data, "3gp", 3) == 0 ||
2219       memcmp (data, "3gr", 3) == 0 ||
2220       memcmp (data, "3gs", 3) == 0 || memcmp (data, "3gg", 3) == 0) {
2221     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, Q3GP_CAPS);
2222     return;
2223   }
2224
2225   /* check compatible brands */
2226   if ((data = gst_type_find_peek (tf, 0, 4)) != NULL) {
2227     ftyp_size = GST_READ_UINT32_BE (data);
2228   }
2229   for (offset = 16; offset < ftyp_size; offset += 4) {
2230     if ((data = gst_type_find_peek (tf, offset, 3)) == NULL) {
2231       break;
2232     }
2233     if (memcmp (data, "3gp", 3) == 0 ||
2234         memcmp (data, "3gr", 3) == 0 ||
2235         memcmp (data, "3gs", 3) == 0 || memcmp (data, "3gg", 3) == 0) {
2236       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, Q3GP_CAPS);
2237       break;
2238     }
2239   }
2240
2241   return;
2242
2243 }
2244
2245 /*** video/mj2 and image/jp2 ***/
2246 static GstStaticCaps mj2_caps = GST_STATIC_CAPS ("video/mj2");
2247
2248 #define MJ2_CAPS gst_static_caps_get(&mj2_caps)
2249
2250 static GstStaticCaps jp2_caps = GST_STATIC_CAPS ("image/jp2");
2251
2252 #define JP2_CAPS gst_static_caps_get(&jp2_caps)
2253
2254 static void
2255 jp2_type_find (GstTypeFind * tf, gpointer unused)
2256 {
2257   guint8 *data;
2258
2259   data = gst_type_find_peek (tf, 0, 24);
2260   if (!data)
2261     return;
2262
2263   /* jp2 signature */
2264   if (memcmp (data, "\000\000\000\014jP  \015\012\207\012", 12) != 0)
2265     return;
2266
2267   /* check ftyp box */
2268   data += 12;
2269   if (memcmp (data + 4, "ftyp", 4) == 0) {
2270     if (memcmp (data + 8, "jp2 ", 4) == 0)
2271       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JP2_CAPS);
2272     else if (memcmp (data + 8, "mjp2", 4) == 0)
2273       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MJ2_CAPS);
2274   }
2275 }
2276
2277 /*** video/quicktime ***/
2278
2279 static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime");
2280
2281 #define QT_CAPS gst_static_caps_get(&qt_caps)
2282 #define STRNCMP(x,y,z) (strncmp ((char*)(x), (char*)(y), z))
2283
2284 static void
2285 qt_type_find (GstTypeFind * tf, gpointer unused)
2286 {
2287   guint8 *data;
2288   guint tip = 0;
2289   guint64 offset = 0;
2290   guint64 size;
2291   const gchar *variant = NULL;
2292
2293   while ((data = gst_type_find_peek (tf, offset, 12)) != NULL) {
2294     guint64 new_offset;
2295
2296     if (STRNCMP (&data[4], "ftypqt  ", 8) == 0) {
2297       tip = GST_TYPE_FIND_MAXIMUM;
2298       break;
2299     }
2300
2301     if (STRNCMP (&data[4], "ftypisom", 8) == 0) {
2302       tip = GST_TYPE_FIND_MAXIMUM;
2303       variant = "iso";
2304       break;
2305     }
2306
2307     /* box/atom types that are in common with ISO base media file format */
2308     if (STRNCMP (&data[4], "moov", 4) == 0 ||
2309         STRNCMP (&data[4], "mdat", 4) == 0 ||
2310         STRNCMP (&data[4], "ftyp", 4) == 0 ||
2311         STRNCMP (&data[4], "free", 4) == 0 ||
2312         STRNCMP (&data[4], "uuid", 4) == 0 ||
2313         STRNCMP (&data[4], "skip", 4) == 0) {
2314       if (tip == 0) {
2315         tip = GST_TYPE_FIND_LIKELY;
2316       } else {
2317         tip = GST_TYPE_FIND_NEARLY_CERTAIN;
2318       }
2319     }
2320     /* other box/atom types, apparently quicktime specific */
2321     else if (STRNCMP (&data[4], "pnot", 4) == 0 ||
2322         STRNCMP (&data[4], "PICT", 4) == 0 ||
2323         STRNCMP (&data[4], "wide", 4) == 0 ||
2324         STRNCMP (&data[4], "prfl", 4) == 0) {
2325       tip = GST_TYPE_FIND_MAXIMUM;
2326       break;
2327     } else {
2328       tip = 0;
2329       break;
2330     }
2331     size = GST_READ_UINT32_BE (data);
2332     if (size == 1) {
2333       guint8 *sizedata;
2334
2335       sizedata = gst_type_find_peek (tf, offset + 8, 8);
2336       if (sizedata == NULL)
2337         break;
2338
2339       size = GST_READ_UINT64_BE (sizedata);
2340     } else {
2341       if (size < 8)
2342         break;
2343     }
2344     new_offset = offset + size;
2345     if (new_offset <= offset)
2346       break;
2347     offset = new_offset;
2348   }
2349
2350   if (tip > 0) {
2351     if (variant) {
2352       GstCaps *caps = gst_caps_copy (QT_CAPS);
2353
2354       gst_caps_set_simple (caps, "variant", G_TYPE_STRING, variant, NULL);
2355       gst_type_find_suggest (tf, tip, caps);
2356       gst_caps_unref (caps);
2357     } else {
2358       gst_type_find_suggest (tf, tip, QT_CAPS);
2359     }
2360   }
2361 };
2362
2363
2364 /*** image/x-quicktime ***/
2365
2366 static GstStaticCaps qtif_caps = GST_STATIC_CAPS ("image/x-quicktime");
2367
2368 #define QTIF_CAPS gst_static_caps_get(&qtif_caps)
2369
2370 /* how many atoms we check before we give up */
2371 #define QTIF_MAXROUNDS 25
2372
2373 static void
2374 qtif_type_find (GstTypeFind * tf, gpointer unused)
2375 {
2376   const guint8 *data;
2377   gboolean found_idsc = FALSE;
2378   gboolean found_idat = FALSE;
2379   guint64 offset = 0;
2380   guint rounds = 0;
2381
2382   while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
2383     guint64 size;
2384
2385     size = GST_READ_UINT32_BE (data);
2386     if (size == 1) {
2387       const guint8 *sizedata;
2388
2389       sizedata = gst_type_find_peek (tf, offset + 8, 8);
2390       if (sizedata == NULL)
2391         break;
2392
2393       size = GST_READ_UINT64_BE (sizedata);
2394     }
2395     if (size < 8)
2396       break;
2397
2398     if (STRNCMP (data + 4, "idsc", 4) == 0)
2399       found_idsc = TRUE;
2400     if (STRNCMP (data + 4, "idat", 4) == 0)
2401       found_idat = TRUE;
2402
2403     if (found_idsc && found_idat) {
2404       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, QTIF_CAPS);
2405       return;
2406     }
2407
2408     offset += size;
2409     if (++rounds > QTIF_MAXROUNDS)
2410       break;
2411   }
2412
2413   if (found_idsc || found_idat) {
2414     gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, QTIF_CAPS);
2415     return;
2416   }
2417 };
2418
2419 /*** audio/x-mod ***/
2420
2421 static GstStaticCaps mod_caps = GST_STATIC_CAPS ("audio/x-mod");
2422
2423 #define MOD_CAPS gst_static_caps_get(&mod_caps)
2424 /* FIXME: M15 CheckType to do */
2425 static void
2426 mod_type_find (GstTypeFind * tf, gpointer unused)
2427 {
2428   guint8 *data;
2429
2430   /* MOD */
2431   if ((data = gst_type_find_peek (tf, 1080, 4)) != NULL) {
2432     /* Protracker and variants */
2433     if ((memcmp (data, "M.K.", 4) == 0) || (memcmp (data, "M!K!", 4) == 0) ||
2434         /* Star Tracker */
2435         (memcmp (data, "FLT", 3) == 0 && isdigit (data[3])) ||
2436         (memcmp (data, "EXO", 3) == 0 && isdigit (data[3])) ||
2437         /* Oktalyzer (Amiga) */
2438         (memcmp (data, "OKTA", 4) == 0) ||
2439         /* Oktalyser (Atari) */
2440         (memcmp (data, "CD81", 4) == 0) ||
2441         /* Fasttracker */
2442         (memcmp (data + 1, "CHN", 3) == 0 && isdigit (data[0])) ||
2443         /* Fasttracker or Taketracker */
2444         (memcmp (data + 2, "CH", 2) == 0 && isdigit (data[0])
2445             && isdigit (data[1])) || (memcmp (data + 2, "CN", 2) == 0
2446             && isdigit (data[0]) && isdigit (data[1]))) {
2447       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2448       return;
2449     }
2450   }
2451   /* XM */
2452   if ((data = gst_type_find_peek (tf, 0, 38)) != NULL) {
2453     if (memcmp (data, "Extended Module: ", 17) == 0 && data[37] == 0x1A) {
2454       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2455       return;
2456     }
2457   }
2458   /* OKT */
2459   if (data || (data = gst_type_find_peek (tf, 0, 8)) != NULL) {
2460     if (memcmp (data, "OKTASONG", 8) == 0) {
2461       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2462       return;
2463     }
2464   }
2465   if (data || (data = gst_type_find_peek (tf, 0, 4)) != NULL) {
2466     /* 669 */
2467     if ((memcmp (data, "if", 2) == 0) || (memcmp (data, "JN", 2) == 0)) {
2468       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2469       return;
2470     }
2471     /* AMF */
2472     if ((memcmp (data, "AMF", 3) == 0 && data[3] > 10 && data[3] < 14) ||
2473         /* IT */
2474         (memcmp (data, "IMPM", 4) == 0) ||
2475         /* MED */
2476         (memcmp (data, "MMD0", 4) == 0) || (memcmp (data, "MMD1", 4) == 0) ||
2477         /* MTM */
2478         (memcmp (data, "MTM", 3) == 0)) {
2479       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2480       return;
2481     }
2482     /* DSM */
2483     if (memcmp (data, "RIFF", 4) == 0) {
2484       guint8 *data2 = gst_type_find_peek (tf, 8, 4);
2485
2486       if (data2) {
2487         if (memcmp (data2, "DSMF", 4) == 0) {
2488           gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2489           return;
2490         }
2491       }
2492     }
2493     /* FAM */
2494     if (memcmp (data, "FAM\xFE", 4) == 0) {
2495       guint8 *data2 = gst_type_find_peek (tf, 44, 3);
2496
2497       if (data2) {
2498         if (memcmp (data2, "compare", 3) == 0) {
2499           gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2500           return;
2501         }
2502       } else {
2503         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2504         return;
2505       }
2506     }
2507     /* GDM */
2508     if (memcmp (data, "GDM\xFE", 4) == 0) {
2509       guint8 *data2 = gst_type_find_peek (tf, 71, 4);
2510
2511       if (data2) {
2512         if (memcmp (data2, "GMFS", 4) == 0) {
2513           gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2514           return;
2515         }
2516       } else {
2517         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2518         return;
2519       }
2520     }
2521   }
2522   /* IMF */
2523   if ((data = gst_type_find_peek (tf, 60, 4)) != NULL) {
2524     if (memcmp (data, "IM10", 4) == 0) {
2525       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2526       return;
2527     }
2528   }
2529   /* S3M */
2530   if ((data = gst_type_find_peek (tf, 44, 4)) != NULL) {
2531     if (memcmp (data, "SCRM", 4) == 0) {
2532       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2533       return;
2534     }
2535   }
2536   /* STM */
2537   if ((data = gst_type_find_peek (tf, 20, 8)) != NULL) {
2538     if (g_ascii_strncasecmp ((gchar *) data, "!Scream!", 8) == 0 ||
2539         g_ascii_strncasecmp ((gchar *) data, "BMOD2STM", 8) == 0) {
2540       guint8 *id, *stmtype;
2541
2542       if ((id = gst_type_find_peek (tf, 28, 1)) == NULL)
2543         return;
2544       if ((stmtype = gst_type_find_peek (tf, 29, 1)) == NULL)
2545         return;
2546       if (*id == 0x1A && *stmtype == 2)
2547         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2548       return;
2549     }
2550   }
2551 }
2552
2553 /*** application/x-shockwave-flash ***/
2554
2555 static GstStaticCaps swf_caps =
2556 GST_STATIC_CAPS ("application/x-shockwave-flash");
2557 #define SWF_CAPS (gst_static_caps_get(&swf_caps))
2558 static void
2559 swf_type_find (GstTypeFind * tf, gpointer unused)
2560 {
2561   guint8 *data = gst_type_find_peek (tf, 0, 4);
2562
2563   if (data && (data[0] == 'F' || data[0] == 'C') &&
2564       data[1] == 'W' && data[2] == 'S') {
2565     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SWF_CAPS);
2566   }
2567 }
2568
2569 /*** image/jpeg ***/
2570
2571 static GstStaticCaps jpeg_caps = GST_STATIC_CAPS ("image/jpeg");
2572
2573 #define JPEG_CAPS (gst_static_caps_get(&jpeg_caps))
2574 static void
2575 jpeg_type_find (GstTypeFind * tf, gpointer unused)
2576 {
2577   guint8 *data = gst_type_find_peek (tf, 0, 10);
2578   guint8 header[2] = { 0xFF, 0xD8 };
2579
2580   if (data && memcmp (data, header, 2) == 0) {
2581     if (memcmp (data + 6, "JFIF", 4) == 0) {
2582       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JPEG_CAPS);
2583     } else if (memcmp (data + 6, "Exif", 4) == 0) {
2584       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JPEG_CAPS);
2585     } else {
2586       gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, JPEG_CAPS);
2587     }
2588   }
2589 }
2590
2591 /*** image/bmp ***/
2592
2593 static GstStaticCaps bmp_caps = GST_STATIC_CAPS ("image/bmp");
2594
2595 #define BMP_CAPS (gst_static_caps_get(&bmp_caps))
2596 static void
2597 bmp_type_find (GstTypeFind * tf, gpointer unused)
2598 {
2599   DataScanCtx c = { 0, NULL, 0 };
2600   guint32 struct_size, w, h, planes, bpp;
2601
2602   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 54)))
2603     return;
2604
2605   if (c.data[0] != 'B' || c.data[1] != 'M')
2606     return;
2607
2608   /* skip marker + size */
2609   data_scan_ctx_advance (tf, &c, 2 + 4);
2610
2611   /* reserved, must be 0 */
2612   if (c.data[0] != 0 || c.data[1] != 0 || c.data[2] != 0 || c.data[3] != 0)
2613     return;
2614
2615   data_scan_ctx_advance (tf, &c, 2 + 2);
2616
2617   /* offset to start of image data in bytes (check for sanity) */
2618   GST_LOG ("offset=%u", GST_READ_UINT32_LE (c.data));
2619   if (GST_READ_UINT32_LE (c.data) > (10 * 1024 * 1024))
2620     return;
2621
2622   struct_size = GST_READ_UINT32_LE (c.data + 4);
2623   GST_LOG ("struct_size=%u", struct_size);
2624
2625   data_scan_ctx_advance (tf, &c, 4 + 4);
2626
2627   if (struct_size == 0x0C) {
2628     w = GST_READ_UINT16_LE (c.data);
2629     h = GST_READ_UINT16_LE (c.data + 2);
2630     planes = GST_READ_UINT16_LE (c.data + 2 + 2);
2631     bpp = GST_READ_UINT16_LE (c.data + 2 + 2 + 2);
2632   } else if (struct_size == 40 || struct_size == 64 || struct_size == 108
2633       || struct_size == 124 || struct_size == 0xF0) {
2634     w = GST_READ_UINT32_LE (c.data);
2635     h = GST_READ_UINT32_LE (c.data + 4);
2636     planes = GST_READ_UINT16_LE (c.data + 4 + 4);
2637     bpp = GST_READ_UINT16_LE (c.data + 4 + 4 + 2);
2638   } else {
2639     return;
2640   }
2641
2642   /* image sizes sanity check */
2643   GST_LOG ("w=%u, h=%u, planes=%u, bpp=%u", w, h, planes, bpp);
2644   if (w == 0 || w > 0xfffff || h == 0 || h > 0xfffff || planes != 1 ||
2645       (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32))
2646     return;
2647
2648   gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "image/bmp",
2649       "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, "bpp", G_TYPE_INT, bpp,
2650       NULL);
2651 }
2652
2653 /*** image/tiff ***/
2654 static GstStaticCaps tiff_caps = GST_STATIC_CAPS ("image/tiff, "
2655     "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }");
2656 #define TIFF_CAPS (gst_static_caps_get(&tiff_caps))
2657 static GstStaticCaps tiff_be_caps = GST_STATIC_CAPS ("image/tiff, "
2658     "endianness = (int) BIG_ENDIAN");
2659 #define TIFF_BE_CAPS (gst_static_caps_get(&tiff_be_caps))
2660 static GstStaticCaps tiff_le_caps = GST_STATIC_CAPS ("image/tiff, "
2661     "endianness = (int) LITTLE_ENDIAN");
2662 #define TIFF_LE_CAPS (gst_static_caps_get(&tiff_le_caps))
2663 static void
2664 tiff_type_find (GstTypeFind * tf, gpointer ununsed)
2665 {
2666   guint8 *data = gst_type_find_peek (tf, 0, 8);
2667   guint8 le_header[4] = { 0x49, 0x49, 0x2A, 0x00 };
2668   guint8 be_header[4] = { 0x4D, 0x4D, 0x00, 0x2A };
2669
2670   if (data) {
2671     if (memcmp (data, le_header, 4) == 0) {
2672       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_LE_CAPS);
2673     } else if (memcmp (data, be_header, 4) == 0) {
2674       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_BE_CAPS);
2675     }
2676   }
2677 }
2678
2679 /*** PNM ***/
2680
2681 static GstStaticCaps pnm_caps = GST_STATIC_CAPS ("image/x-portable-bitmap; "
2682     "image/x-portable-graymap; image/x-portable-pixmap; "
2683     "image/x-portable-anymap");
2684
2685 #define PNM_CAPS (gst_static_caps_get(&pnm_caps))
2686
2687 #define IS_PNM_WHITESPACE(c) \
2688     ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == 't')
2689
2690 static void
2691 pnm_type_find (GstTypeFind * tf, gpointer ununsed)
2692 {
2693   const gchar *media_type = NULL;
2694   DataScanCtx c = { 0, NULL, 0 };
2695   guint h = 0, w = 0;
2696
2697   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 16)))
2698     return;
2699
2700   /* see http://en.wikipedia.org/wiki/Netpbm_format */
2701   if (c.data[0] != 'P' || c.data[1] < '1' || c.data[1] > '7' ||
2702       !IS_PNM_WHITESPACE (c.data[2]) ||
2703       (c.data[3] != '#' && c.data[3] < '0' && c.data[3] > '9'))
2704     return;
2705
2706   switch (c.data[1]) {
2707     case '1':
2708       media_type = "image/x-portable-bitmap";   /* ASCII */
2709       break;
2710     case '2':
2711       media_type = "image/x-portable-graymap";  /* ASCII */
2712       break;
2713     case '3':
2714       media_type = "image/x-portable-pixmap";   /* ASCII */
2715       break;
2716     case '4':
2717       media_type = "image/x-portable-bitmap";   /* Raw */
2718       break;
2719     case '5':
2720       media_type = "image/x-portable-graymap";  /* Raw */
2721       break;
2722     case '6':
2723       media_type = "image/x-portable-pixmap";   /* Raw */
2724       break;
2725     case '7':
2726       media_type = "image/x-portable-anymap";
2727       break;
2728     default:
2729       g_return_if_reached ();
2730   }
2731
2732   /* try to extract width and height as well */
2733   if (c.data[1] != '7') {
2734     gchar s[64] = { 0, }
2735     , sep1, sep2;
2736
2737     /* need to skip any comment lines first */
2738     data_scan_ctx_advance (tf, &c, 3);
2739     while (c.data[0] == '#') {  /* we know there's still data left */
2740       data_scan_ctx_advance (tf, &c, 1);
2741       while (c.data[0] != '\n' && c.data[0] != '\r') {
2742         if (!data_scan_ctx_ensure_data (tf, &c, 4))
2743           return;
2744         data_scan_ctx_advance (tf, &c, 1);
2745       }
2746       data_scan_ctx_advance (tf, &c, 1);
2747       GST_LOG ("skipped comment line in PNM header");
2748     }
2749
2750     if (!data_scan_ctx_ensure_data (tf, &c, 32) &&
2751         !data_scan_ctx_ensure_data (tf, &c, 4)) {
2752       return;
2753     }
2754
2755     /* need to NUL-terminate data for sscanf */
2756     memcpy (s, c.data, MIN (sizeof (s) - 1, c.size));
2757     if (sscanf (s, "%u%c%u%c", &w, &sep1, &h, &sep2) == 4 &&
2758         IS_PNM_WHITESPACE (sep1) && IS_PNM_WHITESPACE (sep2) &&
2759         w > 0 && w < G_MAXINT && h > 0 && h < G_MAXINT) {
2760       GST_LOG ("extracted PNM width and height: %dx%d", w, h);
2761     } else {
2762       w = 0;
2763       h = 0;
2764     }
2765   } else {
2766     /* FIXME: extract width + height for anymaps too */
2767   }
2768
2769   if (w > 0 && h > 0) {
2770     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, media_type,
2771         "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL);
2772   } else {
2773     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, media_type, NULL);
2774   }
2775 }
2776
2777 static GstStaticCaps sds_caps = GST_STATIC_CAPS ("audio/x-sds");
2778
2779 #define SDS_CAPS (gst_static_caps_get(&sds_caps))
2780 static void
2781 sds_type_find (GstTypeFind * tf, gpointer ununsed)
2782 {
2783   guint8 *data = gst_type_find_peek (tf, 0, 4);
2784   guint8 mask[4] = { 0xFF, 0xFF, 0x80, 0xFF };
2785   guint8 match[4] = { 0xF0, 0x7E, 0, 0x01 };
2786   gint x;
2787
2788   if (data) {
2789     for (x = 0; x < 4; x++) {
2790       if ((data[x] & mask[x]) != match[x]) {
2791         return;
2792       }
2793     }
2794     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SDS_CAPS);
2795   }
2796 }
2797
2798 static GstStaticCaps ircam_caps = GST_STATIC_CAPS ("audio/x-ircam");
2799
2800 #define IRCAM_CAPS (gst_static_caps_get(&ircam_caps))
2801 static void
2802 ircam_type_find (GstTypeFind * tf, gpointer ununsed)
2803 {
2804   guint8 *data = gst_type_find_peek (tf, 0, 4);
2805   guint8 mask[4] = { 0xFF, 0xFF, 0xF8, 0xFF };
2806   guint8 match[4] = { 0x64, 0xA3, 0x00, 0x00 };
2807   gint x;
2808   gboolean matched = TRUE;
2809
2810   if (!data) {
2811     return;
2812   }
2813   for (x = 0; x < 4; x++) {
2814     if ((data[x] & mask[x]) != match[x]) {
2815       matched = FALSE;
2816     }
2817   }
2818   if (matched) {
2819     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, IRCAM_CAPS);
2820     return;
2821   }
2822   /* now try the reverse version */
2823   matched = TRUE;
2824   for (x = 0; x < 4; x++) {
2825     if ((data[x] & mask[3 - x]) != match[3 - x]) {
2826       matched = FALSE;
2827     }
2828   }
2829 }
2830
2831 /* EBML typefind helper */
2832 static gboolean
2833 ebml_check_header (GstTypeFind * tf, const gchar * doctype, int doctype_len)
2834 {
2835   /* 4 bytes for EBML ID, 1 byte for header length identifier */
2836   guint8 *data = gst_type_find_peek (tf, 0, 4 + 1);
2837   gint len_mask = 0x80, size = 1, n = 1, total;
2838
2839   if (!data)
2840     return FALSE;
2841
2842   /* ebml header? */
2843   if (data[0] != 0x1A || data[1] != 0x45 || data[2] != 0xDF || data[3] != 0xA3)
2844     return FALSE;
2845
2846   /* length of header */
2847   total = data[4];
2848   while (size <= 8 && !(total & len_mask)) {
2849     size++;
2850     len_mask >>= 1;
2851   }
2852   if (size > 8)
2853     return FALSE;
2854   total &= (len_mask - 1);
2855   while (n < size)
2856     total = (total << 8) | data[4 + n++];
2857
2858   /* get new data for full header, 4 bytes for EBML ID,
2859    * EBML length tag and the actual header */
2860   data = gst_type_find_peek (tf, 0, 4 + size + total);
2861   if (!data)
2862     return FALSE;
2863
2864   /* the header must contain the doctype. For now, we don't parse the
2865    * whole header but simply check for the availability of that array
2866    * of characters inside the header. Not fully fool-proof, but good
2867    * enough. */
2868   for (n = 4 + size; n <= 4 + size + total - doctype_len; n++)
2869     if (!memcmp (&data[n], doctype, doctype_len))
2870       return TRUE;
2871
2872   return FALSE;
2873 }
2874
2875 /*** video/x-matroska ***/
2876 static GstStaticCaps matroska_caps = GST_STATIC_CAPS ("video/x-matroska");
2877
2878 #define MATROSKA_CAPS (gst_static_caps_get(&matroska_caps))
2879 static void
2880 matroska_type_find (GstTypeFind * tf, gpointer ununsed)
2881 {
2882   if (ebml_check_header (tf, "matroska", 8))
2883     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MATROSKA_CAPS);
2884 }
2885
2886 /*** video/webm ***/
2887 static GstStaticCaps webm_caps = GST_STATIC_CAPS ("video/webm");
2888
2889 #define WEBM_CAPS (gst_static_caps_get(&webm_caps))
2890 static void
2891 webm_type_find (GstTypeFind * tf, gpointer ununsed)
2892 {
2893   if (ebml_check_header (tf, "webm", 4))
2894     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, WEBM_CAPS);
2895 }
2896
2897 /*** application/mxf ***/
2898 static GstStaticCaps mxf_caps = GST_STATIC_CAPS ("application/mxf");
2899
2900 #define MXF_MAX_PROBE_LENGTH (1024 * 64)
2901 #define MXF_CAPS (gst_static_caps_get(&mxf_caps))
2902
2903 /*
2904  * MXF files start with a header partition pack key of 16 bytes which is defined
2905  * at SMPTE-377M 6.1. Before this there can be up to 64K of run-in which _must_
2906  * not contain the partition pack key.
2907  */
2908 static void
2909 mxf_type_find (GstTypeFind * tf, gpointer ununsed)
2910 {
2911   static const guint8 partition_pack_key[] =
2912       { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
2913     0x01
2914   };
2915   DataScanCtx c = { 0, NULL, 0 };
2916
2917   while (c.offset <= MXF_MAX_PROBE_LENGTH) {
2918     guint i;
2919     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 1024)))
2920       break;
2921
2922     /* look over in chunks of 1kbytes to avoid too much overhead */
2923
2924     for (i = 0; i < 1024 - 16; i++) {
2925       /* Check first byte before calling more expensive memcmp function */
2926       if (G_UNLIKELY (c.data[i] == 0x06
2927               && memcmp (c.data + i, partition_pack_key, 13) == 0)) {
2928         /* Header partition pack? */
2929         if (c.data[i + 13] != 0x02)
2930           goto advance;
2931
2932         /* Partition status */
2933         if (c.data[i + 14] >= 0x05)
2934           goto advance;
2935
2936         /* Reserved, must be 0x00 */
2937         if (c.data[i + 15] != 0x00)
2938           goto advance;
2939
2940         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXF_CAPS);
2941         return;
2942       }
2943     }
2944
2945   advance:
2946     data_scan_ctx_advance (tf, &c, 1024 - 16);
2947   }
2948 }
2949
2950 /*** video/x-dv ***/
2951
2952 static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, "
2953     "systemstream = (boolean) true");
2954 #define DV_CAPS (gst_static_caps_get(&dv_caps))
2955 static void
2956 dv_type_find (GstTypeFind * tf, gpointer private)
2957 {
2958   guint8 *data;
2959
2960   data = gst_type_find_peek (tf, 0, 5);
2961
2962   /* check for DIF  and DV flag */
2963   if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00)) {
2964     const gchar *format;
2965
2966     if (data[3] & 0x80) {
2967       format = "PAL";
2968     } else {
2969       format = "NTSC";
2970     }
2971
2972     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "video/x-dv",
2973         "systemstream", G_TYPE_BOOLEAN, TRUE,
2974         "format", G_TYPE_STRING, format, NULL);
2975   }
2976 }
2977
2978
2979 /*** application/ogg and application/x-annodex ***/
2980 static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
2981 static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
2982 static GstStaticCaps ogg_annodex_caps =
2983     GST_STATIC_CAPS ("application/ogg;application/x-annodex");
2984
2985 #define OGGANX_CAPS (gst_static_caps_get(&ogg_annodex_caps))
2986
2987 static void
2988 ogganx_type_find (GstTypeFind * tf, gpointer private)
2989 {
2990   guint8 *data = gst_type_find_peek (tf, 0, 4);
2991
2992   if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) {
2993
2994     /* Check for an annodex fishbone header */
2995     data = gst_type_find_peek (tf, 28, 8);
2996     if (data && memcmp (data, "fishead\0", 8) == 0)
2997       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
2998           gst_static_caps_get (&annodex_caps));
2999
3000     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
3001         gst_static_caps_get (&ogg_caps));
3002   }
3003 }
3004
3005 /*** audio/x-vorbis ***/
3006 static GstStaticCaps vorbis_caps = GST_STATIC_CAPS ("audio/x-vorbis");
3007
3008 #define VORBIS_CAPS (gst_static_caps_get(&vorbis_caps))
3009 static void
3010 vorbis_type_find (GstTypeFind * tf, gpointer private)
3011 {
3012   guint8 *data = gst_type_find_peek (tf, 0, 30);
3013
3014   if (data) {
3015     guint blocksize_0;
3016     guint blocksize_1;
3017
3018     /* 1 byte packet type (identification=0x01)
3019        6 byte string "vorbis"
3020        4 byte vorbis version */
3021     if (memcmp (data, "\001vorbis\000\000\000\000", 11) != 0)
3022       return;
3023     data += 11;
3024     /* 1 byte channels must be != 0 */
3025     if (data[0] == 0)
3026       return;
3027     data++;
3028     /* 4 byte samplerate must be != 0 */
3029     if (GST_READ_UINT32_LE (data) == 0)
3030       return;
3031     data += 16;
3032     /* blocksize checks */
3033     blocksize_0 = data[0] & 0x0F;
3034     blocksize_1 = (data[0] & 0xF0) >> 4;
3035     if (blocksize_0 > blocksize_1)
3036       return;
3037     if (blocksize_0 < 6 || blocksize_0 > 13)
3038       return;
3039     if (blocksize_1 < 6 || blocksize_1 > 13)
3040       return;
3041     data++;
3042     /* framing bit */
3043     if ((data[0] & 0x01) != 1)
3044       return;
3045     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VORBIS_CAPS);
3046   }
3047 }
3048
3049 /*** video/x-theora ***/
3050
3051 static GstStaticCaps theora_caps = GST_STATIC_CAPS ("video/x-theora");
3052
3053 #define THEORA_CAPS (gst_static_caps_get(&theora_caps))
3054 static void
3055 theora_type_find (GstTypeFind * tf, gpointer private)
3056 {
3057   guint8 *data = gst_type_find_peek (tf, 0, 7); //42);
3058
3059   if (data) {
3060     if (data[0] != 0x80)
3061       return;
3062     if (memcmp (&data[1], "theora", 6) != 0)
3063       return;
3064     /* FIXME: make this more reliable when specs are out */
3065
3066     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, THEORA_CAPS);
3067   }
3068 }
3069
3070 /*** kate ***/
3071 static void
3072 kate_type_find (GstTypeFind * tf, gpointer private)
3073 {
3074   guint8 *data = gst_type_find_peek (tf, 0, 64);
3075   gchar category[16] = { 0, };
3076
3077   if (G_UNLIKELY (data == NULL))
3078     return;
3079
3080   /* see: http://wiki.xiph.org/index.php/OggKate#Format_specification */
3081   if (G_LIKELY (memcmp (data, "\200kate\0\0\0", 8) != 0))
3082     return;
3083
3084   /* make sure we always have a NUL-terminated string */
3085   memcpy (category, data + 48, 15);
3086   GST_LOG ("kate category: %s", category);
3087   /* canonical categories for subtitles: subtitles, spu-subtitles, SUB, K-SPU */
3088   if (strcmp (category, "subtitles") == 0 || strcmp (category, "SUB") == 0 ||
3089       strcmp (category, "spu-subtitles") == 0 ||
3090       strcmp (category, "K-SPU") == 0) {
3091     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
3092         "subtitle/x-kate", NULL);
3093   } else {
3094     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
3095         "application/x-kate", NULL);
3096   }
3097 }
3098
3099 /*** application/x-ogm-video or audio***/
3100
3101 static GstStaticCaps ogmvideo_caps =
3102 GST_STATIC_CAPS ("application/x-ogm-video");
3103 #define OGMVIDEO_CAPS (gst_static_caps_get(&ogmvideo_caps))
3104 static void
3105 ogmvideo_type_find (GstTypeFind * tf, gpointer private)
3106 {
3107   guint8 *data = gst_type_find_peek (tf, 0, 9);
3108
3109   if (data) {
3110     if (memcmp (data, "\001video\000\000\000", 9) != 0)
3111       return;
3112     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMVIDEO_CAPS);
3113   }
3114 }
3115
3116 static GstStaticCaps ogmaudio_caps =
3117 GST_STATIC_CAPS ("application/x-ogm-audio");
3118 #define OGMAUDIO_CAPS (gst_static_caps_get(&ogmaudio_caps))
3119 static void
3120 ogmaudio_type_find (GstTypeFind * tf, gpointer private)
3121 {
3122   guint8 *data = gst_type_find_peek (tf, 0, 9);
3123
3124   if (data) {
3125     if (memcmp (data, "\001audio\000\000\000", 9) != 0)
3126       return;
3127     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMAUDIO_CAPS);
3128   }
3129 }
3130
3131 static GstStaticCaps ogmtext_caps = GST_STATIC_CAPS ("application/x-ogm-text");
3132
3133 #define OGMTEXT_CAPS (gst_static_caps_get(&ogmtext_caps))
3134 static void
3135 ogmtext_type_find (GstTypeFind * tf, gpointer private)
3136 {
3137   guint8 *data = gst_type_find_peek (tf, 0, 9);
3138
3139   if (data) {
3140     if (memcmp (data, "\001text\000\000\000\000", 9) != 0)
3141       return;
3142     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMTEXT_CAPS);
3143   }
3144 }
3145
3146 /*** audio/x-speex ***/
3147
3148 static GstStaticCaps speex_caps = GST_STATIC_CAPS ("audio/x-speex");
3149
3150 #define SPEEX_CAPS (gst_static_caps_get(&speex_caps))
3151 static void
3152 speex_type_find (GstTypeFind * tf, gpointer private)
3153 {
3154   guint8 *data = gst_type_find_peek (tf, 0, 80);
3155
3156   if (data) {
3157     /* 8 byte string "Speex   "
3158        24 byte speex version string + int */
3159     if (memcmp (data, "Speex   ", 8) != 0)
3160       return;
3161     data += 32;
3162
3163     /* 4 byte header size >= 80 */
3164     if (GST_READ_UINT32_LE (data) < 80)
3165       return;
3166     data += 4;
3167
3168     /* 4 byte sample rate <= 48000 */
3169     if (GST_READ_UINT32_LE (data) > 48000)
3170       return;
3171     data += 4;
3172
3173     /* currently there are only 3 speex modes. */
3174     if (GST_READ_UINT32_LE (data) > 3)
3175       return;
3176     data += 12;
3177
3178     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SPEEX_CAPS);
3179   }
3180 }
3181
3182 /*** audio/x-celt ***/
3183
3184 static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt");
3185
3186 #define CELT_CAPS (gst_static_caps_get(&celt_caps))
3187 static void
3188 celt_type_find (GstTypeFind * tf, gpointer private)
3189 {
3190   guint8 *data = gst_type_find_peek (tf, 0, 8);
3191
3192   if (data) {
3193     /* 8 byte string "CELT   " */
3194     if (memcmp (data, "CELT    ", 8) != 0)
3195       return;
3196
3197     /* TODO: Check other values of the CELT header */
3198     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CELT_CAPS);
3199   }
3200 }
3201
3202 /*** application/x-ogg-skeleton ***/
3203 static GstStaticCaps ogg_skeleton_caps =
3204 GST_STATIC_CAPS ("application/x-ogg-skeleton, parsed=(boolean)FALSE");
3205 #define OGG_SKELETON_CAPS (gst_static_caps_get(&ogg_skeleton_caps))
3206 static void
3207 oggskel_type_find (GstTypeFind * tf, gpointer private)
3208 {
3209   guint8 *data = gst_type_find_peek (tf, 0, 12);
3210
3211   if (data) {
3212     /* 8 byte string "fishead\0" for the ogg skeleton stream */
3213     if (memcmp (data, "fishead\0", 8) != 0)
3214       return;
3215     data += 8;
3216
3217     /* Require that the header contains version 3.0 */
3218     if (GST_READ_UINT16_LE (data) != 3)
3219       return;
3220     data += 2;
3221     if (GST_READ_UINT16_LE (data) != 0)
3222       return;
3223
3224     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGG_SKELETON_CAPS);
3225   }
3226 }
3227
3228 static GstStaticCaps cmml_caps = GST_STATIC_CAPS ("text/x-cmml");
3229
3230 #define CMML_CAPS (gst_static_caps_get(&cmml_caps))
3231 static void
3232 cmml_type_find (GstTypeFind * tf, gpointer private)
3233 {
3234   /* Header is 12 bytes minimum (though we don't check the minor version */
3235   guint8 *data = gst_type_find_peek (tf, 0, 12);
3236
3237   if (data) {
3238
3239     /* 8 byte string "CMML\0\0\0\0" for the magic number */
3240     if (memcmp (data, "CMML\0\0\0\0", 8) != 0)
3241       return;
3242     data += 8;
3243
3244     /* Require that the header contains at least version 2.0 */
3245     if (GST_READ_UINT16_LE (data) < 2)
3246       return;
3247
3248     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CMML_CAPS);
3249   }
3250 }
3251
3252 /*** application/x-tar ***/
3253
3254 static GstStaticCaps tar_caps = GST_STATIC_CAPS ("application/x-tar");
3255
3256 #define TAR_CAPS (gst_static_caps_get(&tar_caps))
3257 #define OLDGNU_MAGIC "ustar  "  /* 7 chars and a NUL */
3258 #define NEWGNU_MAGIC "ustar"    /* 5 chars and a NUL */
3259 static void
3260 tar_type_find (GstTypeFind * tf, gpointer unused)
3261 {
3262   guint8 *data = gst_type_find_peek (tf, 257, 8);
3263
3264   /* of course we are not certain, but we don't want other typefind funcs
3265    * to detect formats of files within the tar archive, e.g. mp3s */
3266   if (data) {
3267     if (memcmp (data, OLDGNU_MAGIC, 8) == 0) {  /* sic */
3268       gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS);
3269     } else if (memcmp (data, NEWGNU_MAGIC, 6) == 0 &&   /* sic */
3270         g_ascii_isdigit (data[6]) && g_ascii_isdigit (data[7])) {
3271       gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS);
3272     }
3273   }
3274 }
3275
3276 /*** application/x-ar ***/
3277
3278 static GstStaticCaps ar_caps = GST_STATIC_CAPS ("application/x-ar");
3279
3280 #define AR_CAPS (gst_static_caps_get(&ar_caps))
3281 static void
3282 ar_type_find (GstTypeFind * tf, gpointer unused)
3283 {
3284   guint8 *data = gst_type_find_peek (tf, 0, 24);
3285
3286   if (data && memcmp (data, "!<arch>", 7) == 0) {
3287     gint i;
3288
3289     for (i = 7; i < 24; ++i) {
3290       if (!g_ascii_isprint (data[i]) && data[i] != '\n') {
3291         gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, AR_CAPS);
3292       }
3293     }
3294
3295     gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, AR_CAPS);
3296   }
3297 }
3298
3299 /*** audio/x-au ***/
3300
3301 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
3302  * as it is only possible to register one typefind factory per 'name'
3303  * (which is in this case the caps), and the first one would be replaced by
3304  * the second one. */
3305 static GstStaticCaps au_caps = GST_STATIC_CAPS ("audio/x-au");
3306
3307 #define AU_CAPS (gst_static_caps_get(&au_caps))
3308 static void
3309 au_type_find (GstTypeFind * tf, gpointer unused)
3310 {
3311   guint8 *data = gst_type_find_peek (tf, 0, 4);
3312
3313   if (data) {
3314     if (memcmp (data, ".snd", 4) == 0 || memcmp (data, "dns.", 4) == 0) {
3315       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AU_CAPS);
3316     }
3317   }
3318 }
3319
3320
3321 /*** video/x-nuv ***/
3322
3323 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
3324  * as it is only possible to register one typefind factory per 'name'
3325  * (which is in this case the caps), and the first one would be replaced by
3326  * the second one. */
3327 static GstStaticCaps nuv_caps = GST_STATIC_CAPS ("video/x-nuv");
3328
3329 #define NUV_CAPS (gst_static_caps_get(&nuv_caps))
3330 static void
3331 nuv_type_find (GstTypeFind * tf, gpointer unused)
3332 {
3333   guint8 *data = gst_type_find_peek (tf, 0, 11);
3334
3335   if (data) {
3336     if (memcmp (data, "MythTVVideo", 11) == 0
3337         || memcmp (data, "NuppelVideo", 11) == 0) {
3338       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, NUV_CAPS);
3339     }
3340   }
3341 }
3342
3343 /*** audio/x-paris ***/
3344 /* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */
3345 static GstStaticCaps paris_caps = GST_STATIC_CAPS ("audio/x-paris");
3346
3347 #define PARIS_CAPS (gst_static_caps_get(&paris_caps))
3348 static void
3349 paris_type_find (GstTypeFind * tf, gpointer unused)
3350 {
3351   guint8 *data = gst_type_find_peek (tf, 0, 4);
3352
3353   if (data) {
3354     if (memcmp (data, " paf", 4) == 0 || memcmp (data, "fap ", 4) == 0) {
3355       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, PARIS_CAPS);
3356     }
3357   }
3358 }
3359
3360 /*** audio/iLBC-sh ***/
3361 /* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */
3362 static GstStaticCaps ilbc_caps = GST_STATIC_CAPS ("audio/iLBC-sh");
3363
3364 #define ILBC_CAPS (gst_static_caps_get(&ilbc_caps))
3365 static void
3366 ilbc_type_find (GstTypeFind * tf, gpointer unused)
3367 {
3368   guint8 *data = gst_type_find_peek (tf, 0, 8);
3369
3370   if (data) {
3371     if (memcmp (data, "#!iLBC30", 8) == 0 || memcmp (data, "#!iLBC20", 8) == 0) {
3372       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, ILBC_CAPS);
3373     }
3374   }
3375 }
3376
3377 /*** application/x-ms-dos-executable ***/
3378
3379 static GstStaticCaps msdos_caps =
3380 GST_STATIC_CAPS ("application/x-ms-dos-executable");
3381 #define MSDOS_CAPS (gst_static_caps_get(&msdos_caps))
3382 /* see http://www.madchat.org/vxdevl/papers/winsys/pefile/pefile.htm */
3383 static void
3384 msdos_type_find (GstTypeFind * tf, gpointer unused)
3385 {
3386   guint8 *data = gst_type_find_peek (tf, 0, 64);
3387
3388   if (data && data[0] == 'M' && data[1] == 'Z' &&
3389       GST_READ_UINT16_LE (data + 8) == 4) {
3390     guint32 pe_offset = GST_READ_UINT32_LE (data + 60);
3391
3392     data = gst_type_find_peek (tf, pe_offset, 2);
3393     if (data && data[0] == 'P' && data[1] == 'E') {
3394       gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, MSDOS_CAPS);
3395     }
3396   }
3397 }
3398
3399 /*** application/x-mmsh ***/
3400
3401 static GstStaticCaps mmsh_caps = GST_STATIC_CAPS ("application/x-mmsh");
3402
3403 #define MMSH_CAPS gst_static_caps_get(&mmsh_caps)
3404
3405 /* This is to recognise mssh-over-http */
3406 static void
3407 mmsh_type_find (GstTypeFind * tf, gpointer unused)
3408 {
3409   static const guint8 asf_marker[16] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66,
3410     0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
3411   };
3412
3413   guint8 *data;
3414
3415   data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16);
3416   if (data && data[0] == 0x24 && data[1] == 0x48 &&
3417       GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 &&
3418       memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) {
3419     gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMSH_CAPS);
3420   }
3421 }
3422
3423 /*** video/x-dirac ***/
3424
3425 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
3426  * as it is only possible to register one typefind factory per 'name'
3427  * (which is in this case the caps), and the first one would be replaced by
3428  * the second one. */
3429 static GstStaticCaps dirac_caps = GST_STATIC_CAPS ("video/x-dirac");
3430
3431 #define DIRAC_CAPS (gst_static_caps_get(&dirac_caps))
3432 static void
3433 dirac_type_find (GstTypeFind * tf, gpointer unused)
3434 {
3435   guint8 *data = gst_type_find_peek (tf, 0, 8);
3436
3437   if (data) {
3438     if (memcmp (data, "BBCD", 4) == 0 || memcmp (data, "KW-DIRAC", 8) == 0) {
3439       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DIRAC_CAPS);
3440     }
3441   }
3442 }
3443
3444 /*** video/vivo ***/
3445
3446 static GstStaticCaps vivo_caps = GST_STATIC_CAPS ("video/vivo");
3447
3448 #define VIVO_CAPS gst_static_caps_get(&vivo_caps)
3449
3450 static void
3451 vivo_type_find (GstTypeFind * tf, gpointer unused)
3452 {
3453   static const guint8 vivo_marker[] = { 'V', 'e', 'r', 's', 'i', 'o', 'n',
3454     ':', 'V', 'i', 'v', 'o', '/'
3455   };
3456   guint8 *data;
3457   guint hdr_len, pos;
3458
3459   data = gst_type_find_peek (tf, 0, 1024);
3460   if (data == NULL || data[0] != 0x00)
3461     return;
3462
3463   if ((data[1] & 0x80)) {
3464     if ((data[2] & 0x80))
3465       return;
3466     hdr_len = ((guint) (data[1] & 0x7f)) << 7;
3467     hdr_len += data[2];
3468     if (hdr_len > 2048)
3469       return;
3470     pos = 3;
3471   } else {
3472     hdr_len = data[1];
3473     pos = 2;
3474   }
3475
3476   /* 1008 = 1022 - strlen ("Version:Vivo/") - 1 */
3477   while (pos < 1008 && data[pos] == '\r' && data[pos + 1] == '\n')
3478     pos += 2;
3479
3480   if (memcmp (data + pos, vivo_marker, sizeof (vivo_marker)) == 0) {
3481     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VIVO_CAPS);
3482   }
3483 }
3484
3485 /*** XDG MIME typefinder (to avoid false positives mostly) ***/
3486
3487 #ifdef USE_GIO
3488 static void
3489 xdgmime_typefind (GstTypeFind * find, gpointer user_data)
3490 {
3491   gchar *mimetype;
3492   gsize length = 16384;
3493   guint64 tf_length;
3494   guint8 *data;
3495   gchar *tmp;
3496
3497   if ((tf_length = gst_type_find_get_length (find)) > 0)
3498     length = MIN (length, tf_length);
3499
3500   if ((data = gst_type_find_peek (find, 0, length)) == NULL)
3501     return;
3502
3503   tmp = g_content_type_guess (NULL, data, length, NULL);
3504   if (tmp == NULL || g_content_type_is_unknown (tmp)) {
3505     g_free (tmp);
3506     return;
3507   }
3508
3509   mimetype = g_content_type_get_mime_type (tmp);
3510   g_free (tmp);
3511
3512   if (mimetype == NULL)
3513     return;
3514
3515   GST_DEBUG ("Got mimetype '%s'", mimetype);
3516
3517   /* Ignore audio/video types:
3518    *  - our own typefinders in -base are likely to be better at this
3519    *    (and if they're not, we really want to fix them, that's why we don't
3520    *    report xdg-detected audio/video types at all, not even with a low
3521    *    probability)
3522    *  - we want to detect GStreamer media types and not MIME types
3523    *  - the purpose of this xdg mime finder is mainly to prevent false
3524    *    positives of non-media formats, not to typefind audio/video formats */
3525   if (g_str_has_prefix (mimetype, "audio/") ||
3526       g_str_has_prefix (mimetype, "video/")) {
3527     GST_LOG ("Ignoring audio/video mime type");
3528     g_free (mimetype);
3529     return;
3530   }
3531
3532   /* Again, we mainly want the xdg typefinding to prevent false-positives on
3533    * non-media formats, so suggest the type with a probability that trumps
3534    * uncertain results of our typefinders, but not more than that. */
3535   GST_LOG ("Suggesting '%s' with probability POSSIBLE", mimetype);
3536   gst_type_find_suggest_simple (find, GST_TYPE_FIND_POSSIBLE, mimetype, NULL);
3537   g_free (mimetype);
3538 }
3539 #endif /* USE_GIO */
3540
3541 /*** generic typefind for streams that have some data at a specific position***/
3542 typedef struct
3543 {
3544   const guint8 *data;
3545   guint size;
3546   guint probability;
3547   GstCaps *caps;
3548 }
3549 GstTypeFindData;
3550
3551 static void
3552 start_with_type_find (GstTypeFind * tf, gpointer private)
3553 {
3554   GstTypeFindData *start_with = (GstTypeFindData *) private;
3555   guint8 *data;
3556
3557   GST_LOG ("trying to find mime type %s with the first %u bytes of data",
3558       gst_structure_get_name (gst_caps_get_structure (start_with->caps, 0)),
3559       start_with->size);
3560   data = gst_type_find_peek (tf, 0, start_with->size);
3561   if (data && memcmp (data, start_with->data, start_with->size) == 0) {
3562     gst_type_find_suggest (tf, start_with->probability, start_with->caps);
3563   }
3564 }
3565
3566 static void
3567 sw_data_destroy (GstTypeFindData * sw_data)
3568 {
3569   if (G_LIKELY (sw_data->caps != NULL))
3570     gst_caps_unref (sw_data->caps);
3571   g_free (sw_data);
3572 }
3573
3574 #define TYPE_FIND_REGISTER_START_WITH(plugin,name,rank,ext,_data,_size,_probability)\
3575 G_BEGIN_DECLS{                                                          \
3576   GstTypeFindData *sw_data = g_new (GstTypeFindData, 1);                \
3577   sw_data->data = (const guint8 *)_data;                                \
3578   sw_data->size = _size;                                                \
3579   sw_data->probability = _probability;                                  \
3580   sw_data->caps = gst_caps_new_simple (name, NULL);                     \
3581   if (!gst_type_find_register (plugin, name, rank, start_with_type_find,\
3582                       (char **) ext, sw_data->caps, sw_data,            \
3583                      (GDestroyNotify) (sw_data_destroy))) {             \
3584     gst_caps_unref (sw_data->caps);                                     \
3585     g_free (sw_data);                                                   \
3586   }                                                                     \
3587 }G_END_DECLS
3588
3589 /*** same for riff types ***/
3590
3591 static void
3592 riff_type_find (GstTypeFind * tf, gpointer private)
3593 {
3594   GstTypeFindData *riff_data = (GstTypeFindData *) private;
3595   guint8 *data = gst_type_find_peek (tf, 0, 12);
3596
3597   if (data && (memcmp (data, "RIFF", 4) == 0 || memcmp (data, "AVF0", 4) == 0)) {
3598     data += 8;
3599     if (memcmp (data, riff_data->data, 4) == 0)
3600       gst_type_find_suggest (tf, riff_data->probability, riff_data->caps);
3601   }
3602 }
3603
3604 #define TYPE_FIND_REGISTER_RIFF(plugin,name,rank,ext,_data)             \
3605 G_BEGIN_DECLS{                                                          \
3606   GstTypeFindData *sw_data = g_new (GstTypeFindData, 1);                \
3607   sw_data->data = (gpointer)_data;                                      \
3608   sw_data->size = 4;                                                    \
3609   sw_data->probability = GST_TYPE_FIND_MAXIMUM;                         \
3610   sw_data->caps = gst_caps_new_simple (name, NULL);                     \
3611   if (!gst_type_find_register (plugin, name, rank, riff_type_find,      \
3612                       (char **) ext, sw_data->caps, sw_data,            \
3613                       (GDestroyNotify) (sw_data_destroy))) {            \
3614     gst_caps_unref (sw_data->caps);                                     \
3615     g_free (sw_data);                                                   \
3616   }                                                                     \
3617 }G_END_DECLS
3618
3619
3620 /*** plugin initialization ***/
3621
3622 #define TYPE_FIND_REGISTER(plugin,name,rank,func,ext,caps,priv,notify) \
3623 G_BEGIN_DECLS{\
3624   if (!gst_type_find_register (plugin, name, rank, func, (char **) ext, caps, priv, notify))\
3625     return FALSE; \
3626 }G_END_DECLS
3627
3628
3629 static gboolean
3630 plugin_init (GstPlugin * plugin)
3631 {
3632   /* can't initialize this via a struct as caps can't be statically initialized */
3633
3634   /* note: asx/wax/wmx are XML files, asf doesn't handle them */
3635   /* FIXME-0.11: these should be const,
3636      this requires gstreamer/gst/gsttypefind::gst_type_find_register()
3637      to have define the parameter as const
3638    */
3639   static const gchar *asf_exts[] = { "asf", "wm", "wma", "wmv", NULL };
3640   static const gchar *au_exts[] = { "au", "snd", NULL };
3641   static const gchar *avi_exts[] = { "avi", NULL };
3642   static const gchar *qcp_exts[] = { "qcp", NULL };
3643   static const gchar *cdxa_exts[] = { "dat", NULL };
3644   static const gchar *flac_exts[] = { "flac", NULL };
3645   static const gchar *flx_exts[] = { "flc", "fli", NULL };
3646   static const gchar *id3_exts[] =
3647       { "mp3", "mp2", "mp1", "mpga", "ogg", "flac", "tta", NULL };
3648   static const gchar *apetag_exts[] = { "ape", "mpc", "wv", NULL };     /* and mp3 and wav? */
3649   static const gchar *tta_exts[] = { "tta", NULL };
3650   static const gchar *mod_exts[] = { "669", "amf", "dsm", "gdm", "far", "imf",
3651     "it", "med", "mod", "mtm", "okt", "sam",
3652     "s3m", "stm", "stx", "ult", "xm", NULL
3653   };
3654   static const gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
3655   static const gchar *ac3_exts[] = { "ac3", NULL };
3656   static const gchar *gsm_exts[] = { "gsm", NULL };
3657   static const gchar *musepack_exts[] = { "mpc", "mpp", "mp+", NULL };
3658   static const gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
3659   static const gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
3660   static const gchar *mpeg_ts_exts[] = { "ts", NULL };
3661   static const gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL };
3662   static const gchar *qt_exts[] = { "mov", NULL };
3663   static const gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL };
3664   static const gchar *mj2_exts[] = { "mj2", NULL };
3665   static const gchar *jp2_exts[] = { "jp2", NULL };
3666   static const gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL };
3667   static const gchar *swf_exts[] = { "swf", "swfl", NULL };
3668   static const gchar *utf8_exts[] = { "txt", NULL };
3669   static const gchar *wav_exts[] = { "wav", NULL };
3670   static const gchar *aiff_exts[] = { "aiff", "aif", "aifc", NULL };
3671   static const gchar *svx_exts[] = { "iff", "svx", NULL };
3672   static const gchar *paris_exts[] = { "paf", NULL };
3673   static const gchar *nist_exts[] = { "nist", NULL };
3674   static const gchar *voc_exts[] = { "voc", NULL };
3675   static const gchar *sds_exts[] = { "sds", NULL };
3676   static const gchar *ircam_exts[] = { "sf", NULL };
3677   static const gchar *w64_exts[] = { "w64", NULL };
3678   static const gchar *shn_exts[] = { "shn", NULL };
3679   static const gchar *ape_exts[] = { "ape", NULL };
3680   static const gchar *uri_exts[] = { "ram", NULL };
3681   static const gchar *sdp_exts[] = { "sdp", NULL };
3682   static const gchar *smil_exts[] = { "smil", NULL };
3683   static const gchar *html_exts[] = { "htm", "html", NULL };
3684   static const gchar *xml_exts[] = { "xml", NULL };
3685   static const gchar *jpeg_exts[] = { "jpg", "jpe", "jpeg", NULL };
3686   static const gchar *gif_exts[] = { "gif", NULL };
3687   static const gchar *png_exts[] = { "png", NULL };
3688   static const gchar *bmp_exts[] = { "bmp", NULL };
3689   static const gchar *tiff_exts[] = { "tif", "tiff", NULL };
3690   static const gchar *matroska_exts[] = { "mkv", "mka", NULL };
3691   static const gchar *webm_exts[] = { "webm", "weba", "webv", NULL };
3692   static const gchar *mve_exts[] = { "mve", NULL };
3693   static const gchar *dv_exts[] = { "dv", "dif", NULL };
3694   static const gchar *amr_exts[] = { "amr", NULL };
3695   static const gchar *ilbc_exts[] = { "ilbc", NULL };
3696   static const gchar *sid_exts[] = { "sid", NULL };
3697   static const gchar *xcf_exts[] = { "xcf", NULL };
3698   static const gchar *mng_exts[] = { "mng", NULL };
3699   static const gchar *jng_exts[] = { "jng", NULL };
3700   static const gchar *xpm_exts[] = { "xpm", NULL };
3701   static const gchar *pnm_exts[] = { "pnm", "ppm", "pgm", "pbm", NULL };
3702   static const gchar *ras_exts[] = { "ras", NULL };
3703   static const gchar *bz2_exts[] = { "bz2", NULL };
3704   static const gchar *gz_exts[] = { "gz", NULL };
3705   static const gchar *zip_exts[] = { "zip", NULL };
3706   static const gchar *compress_exts[] = { "Z", NULL };
3707   static const gchar *m4a_exts[] = { "m4a", NULL };
3708   static const gchar *q3gp_exts[] = { "3gp", NULL };
3709   static const gchar *aac_exts[] = { "aac", NULL };
3710   static const gchar *spc_exts[] = { "spc", NULL };
3711   static const gchar *wavpack_exts[] = { "wv", "wvp", NULL };
3712   static const gchar *wavpack_correction_exts[] = { "wvc", NULL };
3713   static const gchar *rar_exts[] = { "rar", NULL };
3714   static const gchar *tar_exts[] = { "tar", NULL };
3715   static const gchar *ar_exts[] = { "a", NULL };
3716   static const gchar *msdos_exts[] = { "dll", "exe", "ocx", "sys", "scr",
3717     "msstyles", "cpl", NULL
3718   };
3719   static const gchar *flv_exts[] = { "flv", NULL };
3720   static const gchar *m4v_exts[] = { "m4v", NULL };
3721   static const gchar *h264_exts[] = { "h264", "x264", "264", NULL };
3722   static const gchar *nuv_exts[] = { "nuv", NULL };
3723   static const gchar *vivo_exts[] = { "viv", NULL };
3724   static const gchar *nsf_exts[] = { "nsf", NULL };
3725   static const gchar *gym_exts[] = { "gym", NULL };
3726   static const gchar *ay_exts[] = { "ay", NULL };
3727   static const gchar *gbs_exts[] = { "gbs", NULL };
3728   static const gchar *kss_exts[] = { "kss", NULL };
3729   static const gchar *sap_exts[] = { "sap", NULL };
3730   static const gchar *vgm_exts[] = { "vgm", NULL };
3731   static const gchar *mid_exts[] = { "mid", "midi", NULL };
3732   static const gchar *mxmf_exts[] = { "mxmf", NULL };
3733   static const gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL };
3734   static const gchar *pdf_exts[] = { "pdf", NULL };
3735   static const gchar *ps_exts[] = { "ps", NULL };
3736   static const gchar *svg_exts[] = { "svg", NULL };
3737   static const gchar *mxf_exts[] = { "mxf", NULL };
3738   static const gchar *ivf_exts[] = { "ivf", NULL };
3739   static const gchar *msword_exts[] = { "doc", NULL };
3740   static const gchar *dsstore_exts[] = { "DS_Store", NULL };
3741   static const gchar *psd_exts[] = { "psd", NULL };
3742
3743   GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions",
3744       GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions");
3745
3746   /* must use strings, macros don't accept initializers */
3747   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-ms-asf", GST_RANK_SECONDARY,
3748       asf_exts,
3749       "\060\046\262\165\216\146\317\021\246\331\000\252\000\142\316\154", 16,
3750       GST_TYPE_FIND_MAXIMUM);
3751   TYPE_FIND_REGISTER (plugin, "audio/x-musepack", GST_RANK_PRIMARY,
3752       musepack_type_find, musepack_exts, MUSEPACK_CAPS, NULL, NULL);
3753   TYPE_FIND_REGISTER (plugin, "audio/x-au", GST_RANK_MARGINAL,
3754       au_type_find, au_exts, AU_CAPS, NULL, NULL);
3755   TYPE_FIND_REGISTER_RIFF (plugin, "video/x-msvideo", GST_RANK_PRIMARY,
3756       avi_exts, "AVI ");
3757   TYPE_FIND_REGISTER_RIFF (plugin, "audio/qcelp", GST_RANK_PRIMARY,
3758       qcp_exts, "QLCM");
3759   TYPE_FIND_REGISTER_RIFF (plugin, "video/x-cdxa", GST_RANK_PRIMARY,
3760       cdxa_exts, "CDXA");
3761   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-vcd", GST_RANK_PRIMARY,
3762       cdxa_exts, "\000\377\377\377\377\377\377\377\377\377\377\000", 12,
3763       GST_TYPE_FIND_MAXIMUM);
3764   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-imelody", GST_RANK_PRIMARY,
3765       imelody_exts, "BEGIN:IMELODY", 13, GST_TYPE_FIND_MAXIMUM);
3766 #if 0
3767   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-smoke", GST_RANK_PRIMARY,
3768       NULL, "\x80smoke\x00\x01\x00", 6, GST_TYPE_FIND_MAXIMUM);
3769 #endif
3770   TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find,
3771       mid_exts, MID_CAPS, NULL, NULL);
3772   TYPE_FIND_REGISTER_RIFF (plugin, "audio/riff-midi", GST_RANK_PRIMARY,
3773       mid_exts, "RMID");
3774   TYPE_FIND_REGISTER (plugin, "audio/mobile-xmf", GST_RANK_PRIMARY,
3775       mxmf_type_find, mxmf_exts, MXMF_CAPS, NULL, NULL);
3776   TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find,
3777       flx_exts, FLX_CAPS, NULL, NULL);
3778   TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103,
3779       id3v2_type_find, id3_exts, ID3_CAPS, NULL, NULL);
3780   TYPE_FIND_REGISTER (plugin, "application/x-id3v1", GST_RANK_PRIMARY + 101,
3781       id3v1_type_find, id3_exts, ID3_CAPS, NULL, NULL);
3782   TYPE_FIND_REGISTER (plugin, "application/x-apetag", GST_RANK_PRIMARY + 102,
3783       apetag_type_find, apetag_exts, APETAG_CAPS, NULL, NULL);
3784   TYPE_FIND_REGISTER (plugin, "audio/x-ttafile", GST_RANK_PRIMARY,
3785       tta_type_find, tta_exts, TTA_CAPS, NULL, NULL);
3786   TYPE_FIND_REGISTER (plugin, "audio/x-mod", GST_RANK_SECONDARY, mod_type_find,
3787       mod_exts, MOD_CAPS, NULL, NULL);
3788   TYPE_FIND_REGISTER (plugin, "audio/mpeg", GST_RANK_PRIMARY, mp3_type_find,
3789       mp3_exts, MP3_CAPS, NULL, NULL);
3790   TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
3791       ac3_exts, AC3_CAPS, NULL, NULL);
3792   TYPE_FIND_REGISTER (plugin, "audio/x-gsm", GST_RANK_PRIMARY, NULL, gsm_exts,
3793       GSM_CAPS, NULL, NULL);
3794   TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
3795       mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
3796   TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
3797       mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
3798   TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
3799       ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
3800   TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL,
3801       mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
3802       NULL);
3803   TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,
3804       mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL);
3805   TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY,
3806       h264_video_type_find, h264_exts, MPEG_VIDEO_CAPS, NULL, NULL);
3807   TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY, nuv_type_find,
3808       nuv_exts, NUV_CAPS, NULL, NULL);
3809
3810   /* ISO formats */
3811   TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find,
3812       m4a_exts, M4A_CAPS, NULL, NULL);
3813   TYPE_FIND_REGISTER (plugin, "application/x-3gp", GST_RANK_PRIMARY,
3814       q3gp_type_find, q3gp_exts, Q3GP_CAPS, NULL, NULL);
3815   TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY,
3816       qt_type_find, qt_exts, QT_CAPS, NULL, NULL);
3817   TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY,
3818       qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL);
3819   TYPE_FIND_REGISTER (plugin, "image/jp2", GST_RANK_PRIMARY,
3820       jp2_type_find, jp2_exts, JP2_CAPS, NULL, NULL);
3821   TYPE_FIND_REGISTER (plugin, "video/mj2", GST_RANK_PRIMARY,
3822       jp2_type_find, mj2_exts, MJ2_CAPS, NULL, NULL);
3823
3824   TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find,
3825       html_exts, HTML_CAPS, NULL, NULL);
3826   TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia",
3827       GST_RANK_SECONDARY, rm_exts, ".RMF", 4, GST_TYPE_FIND_MAXIMUM);
3828   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-pn-realaudio",
3829       GST_RANK_SECONDARY, rm_exts, ".ra\375", 4, GST_TYPE_FIND_MAXIMUM);
3830   TYPE_FIND_REGISTER (plugin, "application/x-shockwave-flash",
3831       GST_RANK_SECONDARY, swf_type_find, swf_exts, SWF_CAPS, NULL, NULL);
3832   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-flv", GST_RANK_SECONDARY,
3833       flv_exts, "FLV", 3, GST_TYPE_FIND_MAXIMUM);
3834   TYPE_FIND_REGISTER (plugin, "text/plain", GST_RANK_MARGINAL, utf8_type_find,
3835       utf8_exts, UTF8_CAPS, NULL, NULL);
3836   TYPE_FIND_REGISTER (plugin, "text/uri-list", GST_RANK_MARGINAL, uri_type_find,
3837       uri_exts, URI_CAPS, NULL, NULL);
3838   TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY,
3839       sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL);
3840   TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY,
3841       smil_type_find, smil_exts, SMIL_CAPS, NULL, NULL);
3842   TYPE_FIND_REGISTER (plugin, "application/xml", GST_RANK_MARGINAL,
3843       xml_type_find, xml_exts, GENERIC_XML_CAPS, NULL, NULL);
3844   TYPE_FIND_REGISTER_RIFF (plugin, "audio/x-wav", GST_RANK_PRIMARY, wav_exts,
3845       "WAVE");
3846   TYPE_FIND_REGISTER (plugin, "audio/x-aiff", GST_RANK_SECONDARY,
3847       aiff_type_find, aiff_exts, AIFF_CAPS, NULL, NULL);
3848   TYPE_FIND_REGISTER (plugin, "audio/x-svx", GST_RANK_SECONDARY, svx_type_find,
3849       svx_exts, SVX_CAPS, NULL, NULL);
3850   TYPE_FIND_REGISTER (plugin, "audio/x-paris", GST_RANK_SECONDARY,
3851       paris_type_find, paris_exts, PARIS_CAPS, NULL, NULL);
3852   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nist", GST_RANK_SECONDARY,
3853       nist_exts, "NIST", 4, GST_TYPE_FIND_MAXIMUM);
3854   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-voc", GST_RANK_SECONDARY,
3855       voc_exts, "Creative", 8, GST_TYPE_FIND_MAXIMUM);
3856   TYPE_FIND_REGISTER (plugin, "audio/x-sds", GST_RANK_SECONDARY, sds_type_find,
3857       sds_exts, SDS_CAPS, NULL, NULL);
3858   TYPE_FIND_REGISTER (plugin, "audio/x-ircam", GST_RANK_SECONDARY,
3859       ircam_type_find, ircam_exts, IRCAM_CAPS, NULL, NULL);
3860   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-w64", GST_RANK_SECONDARY,
3861       w64_exts, "riff", 4, GST_TYPE_FIND_MAXIMUM);
3862   TYPE_FIND_REGISTER (plugin, "audio/x-shorten", GST_RANK_SECONDARY,
3863       shn_type_find, shn_exts, SHN_CAPS, NULL, NULL);
3864   TYPE_FIND_REGISTER (plugin, "application/x-ape", GST_RANK_SECONDARY,
3865       ape_type_find, ape_exts, APE_CAPS, NULL, NULL);
3866   TYPE_FIND_REGISTER (plugin, "image/jpeg", GST_RANK_PRIMARY + 15,
3867       jpeg_type_find, jpeg_exts, JPEG_CAPS, NULL, NULL);
3868   TYPE_FIND_REGISTER_START_WITH (plugin, "image/gif", GST_RANK_PRIMARY,
3869       gif_exts, "GIF8", 4, GST_TYPE_FIND_MAXIMUM);
3870   TYPE_FIND_REGISTER_START_WITH (plugin, "image/png", GST_RANK_PRIMARY + 14,
3871       png_exts, "\211PNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3872   TYPE_FIND_REGISTER (plugin, "image/bmp", GST_RANK_PRIMARY, bmp_type_find,
3873       bmp_exts, BMP_CAPS, NULL, NULL);
3874   TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find,
3875       tiff_exts, TIFF_CAPS, NULL, NULL);
3876   TYPE_FIND_REGISTER (plugin, "image/x-portable-pixmap", GST_RANK_SECONDARY,
3877       pnm_type_find, pnm_exts, PNM_CAPS, NULL, NULL);
3878   TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY,
3879       matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL);
3880   TYPE_FIND_REGISTER (plugin, "video/webm", GST_RANK_PRIMARY,
3881       webm_type_find, webm_exts, WEBM_CAPS, NULL, NULL);
3882   TYPE_FIND_REGISTER (plugin, "application/mxf", GST_RANK_PRIMARY,
3883       mxf_type_find, mxf_exts, MXF_CAPS, NULL, NULL);
3884   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY,
3885       mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
3886       GST_TYPE_FIND_MAXIMUM);
3887   TYPE_FIND_REGISTER (plugin, "video/x-dv", GST_RANK_SECONDARY, dv_type_find,
3888       dv_exts, DV_CAPS, NULL, NULL);
3889   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-nb-sh", GST_RANK_PRIMARY,
3890       amr_exts, "#!AMR", 5, GST_TYPE_FIND_LIKELY);
3891   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-wb-sh", GST_RANK_PRIMARY,
3892       amr_exts, "#!AMR-WB", 7, GST_TYPE_FIND_MAXIMUM);
3893   TYPE_FIND_REGISTER (plugin, "audio/iLBC-sh", GST_RANK_PRIMARY,
3894       ilbc_type_find, ilbc_exts, ILBC_CAPS, NULL, NULL);
3895   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-sid", GST_RANK_MARGINAL,
3896       sid_exts, "PSID", 4, GST_TYPE_FIND_MAXIMUM);
3897   TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xcf", GST_RANK_SECONDARY,
3898       xcf_exts, "gimp xcf", 8, GST_TYPE_FIND_MAXIMUM);
3899   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mng", GST_RANK_SECONDARY,
3900       mng_exts, "\212MNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3901   TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-jng", GST_RANK_SECONDARY,
3902       jng_exts, "\213JNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3903   TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xpixmap", GST_RANK_SECONDARY,
3904       xpm_exts, "/* XPM */", 9, GST_TYPE_FIND_MAXIMUM);
3905   TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-sun-raster",
3906       GST_RANK_SECONDARY, ras_exts, "\131\246\152\225", 4,
3907       GST_TYPE_FIND_MAXIMUM);
3908   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-bzip",
3909       GST_RANK_SECONDARY, bz2_exts, "BZh", 3, GST_TYPE_FIND_LIKELY);
3910   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-gzip",
3911       GST_RANK_SECONDARY, gz_exts, "\037\213", 2, GST_TYPE_FIND_LIKELY);
3912   TYPE_FIND_REGISTER_START_WITH (plugin, "application/zip", GST_RANK_SECONDARY,
3913       zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY);
3914   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress",
3915       GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY);
3916   TYPE_FIND_REGISTER (plugin, "subtitle/x-kate", GST_RANK_MARGINAL,
3917       kate_type_find, NULL, NULL, NULL, NULL);
3918   TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY,
3919       flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL);
3920   TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY,
3921       vorbis_type_find, NULL, VORBIS_CAPS, NULL, NULL);
3922   TYPE_FIND_REGISTER (plugin, "video/x-theora", GST_RANK_PRIMARY,
3923       theora_type_find, NULL, THEORA_CAPS, NULL, NULL);
3924   TYPE_FIND_REGISTER (plugin, "application/x-ogm-video", GST_RANK_PRIMARY,
3925       ogmvideo_type_find, NULL, OGMVIDEO_CAPS, NULL, NULL);
3926   TYPE_FIND_REGISTER (plugin, "application/x-ogm-audio", GST_RANK_PRIMARY,
3927       ogmaudio_type_find, NULL, OGMAUDIO_CAPS, NULL, NULL);
3928   TYPE_FIND_REGISTER (plugin, "application/x-ogm-text", GST_RANK_PRIMARY,
3929       ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL);
3930   TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY,
3931       speex_type_find, NULL, SPEEX_CAPS, NULL, NULL);
3932   TYPE_FIND_REGISTER (plugin, "audio/x-celt", GST_RANK_PRIMARY,
3933       celt_type_find, NULL, CELT_CAPS, NULL, NULL);
3934   TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY,
3935       oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL);
3936   TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find,
3937       NULL, CMML_CAPS, NULL, NULL);
3938   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-executable",
3939       GST_RANK_MARGINAL, NULL, "\177ELF", 4, GST_TYPE_FIND_MAXIMUM);
3940   TYPE_FIND_REGISTER (plugin, "adts_mpeg_stream", GST_RANK_SECONDARY,
3941       aac_type_find, aac_exts, AAC_CAPS, NULL, NULL);
3942   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-spc", GST_RANK_SECONDARY,
3943       spc_exts, "SNES-SPC700 Sound File Data", 27, GST_TYPE_FIND_MAXIMUM);
3944   TYPE_FIND_REGISTER (plugin, "audio/x-wavpack", GST_RANK_SECONDARY,
3945       wavpack_type_find, wavpack_exts, WAVPACK_CAPS, NULL, NULL);
3946   TYPE_FIND_REGISTER (plugin, "audio/x-wavpack-correction", GST_RANK_SECONDARY,
3947       wavpack_type_find, wavpack_correction_exts, WAVPACK_CORRECTION_CAPS, NULL,
3948       NULL);
3949   TYPE_FIND_REGISTER (plugin, "application/postscript", GST_RANK_SECONDARY,
3950       postscript_type_find, ps_exts, POSTSCRIPT_CAPS, NULL, NULL);
3951   TYPE_FIND_REGISTER (plugin, "image/svg+xml", GST_RANK_SECONDARY,
3952       svg_type_find, svg_exts, SVG_CAPS, NULL, NULL);
3953   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-rar",
3954       GST_RANK_SECONDARY, rar_exts, "Rar!", 4, GST_TYPE_FIND_LIKELY);
3955   TYPE_FIND_REGISTER (plugin, "application/x-tar", GST_RANK_SECONDARY,
3956       tar_type_find, tar_exts, TAR_CAPS, NULL, NULL);
3957   TYPE_FIND_REGISTER (plugin, "application/x-ar", GST_RANK_SECONDARY,
3958       ar_type_find, ar_exts, AR_CAPS, NULL, NULL);
3959   TYPE_FIND_REGISTER (plugin, "application/x-ms-dos-executable",
3960       GST_RANK_SECONDARY, msdos_type_find, msdos_exts, MSDOS_CAPS, NULL, NULL);
3961   TYPE_FIND_REGISTER (plugin, "video/x-dirac", GST_RANK_PRIMARY,
3962       dirac_type_find, NULL, DIRAC_CAPS, NULL, NULL);
3963   TYPE_FIND_REGISTER (plugin, "multipart/x-mixed-replace", GST_RANK_SECONDARY,
3964       multipart_type_find, NULL, MULTIPART_CAPS, NULL, NULL);
3965   TYPE_FIND_REGISTER (plugin, "application/x-mmsh", GST_RANK_SECONDARY,
3966       mmsh_type_find, NULL, MMSH_CAPS, NULL, NULL);
3967   TYPE_FIND_REGISTER (plugin, "video/vivo", GST_RANK_SECONDARY,
3968       vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL);
3969   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf",
3970       GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM);
3971   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-gym",
3972       GST_RANK_SECONDARY, gym_exts, "GYMX", 4, GST_TYPE_FIND_MAXIMUM);
3973   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-ay",
3974       GST_RANK_SECONDARY, ay_exts, "ZXAYEMUL", 8, GST_TYPE_FIND_MAXIMUM);
3975   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-gbs",
3976       GST_RANK_SECONDARY, gbs_exts, "GBS\x01", 4, GST_TYPE_FIND_MAXIMUM);
3977   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-vgm",
3978       GST_RANK_SECONDARY, vgm_exts, "Vgm\x20", 4, GST_TYPE_FIND_MAXIMUM);
3979   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-sap",
3980       GST_RANK_SECONDARY, sap_exts, "SAP\x0d\x0aAUTHOR\x20", 12,
3981       GST_TYPE_FIND_MAXIMUM);
3982   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-ivf", GST_RANK_SECONDARY,
3983       ivf_exts, "DKIF", 4, GST_TYPE_FIND_NEARLY_CERTAIN);
3984   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-kss", GST_RANK_SECONDARY,
3985       kss_exts, "KSSX\0", 5, GST_TYPE_FIND_MAXIMUM);
3986   TYPE_FIND_REGISTER_START_WITH (plugin, "application/pdf", GST_RANK_SECONDARY,
3987       pdf_exts, "%PDF-", 5, GST_TYPE_FIND_LIKELY);
3988   TYPE_FIND_REGISTER_START_WITH (plugin, "application/msword",
3989       GST_RANK_SECONDARY, msword_exts, "\320\317\021\340\241\261\032\341", 8,
3990       GST_TYPE_FIND_LIKELY);
3991   /* Mac OS X .DS_Store files tend to be taken for video/mpeg */
3992   TYPE_FIND_REGISTER_START_WITH (plugin, "application/octet-stream",
3993       GST_RANK_SECONDARY, dsstore_exts, "\000\000\000\001Bud1", 8,
3994       GST_TYPE_FIND_LIKELY);
3995   TYPE_FIND_REGISTER_START_WITH (plugin, "image/vnd.adobe.photoshop",
3996       GST_RANK_SECONDARY, psd_exts, "8BPS\000\001\000\000\000\000", 10,
3997       GST_TYPE_FIND_LIKELY);
3998
3999 #ifdef USE_GIO
4000   TYPE_FIND_REGISTER (plugin, "xdgmime-base", GST_RANK_MARGINAL,
4001       xdgmime_typefind, NULL, NULL, NULL, NULL);
4002 #endif
4003
4004   return TRUE;
4005 }
4006
4007 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
4008     GST_VERSION_MINOR,
4009     "typefindfunctions",
4010     "default typefind functions",
4011     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)