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