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