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