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