gst_plugins_base/gst/typefind/gsttypefindfunctions.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    21 
    21 
    22 #ifdef HAVE_CONFIG_H
    22 #ifdef HAVE_CONFIG_H
    23 #include "config.h"
    23 #include "config.h"
    24 #endif
    24 #endif
    25 
    25 
    26 #ifdef __SYMBIAN32__
    26 #include <glib.h>
    27 #include <gst_global.h>
       
    28 #endif
       
    29 
       
    30 #include <glib/gstrfuncs.h>
       
    31 
    27 
    32 #include <gst/gsttypefind.h>
    28 #include <gst/gsttypefind.h>
    33 #include <gst/gstelement.h>
    29 #include <gst/gstelement.h>
    34 #include <gst/gstversion.h>
    30 #include <gst/gstversion.h>
    35 #include <gst/gstinfo.h>
    31 #include <gst/gstinfo.h>
    36 #include <gst/gstutils.h>
    32 #include <gst/gstutils.h>
    37 
    33 
    38 #include <string.h>
    34 #include <string.h>
    39 #include <ctype.h>
    35 #include <ctype.h>
    40 
    36 
    41 #ifdef __SYMBIAN32__
       
    42 #include <glib_global.h>
       
    43 #endif
       
    44 
       
    45 GST_DEBUG_CATEGORY_STATIC (type_find_debug);
    37 GST_DEBUG_CATEGORY_STATIC (type_find_debug);
    46 #define GST_CAT_DEFAULT type_find_debug
    38 #define GST_CAT_DEFAULT type_find_debug
       
    39 
       
    40 /* DataScanCtx: helper for typefind functions that scan through data
       
    41  * step-by-step, to avoid doing a peek at each and every offset */
       
    42 
       
    43 #define DATA_SCAN_CTX_CHUNK_SIZE 4096
       
    44 
       
    45 typedef struct
       
    46 {
       
    47   guint64 offset;
       
    48   const guint8 *data;
       
    49   gint size;
       
    50 } DataScanCtx;
       
    51 
       
    52 static inline void
       
    53 data_scan_ctx_advance (GstTypeFind * tf, DataScanCtx * c, guint bytes_to_skip)
       
    54 {
       
    55   c->offset += bytes_to_skip;
       
    56   if (G_LIKELY (c->size > bytes_to_skip)) {
       
    57     c->size -= bytes_to_skip;
       
    58     c->data += bytes_to_skip;
       
    59   } else {
       
    60     c->data += c->size;
       
    61     c->size = 0;
       
    62   }
       
    63 }
       
    64 
       
    65 static inline gboolean
       
    66 data_scan_ctx_ensure_data (GstTypeFind * tf, DataScanCtx * c, gint min_len)
       
    67 {
       
    68   const guint8 *data;
       
    69   guint64 len;
       
    70   guint chunk_len = MAX (DATA_SCAN_CTX_CHUNK_SIZE, min_len);
       
    71 
       
    72   if (G_LIKELY (c->size >= min_len))
       
    73     return TRUE;
       
    74 
       
    75   data = gst_type_find_peek (tf, c->offset, chunk_len);
       
    76   if (G_LIKELY (data != NULL)) {
       
    77     c->data = data;
       
    78     c->size = chunk_len;
       
    79     return TRUE;
       
    80   }
       
    81 
       
    82   /* if there's less than our chunk size, try to get as much as we can, but
       
    83    * always at least min_len bytes (we might be typefinding the first buffer
       
    84    * of the stream and not have as much data available as we'd like) */
       
    85   len = gst_type_find_get_length (tf);
       
    86   if (len > 0) {
       
    87     len = CLAMP (len - c->offset, min_len, chunk_len);
       
    88   } else {
       
    89     len = min_len;
       
    90   }
       
    91 
       
    92   data = gst_type_find_peek (tf, c->offset, len);
       
    93   if (data != NULL) {
       
    94     c->data = data;
       
    95     c->size = len;
       
    96     return TRUE;
       
    97   }
       
    98 
       
    99   return FALSE;
       
   100 }
    47 
   101 
    48 /*** text/plain ***/
   102 /*** text/plain ***/
    49 static gboolean xml_check_first_element (GstTypeFind * tf,
   103 static gboolean xml_check_first_element (GstTypeFind * tf,
    50     const gchar * element, guint elen, gboolean strict);
   104     const gchar * element, guint elen, gboolean strict);
    51 static gboolean sdp_check_header (GstTypeFind * tf);
   105 static gboolean sdp_check_header (GstTypeFind * tf);
    62 
   116 
    63   /* randomly decided values */
   117   /* randomly decided values */
    64   guint min_size = 16;          /* minimum size  */
   118   guint min_size = 16;          /* minimum size  */
    65   guint size = 32 * 1024;       /* starting size */
   119   guint size = 32 * 1024;       /* starting size */
    66   guint probability = 95;       /* starting probability */
   120   guint probability = 95;       /* starting probability */
    67   guint step = 10;              /* how much we reduce probability in each iteration */
   121   guint step = 10;              /* how much we reduce probability in each
       
   122                                  * iteration */
    68 
   123 
    69   while (probability > step && size > min_size) {
   124   while (probability > step && size > min_size) {
    70     data = gst_type_find_peek (tf, offset, size);
   125     data = gst_type_find_peek (tf, offset, size);
    71     if (data) {
   126     if (data) {
    72       gchar *end;
   127       gchar *end;
   357   if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h'
   412   if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h'
   358       && data[3] == 'd')
   413       && data[3] == 'd')
   359     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS);
   414     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS);
   360 }
   415 }
   361 
   416 
       
   417 /*** audio/mobile-xmf ***/
       
   418 
       
   419 static GstStaticCaps mxmf_caps = GST_STATIC_CAPS ("audio/mobile-xmf");
       
   420 
       
   421 #define MXMF_CAPS gst_static_caps_get(&mxmf_caps)
       
   422 static void
       
   423 mxmf_type_find (GstTypeFind * tf, gpointer unused)
       
   424 {
       
   425   guint8 *data = NULL;
       
   426 
       
   427   /* Search FileId "XMF_" 4 bytes */
       
   428   data = gst_type_find_peek (tf, 0, 4);
       
   429   if (data && data[0] == 'X' && data[1] == 'M' && data[2] == 'F'
       
   430       && data[3] == '_') {
       
   431     /* Search Format version "2.00" 4 bytes */
       
   432     data = gst_type_find_peek (tf, 4, 4);
       
   433     if (data && data[0] == '2' && data[1] == '.' && data[2] == '0'
       
   434         && data[3] == '0') {
       
   435       /* Search TypeId 2     1 byte */
       
   436       data = gst_type_find_peek (tf, 11, 1);
       
   437       if (data && data[0] == 2) {
       
   438         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXMF_CAPS);
       
   439       }
       
   440     }
       
   441   }
       
   442 }
       
   443 
       
   444 
   362 /*** video/x-fli ***/
   445 /*** video/x-fli ***/
   363 
   446 
   364 static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli");
   447 static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli");
   365 
   448 
   366 #define FLX_CAPS gst_static_caps_get(&flx_caps)
   449 #define FLX_CAPS gst_static_caps_get(&flx_caps)
   467 #define FLAC_CAPS (gst_static_caps_get(&flac_caps))
   550 #define FLAC_CAPS (gst_static_caps_get(&flac_caps))
   468 
   551 
   469 static void
   552 static void
   470 flac_type_find (GstTypeFind * tf, gpointer unused)
   553 flac_type_find (GstTypeFind * tf, gpointer unused)
   471 {
   554 {
   472   guint8 *data;
   555   DataScanCtx c = { 0, NULL, 0 };
   473 
   556 
   474   data = gst_type_find_peek (tf, 0, 5);
   557   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
   475   if (G_LIKELY (data)) {
   558     return;
   476     /* standard flac */
   559 
   477     if (memcmp (data, "fLaC", 4) == 0) {
   560   /* standard flac (also old/broken flac-in-ogg with an initial 4-byte marker
   478       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
   561    * packet and without the usual packet framing) */
   479     }
   562   if (memcmp (c.data, "fLaC", 4) == 0) {
   480     /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
   563     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
   481     else if (memcmp (data, "\177FLAC\001", 6) == 0) {
   564     return;
   482       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
   565   }
   483     }
   566 
       
   567   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
       
   568     return;
       
   569 
       
   570   /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
       
   571   if (memcmp (c.data, "\177FLAC\001", 6) == 0) {
       
   572     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
       
   573     return;
       
   574   }
       
   575 
       
   576   /* flac without headers (subset format) */
       
   577   /* 64K should be enough */
       
   578   while (c.offset < (64 * 1024)) {
       
   579     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
       
   580       break;
       
   581 
       
   582     /* look for frame header,
       
   583      * http://flac.sourceforge.net/format.html#frame_header
       
   584      */
       
   585     if (c.data[0] == 0xff && (c.data[1] >> 2) == 0x3e) {
       
   586       /* bit 15 in the header must be 0 */
       
   587       if (((c.data[1] >> 1) & 0x01) == 0x01)
       
   588         goto advance;
       
   589 
       
   590       /* blocksize must be != 0x00 */
       
   591       if ((c.data[2] >> 4) == 0x00)
       
   592         goto advance;
       
   593 
       
   594       /* samplerate must be != 0x0f */
       
   595       if ((c.data[2] & 0x0f) == 0x0f)
       
   596         goto advance;
       
   597       /* also 0 is invalid, as it means get the info from the header and we
       
   598        * don't have headers if we are here */
       
   599       if ((c.data[2] & 0x0f) == 0x00)
       
   600         goto advance;
       
   601 
       
   602       /* channel assignment must be < 11 */
       
   603       if ((c.data[3] >> 4) >= 11)
       
   604         goto advance;
       
   605 
       
   606       /* sample size must be != 0x07 and != 0x05 */
       
   607       if (((c.data[3] >> 1) & 0x07) == 0x07)
       
   608         goto advance;
       
   609       if (((c.data[3] >> 1) & 0x07) == 0x05)
       
   610         goto advance;
       
   611       /* also 0 is invalid, as it means get the info from the header and we
       
   612        * don't have headers if we are here */
       
   613       if (((c.data[3] >> 1) & 0x07) == 0x00)
       
   614         goto advance;
       
   615 
       
   616       /* next bit must be 0 */
       
   617       if ((c.data[3] & 0x01) == 0x01)
       
   618         goto advance;
       
   619 
       
   620       /* FIXME: shouldn't we include the crc check ? */
       
   621 
       
   622       GST_DEBUG ("Found flac without headers at %d", (gint) c.offset);
       
   623       gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, FLAC_CAPS);
       
   624       return;
       
   625     }
       
   626   advance:
       
   627     data_scan_ctx_advance (tf, &c, 1);
   484   }
   628   }
   485 }
   629 }
   486 
   630 
   487 /*** audio/mpeg version 2, 4 ***/
   631 /*** audio/mpeg version 2, 4 ***/
   488 
   632 
   491 #define AAC_CAPS (gst_static_caps_get(&aac_caps))
   635 #define AAC_CAPS (gst_static_caps_get(&aac_caps))
   492 #define AAC_AMOUNT (4096)
   636 #define AAC_AMOUNT (4096)
   493 static void
   637 static void
   494 aac_type_find (GstTypeFind * tf, gpointer unused)
   638 aac_type_find (GstTypeFind * tf, gpointer unused)
   495 {
   639 {
   496   guint8 *data = gst_type_find_peek (tf, 0, AAC_AMOUNT);
   640   DataScanCtx c = { 0, NULL, 0 };
   497   gint snc;
   641 
   498 
   642   while (c.offset < AAC_AMOUNT) {
   499   /* detect adts header or adif header.
   643     guint snc, len;
   500    * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
   644 
   501    * the other hand, is 14 bits only, so we require one valid frame with
   645     /* detect adts header or adif header.
   502    * again a valid syncpoint on the next one (28 bits) for certainty. We
   646      * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
   503    * require 4 kB, which is quite a lot, since frames are generally 200-400
   647      * the other hand, is 14 bits only, so we require one valid frame with
   504    * bytes.
   648      * again a valid syncpoint on the next one (28 bits) for certainty. We
   505    */
   649      * require 4 kB, which is quite a lot, since frames are generally 200-400
   506   if (data) {
   650      * bytes.
   507     gint n;
   651      */
   508 
   652     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
   509     for (n = 0; n < AAC_AMOUNT - 3; n++) {
   653       break;
   510       snc = GST_READ_UINT16_BE (&data[n]);
   654 
       
   655     snc = GST_READ_UINT16_BE (c.data);
       
   656     if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) {
       
   657       /* ADTS header - find frame length */
       
   658       GST_DEBUG ("Found one ADTS syncpoint at offset 0x%" G_GINT64_MODIFIER
       
   659           "x, tracing next...", c.offset);
       
   660       len = ((c.data[3] & 0x03) << 11) |
       
   661           (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
       
   662 
       
   663       if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
       
   664         GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
       
   665         goto next;
       
   666       }
       
   667 
       
   668       snc = GST_READ_UINT16_BE (c.data + len);
   511       if ((snc & 0xfff6) == 0xfff0) {
   669       if ((snc & 0xfff6) == 0xfff0) {
   512         /* ADTS header - find frame length */
   670         gint mpegversion;
   513         gint len;
   671 
   514 
   672         mpegversion = (c.data[1] & 0x08) ? 2 : 4;
   515         GST_DEBUG ("Found one ADTS syncpoint at offset 0x%x, tracing next...",
   673         GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%"
   516             n);
   674             G_GINT64_MODIFIER "x, framelen %u", mpegversion, c.offset, len);
   517         if (AAC_AMOUNT - n < 5) {
   675         gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
   518           GST_DEBUG ("Not enough data to parse ADTS header");
       
   519           break;
       
   520         }
       
   521         len = ((data[n + 3] & 0x03) << 11) |
       
   522             (data[n + 4] << 3) | ((data[n + 5] & 0xe0) >> 5);
       
   523         if (n + len + 2 >= AAC_AMOUNT) {
       
   524           GST_DEBUG ("Next frame is not within reach");
       
   525           break;
       
   526         } else if (len == 0) {
       
   527           continue;
       
   528         }
       
   529 
       
   530         snc = GST_READ_UINT16_BE (&data[n + len]);
       
   531         if ((snc & 0xfff6) == 0xfff0) {
       
   532           gint mpegversion = (data[n + 1] & 0x08) ? 2 : 4;
       
   533           GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
       
   534               "framed", G_TYPE_BOOLEAN, FALSE,
       
   535               "mpegversion", G_TYPE_INT, mpegversion,
       
   536               NULL);
       
   537 
       
   538           gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
       
   539           gst_caps_unref (caps);
       
   540 
       
   541           GST_DEBUG ("Found ADTS-%d syncpoint at offset 0x%x (framelen %u)",
       
   542               mpegversion, n, len);
       
   543           break;
       
   544         }
       
   545 
       
   546         GST_DEBUG ("No next frame found... (should be at 0x%x)", n + len);
       
   547       } else if (!memcmp (&data[n], "ADIF", 4)) {
       
   548         /* ADIF header */
       
   549         GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
       
   550             "framed", G_TYPE_BOOLEAN, FALSE,
   676             "framed", G_TYPE_BOOLEAN, FALSE,
   551             "mpegversion", G_TYPE_INT, 4,
   677             "mpegversion", G_TYPE_INT, mpegversion, NULL);
   552             NULL);
   678         break;
   553 
       
   554         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
       
   555         gst_caps_unref (caps);
       
   556       }
   679       }
   557     }
   680 
       
   681       GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
       
   682     } else if (!memcmp (c.data, "ADIF", 4)) {
       
   683       /* ADIF header */
       
   684       gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
       
   685           "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4, NULL);
       
   686       break;
       
   687     }
       
   688 
       
   689   next:
       
   690 
       
   691     data_scan_ctx_advance (tf, &c, 1);
   558   }
   692   }
   559 }
   693 }
   560 
   694 
   561 /*** audio/mpeg version 1 ***/
   695 /*** audio/mpeg version 1 ***/
   562 
   696 
   799               start_off + offset);
   933               start_off + offset);
   800         }
   934         }
   801         offset += length;
   935         offset += length;
   802       }
   936       }
   803       g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
   937       g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
       
   938       if (head_data == NULL &&
       
   939           gst_type_find_peek (tf, offset + start_off - 1, 1) == NULL)
       
   940         /* Incomplete last frame - don't count it. */
       
   941         found--;
   804       if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
   942       if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
   805           (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
   943           (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
   806         /* we can make a valid guess */
   944         /* we can make a valid guess */
   807         guint probability = found * GST_TYPE_FIND_MAXIMUM *
   945         guint probability = found * GST_TYPE_FIND_MAXIMUM *
   808             (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
   946             (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
   896 
  1034 
   897   return;
  1035   return;
   898 
  1036 
   899 suggest:
  1037 suggest:
   900   {
  1038   {
   901     GstCaps *caps;
  1039     g_return_if_fail (layer >= 1 && layer <= 3);
   902 
  1040 
   903     g_assert (layer > 0);
  1041     gst_type_find_suggest_simple (tf, prob, "audio/mpeg",
   904 
  1042         "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
   905     caps = gst_caps_make_writable (MP3_CAPS);
       
   906     gst_structure_set (gst_caps_get_structure (caps, 0), "layer",
       
   907         G_TYPE_INT, layer, NULL);
       
   908     gst_type_find_suggest (tf, prob, caps);
       
   909     gst_caps_unref (caps);
       
   910     return;
       
   911   }
  1043   }
   912 }
  1044 }
   913 
  1045 
   914 /*** audio/x-musepack ***/
  1046 /*** audio/x-musepack ***/
   915 
  1047 
   916 static GstStaticCaps musepack_caps = GST_STATIC_CAPS ("audio/x-musepack");
  1048 static GstStaticCaps musepack_caps =
       
  1049 GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }");
   917 
  1050 
   918 #define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps))
  1051 #define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps))
   919 static void
  1052 static void
   920 musepack_type_find (GstTypeFind * tf, gpointer unused)
  1053 musepack_type_find (GstTypeFind * tf, gpointer unused)
   921 {
  1054 {
   922   guint8 *data = gst_type_find_peek (tf, 0, 4);
  1055   guint8 *data = gst_type_find_peek (tf, 0, 4);
       
  1056   GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM;
       
  1057   gint streamversion = -1;
   923 
  1058 
   924   if (data && memcmp (data, "MP+", 3) == 0) {
  1059   if (data && memcmp (data, "MP+", 3) == 0) {
       
  1060     streamversion = 7;
   925     if ((data[3] & 0x7f) == 7) {
  1061     if ((data[3] & 0x7f) == 7) {
   926       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MUSEPACK_CAPS);
  1062       prop = GST_TYPE_FIND_MAXIMUM;
   927     } else {
  1063     } else {
   928       gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, MUSEPACK_CAPS);
  1064       prop = GST_TYPE_FIND_LIKELY + 10;
   929     }
  1065     }
       
  1066   } else if (data && memcmp (data, "MPCK", 4) == 0) {
       
  1067     streamversion = 8;
       
  1068     prop = GST_TYPE_FIND_MAXIMUM;
       
  1069   }
       
  1070 
       
  1071   if (streamversion != -1) {
       
  1072     gst_type_find_suggest_simple (tf, prop, "audio/x-musepack",
       
  1073         "streamversion", G_TYPE_INT, streamversion, NULL);
   930   }
  1074   }
   931 }
  1075 }
   932 
  1076 
   933 /*** audio/x-ac3 ***/
  1077 /*** audio/x-ac3 ***/
   934 /* This should be audio/ac3, but isn't for backwards compatibility */
  1078 /* This should be audio/ac3, but isn't for backwards compatibility */
  1025     offset++;
  1169     offset++;
  1026     data = gst_type_find_peek (tf, offset, 5);
  1170     data = gst_type_find_peek (tf, offset, 5);
  1027   }
  1171   }
  1028 }
  1172 }
  1029 
  1173 
       
  1174 /*** gsm ***/
       
  1175 
       
  1176 /* can only be detected by using the extension, in which case we use the default
       
  1177  * GSM properties */
       
  1178 static GstStaticCaps gsm_caps =
       
  1179 GST_STATIC_CAPS ("audio/x-gsm, rate=8000, channels=1");
       
  1180 
       
  1181 #define GSM_CAPS (gst_static_caps_get(&gsm_caps))
       
  1182 
  1030 /*** wavpack ***/
  1183 /*** wavpack ***/
  1031 
  1184 
  1032 static GstStaticCaps wavpack_caps =
  1185 static GstStaticCaps wavpack_caps =
  1033 GST_STATIC_CAPS ("audio/x-wavpack, framed = (boolean) false");
  1186 GST_STATIC_CAPS ("audio/x-wavpack, framed = (boolean) false");
  1034 
  1187 
  1134     if (!isascii (*x)) {
  1287     if (!isascii (*x)) {
  1135       return;
  1288       return;
  1136     }
  1289     }
  1137     if (*x == '\n' &&
  1290     if (*x == '\n' &&
  1138         !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) {
  1291         !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) {
  1139       GstCaps *caps = gst_caps_copy (MULTIPART_CAPS);
  1292       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MULTIPART_CAPS);
  1140 
       
  1141       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, caps);
       
  1142       gst_caps_unref (caps);
       
  1143       return;
  1293       return;
  1144     }
  1294     }
  1145   }
  1295   }
  1146 }
  1296 }
  1147 
  1297 
  1148 /*** video/mpeg systemstream ***/
  1298 /*** video/mpeg systemstream ***/
  1149 static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
  1299 static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
  1150     "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]");
  1300     "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]");
  1151 
  1301 
  1152 #define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps)
  1302 #define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps)
  1153 #define IS_MPEG_HEADER(data)            ((((guint8 *)(data))[0] == 0x00) &&  \
  1303 #define IS_MPEG_HEADER(data) (G_UNLIKELY((((guint8 *)(data))[0] == 0x00) &&  \
  1154                                          (((guint8 *)(data))[1] == 0x00) &&  \
  1304                                          (((guint8 *)(data))[1] == 0x00) &&  \
  1155                                          (((guint8 *)(data))[2] == 0x01))
  1305                                          (((guint8 *)(data))[2] == 0x01)))
  1156 
  1306 
  1157 #define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
  1307 #define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
  1158 #define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
  1308 #define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
  1159 #define IS_MPEG_PACK_HEADER(data)       (IS_MPEG_HEADER (data) &&            \
  1309 #define IS_MPEG_PACK_HEADER(data)       (IS_MPEG_HEADER (data) &&            \
  1160                                          IS_MPEG_PACK_CODE (((guint8 *)(data))[3]))
  1310                                          IS_MPEG_PACK_CODE (((guint8 *)(data))[3]))
  1169 
  1319 
  1170 #define MPEG2_MIN_SYS_HEADERS 2
  1320 #define MPEG2_MIN_SYS_HEADERS 2
  1171 #define MPEG2_MAX_SYS_HEADERS 5
  1321 #define MPEG2_MAX_SYS_HEADERS 5
  1172 
  1322 
  1173 static gboolean
  1323 static gboolean
  1174 mpeg_sys_is_valid_pack (GstTypeFind * tf, guint8 * data, guint len,
  1324 mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len,
  1175     guint * pack_size)
  1325     guint * pack_size)
  1176 {
  1326 {
  1177   /* Check the pack header @ offset for validity, assuming that the 4 byte header
  1327   /* Check the pack header @ offset for validity, assuming that the 4 byte header
  1178    * itself has already been checked. */
  1328    * itself has already been checked. */
  1179   guint8 stuff_len;
  1329   guint8 stuff_len;
  1385     goto suggest;
  1535     goto suggest;
  1386 
  1536 
  1387   return;
  1537   return;
  1388 suggest:
  1538 suggest:
  1389   {
  1539   {
  1390     GstCaps *caps = gst_caps_copy (MPEG_SYS_CAPS);
       
  1391     guint prob;
  1540     guint prob;
  1392 
  1541 
  1393     prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
  1542     prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
  1394     prob = MIN (prob, GST_TYPE_FIND_MAXIMUM);
  1543     prob = MIN (prob, GST_TYPE_FIND_MAXIMUM);
  1395 
  1544 
  1398       prob -= 10;
  1547       prob -= 10;
  1399 
  1548 
  1400     GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
  1549     GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
  1401         mpegversion, pack_headers, pes_headers, prob);
  1550         mpegversion, pack_headers, pes_headers, prob);
  1402 
  1551 
  1403     gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
  1552     gst_type_find_suggest_simple (tf, prob, "video/mpeg",
  1404         G_TYPE_INT, mpegversion, NULL);
  1553         "systemstream", G_TYPE_BOOLEAN, TRUE,
  1405     gst_type_find_suggest (tf, prob, caps);
  1554         "mpegversion", G_TYPE_INT, mpegversion, NULL);
  1406     gst_caps_unref (caps);
       
  1407   }
  1555   }
  1408 };
  1556 };
  1409 
  1557 
  1410 /** video/mpegts Transport Stream **/
  1558 /** video/mpegts Transport Stream **/
  1411 static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
  1559 static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
  1479 
  1627 
  1480         /* Probe ahead at size pack_sizes[p] */
  1628         /* Probe ahead at size pack_sizes[p] */
  1481         found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]);
  1629         found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]);
  1482         if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
  1630         if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
  1483           gint probability;
  1631           gint probability;
  1484           GstCaps *caps = gst_caps_copy (MPEGTS_CAPS);
       
  1485 
       
  1486           gst_structure_set (gst_caps_get_structure (caps, 0), "packetsize",
       
  1487               G_TYPE_INT, pack_sizes[p], NULL);
       
  1488 
  1632 
  1489           /* found at least 4 headers. 10 headers = MAXIMUM probability. 
  1633           /* found at least 4 headers. 10 headers = MAXIMUM probability. 
  1490            * Arbitrarily, I assigned 10% probability for each header we
  1634            * Arbitrarily, I assigned 10% probability for each header we
  1491            * found, 40% -> 100% */
  1635            * found, 40% -> 100% */
  1492           probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
  1636           probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
  1493 
  1637 
  1494           gst_type_find_suggest (tf, probability, caps);
  1638           gst_type_find_suggest_simple (tf, probability, "video/mpegts",
  1495           gst_caps_unref (caps);
  1639               "systemstream", G_TYPE_BOOLEAN, TRUE,
       
  1640               "packetsize", G_TYPE_INT, pack_sizes[p], NULL);
  1496           return;
  1641           return;
  1497         }
  1642         }
  1498       }
  1643       }
  1499     }
  1644     }
  1500     data++;
  1645     data++;
  1533       else if (sc >= 0x00 && sc <= 0x1F) {      /* video_object_start_code */
  1678       else if (sc >= 0x00 && sc <= 0x1F) {      /* video_object_start_code */
  1534         offset += 4;
  1679         offset += 4;
  1535         seen_vos = TRUE;
  1680         seen_vos = TRUE;
  1536       } else if (sc >= 0x20 && sc <= 0x2F) {    /* video_object_layer_start_code */
  1681       } else if (sc >= 0x20 && sc <= 0x2F) {    /* video_object_layer_start_code */
  1537         if (seen_vos) {
  1682         if (seen_vos) {
  1538           GstCaps *caps = gst_caps_copy (MPEG4_VIDEO_CAPS);
  1683           gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN,
  1539 
  1684               MPEG4_VIDEO_CAPS);
  1540           gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
       
  1541           gst_caps_unref (caps);
       
  1542           return;
  1685           return;
  1543         } else
  1686         } else
  1544           return;
  1687           return;
  1545       } else
  1688       } else
  1546         return;
  1689         return;
  1558 #define H264_MAX_PROBE_LENGTH (128 * 1024)      /* 128kB for HD should be enough. */
  1701 #define H264_MAX_PROBE_LENGTH (128 * 1024)      /* 128kB for HD should be enough. */
  1559 
  1702 
  1560 static void
  1703 static void
  1561 h264_video_type_find (GstTypeFind * tf, gpointer unused)
  1704 h264_video_type_find (GstTypeFind * tf, gpointer unused)
  1562 {
  1705 {
       
  1706   DataScanCtx c = { 0, NULL, 0 };
       
  1707 
  1563   /* Stream consists of: a series of sync codes (00 00 00 01) followed 
  1708   /* Stream consists of: a series of sync codes (00 00 00 01) followed 
  1564    * by NALs
  1709    * by NALs
  1565    */
  1710    */
  1566   guint8 *data = NULL;
       
  1567   int offset = 0;
       
  1568   int stat_slice = 0;
  1711   int stat_slice = 0;
  1569   int stat_dpa = 0;
  1712   int stat_dpa = 0;
  1570   int stat_dpb = 0;
  1713   int stat_dpb = 0;
  1571   int stat_dpc = 0;
  1714   int stat_dpc = 0;
  1572   int stat_idr = 0;
  1715   int stat_idr = 0;
  1573   int stat_sps = 0;
  1716   int stat_sps = 0;
  1574   int stat_pps = 0;
  1717   int stat_pps = 0;
  1575   int nut, ref;
  1718   int nut, ref;
  1576 
  1719 
  1577   while (offset < H264_MAX_PROBE_LENGTH) {
  1720   while (c.offset < H264_MAX_PROBE_LENGTH) {
  1578     data = gst_type_find_peek (tf, offset, 4);
  1721     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
  1579     if (data && IS_MPEG_HEADER (data)) {
  1722       break;
  1580       nut = data[3] & 0x9f;     /* forbiden_zero_bit | nal_unit_type */
  1723 
  1581       ref = data[3] & 0x60;     /* nal_ref_idc */
  1724     if (IS_MPEG_HEADER (c.data)) {
       
  1725       nut = c.data[3] & 0x9f;   /* forbiden_zero_bit | nal_unit_type */
       
  1726       ref = c.data[3] & 0x60;   /* nal_ref_idc */
  1582 
  1727 
  1583       /* if forbiden bit is different to 0 won't be h264 */
  1728       /* if forbiden bit is different to 0 won't be h264 */
  1584       if (nut > 0x1f)
  1729       if (nut > 0x1f)
  1585         goto done;
  1730         break;
  1586 
  1731 
  1587       /* collect statistics about the NAL types */
  1732       /* collect statistics about the NAL types */
  1588       if (nut == 1)
  1733       if (nut == 1)
  1589         stat_slice++;
  1734         stat_slice++;
  1590       else if (nut == 2)
  1735       else if (nut == 2)
  1598       else if ((nut == 7) && (ref != 0))
  1743       else if ((nut == 7) && (ref != 0))
  1599         stat_sps++;
  1744         stat_sps++;
  1600       else if ((nut == 8) && (ref != 0))
  1745       else if ((nut == 8) && (ref != 0))
  1601         stat_pps++;
  1746         stat_pps++;
  1602 
  1747 
  1603       offset += 4;
  1748       if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
  1604     }
  1749           stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
  1605     offset += 1;
  1750         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
  1606 
  1751         return;
  1607     if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
  1752       }
  1608         stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
  1753 
  1609       GstCaps *caps = gst_caps_copy (H264_VIDEO_CAPS);
  1754       data_scan_ctx_advance (tf, &c, 4);
  1610 
  1755     }
  1611       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 1, caps);
  1756     data_scan_ctx_advance (tf, &c, 1);
  1612       gst_caps_unref (caps);
  1757   }
  1613 
       
  1614       goto done;
       
  1615     }
       
  1616   }
       
  1617 
       
  1618 done:
       
  1619   return;
       
  1620 }
  1758 }
  1621 
  1759 
  1622 /*** video/mpeg video stream ***/
  1760 /*** video/mpeg video stream ***/
  1623 
  1761 
  1624 static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
  1762 static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
  1625     "systemstream = (boolean) false");
  1763     "systemstream = (boolean) false");
  1626 #define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps)
  1764 #define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps)
  1627 static void
       
  1628 mpeg_video_type_find (GstTypeFind * tf, gpointer unused)
       
  1629 {
       
  1630   static const guint8 sequence_header[] = { 0x00, 0x00, 0x01, 0xb3 };
       
  1631   guint8 *data = NULL;
       
  1632 
       
  1633   data = gst_type_find_peek (tf, 0, 8);
       
  1634 
       
  1635   if (data && memcmp (data, sequence_header, 4) == 0) {
       
  1636     GstCaps *caps = gst_caps_copy (MPEG_VIDEO_CAPS);
       
  1637 
       
  1638     gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
       
  1639         G_TYPE_INT, 1, NULL);
       
  1640     gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, caps);
       
  1641     gst_caps_unref (caps);
       
  1642   }
       
  1643 }
       
  1644 
  1765 
  1645 /*
  1766 /*
  1646  * Idea is the same as MPEG system stream typefinding: We check each
  1767  * Idea is the same as MPEG system stream typefinding: We check each
  1647  * byte of the stream to see if - from that point on - the stream
  1768  * byte of the stream to see if - from that point on - the stream
  1648  * matches a predefined set of marker bits as defined in the MPEG
  1769  * matches a predefined set of marker bits as defined in the MPEG
  1651  * I'm sure someone will do a chance calculation here too.
  1772  * I'm sure someone will do a chance calculation here too.
  1652  */
  1773  */
  1653 
  1774 
  1654 #define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6
  1775 #define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6
  1655 #define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024)      /* 100 kB */
  1776 #define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024)      /* 100 kB */
  1656 #define GST_MPEGVID_TYPEFIND_SYNC_SIZE 2048
       
  1657 
  1777 
  1658 static void
  1778 static void
  1659 mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
  1779 mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
  1660 {
  1780 {
  1661   gint size = 0, found = 0;
  1781   DataScanCtx c = { 0, NULL, 0 };
  1662   guint64 skipped = 0;
  1782   gboolean seen_seq_at_0 = FALSE;
  1663   guint8 *data = NULL;
  1783   gboolean seen_seq = FALSE;
  1664 
  1784   gboolean seen_gop = FALSE;
  1665   while (1) {
  1785   guint64 last_pic_offset = 0;
  1666     if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) {
  1786   guint num_pic_headers = 0;
  1667       GstCaps *caps = gst_caps_copy (MPEG_VIDEO_CAPS);
  1787   gint found = 0;
  1668 
  1788 
  1669       gst_structure_set (gst_caps_get_structure (caps, 0), "mpegversion",
  1789   while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) {
  1670           G_TYPE_INT, 1, NULL);
  1790     if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
  1671       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM - 2, caps);
       
  1672       gst_caps_unref (caps);
       
  1673       return;
       
  1674     }
       
  1675 
       
  1676     if (skipped > GST_MPEGVID_TYPEFIND_TRY_SYNC)
       
  1677       break;
  1791       break;
  1678 
  1792 
  1679     if (size < 5) {
  1793     if (!data_scan_ctx_ensure_data (tf, &c, 5))
  1680       data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
  1794       break;
  1681       if (!data)
  1795 
  1682         break;
  1796     if (!IS_MPEG_HEADER (c.data))
  1683       size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
  1797       goto next;
  1684     }
  1798 
  1685 
  1799     /* a pack header indicates that this isn't an elementary stream */
  1686     if (IS_MPEG_HEADER (data)) {
  1800     if (c.data[3] == 0xBA && mpeg_sys_is_valid_pack (tf, c.data, c.size, NULL))
  1687       /* An MPEG PACK header indicates that this isn't an elementary stream */
  1801       return;
  1688       if (IS_MPEG_PACK_CODE (data[3])) {
  1802 
  1689         if (mpeg_sys_is_valid_pack (tf, data, size, NULL))
  1803     /* do we have a sequence header? */
  1690           break;
  1804     if (c.data[3] == 0xB3) {
  1691       }
  1805       seen_seq_at_0 = seen_seq_at_0 || (c.offset == 0);
  1692 
  1806       seen_seq = TRUE;
  1693       /* are we a sequence (0xB3) or GOP (0xB8) header? */
  1807       data_scan_ctx_advance (tf, &c, 4 + 8);
  1694       if (data[3] == 0xB3 || data[3] == 0xB8) {
  1808       continue;
  1695         size -= 8;
  1809     }
  1696         data += 8;
  1810 
  1697         skipped += 8;
  1811     /* or a GOP header */
  1698         if (data[3] == 0xB3)
  1812     if (c.data[3] == 0xB8) {
  1699           continue;
  1813       seen_gop = TRUE;
  1700         else if (size < 4) {
  1814       data_scan_ctx_advance (tf, &c, 8);
  1701           data =
  1815       continue;
  1702               gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
  1816     }
  1703           size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
  1817 
  1704           if (!data)
  1818     /* but what we'd really like to see is a picture header */
  1705             break;
  1819     if (c.data[3] == 0x00) {
  1706         }
  1820       ++num_pic_headers;
  1707         /* else, we should now see an image */
  1821       last_pic_offset = c.offset;
  1708       }
  1822       data_scan_ctx_advance (tf, &c, 8);
  1709     }
  1823       continue;
  1710 
  1824     }
  1711     /* image header (and, when found, slice header) */
  1825 
  1712     if (IS_MPEG_HEADER (data) && data[4] == 0x0) {
  1826     /* ... each followed by a slice header with slice_vertical_pos=1 that's
  1713       size -= 8;
  1827      * not too far away from the previously seen picture header. */
  1714       data += 8;
  1828     if (c.data[3] == 0x01 && num_pic_headers > found &&
  1715       skipped += 8;
  1829         (c.offset - last_pic_offset) >= 4 &&
  1716       if (size < 5) {
  1830         (c.offset - last_pic_offset) <= 64) {
  1717         data = gst_type_find_peek (tf, skipped, GST_MPEGVID_TYPEFIND_SYNC_SIZE);
  1831       data_scan_ctx_advance (tf, &c, 4);
  1718         size = GST_MPEGVID_TYPEFIND_SYNC_SIZE;
  1832       found += 1;
  1719         if (!data)
  1833       continue;
  1720           break;
  1834     }
  1721       }
  1835 
  1722       if ((IS_MPEG_HEADER (data) && data[3] == 0x1) ||
  1836   next:
  1723           (IS_MPEG_HEADER (data + 1) && data[4] == 0x1)) {
  1837 
  1724         size -= 4;
  1838     data_scan_ctx_advance (tf, &c, 1);
  1725         data += 4;
  1839   }
  1726         skipped += 4;
  1840 
  1727         found += 1;
  1841   if (found > 0 || seen_seq) {
  1728         continue;
  1842     GstTypeFindProbability probability = 0;
  1729       }
  1843 
  1730     }
  1844     GST_LOG ("Found %d pictures, seq:%d, gop:%d", found, seen_seq, seen_gop);
  1731 
  1845 
  1732     size--;
  1846     if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq && seen_gop)
  1733     data++;
  1847       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1;
  1734     skipped++;
  1848     else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq)
       
  1849       probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9;
       
  1850     else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
       
  1851       probability = GST_TYPE_FIND_LIKELY;
       
  1852     else if (seen_seq_at_0 && seen_gop && found > 2)
       
  1853       probability = GST_TYPE_FIND_LIKELY - 10;
       
  1854     else if (seen_seq && seen_gop && found > 2)
       
  1855       probability = GST_TYPE_FIND_LIKELY - 20;
       
  1856     else if (seen_seq_at_0 && found > 0)
       
  1857       probability = GST_TYPE_FIND_POSSIBLE;
       
  1858     else if (seen_seq && found > 0)
       
  1859       probability = GST_TYPE_FIND_POSSIBLE - 5;
       
  1860     else if (found > 0)
       
  1861       probability = GST_TYPE_FIND_POSSIBLE - 10;
       
  1862     else if (seen_seq)
       
  1863       probability = GST_TYPE_FIND_POSSIBLE - 20;
       
  1864 
       
  1865     gst_type_find_suggest_simple (tf, probability, "video/mpeg",
       
  1866         "systemstream", G_TYPE_BOOLEAN, FALSE,
       
  1867         "mpegversion", G_TYPE_INT, 1, NULL);
  1735   }
  1868   }
  1736 }
  1869 }
  1737 
  1870 
  1738 /*** audio/x-aiff ***/
  1871 /*** audio/x-aiff ***/
  1739 
  1872 
  1874 
  2007 
  1875   return;
  2008   return;
  1876 
  2009 
  1877 }
  2010 }
  1878 
  2011 
       
  2012 /*** video/mj2 and image/jp2 ***/
       
  2013 static GstStaticCaps mj2_caps = GST_STATIC_CAPS ("video/mj2");
       
  2014 
       
  2015 #define MJ2_CAPS gst_static_caps_get(&mj2_caps)
       
  2016 
       
  2017 static GstStaticCaps jp2_caps = GST_STATIC_CAPS ("image/jp2");
       
  2018 
       
  2019 #define JP2_CAPS gst_static_caps_get(&jp2_caps)
       
  2020 
       
  2021 static void
       
  2022 jp2_type_find (GstTypeFind * tf, gpointer unused)
       
  2023 {
       
  2024   guint8 *data;
       
  2025 
       
  2026   data = gst_type_find_peek (tf, 0, 24);
       
  2027   if (!data)
       
  2028     return;
       
  2029 
       
  2030   /* jp2 signature */
       
  2031   if (memcmp (data, "\000\000\000\014jP  \015\012\207\012", 12) != 0)
       
  2032     return;
       
  2033 
       
  2034   /* check ftyp box */
       
  2035   data += 12;
       
  2036   if (memcmp (data + 4, "ftyp", 4) == 0) {
       
  2037     if (memcmp (data + 8, "jp2 ", 4) == 0)
       
  2038       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JP2_CAPS);
       
  2039     else if (memcmp (data + 8, "mjp2", 4) == 0)
       
  2040       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MJ2_CAPS);
       
  2041   }
       
  2042 }
       
  2043 
  1879 /*** video/quicktime ***/
  2044 /*** video/quicktime ***/
  1880 
  2045 
  1881 static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime");
  2046 static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime");
  1882 
  2047 
  1883 #define QT_CAPS gst_static_caps_get(&qt_caps)
  2048 #define QT_CAPS gst_static_caps_get(&qt_caps)
  1890   guint tip = 0;
  2055   guint tip = 0;
  1891   guint64 offset = 0;
  2056   guint64 offset = 0;
  1892   guint64 size;
  2057   guint64 size;
  1893 
  2058 
  1894   while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
  2059   while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
       
  2060     guint64 new_offset;
       
  2061 
  1895     /* box/atom types that are in common with ISO base media file format */
  2062     /* box/atom types that are in common with ISO base media file format */
  1896     if (STRNCMP (&data[4], "moov", 4) == 0 ||
  2063     if (STRNCMP (&data[4], "moov", 4) == 0 ||
  1897         STRNCMP (&data[4], "mdat", 4) == 0 ||
  2064         STRNCMP (&data[4], "mdat", 4) == 0 ||
  1898         STRNCMP (&data[4], "ftyp", 4) == 0 ||
  2065         STRNCMP (&data[4], "ftyp", 4) == 0 ||
  1899         STRNCMP (&data[4], "free", 4) == 0 ||
  2066         STRNCMP (&data[4], "free", 4) == 0 ||
  1927       size = GST_READ_UINT64_BE (sizedata);
  2094       size = GST_READ_UINT64_BE (sizedata);
  1928     } else {
  2095     } else {
  1929       if (size < 8)
  2096       if (size < 8)
  1930         break;
  2097         break;
  1931     }
  2098     }
  1932     offset += size;
  2099     new_offset = offset + size;
       
  2100     if (new_offset <= offset)
       
  2101       break;
       
  2102     offset = new_offset;
  1933   }
  2103   }
  1934   if (tip > 0) {
  2104   if (tip > 0) {
  1935     gst_type_find_suggest (tf, tip, QT_CAPS);
  2105     gst_type_find_suggest (tf, tip, QT_CAPS);
  1936   }
  2106   }
  1937 };
  2107 };
  2155 
  2325 
  2156 #define BMP_CAPS (gst_static_caps_get(&bmp_caps))
  2326 #define BMP_CAPS (gst_static_caps_get(&bmp_caps))
  2157 static void
  2327 static void
  2158 bmp_type_find (GstTypeFind * tf, gpointer unused)
  2328 bmp_type_find (GstTypeFind * tf, gpointer unused)
  2159 {
  2329 {
  2160   guint8 *data = gst_type_find_peek (tf, 0, 18);
  2330   DataScanCtx c = { 0, NULL, 0 };
  2161 
  2331   guint32 struct_size, w, h, planes, bpp;
  2162   if (data && memcmp (data, "BM", 2) == 0) {
  2332 
  2163     if ((data[14] == 0x0C ||
  2333   if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 54)))
  2164             data[14] == 0x28 ||
  2334     return;
  2165             data[14] == 0xF0) &&
  2335 
  2166         data[15] == 0 && data[16] == 0 && data[17] == 0) {
  2336   if (c.data[0] != 'B' || c.data[1] != 'M')
  2167       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, BMP_CAPS);
  2337     return;
  2168     }
  2338 
  2169   }
  2339   /* skip marker + size */
       
  2340   data_scan_ctx_advance (tf, &c, 2 + 4);
       
  2341 
       
  2342   /* reserved, must be 0 */
       
  2343   if (c.data[0] != 0 || c.data[1] != 0 || c.data[2] != 0 || c.data[3] != 0)
       
  2344     return;
       
  2345 
       
  2346   data_scan_ctx_advance (tf, &c, 2 + 2);
       
  2347 
       
  2348   /* offset to start of image data in bytes (check for sanity) */
       
  2349   GST_LOG ("offset=%u", GST_READ_UINT32_LE (c.data));
       
  2350   if (GST_READ_UINT32_LE (c.data) > (10 * 1024 * 1024))
       
  2351     return;
       
  2352 
       
  2353   struct_size = GST_READ_UINT32_LE (c.data + 4);
       
  2354   GST_LOG ("struct_size=%u", struct_size);
       
  2355 
       
  2356   data_scan_ctx_advance (tf, &c, 4 + 4);
       
  2357 
       
  2358   if (struct_size == 0x0C) {
       
  2359     w = GST_READ_UINT16_LE (c.data);
       
  2360     h = GST_READ_UINT16_LE (c.data + 2);
       
  2361     planes = GST_READ_UINT16_LE (c.data + 2 + 2);
       
  2362     bpp = GST_READ_UINT16_LE (c.data + 2 + 2 + 2);
       
  2363   } else if (struct_size == 40 || struct_size == 64 || struct_size == 108
       
  2364       || struct_size == 124 || struct_size == 0xF0) {
       
  2365     w = GST_READ_UINT32_LE (c.data);
       
  2366     h = GST_READ_UINT32_LE (c.data + 4);
       
  2367     planes = GST_READ_UINT16_LE (c.data + 4 + 4);
       
  2368     bpp = GST_READ_UINT16_LE (c.data + 4 + 4 + 2);
       
  2369   } else {
       
  2370     return;
       
  2371   }
       
  2372 
       
  2373   /* image sizes sanity check */
       
  2374   GST_LOG ("w=%u, h=%u, planes=%u, bpp=%u", w, h, planes, bpp);
       
  2375   if (w == 0 || w > 0xfffff || h == 0 || h > 0xfffff || planes != 1 ||
       
  2376       (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32))
       
  2377     return;
       
  2378 
       
  2379   gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "image/bmp",
       
  2380       "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, "bpp", G_TYPE_INT, bpp,
       
  2381       NULL);
  2170 }
  2382 }
  2171 
  2383 
  2172 /*** image/tiff ***/
  2384 /*** image/tiff ***/
  2173 static GstStaticCaps tiff_caps = GST_STATIC_CAPS ("image/tiff, "
  2385 static GstStaticCaps tiff_caps = GST_STATIC_CAPS ("image/tiff, "
  2174     "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }");
  2386     "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }");
  2296       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MATROSKA_CAPS);
  2508       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MATROSKA_CAPS);
  2297       break;
  2509       break;
  2298     }
  2510     }
  2299 }
  2511 }
  2300 
  2512 
       
  2513 /*** application/mxf ***/
       
  2514 static GstStaticCaps mxf_caps = GST_STATIC_CAPS ("application/mxf");
       
  2515 
       
  2516 #define MXF_MAX_PROBE_LENGTH (1024 * 64)
       
  2517 #define MXF_CAPS (gst_static_caps_get(&mxf_caps))
       
  2518 
       
  2519 /*
       
  2520  * MXF files start with a header partition pack key of 16 bytes which is defined
       
  2521  * at SMPTE-377M 6.1. Before this there can be up to 64K of run-in which _must_
       
  2522  * not contain the partition pack key.
       
  2523  */
       
  2524 static void
       
  2525 mxf_type_find (GstTypeFind * tf, gpointer ununsed)
       
  2526 {
       
  2527   static const guint8 partition_pack_key[] =
       
  2528       { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
       
  2529     0x01
       
  2530   };
       
  2531   DataScanCtx c = { 0, NULL, 0 };
       
  2532 
       
  2533   while (c.offset <= MXF_MAX_PROBE_LENGTH) {
       
  2534     if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 16)))
       
  2535       break;
       
  2536 
       
  2537     if (memcmp (c.data, partition_pack_key, 13) == 0) {
       
  2538       /* Header partition pack? */
       
  2539       if (c.data[13] != 0x02)
       
  2540         goto advance;
       
  2541 
       
  2542       /* Partition status */
       
  2543       if (c.data[14] >= 0x05)
       
  2544         goto advance;
       
  2545 
       
  2546       /* Reserved, must be 0x00 */
       
  2547       if (c.data[15] != 0x00)
       
  2548         goto advance;
       
  2549 
       
  2550       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXF_CAPS);
       
  2551       return;
       
  2552     }
       
  2553 
       
  2554   advance:
       
  2555     data_scan_ctx_advance (tf, &c, 1);
       
  2556   }
       
  2557 }
       
  2558 
  2301 /*** video/x-dv ***/
  2559 /*** video/x-dv ***/
  2302 
  2560 
  2303 static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, "
  2561 static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, "
  2304     "systemstream = (boolean) true");
  2562     "systemstream = (boolean) true");
  2305 #define DV_CAPS (gst_static_caps_get(&dv_caps))
  2563 #define DV_CAPS (gst_static_caps_get(&dv_caps))
  2309   guint8 *data;
  2567   guint8 *data;
  2310 
  2568 
  2311   data = gst_type_find_peek (tf, 0, 5);
  2569   data = gst_type_find_peek (tf, 0, 5);
  2312 
  2570 
  2313   /* check for DIF  and DV flag */
  2571   /* check for DIF  and DV flag */
  2314   if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00) &&
  2572   if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00)) {
  2315       ((data[4] & 0x01) == 0)) {
  2573     const gchar *format;
  2316     gchar *format;
       
  2317     GstCaps *caps = gst_caps_copy (DV_CAPS);
       
  2318 
  2574 
  2319     if (data[3] & 0x80) {
  2575     if (data[3] & 0x80) {
  2320       format = "PAL";
  2576       format = "PAL";
  2321     } else {
  2577     } else {
  2322       format = "NTSC";
  2578       format = "NTSC";
  2323     }
  2579     }
  2324     gst_structure_set (gst_caps_get_structure (caps, 0), "format",
  2580 
  2325         G_TYPE_STRING, format, NULL);
  2581     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "video/x-dv",
  2326 
  2582         "systemstream", G_TYPE_BOOLEAN, TRUE,
  2327     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, caps);
  2583         "format", G_TYPE_STRING, format, NULL);
  2328     gst_caps_unref (caps);
       
  2329   }
  2584   }
  2330 }
  2585 }
  2331 
  2586 
  2332 
  2587 
  2333 /*** application/ogg and application/x-annodex ***/
  2588 /*** application/ogg and application/x-annodex ***/
  2334 static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
  2589 static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
  2335 static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
  2590 static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
  2336 
  2591 static GstStaticCaps ogg_annodex_caps =
  2337 #define OGGANX_CAPS (gst_static_caps_get(&annodex_caps))
  2592     GST_STATIC_CAPS ("application/ogg;application/x-annodex");
       
  2593 
       
  2594 #define OGGANX_CAPS (gst_static_caps_get(&ogg_annodex_caps))
  2338 
  2595 
  2339 static void
  2596 static void
  2340 ogganx_type_find (GstTypeFind * tf, gpointer private)
  2597 ogganx_type_find (GstTypeFind * tf, gpointer private)
  2341 {
  2598 {
  2342   guint8 *data = gst_type_find_peek (tf, 0, 4);
  2599   guint8 *data = gst_type_find_peek (tf, 0, 4);
  2344   if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) {
  2601   if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) {
  2345 
  2602 
  2346     /* Check for an annodex fishbone header */
  2603     /* Check for an annodex fishbone header */
  2347     data = gst_type_find_peek (tf, 28, 8);
  2604     data = gst_type_find_peek (tf, 28, 8);
  2348     if (data && memcmp (data, "fishead\0", 8) == 0)
  2605     if (data && memcmp (data, "fishead\0", 8) == 0)
  2349       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGGANX_CAPS);
  2606       gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
       
  2607           gst_static_caps_get (&annodex_caps));
  2350 
  2608 
  2351     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
  2609     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
  2352         gst_static_caps_get (&ogg_caps));
  2610         gst_static_caps_get (&ogg_caps));
  2353   }
  2611   }
  2354 }
  2612 }
  2416 
  2674 
  2417     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, THEORA_CAPS);
  2675     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, THEORA_CAPS);
  2418   }
  2676   }
  2419 }
  2677 }
  2420 
  2678 
       
  2679 /*** kate ***/
       
  2680 static void
       
  2681 kate_type_find (GstTypeFind * tf, gpointer private)
       
  2682 {
       
  2683   guint8 *data = gst_type_find_peek (tf, 0, 64);
       
  2684   gchar category[16] = { 0, };
       
  2685 
       
  2686   if (G_UNLIKELY (data == NULL))
       
  2687     return;
       
  2688 
       
  2689   /* see: http://wiki.xiph.org/index.php/OggKate#Format_specification */
       
  2690   if (G_LIKELY (memcmp (data, "\200kate\0\0\0", 8) != 0))
       
  2691     return;
       
  2692 
       
  2693   /* make sure we always have a NUL-terminated string */
       
  2694   memcpy (category, data + 48, 15);
       
  2695   GST_LOG ("kate category: %s", category);
       
  2696   /* canonical categories for subtitles: subtitles, spu-subtitles, SUB, K-SPU */
       
  2697   if (strcmp (category, "subtitles") == 0 || strcmp (category, "SUB") == 0 ||
       
  2698       strcmp (category, "spu-subtitles") == 0 ||
       
  2699       strcmp (category, "K-SPU") == 0) {
       
  2700     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
       
  2701         "subtitle/x-kate", NULL);
       
  2702   } else {
       
  2703     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM,
       
  2704         "application/x-kate", NULL);
       
  2705   }
       
  2706 }
       
  2707 
  2421 /*** application/x-ogm-video or audio***/
  2708 /*** application/x-ogm-video or audio***/
  2422 
  2709 
  2423 static GstStaticCaps ogmvideo_caps =
  2710 static GstStaticCaps ogmvideo_caps =
  2424 GST_STATIC_CAPS ("application/x-ogm-video");
  2711 GST_STATIC_CAPS ("application/x-ogm-video");
  2425 #define OGMVIDEO_CAPS (gst_static_caps_get(&ogmvideo_caps))
  2712 #define OGMVIDEO_CAPS (gst_static_caps_get(&ogmvideo_caps))
  2496     if (GST_READ_UINT32_LE (data) > 3)
  2783     if (GST_READ_UINT32_LE (data) > 3)
  2497       return;
  2784       return;
  2498     data += 12;
  2785     data += 12;
  2499 
  2786 
  2500     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SPEEX_CAPS);
  2787     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SPEEX_CAPS);
       
  2788   }
       
  2789 }
       
  2790 
       
  2791 /*** audio/x-celt ***/
       
  2792 
       
  2793 static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt");
       
  2794 
       
  2795 #define CELT_CAPS (gst_static_caps_get(&celt_caps))
       
  2796 static void
       
  2797 celt_type_find (GstTypeFind * tf, gpointer private)
       
  2798 {
       
  2799   guint8 *data = gst_type_find_peek (tf, 0, 8);
       
  2800 
       
  2801   if (data) {
       
  2802     /* 8 byte string "CELT   " */
       
  2803     if (memcmp (data, "CELT    ", 8) != 0)
       
  2804       return;
       
  2805 
       
  2806     /* TODO: Check other values of the CELT header */
       
  2807     gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CELT_CAPS);
  2501   }
  2808   }
  2502 }
  2809 }
  2503 
  2810 
  2504 /*** application/x-ogg-skeleton ***/
  2811 /*** application/x-ogg-skeleton ***/
  2505 static GstStaticCaps ogg_skeleton_caps =
  2812 static GstStaticCaps ogg_skeleton_caps =
  2716 
  3023 
  2717   data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16);
  3024   data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16);
  2718   if (data && data[0] == 0x24 && data[1] == 0x48 &&
  3025   if (data && data[0] == 0x24 && data[1] == 0x48 &&
  2719       GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 &&
  3026       GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 &&
  2720       memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) {
  3027       memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) {
  2721     GstCaps *caps = gst_caps_copy (MMSH_CAPS);
  3028     gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMSH_CAPS);
  2722 
       
  2723     gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
       
  2724     gst_caps_unref (caps);
       
  2725     return;
       
  2726   }
  3029   }
  2727 }
  3030 }
  2728 
  3031 
  2729 /*** video/x-dirac ***/
  3032 /*** video/x-dirac ***/
  2730 
  3033 
  2901     "it", "med", "mod", "mtm", "okt", "sam",
  3204     "it", "med", "mod", "mtm", "okt", "sam",
  2902     "s3m", "stm", "stx", "ult", "xm", NULL
  3205     "s3m", "stm", "stx", "ult", "xm", NULL
  2903   };
  3206   };
  2904   static gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
  3207   static gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
  2905   static gchar *ac3_exts[] = { "ac3", NULL };
  3208   static gchar *ac3_exts[] = { "ac3", NULL };
  2906   static gchar *musepack_exts[] = { "mpc", NULL };
  3209   static gchar *gsm_exts[] = { "gsm", NULL };
       
  3210   static gchar *musepack_exts[] = { "mpc", "mpp", "mp+", NULL };
  2907   static gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
  3211   static gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
  2908   static gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
  3212   static gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
  2909   static gchar *mpeg_ts_exts[] = { "ts", NULL };
  3213   static gchar *mpeg_ts_exts[] = { "ts", NULL };
  2910   static gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL };
  3214   static gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL };
  2911   static gchar *qt_exts[] = { "mov", NULL };
  3215   static gchar *qt_exts[] = { "mov", NULL };
  2912   static gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL };
  3216   static gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL };
       
  3217   static gchar *mj2_exts[] = { "mj2", NULL };
       
  3218   static gchar *jp2_exts[] = { "jp2", NULL };
  2913   static gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL };
  3219   static gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL };
  2914   static gchar *swf_exts[] = { "swf", "swfl", NULL };
  3220   static gchar *swf_exts[] = { "swf", "swfl", NULL };
  2915   static gchar *utf8_exts[] = { "txt", NULL };
  3221   static gchar *utf8_exts[] = { "txt", NULL };
  2916   static gchar *wav_exts[] = { "wav", NULL };
  3222   static gchar *wav_exts[] = { "wav", NULL };
  2917   static gchar *aiff_exts[] = { "aiff", "aif", "aifc", NULL };
  3223   static gchar *aiff_exts[] = { "aiff", "aif", "aifc", NULL };
  2966   static gchar *h264_exts[] = { "h264", "x264", "264", NULL };
  3272   static gchar *h264_exts[] = { "h264", "x264", "264", NULL };
  2967   static gchar *nuv_exts[] = { "nuv", NULL };
  3273   static gchar *nuv_exts[] = { "nuv", NULL };
  2968   static gchar *vivo_exts[] = { "viv", NULL };
  3274   static gchar *vivo_exts[] = { "viv", NULL };
  2969   static gchar *nsf_exts[] = { "nsf", NULL };
  3275   static gchar *nsf_exts[] = { "nsf", NULL };
  2970   static gchar *mid_exts[] = { "mid", "midi", NULL };
  3276   static gchar *mid_exts[] = { "mid", "midi", NULL };
       
  3277   static gchar *mxmf_exts[] = { "mxmf", NULL };
  2971   static gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL };
  3278   static gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL };
       
  3279   static gchar *pdf_exts[] = { "pdf", NULL };
       
  3280   static gchar *mxf_exts[] = { "mxf", NULL };
       
  3281   static gchar *msword_exts[] = { "doc", NULL };
       
  3282   static gchar *dsstore_exts[] = { "DS_Store", NULL };
       
  3283   static gchar *psd_exts[] = { "psd", NULL };
  2972 
  3284 
  2973   GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions",
  3285   GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions",
  2974       GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions");
  3286       GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions");
  2975 
  3287 
  2976   /* must use strings, macros don't accept initializers */
  3288   /* must use strings, macros don't accept initializers */
  2997   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-smoke", GST_RANK_PRIMARY,
  3309   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-smoke", GST_RANK_PRIMARY,
  2998       NULL, "\x80smoke\x00\x01\x00", 6, GST_TYPE_FIND_MAXIMUM);
  3310       NULL, "\x80smoke\x00\x01\x00", 6, GST_TYPE_FIND_MAXIMUM);
  2999 #endif
  3311 #endif
  3000   TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find,
  3312   TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find,
  3001       mid_exts, MID_CAPS, NULL, NULL);
  3313       mid_exts, MID_CAPS, NULL, NULL);
       
  3314   TYPE_FIND_REGISTER (plugin, "audio/mobile-xmf", GST_RANK_PRIMARY,
       
  3315       mxmf_type_find, mxmf_exts, MXMF_CAPS, NULL, NULL);
  3002   TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find,
  3316   TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find,
  3003       flx_exts, FLX_CAPS, NULL, NULL);
  3317       flx_exts, FLX_CAPS, NULL, NULL);
  3004   TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103,
  3318   TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103,
  3005       id3v2_type_find, id3_exts, ID3_CAPS, NULL, NULL);
  3319       id3v2_type_find, id3_exts, ID3_CAPS, NULL, NULL);
  3006   TYPE_FIND_REGISTER (plugin, "application/x-id3v1", GST_RANK_PRIMARY + 101,
  3320   TYPE_FIND_REGISTER (plugin, "application/x-id3v1", GST_RANK_PRIMARY + 101,
  3013       mod_exts, MOD_CAPS, NULL, NULL);
  3327       mod_exts, MOD_CAPS, NULL, NULL);
  3014   TYPE_FIND_REGISTER (plugin, "audio/mpeg", GST_RANK_PRIMARY, mp3_type_find,
  3328   TYPE_FIND_REGISTER (plugin, "audio/mpeg", GST_RANK_PRIMARY, mp3_type_find,
  3015       mp3_exts, MP3_CAPS, NULL, NULL);
  3329       mp3_exts, MP3_CAPS, NULL, NULL);
  3016   TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
  3330   TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
  3017       ac3_exts, AC3_CAPS, NULL, NULL);
  3331       ac3_exts, AC3_CAPS, NULL, NULL);
       
  3332   TYPE_FIND_REGISTER (plugin, "audio/x-gsm", GST_RANK_PRIMARY, NULL,
       
  3333       gsm_exts, GSM_CAPS, NULL, NULL);
  3018   TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
  3334   TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
  3019       mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
  3335       mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
  3020   TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
  3336   TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
  3021       mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
  3337       mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
  3022   TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
  3338   TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
  3023       ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
  3339       ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
  3024   TYPE_FIND_REGISTER (plugin, "video/mpeg,elementary", GST_RANK_SECONDARY,
  3340   TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL,
  3025       mpeg_video_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL, NULL);
       
  3026   TYPE_FIND_REGISTER (plugin, "video/mpeg-stream", GST_RANK_MARGINAL,
       
  3027       mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
  3341       mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
  3028       NULL);
  3342       NULL);
  3029   TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,
  3343   TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,
  3030       mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL);
  3344       mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL);
  3031   TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY,
  3345   TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY,
  3032       h264_video_type_find, h264_exts, MPEG_VIDEO_CAPS, NULL, NULL);
  3346       h264_video_type_find, h264_exts, MPEG_VIDEO_CAPS, NULL, NULL);
  3033   TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY,
  3347   TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY, nuv_type_find,
  3034       nuv_type_find, nuv_exts, NUV_CAPS, NULL, NULL);
  3348       nuv_exts, NUV_CAPS, NULL, NULL);
  3035 
  3349 
  3036   /* ISO formats */
  3350   /* ISO formats */
  3037   TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find,
  3351   TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find,
  3038       m4a_exts, M4A_CAPS, NULL, NULL);
  3352       m4a_exts, M4A_CAPS, NULL, NULL);
  3039   TYPE_FIND_REGISTER (plugin, "application/x-3gp", GST_RANK_PRIMARY,
  3353   TYPE_FIND_REGISTER (plugin, "application/x-3gp", GST_RANK_PRIMARY,
  3040       q3gp_type_find, q3gp_exts, Q3GP_CAPS, NULL, NULL);
  3354       q3gp_type_find, q3gp_exts, Q3GP_CAPS, NULL, NULL);
  3041   TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY,
  3355   TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY,
  3042       qt_type_find, qt_exts, QT_CAPS, NULL, NULL);
  3356       qt_type_find, qt_exts, QT_CAPS, NULL, NULL);
  3043   TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY,
  3357   TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY,
  3044       qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL);
  3358       qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL);
       
  3359   TYPE_FIND_REGISTER (plugin, "image/jp2", GST_RANK_PRIMARY,
       
  3360       jp2_type_find, jp2_exts, JP2_CAPS, NULL, NULL);
       
  3361   TYPE_FIND_REGISTER (plugin, "video/mj2", GST_RANK_PRIMARY,
       
  3362       jp2_type_find, mj2_exts, MJ2_CAPS, NULL, NULL);
  3045 
  3363 
  3046   TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find,
  3364   TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find,
  3047       html_exts, HTML_CAPS, NULL, NULL);
  3365       html_exts, HTML_CAPS, NULL, NULL);
  3048   TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia",
  3366   TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia",
  3049       GST_RANK_SECONDARY, rm_exts, ".RMF", 4, GST_TYPE_FIND_MAXIMUM);
  3367       GST_RANK_SECONDARY, rm_exts, ".RMF", 4, GST_TYPE_FIND_MAXIMUM);
  3095       bmp_exts, BMP_CAPS, NULL, NULL);
  3413       bmp_exts, BMP_CAPS, NULL, NULL);
  3096   TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find,
  3414   TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find,
  3097       tiff_exts, TIFF_CAPS, NULL, NULL);
  3415       tiff_exts, TIFF_CAPS, NULL, NULL);
  3098   TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY,
  3416   TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY,
  3099       matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL);
  3417       matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL);
       
  3418   TYPE_FIND_REGISTER (plugin, "application/mxf", GST_RANK_PRIMARY,
       
  3419       mxf_type_find, mxf_exts, MXF_CAPS, NULL, NULL);
  3100   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY,
  3420   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY,
  3101       mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
  3421       mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
  3102       GST_TYPE_FIND_MAXIMUM);
  3422       GST_TYPE_FIND_MAXIMUM);
  3103   TYPE_FIND_REGISTER (plugin, "video/x-dv", GST_RANK_SECONDARY, dv_type_find,
  3423   TYPE_FIND_REGISTER (plugin, "video/x-dv", GST_RANK_SECONDARY, dv_type_find,
  3104       dv_exts, DV_CAPS, NULL, NULL);
  3424       dv_exts, DV_CAPS, NULL, NULL);
  3127       GST_RANK_SECONDARY, gz_exts, "\037\213", 2, GST_TYPE_FIND_LIKELY);
  3447       GST_RANK_SECONDARY, gz_exts, "\037\213", 2, GST_TYPE_FIND_LIKELY);
  3128   TYPE_FIND_REGISTER_START_WITH (plugin, "application/zip", GST_RANK_SECONDARY,
  3448   TYPE_FIND_REGISTER_START_WITH (plugin, "application/zip", GST_RANK_SECONDARY,
  3129       zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY);
  3449       zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY);
  3130   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress",
  3450   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress",
  3131       GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY);
  3451       GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY);
       
  3452   TYPE_FIND_REGISTER (plugin, "subtitle/x-kate", GST_RANK_MARGINAL,
       
  3453       kate_type_find, NULL, NULL, NULL, NULL);
  3132   TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY,
  3454   TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY,
  3133       flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL);
  3455       flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL);
  3134   TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY,
  3456   TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY,
  3135       vorbis_type_find, NULL, VORBIS_CAPS, NULL, NULL);
  3457       vorbis_type_find, NULL, VORBIS_CAPS, NULL, NULL);
  3136   TYPE_FIND_REGISTER (plugin, "video/x-theora", GST_RANK_PRIMARY,
  3458   TYPE_FIND_REGISTER (plugin, "video/x-theora", GST_RANK_PRIMARY,
  3141       ogmaudio_type_find, NULL, OGMAUDIO_CAPS, NULL, NULL);
  3463       ogmaudio_type_find, NULL, OGMAUDIO_CAPS, NULL, NULL);
  3142   TYPE_FIND_REGISTER (plugin, "application/x-ogm-text", GST_RANK_PRIMARY,
  3464   TYPE_FIND_REGISTER (plugin, "application/x-ogm-text", GST_RANK_PRIMARY,
  3143       ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL);
  3465       ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL);
  3144   TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY,
  3466   TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY,
  3145       speex_type_find, NULL, SPEEX_CAPS, NULL, NULL);
  3467       speex_type_find, NULL, SPEEX_CAPS, NULL, NULL);
       
  3468   TYPE_FIND_REGISTER (plugin, "audio/x-celt", GST_RANK_PRIMARY,
       
  3469       celt_type_find, NULL, CELT_CAPS, NULL, NULL);
  3146   TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY,
  3470   TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY,
  3147       oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL);
  3471       oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL);
  3148   TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find,
  3472   TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find,
  3149       NULL, CMML_CAPS, NULL, NULL);
  3473       NULL, CMML_CAPS, NULL, NULL);
  3150   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-executable",
  3474   TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-executable",
  3174       mmsh_type_find, NULL, MMSH_CAPS, NULL, NULL);
  3498       mmsh_type_find, NULL, MMSH_CAPS, NULL, NULL);
  3175   TYPE_FIND_REGISTER (plugin, "video/vivo", GST_RANK_SECONDARY,
  3499   TYPE_FIND_REGISTER (plugin, "video/vivo", GST_RANK_SECONDARY,
  3176       vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL);
  3500       vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL);
  3177   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf",
  3501   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf",
  3178       GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM);
  3502       GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM);
       
  3503   TYPE_FIND_REGISTER_START_WITH (plugin, "application/pdf",
       
  3504       GST_RANK_SECONDARY, pdf_exts, "%PDF-", 5, GST_TYPE_FIND_LIKELY);
       
  3505   TYPE_FIND_REGISTER_START_WITH (plugin, "application/msword",
       
  3506       GST_RANK_SECONDARY, msword_exts, "\320\317\021\340\241\261\032\341", 8,
       
  3507       GST_TYPE_FIND_LIKELY);
       
  3508   /* Mac OS X .DS_Store files tend to be taken for video/mpeg */
       
  3509   TYPE_FIND_REGISTER_START_WITH (plugin, "application/octet-stream",
       
  3510       GST_RANK_SECONDARY, dsstore_exts, "\000\000\000\001Bud1", 8,
       
  3511       GST_TYPE_FIND_LIKELY);
       
  3512   TYPE_FIND_REGISTER_START_WITH (plugin, "image/vnd.adobe.photoshop",
       
  3513       GST_RANK_SECONDARY, psd_exts, "8BPS\000\001\000\000\000\000", 10,
       
  3514       GST_TYPE_FIND_LIKELY);
  3179   return TRUE;
  3515   return TRUE;
  3180 }
  3516 }
  3181 
  3517 
  3182 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
  3518 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
  3183     GST_VERSION_MINOR,
  3519     GST_VERSION_MINOR,