2 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
4 * gsttypefindfunctions.c: collection of various typefind functions
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
26 #include <glib/gstrfuncs.h>
28 #include <gst/gsttypefind.h>
29 #include <gst/gstelement.h>
30 #include <gst/gstversion.h>
31 #include <gst/gstinfo.h>
32 #include <gst/gstutils.h>
37 GST_DEBUG_CATEGORY_STATIC (type_find_debug);
38 #define GST_CAT_DEFAULT type_find_debug
40 /* DataScanCtx: helper for typefind functions that scan through data
41 * step-by-step, to avoid doing a peek at each and every offset */
43 #define DATA_SCAN_CTX_CHUNK_SIZE 4096
53 data_scan_ctx_advance (GstTypeFind * tf, DataScanCtx * c, guint bytes_to_skip)
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;
65 static inline gboolean
66 data_scan_ctx_ensure_data (GstTypeFind * tf, DataScanCtx * c, gint min_len)
71 if (G_LIKELY (c->size >= min_len))
74 data = gst_type_find_peek (tf, c->offset, DATA_SCAN_CTX_CHUNK_SIZE);
75 if (G_LIKELY (data != NULL)) {
77 c->size = DATA_SCAN_CTX_CHUNK_SIZE;
81 /* if there's less than our chunk size, try to get as much as we can, but
82 * always at least min_len bytes (we might be typefinding the first buffer
83 * of the stream and not have as much data available as we'd like) */
84 len = gst_type_find_get_length (tf);
86 len = CLAMP (len - c->offset, min_len, DATA_SCAN_CTX_CHUNK_SIZE);
91 data = gst_type_find_peek (tf, c->offset, len);
102 static gboolean xml_check_first_element (GstTypeFind * tf,
103 const gchar * element, guint elen, gboolean strict);
104 static gboolean sdp_check_header (GstTypeFind * tf);
106 static GstStaticCaps utf8_caps = GST_STATIC_CAPS ("text/plain");
108 #define UTF8_CAPS gst_static_caps_get(&utf8_caps)
111 utf8_type_find_have_valid_utf8_at_offset (GstTypeFind * tf, guint64 offset,
112 GstTypeFindProbability * prob)
116 /* randomly decided values */
117 guint min_size = 16; /* minimum size */
118 guint size = 32 * 1024; /* starting size */
119 guint probability = 95; /* starting probability */
120 guint step = 10; /* how much we reduce probability in each
123 while (probability > step && size > min_size) {
124 data = gst_type_find_peek (tf, offset, size);
127 gchar *start = (gchar *) data;
129 if (g_utf8_validate (start, size, (const gchar **) &end) || (end - start + 4 > size)) { /* allow last char to be cut off */
144 utf8_type_find (GstTypeFind * tf, gpointer unused)
146 GstTypeFindProbability start_prob, mid_prob;
149 /* leave xml to the xml typefinders */
150 if (xml_check_first_element (tf, "", 0, TRUE))
153 /* leave sdp to the sdp typefinders */
154 if (sdp_check_header (tf))
157 /* check beginning of stream */
158 if (!utf8_type_find_have_valid_utf8_at_offset (tf, 0, &start_prob))
161 GST_LOG ("start is plain text with probability of %u", start_prob);
163 /* POSSIBLE is the highest probability we ever return if we can't
164 * probe into the middle of the file and don't know its length */
166 length = gst_type_find_get_length (tf);
167 if (length == 0 || length == (guint64) - 1) {
168 gst_type_find_suggest (tf, MIN (start_prob, GST_TYPE_FIND_POSSIBLE),
173 if (length < 64 * 1024) {
174 gst_type_find_suggest (tf, start_prob, UTF8_CAPS);
178 /* check middle of stream */
179 if (!utf8_type_find_have_valid_utf8_at_offset (tf, length / 2, &mid_prob))
182 GST_LOG ("middle is plain text with probability of %u", mid_prob);
183 gst_type_find_suggest (tf, (start_prob + mid_prob) / 2, UTF8_CAPS);
186 /*** text/uri-list ***/
188 static GstStaticCaps uri_caps = GST_STATIC_CAPS ("text/uri-list");
190 #define URI_CAPS (gst_static_caps_get(&uri_caps))
191 #define BUFFER_SIZE 16 /* If the string is < 16 bytes we're screwed */
192 #define INC_BUFFER { \
194 if (pos == BUFFER_SIZE) { \
196 offset += BUFFER_SIZE; \
197 data = gst_type_find_peek (tf, offset, BUFFER_SIZE); \
198 if (data == NULL) return; \
204 uri_type_find (GstTypeFind * tf, gpointer unused)
206 guint8 *data = gst_type_find_peek (tf, 0, BUFFER_SIZE);
211 /* Search for # comment lines */
212 while (*data == '#') {
213 /* Goto end of line */
214 while (*data != '\n') {
221 if (!g_ascii_isalpha (*data)) {
222 /* Had a non alpha char - can't be uri-list */
228 while (g_ascii_isalnum (*data)) {
233 /* First non alpha char is not a : */
237 /* Get the next 2 bytes as well */
238 data = gst_type_find_peek (tf, offset + pos, 3);
242 if (data[1] != '/' && data[2] != '/') {
246 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, URI_CAPS);
251 /*** application/xml **********************************************************/
253 #define XML_BUFFER_SIZE 16
254 #define XML_INC_BUFFER { \
256 if (pos == XML_BUFFER_SIZE) { \
258 offset += XML_BUFFER_SIZE; \
259 data = gst_type_find_peek (tf, offset, XML_BUFFER_SIZE); \
260 if (data == NULL) return FALSE; \
267 xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen,
275 data = gst_type_find_peek (tf, 0, XML_BUFFER_SIZE);
279 /* look for the XMLDec
280 * see XML spec 2.8, Prolog and Document Type Declaration
281 * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */
282 got_xmldec = (memcmp (data, "<?xml", 5) == 0);
284 if (strict && !got_xmldec)
287 /* skip XMLDec in any case if we've got one */
293 /* look for the first element, it has to be the requested element. Bail
294 * out if it is not within the first 4kB. */
295 while (data && (offset + pos) < 4096) {
296 while (*data != '<' && (offset + pos) < 4096) {
301 if (!g_ascii_isalpha (*data)) {
302 /* if not alphabetic, it's a PI or an element / attribute declaration
303 * like <?xxx or <!xxx */
308 /* the first normal element, check if it's the one asked for */
309 data = gst_type_find_peek (tf, offset + pos, elen + 1);
310 return (data && element && strncmp ((char *) data, element, elen) == 0);
316 static GstStaticCaps generic_xml_caps = GST_STATIC_CAPS ("application/xml");
318 #define GENERIC_XML_CAPS (gst_static_caps_get(&generic_xml_caps))
320 xml_type_find (GstTypeFind * tf, gpointer unused)
322 if (xml_check_first_element (tf, "", 0, TRUE)) {
323 gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, GENERIC_XML_CAPS);
327 /*** application/sdp *********************************************************/
329 static GstStaticCaps sdp_caps = GST_STATIC_CAPS ("application/sdp");
331 #define SDP_CAPS (gst_static_caps_get(&sdp_caps))
333 sdp_check_header (GstTypeFind * tf)
337 data = gst_type_find_peek (tf, 0, 5);
341 /* sdp must start with v=0[\r]\n */
342 if (memcmp (data, "v=0", 3))
345 if (data[3] == '\r' && data[4] != '\n')
354 sdp_type_find (GstTypeFind * tf, gpointer unused)
356 if (sdp_check_header (tf))
357 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SDP_CAPS);
360 /*** application/smil *********************************************************/
362 static GstStaticCaps smil_caps = GST_STATIC_CAPS ("application/smil");
364 #define SMIL_CAPS (gst_static_caps_get(&smil_caps))
366 smil_type_find (GstTypeFind * tf, gpointer unused)
368 if (xml_check_first_element (tf, "smil", 4, FALSE)) {
369 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SMIL_CAPS);
375 static GstStaticCaps html_caps = GST_STATIC_CAPS ("text/html");
377 #define HTML_CAPS gst_static_caps_get (&html_caps)
380 html_type_find (GstTypeFind * tf, gpointer unused)
384 data = (gchar *) gst_type_find_peek (tf, 0, 16);
388 if (!g_ascii_strncasecmp (data, "<!DOCTYPE HTML", 14)) {
389 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
390 } else if (xml_check_first_element (tf, "html", 4, FALSE)) {
391 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
392 } else if ((d = memchr (data, '<', 16))) {
393 data = (gchar *) gst_type_find_peek (tf, d - data, 6);
394 if (data && g_ascii_strncasecmp (data, "<html>", 6) == 0) {
395 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS);
402 static GstStaticCaps mid_caps = GST_STATIC_CAPS ("audio/midi");
404 #define MID_CAPS gst_static_caps_get(&mid_caps)
406 mid_type_find (GstTypeFind * tf, gpointer unused)
408 guint8 *data = gst_type_find_peek (tf, 0, 4);
410 /* http://jedi.ks.uiuc.edu/~johns/links/music/midifile.html */
411 if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h'
413 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS);
416 /*** video/x-fli ***/
418 static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli");
420 #define FLX_CAPS gst_static_caps_get(&flx_caps)
422 flx_type_find (GstTypeFind * tf, gpointer unused)
424 guint8 *data = gst_type_find_peek (tf, 0, 134);
427 /* check magic and the frame type of the first frame */
428 if ((data[4] == 0x11 || data[4] == 0x12 ||
429 data[4] == 0x30 || data[4] == 0x44) &&
431 ((data[132] == 0x00 || data[132] == 0xfa) && data[133] == 0xf1)) {
432 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLX_CAPS);
436 data = gst_type_find_peek (tf, 0, 6);
438 /* check magic only */
439 if ((data[4] == 0x11 || data[4] == 0x12 ||
440 data[4] == 0x30 || data[4] == 0x44) && data[5] == 0xaf) {
441 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, FLX_CAPS);
447 /*** application/x-id3 ***/
449 static GstStaticCaps id3_caps = GST_STATIC_CAPS ("application/x-id3");
451 #define ID3_CAPS gst_static_caps_get(&id3_caps)
453 id3v2_type_find (GstTypeFind * tf, gpointer unused)
455 guint8 *data = gst_type_find_peek (tf, 0, 10);
457 if (data && memcmp (data, "ID3", 3) == 0 &&
458 data[3] != 0xFF && data[4] != 0xFF &&
459 (data[6] & 0x80) == 0 && (data[7] & 0x80) == 0 &&
460 (data[8] & 0x80) == 0 && (data[9] & 0x80) == 0) {
461 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS);
466 id3v1_type_find (GstTypeFind * tf, gpointer unused)
468 guint8 *data = gst_type_find_peek (tf, -128, 3);
470 if (data && memcmp (data, "TAG", 3) == 0) {
471 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS);
475 /*** application/x-ape ***/
477 static GstStaticCaps apetag_caps = GST_STATIC_CAPS ("application/x-apetag");
479 #define APETAG_CAPS gst_static_caps_get(&apetag_caps)
481 apetag_type_find (GstTypeFind * tf, gpointer unused)
485 /* APEv1/2 at start of file */
486 data = gst_type_find_peek (tf, 0, 8);
487 if (data && !memcmp (data, "APETAGEX", 8)) {
488 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS);
492 /* APEv1/2 at end of file */
493 data = gst_type_find_peek (tf, -32, 8);
494 if (data && !memcmp (data, "APETAGEX", 8)) {
495 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS);
500 /*** audio/x-ttafile ***/
502 static GstStaticCaps tta_caps = GST_STATIC_CAPS ("audio/x-ttafile");
504 #define TTA_CAPS gst_static_caps_get(&tta_caps)
506 tta_type_find (GstTypeFind * tf, gpointer unused)
508 guint8 *data = gst_type_find_peek (tf, 0, 3);
511 if (memcmp (data, "TTA", 3) == 0) {
512 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TTA_CAPS);
518 /*** audio/x-flac ***/
519 static GstStaticCaps flac_caps = GST_STATIC_CAPS ("audio/x-flac");
521 #define FLAC_CAPS (gst_static_caps_get(&flac_caps))
524 flac_type_find (GstTypeFind * tf, gpointer unused)
528 data = gst_type_find_peek (tf, 0, 5);
529 if (G_LIKELY (data)) {
531 if (memcmp (data, "fLaC", 4) == 0) {
532 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
534 /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */
535 else if (memcmp (data, "\177FLAC\001", 6) == 0) {
536 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS);
541 /*** audio/mpeg version 2, 4 ***/
543 static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, "
544 "mpegversion = (int) { 2, 4 }, framed = (bool) false");
545 #define AAC_CAPS (gst_static_caps_get(&aac_caps))
546 #define AAC_AMOUNT (4096)
548 aac_type_find (GstTypeFind * tf, gpointer unused)
550 DataScanCtx c = { 0, NULL, 0 };
552 while (c.offset < AAC_AMOUNT) {
555 /* detect adts header or adif header.
556 * The ADIF header is 4 bytes, that should be OK. The ADTS header, on
557 * the other hand, is 14 bits only, so we require one valid frame with
558 * again a valid syncpoint on the next one (28 bits) for certainty. We
559 * require 4 kB, which is quite a lot, since frames are generally 200-400
562 if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6)))
565 snc = GST_READ_UINT16_BE (c.data);
566 if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) {
567 /* ADTS header - find frame length */
568 GST_DEBUG ("Found one ADTS syncpoint at offset 0x%" G_GINT64_MODIFIER
569 "x, tracing next...", c.offset);
570 len = ((c.data[3] & 0x03) << 11) |
571 (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
573 if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
574 GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
578 snc = GST_READ_UINT16_BE (c.data + len);
579 if ((snc & 0xfff6) == 0xfff0) {
582 mpegversion = (c.data[1] & 0x08) ? 2 : 4;
583 GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%"
584 G_GINT64_MODIFIER "x, framelen %u", mpegversion, c.offset, len);
585 gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
586 "framed", G_TYPE_BOOLEAN, FALSE,
587 "mpegversion", G_TYPE_INT, mpegversion, NULL);
591 GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
592 } else if (!memcmp (c.data, "ADIF", 4)) {
594 gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
595 "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4, NULL);
601 data_scan_ctx_advance (tf, &c, 1);
605 /*** audio/mpeg version 1 ***/
608 * The chance that random data is identified as a valid mp3 header is 63 / 2^18
609 * (0.024%) per try. This makes the function for calculating false positives
610 * 1 - (1 - ((63 / 2 ^18) ^ GST_MP3_TYPEFIND_MIN_HEADERS)) ^ buffersize)
611 * This has the following probabilities of false positives:
612 * datasize MIN_HEADERS
614 * 4096 62.6% 0.02% 0% 0%
615 * 16384 98% 0.09% 0% 0%
616 * 1 MiB 100% 5.88% 0% 0%
617 * 1 GiB 100% 100% 1.44% 0%
618 * 1 TiB 100% 100% 100% 0.35%
619 * This means that the current choice (3 headers by most of the time 4096 byte
620 * buffers is pretty safe for now.
622 * The max. size of each frame is 1440 bytes, which means that for N frames to
623 * be detected, we need 1440 * GST_MP3_TYPEFIND_MIN_HEADERS + 3 bytes of data.
624 * Assuming we step into the stream right after the frame header, this
625 * means we need 1440 * (GST_MP3_TYPEFIND_MIN_HEADERS + 1) - 1 + 3 bytes
626 * of data (5762) to always detect any mp3.
629 static const guint mp3types_bitrates[2][3][16] =
630 { {{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
631 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
632 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}},
633 {{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
634 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
635 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}},
638 static const guint mp3types_freqs[3][3] = { {11025, 12000, 8000},
639 {22050, 24000, 16000},
640 {44100, 48000, 32000}
644 mp3_type_frame_length_from_header (guint32 header, guint * put_layer,
645 guint * put_channels, guint * put_bitrate, guint * put_samplerate,
646 gboolean * may_be_free_format, gint possible_free_framelen)
648 guint bitrate, layer, length, mode, samplerate, version, channels;
650 if ((header & 0xffe00000) != 0xffe00000)
653 /* we don't need extension, copyright, original or
654 * emphasis for the frame length */
662 length = header & 0x1;
665 /* sampling frequency */
666 samplerate = header & 0x3;
672 bitrate = header & 0xF;
673 if (bitrate == 0 && possible_free_framelen == -1) {
674 GST_LOG ("Possibly a free format mp3 - signalling");
675 *may_be_free_format = TRUE;
677 if (bitrate == 15 || (bitrate == 0 && possible_free_framelen == -1))
680 /* ignore error correction, too */
684 layer = 4 - (header & 0x3);
689 /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */
690 version = header & 0x3;
695 channels = (mode == 3) ? 1 : 2;
696 samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate];
700 length += possible_free_framelen;
701 bitrate = length * samplerate / 48000;
703 length += possible_free_framelen;
704 bitrate = length * samplerate /
705 ((layer == 3 && version != 3) ? 72000 : 144000);
709 bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate];
711 length = ((12000 * bitrate / samplerate) + length) * 4;
713 length += ((layer == 3
714 && version != 3) ? 72000 : 144000) * bitrate / samplerate;
718 GST_LOG ("mp3typefind: calculated mp3 frame length of %u bytes", length);
720 ("mp3typefind: samplerate = %u - bitrate = %u - layer = %u - version = %u"
721 " - channels = %u", samplerate, bitrate, layer, version, channels);
726 *put_channels = channels;
728 *put_bitrate = bitrate;
730 *put_samplerate = samplerate;
736 static GstStaticCaps mp3_caps = GST_STATIC_CAPS ("audio/mpeg, "
737 "mpegversion = (int) 1, layer = (int) [ 1, 3 ]");
738 #define MP3_CAPS (gst_static_caps_get(&mp3_caps))
740 * random values for typefinding
741 * if no more data is available, we will return a probability of
742 * (found_headers/TRY_HEADERS) * (MAXIMUM * (TRY_SYNC - bytes_skipped)
744 * if found_headers >= MIN_HEADERS
746 #define GST_MP3_TYPEFIND_MIN_HEADERS (2)
747 #define GST_MP3_TYPEFIND_TRY_HEADERS (5)
748 #define GST_MP3_TYPEFIND_TRY_SYNC (GST_TYPE_FIND_MAXIMUM * 100) /* 10kB */
749 #define GST_MP3_TYPEFIND_SYNC_SIZE (2048)
750 #define GST_MP3_WRONG_HEADER (10)
753 mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off,
754 guint * found_layer, GstTypeFindProbability * found_prob)
757 guint8 *data_end = NULL;
760 gint last_free_offset = -1;
761 gint last_free_framelen = -1;
762 gboolean headerstart = TRUE;
769 while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) {
771 size = GST_MP3_TYPEFIND_SYNC_SIZE * 2;
774 data = gst_type_find_peek (tf, skipped + start_off, size);
775 } while (size > 10 && !data);
778 data_end = data + size;
781 guint8 *head_data = NULL;
782 guint layer = 0, bitrate, samplerate, channels;
783 guint found = 0; /* number of valid headers found */
784 guint64 offset = skipped;
786 while (found < GST_MP3_TYPEFIND_TRY_HEADERS) {
789 guint prev_layer = 0, prev_bitrate = 0;
790 guint prev_channels = 0, prev_samplerate = 0;
791 gboolean free = FALSE;
793 if ((gint64) (offset - skipped + 4) >= 0 &&
794 data + offset - skipped + 4 < data_end) {
795 head_data = data + offset - skipped;
797 head_data = gst_type_find_peek (tf, offset + start_off, 4);
801 head = GST_READ_UINT32_BE (head_data);
802 if (!(length = mp3_type_frame_length_from_header (head, &layer,
803 &channels, &bitrate, &samplerate, &free,
804 last_free_framelen))) {
806 if (last_free_offset == -1)
807 last_free_offset = offset;
809 last_free_framelen = offset - last_free_offset;
810 offset = last_free_offset;
814 last_free_framelen = -1;
817 /* Mark the fact that we didn't find a valid header at the beginning */
821 GST_LOG ("%d. header at offset %" G_GUINT64_FORMAT
822 " (0x%" G_GINT64_MODIFIER "x) was not an mp3 header "
823 "(possibly-free: %s)", found + 1, start_off + offset,
824 start_off + offset, free ? "yes" : "no");
827 if ((prev_layer && prev_layer != layer) ||
828 /* (prev_bitrate && prev_bitrate != bitrate) || <-- VBR */
829 (prev_samplerate && prev_samplerate != samplerate) ||
830 (prev_channels && prev_channels != channels)) {
831 /* this means an invalid property, or a change, which might mean
832 * that this is not a mp3 but just a random bytestream. It could
833 * be a freaking funky encoded mp3 though. We'll just not count
836 prev_bitrate = bitrate;
837 prev_channels = channels;
838 prev_samplerate = samplerate;
841 GST_LOG ("found %d. header at offset %" G_GUINT64_FORMAT " (0x%"
842 G_GINT64_MODIFIER "X)", found, start_off + offset,
847 g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
848 if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
849 (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
850 /* we can make a valid guess */
851 guint probability = found * GST_TYPE_FIND_MAXIMUM *
852 (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
853 GST_MP3_TYPEFIND_TRY_HEADERS / GST_MP3_TYPEFIND_TRY_SYNC;
856 && probability > (GST_TYPE_FIND_MINIMUM + GST_MP3_WRONG_HEADER))
857 probability -= GST_MP3_WRONG_HEADER;
858 if (probability < GST_TYPE_FIND_MINIMUM)
859 probability = GST_TYPE_FIND_MINIMUM;
864 ("audio/mpeg calculated %u = %u * %u / %u * (%u - %"
865 G_GUINT64_FORMAT ") / %u", probability, GST_TYPE_FIND_MAXIMUM,
866 found, GST_MP3_TYPEFIND_TRY_HEADERS, GST_MP3_TYPEFIND_TRY_SYNC,
867 (guint64) skipped, GST_MP3_TYPEFIND_TRY_SYNC);
868 /* make sure we're not id3 tagged */
869 head_data = gst_type_find_peek (tf, -128, 3);
870 if (head_data && (memcmp (head_data, "TAG", 3) == 0)) {
873 g_assert (probability <= GST_TYPE_FIND_MAXIMUM);
875 *found_prob = probability;
877 *found_layer = layer;
888 mp3_type_find (GstTypeFind * tf, gpointer unused)
890 GstTypeFindProbability prob, mid_prob;
892 guint layer, mid_layer;
895 mp3_type_find_at_offset (tf, 0, &layer, &prob);
896 length = gst_type_find_get_length (tf);
898 if (length == 0 || length == (guint64) - 1) {
904 /* if we're pretty certain already, skip the additional check */
905 if (prob >= GST_TYPE_FIND_LIKELY)
908 mp3_type_find_at_offset (tf, length / 2, &mid_layer, &mid_prob);
912 GST_LOG ("detected audio/mpeg only in the middle (p=%u)", mid_prob);
918 if (layer != mid_layer) {
919 GST_WARNING ("audio/mpeg layer discrepancy: %u vs. %u", layer, mid_layer);
920 return; /* FIXME: or should we just go with the one in the middle? */
923 /* detected mpeg audio both in middle of the file and at the start */
924 prob = (prob + mid_prob) / 2;
928 /* let's see if there's a valid header right at the start */
929 data = gst_type_find_peek (tf, 0, 4); /* use min. frame size? */
930 if (data && mp3_type_frame_length_from_header (GST_READ_UINT32_BE (data),
931 &layer, NULL, NULL, NULL, NULL, 0) != 0) {
933 prob = GST_TYPE_FIND_POSSIBLE - 10;
935 prob = MAX (GST_TYPE_FIND_POSSIBLE - 10, prob + 10);
945 g_return_if_fail (layer >= 1 && layer <= 3);
947 gst_type_find_suggest_simple (tf, prob, "audio/mpeg",
948 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL);
952 /*** audio/x-musepack ***/
954 static GstStaticCaps musepack_caps =
955 GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }");
957 #define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps))
959 musepack_type_find (GstTypeFind * tf, gpointer unused)
961 guint8 *data = gst_type_find_peek (tf, 0, 4);
962 GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM;
963 gint streamversion = -1;
965 if (data && memcmp (data, "MP+", 3) == 0) {
967 if ((data[3] & 0x7f) == 7) {
968 prop = GST_TYPE_FIND_MAXIMUM;
970 prop = GST_TYPE_FIND_LIKELY + 10;
972 } else if (data && memcmp (data, "MPCK", 4) == 0) {
974 prop = GST_TYPE_FIND_MAXIMUM;
977 if (streamversion != -1) {
978 gst_type_find_suggest_simple (tf, prop, "audio/x-musepack",
979 "streamversion", G_TYPE_INT, streamversion, NULL);
983 /*** audio/x-ac3 ***/
984 /* This should be audio/ac3, but isn't for backwards compatibility */
985 static GstStaticCaps ac3_caps = GST_STATIC_CAPS ("audio/x-ac3");
987 #define AC3_CAPS (gst_static_caps_get(&ac3_caps))
991 unsigned short bit_rate;
992 unsigned short frm_size[3];
995 static const struct ac3_frmsize ac3_frmsizecod_tbl[] = {
1000 {48, {96, 104, 144}},
1001 {48, {96, 105, 144}},
1002 {56, {112, 121, 168}},
1003 {56, {112, 122, 168}},
1004 {64, {128, 139, 192}},
1005 {64, {128, 140, 192}},
1006 {80, {160, 174, 240}},
1007 {80, {160, 175, 240}},
1008 {96, {192, 208, 288}},
1009 {96, {192, 209, 288}},
1010 {112, {224, 243, 336}},
1011 {112, {224, 244, 336}},
1012 {128, {256, 278, 384}},
1013 {128, {256, 279, 384}},
1014 {160, {320, 348, 480}},
1015 {160, {320, 349, 480}},
1016 {192, {384, 417, 576}},
1017 {192, {384, 418, 576}},
1018 {224, {448, 487, 672}},
1019 {224, {448, 488, 672}},
1020 {256, {512, 557, 768}},
1021 {256, {512, 558, 768}},
1022 {320, {640, 696, 960}},
1023 {320, {640, 697, 960}},
1024 {384, {768, 835, 1152}},
1025 {384, {768, 836, 1152}},
1026 {448, {896, 975, 1344}},
1027 {448, {896, 976, 1344}},
1028 {512, {1024, 1114, 1536}},
1029 {512, {1024, 1115, 1536}},
1030 {576, {1152, 1253, 1728}},
1031 {576, {1152, 1254, 1728}},
1032 {640, {1280, 1393, 1920}},
1033 {640, {1280, 1394, 1920}}
1038 ac3_type_find (GstTypeFind * tf, gpointer unused)
1040 guint8 *data = gst_type_find_peek (tf, 0, 5);
1043 /* Search for an ac3 frame; not neccesarily right at the start, but give it
1044 * a lower probability if not found right at the start. Check that the
1045 * frame is followed by a second frame at the expected offset.
1046 * We could also check the two ac3 CRCs, but we don't do that right now */
1047 while (data && offset < 1024) {
1048 if (data[0] == 0x0b && data[1] == 0x77) {
1049 guint fscod = (data[4] >> 6) & 0x03;
1050 guint frmsizecod = data[4] & 0x3f;
1052 if (fscod < 3 && frmsizecod < 38) {
1053 guint frame_size = ac3_frmsizecod_tbl[frmsizecod].frm_size[fscod];
1055 data = gst_type_find_peek (tf, offset + frame_size * 2, 5);
1058 if (data[0] == 0x0b && data[1] == 0x77) {
1059 guint fscod2 = (data[4] >> 6) & 0x03;
1060 guint frmsizecod2 = data[4] & 0x3f;
1062 if (fscod == fscod2 && frmsizecod == frmsizecod2) {
1066 prob = GST_TYPE_FIND_MAXIMUM;
1068 prob = GST_TYPE_FIND_NEARLY_CERTAIN;
1069 gst_type_find_suggest (tf, prob, AC3_CAPS);
1076 data = gst_type_find_peek (tf, offset, 5);
1082 static GstStaticCaps wavpack_caps =
1083 GST_STATIC_CAPS ("audio/x-wavpack, framed = (boolean) false");
1085 #define WAVPACK_CAPS (gst_static_caps_get(&wavpack_caps))
1087 static GstStaticCaps wavpack_correction_caps =
1088 GST_STATIC_CAPS ("audio/x-wavpack-correction, framed = (boolean) false");
1090 #define WAVPACK_CORRECTION_CAPS (gst_static_caps_get(&wavpack_correction_caps))
1093 wavpack_type_find (GstTypeFind * tf, gpointer unused)
1099 data = gst_type_find_peek (tf, 0, 32);
1103 if (data[0] != 'w' || data[1] != 'v' || data[2] != 'p' || data[3] != 'k')
1106 /* Note: wavpack blocks can be fairly large (easily 60-110k), possibly
1107 * larger than the max. limits imposed by certain typefinding elements
1108 * like id3demux or apedemux, so typefinding is most likely only going to
1109 * work in pull-mode */
1110 blocksize = GST_READ_UINT32_LE (data + 4);
1111 GST_LOG ("wavpack header, blocksize=0x%04x", blocksize);
1113 while (offset < 32 + blocksize) {
1116 /* get chunk header */
1117 GST_LOG ("peeking at chunk at offset 0x%04x", (guint) offset);
1118 data = gst_type_find_peek (tf, offset, 4);
1121 sublen = ((guint32) data[1]) << 1;
1122 if (data[0] & 0x80) {
1123 sublen |= (((guint32) data[2]) << 9) | (((guint32) data[3]) << 17);
1124 sublen += 1 + 3; /* id + length */
1126 sublen += 1 + 1; /* id + length */
1128 if (sublen > blocksize - offset + 32) {
1129 GST_LOG ("chunk length too big (%u > %" G_GUINT64_FORMAT ")", sublen,
1130 blocksize - offset);
1133 if ((data[0] & 0x20) == 0) {
1134 switch (data[0] & 0x0f) {
1135 case 0xa: /* ID_WV_BITSTREAM */
1136 case 0xc: /* ID_WVX_BITSTREAM */
1137 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, WAVPACK_CAPS);
1139 case 0xb: /* ID_WVC_BITSTREAM */
1140 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY,
1141 WAVPACK_CORRECTION_CAPS);
1151 /*** multipart/x-mixed-replace mimestream ***/
1153 static GstStaticCaps multipart_caps =
1154 GST_STATIC_CAPS ("multipart/x-mixed-replace");
1155 #define MULTIPART_CAPS gst_static_caps_get(&multipart_caps)
1157 /* multipart/x-mixed replace is:
1158 * <maybe some whitespace>--<some ascii chars>[\r]\n
1159 * <more ascii chars>[\r]\nContent-type:<more ascii>[\r]\n */
1161 multipart_type_find (GstTypeFind * tf, gpointer unused)
1166 #define MULTIPART_MAX_BOUNDARY_OFFSET 16
1167 data = gst_type_find_peek (tf, 0, MULTIPART_MAX_BOUNDARY_OFFSET);
1172 x - data < MULTIPART_MAX_BOUNDARY_OFFSET - 2 && g_ascii_isspace (*x);
1174 if (x[0] != '-' || x[1] != '-')
1177 /* Could be okay, peek what should be enough for a complete header */
1178 #define MULTIPART_MAX_HEADER_SIZE 256
1179 data = gst_type_find_peek (tf, 0, MULTIPART_MAX_HEADER_SIZE);
1183 for (x = data; x - data < MULTIPART_MAX_HEADER_SIZE - 14; x++) {
1184 if (!isascii (*x)) {
1188 !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) {
1189 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MULTIPART_CAPS);
1195 /*** video/mpeg systemstream ***/
1196 static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
1197 "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]");
1199 #define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps)
1200 #define IS_MPEG_HEADER(data) (G_UNLIKELY((((guint8 *)(data))[0] == 0x00) && \
1201 (((guint8 *)(data))[1] == 0x00) && \
1202 (((guint8 *)(data))[2] == 0x01)))
1204 #define IS_MPEG_PACK_CODE(b) ((b) == 0xBA)
1205 #define IS_MPEG_SYS_CODE(b) ((b) == 0xBB)
1206 #define IS_MPEG_PACK_HEADER(data) (IS_MPEG_HEADER (data) && \
1207 IS_MPEG_PACK_CODE (((guint8 *)(data))[3]))
1209 #define IS_MPEG_PES_CODE(b) (((b) & 0xF0) == 0xE0 || ((b) & 0xF0) == 0xC0 || \
1211 #define IS_MPEG_PES_HEADER(data) (IS_MPEG_HEADER (data) && \
1212 IS_MPEG_PES_CODE (((guint8 *)(data))[3]))
1214 #define MPEG2_MAX_PROBE_LENGTH (128 * 1024) /* 128kB should be 64 packs of the
1215 * most common 2kB pack size. */
1217 #define MPEG2_MIN_SYS_HEADERS 2
1218 #define MPEG2_MAX_SYS_HEADERS 5
1221 mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len,
1224 /* Check the pack header @ offset for validity, assuming that the 4 byte header
1225 * itself has already been checked. */
1231 /* Check marker bits */
1232 if ((data[4] & 0xC4) == 0x44) {
1237 if ((data[6] & 0x04) != 0x04 ||
1238 (data[8] & 0x04) != 0x04 ||
1239 (data[9] & 0x01) != 0x01 || (data[12] & 0x03) != 0x03)
1242 stuff_len = data[13] & 0x07;
1244 /* Check the following header bytes, if we can */
1245 if ((14 + stuff_len + 4) <= len) {
1246 if (!IS_MPEG_HEADER (data + 14 + stuff_len))
1250 *pack_size = 14 + stuff_len;
1252 } else if ((data[4] & 0xF1) == 0x21) {
1254 if ((data[6] & 0x01) != 0x01 ||
1255 (data[8] & 0x01) != 0x01 ||
1256 (data[9] & 0x80) != 0x80 || (data[11] & 0x01) != 0x01)
1259 /* Check the following header bytes, if we can */
1260 if ((12 + 4) <= len) {
1261 if (!IS_MPEG_HEADER (data + 12))
1273 mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len,
1276 guint pes_packet_len;
1278 /* Check the PES header at the given position, assuming the header code itself
1279 * was already checked */
1283 /* For MPEG Program streams, unbounded PES is not allowed, so we must have a
1284 * valid length present */
1285 pes_packet_len = GST_READ_UINT16_BE (data + 4);
1286 if (pes_packet_len == 0)
1289 /* Check the following header, if we can */
1290 if (6 + pes_packet_len + 4 <= len) {
1291 if (!IS_MPEG_HEADER (data + 6 + pes_packet_len))
1296 *pack_size = 6 + pes_packet_len;
1301 mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len,
1306 /* Check the System header at the given position, assuming the header code itself
1307 * was already checked */
1310 sys_hdr_len = GST_READ_UINT16_BE (data + 4);
1311 if (sys_hdr_len < 6)
1314 /* Check the following header, if we can */
1315 if (6 + sys_hdr_len + 4 <= len) {
1316 if (!IS_MPEG_HEADER (data + 6 + sys_hdr_len))
1321 *pack_size = 6 + sys_hdr_len;
1326 /* calculation of possibility to identify random data as mpeg systemstream:
1327 * bits that must match in header detection: 32 (or more)
1328 * chance that random data is identifed: 1/2^32
1329 * chance that MPEG2_MIN_PACK_HEADERS headers are identified:
1330 * 1/2^(32*MPEG2_MIN_PACK_HEADERS)
1331 * chance that this happens in MPEG2_MAX_PROBE_LENGTH bytes:
1332 * 1-(1+1/2^(32*MPEG2_MIN_PACK_HEADERS)^MPEG2_MAX_PROBE_LENGTH)
1333 * for current values:
1334 * 1-(1+1/2^(32*4)^101024)
1336 * Since we also check marker bits and pes packet lengths, this probability is a
1337 * very coarse upper bound.
1340 mpeg_sys_type_find (GstTypeFind * tf, gpointer unused)
1342 guint8 *data, *data0, *first_sync, *end;
1343 gint mpegversion = 0;
1344 guint pack_headers = 0;
1345 guint pes_headers = 0;
1347 guint since_last_sync = 0;
1348 guint32 sync_word = 0xffffffff;
1353 len = MPEG2_MAX_PROBE_LENGTH;
1356 data = gst_type_find_peek (tf, 0, 5 + len);
1357 } while (data == NULL && len >= 32);
1369 while (data < end) {
1371 if (sync_word == 0x00000100) {
1372 /* Found potential sync word */
1373 if (first_sync == NULL)
1374 first_sync = data - 3;
1376 if (since_last_sync > 4) {
1377 /* If more than 4 bytes since the last sync word, reset our counters,
1378 * as we're only interested in counting contiguous packets */
1379 pes_headers = pack_headers = 0;
1383 if (IS_MPEG_PACK_CODE (data[0])) {
1384 if ((data[1] & 0xC0) == 0x40) {
1387 } else if ((data[1] & 0xF0) == 0x20) {
1390 if (mpegversion != 0 &&
1391 mpeg_sys_is_valid_pack (tf, data - 3, end - data + 3, &pack_size)) {
1394 } else if (IS_MPEG_PES_CODE (data[0])) {
1396 if (mpeg_sys_is_valid_pes (tf, data - 3, end - data + 3, &pack_size)) {
1398 if (mpegversion == 0)
1401 } else if (IS_MPEG_SYS_CODE (data[0])) {
1402 if (mpeg_sys_is_valid_sys (tf, data - 3, end - data + 3, &pack_size)) {
1407 /* If we found a packet with a known size, skip the bytes in it and loop
1408 * around to check the next packet. */
1409 if (pack_size != 0) {
1410 data += pack_size - 3;
1411 sync_word = 0xffffffff;
1412 since_last_sync = 0;
1417 sync_word |= data[0];
1421 /* If we have found MAX headers, and *some* were pes headers (pack headers
1422 * are optional in an mpeg system stream) then return our high-probability
1424 if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MAX_SYS_HEADERS)
1428 /* If we at least saw MIN headers, and *some* were pes headers (pack headers
1429 * are optional in an mpeg system stream) then return a lower-probability
1431 if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS)
1439 prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers));
1440 prob = MIN (prob, GST_TYPE_FIND_MAXIMUM);
1442 /* lower probability if the first packet wasn't right at the start */
1443 if (data0 != first_sync && prob >= 10)
1446 GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n",
1447 mpegversion, pack_headers, pes_headers, prob);
1449 gst_type_find_suggest_simple (tf, prob, "video/mpeg",
1450 "systemstream", G_TYPE_BOOLEAN, TRUE,
1451 "mpegversion", G_TYPE_INT, mpegversion, NULL);
1455 /** video/mpegts Transport Stream **/
1456 static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, "
1457 "systemstream = (boolean) true, packetsize = (int) [ 188, 208 ]");
1458 #define MPEGTS_CAPS gst_static_caps_get(&mpegts_caps)
1460 #define GST_MPEGTS_TYPEFIND_MIN_HEADERS 4
1461 #define GST_MPEGTS_TYPEFIND_MAX_HEADERS 10
1462 #define GST_MPEGTS_MAX_PACKET_SIZE 208
1463 #define GST_MPEGTS_TYPEFIND_SYNC_SIZE \
1464 (GST_MPEGTS_TYPEFIND_MIN_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
1465 #define GST_MPEGTS_TYPEFIND_MAX_SYNC \
1466 (GST_MPEGTS_TYPEFIND_MAX_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE)
1468 #define MPEGTS_HDR_SIZE 4
1469 /* Check for sync byte, error_indicator == 0 and packet has payload */
1470 #define IS_MPEGTS_HEADER(data) (((data)[0] == 0x47) && \
1471 (((data)[1] & 0x80) == 0x00) && \
1472 (((data)[3] & 0x10) == 0x10))
1474 /* Helper function to search ahead at intervals of packet_size for mpegts
1477 mpeg_ts_probe_headers (GstTypeFind * tf, guint64 offset, gint packet_size)
1479 /* We always enter this function having found at least one header already */
1481 guint8 *data = NULL;
1483 while (found < GST_MPEGTS_TYPEFIND_MAX_HEADERS) {
1484 offset += packet_size;
1486 data = gst_type_find_peek (tf, offset, MPEGTS_HDR_SIZE);
1487 if (data == NULL || !IS_MPEGTS_HEADER (data))
1496 /* Try and detect at least 4 packets in at most 10 packets worth of
1497 * data. Need to try several possible packet sizes */
1499 mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
1501 /* TS packet sizes to test: normal, DVHS packet size and
1502 * FEC with 16 or 20 byte codes packet size. */
1503 const gint pack_sizes[] = { 188, 192, 204, 208 };
1504 const gint n_pack_sizes = sizeof (pack_sizes) / sizeof (gint);
1506 guint8 *data = NULL;
1508 guint64 skipped = 0;
1510 while (skipped < GST_MPEGTS_TYPEFIND_MAX_SYNC) {
1511 if (size < MPEGTS_HDR_SIZE) {
1512 data = gst_type_find_peek (tf, skipped, GST_MPEGTS_TYPEFIND_SYNC_SIZE);
1515 size = GST_MPEGTS_TYPEFIND_SYNC_SIZE;
1518 /* Have at least MPEGTS_HDR_SIZE bytes at this point */
1519 if (IS_MPEGTS_HEADER (data)) {
1522 for (p = 0; p < n_pack_sizes; p++) {
1525 /* Probe ahead at size pack_sizes[p] */
1526 found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]);
1527 if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
1530 /* found at least 4 headers. 10 headers = MAXIMUM probability.
1531 * Arbitrarily, I assigned 10% probability for each header we
1532 * found, 40% -> 100% */
1533 probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
1535 gst_type_find_suggest_simple (tf, probability, "video/mpegts",
1536 "systemstream", G_TYPE_BOOLEAN, TRUE,
1537 "packetsize", G_TYPE_INT, pack_sizes[p], NULL);
1548 /*** video/mpeg MPEG-4 elementary video stream ***/
1550 static GstStaticCaps mpeg4_video_caps = GST_STATIC_CAPS ("video/mpeg, "
1551 "systemstream = (boolean) false, mpegversion = 4");
1552 #define MPEG4_VIDEO_CAPS gst_static_caps_get(&mpeg4_video_caps)
1554 mpeg4_video_type_find (GstTypeFind * tf, gpointer unused)
1556 /* Header consists of: a series of start codes (00 00 01 xx), some with
1558 * Optionally, we start with a visual_object_sequence_start_code, followed by
1559 * (optionally) visual_object_start_code), then the mandatory
1560 * video_object_start_code and video_object_layer_start_code)
1562 guint8 *data = NULL;
1564 gboolean seen_vos = FALSE;
1567 data = gst_type_find_peek (tf, offset, 4);
1568 if (data && IS_MPEG_HEADER (data)) {
1571 if (sc == 0xB0) /* visual_object_sequence_start_code */
1573 else if (sc == 0xB5) /* visual_object_start_code */
1575 else if (sc >= 0x00 && sc <= 0x1F) { /* video_object_start_code */
1578 } else if (sc >= 0x20 && sc <= 0x2F) { /* video_object_layer_start_code */
1580 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN,
1592 /*** video/x-h264 H264 elementary video stream ***/
1594 static GstStaticCaps h264_video_caps = GST_STATIC_CAPS ("video/x-h264");
1596 #define H264_VIDEO_CAPS gst_static_caps_get(&h264_video_caps)
1598 #define H264_MAX_PROBE_LENGTH (128 * 1024) /* 128kB for HD should be enough. */
1601 h264_video_type_find (GstTypeFind * tf, gpointer unused)
1603 DataScanCtx c = { 0, NULL, 0 };
1605 /* Stream consists of: a series of sync codes (00 00 00 01) followed
1617 while (c.offset < H264_MAX_PROBE_LENGTH) {
1618 if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
1621 if (IS_MPEG_HEADER (c.data)) {
1622 nut = c.data[3] & 0x9f; /* forbiden_zero_bit | nal_unit_type */
1623 ref = c.data[3] & 0x60; /* nal_ref_idc */
1625 /* if forbiden bit is different to 0 won't be h264 */
1629 /* collect statistics about the NAL types */
1638 else if ((nut == 5) && (ref != 0))
1640 else if ((nut == 7) && (ref != 0))
1642 else if ((nut == 8) && (ref != 0))
1645 if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
1646 stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
1647 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN,
1652 data_scan_ctx_advance (tf, &c, 4);
1654 data_scan_ctx_advance (tf, &c, 1);
1658 /*** video/mpeg video stream ***/
1660 static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, "
1661 "systemstream = (boolean) false");
1662 #define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps)
1665 * Idea is the same as MPEG system stream typefinding: We check each
1666 * byte of the stream to see if - from that point on - the stream
1667 * matches a predefined set of marker bits as defined in the MPEG
1670 * I'm sure someone will do a chance calculation here too.
1673 #define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6
1674 #define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024) /* 100 kB */
1677 mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused)
1679 DataScanCtx c = { 0, NULL, 0 };
1680 gboolean seen_seq_at_0 = FALSE;
1681 gboolean seen_seq = FALSE;
1682 gboolean seen_gop = FALSE;
1683 guint64 last_pic_offset = 0;
1684 guint num_pic_headers = 0;
1687 while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) {
1688 if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
1691 if (!data_scan_ctx_ensure_data (tf, &c, 5))
1694 if (!IS_MPEG_HEADER (c.data))
1697 /* a pack header indicates that this isn't an elementary stream */
1698 if (c.data[3] == 0xBA && mpeg_sys_is_valid_pack (tf, c.data, c.size, NULL))
1701 /* do we have a sequence header? */
1702 if (c.data[3] == 0xB3) {
1703 seen_seq_at_0 = seen_seq_at_0 || (c.offset == 0);
1705 data_scan_ctx_advance (tf, &c, 4 + 8);
1709 /* or a GOP header */
1710 if (c.data[3] == 0xB8) {
1712 data_scan_ctx_advance (tf, &c, 8);
1716 /* but what we'd really like to see is a picture header */
1717 if (c.data[3] == 0x00) {
1719 last_pic_offset = c.offset;
1720 data_scan_ctx_advance (tf, &c, 8);
1724 /* ... each followed by a slice header with slice_vertical_pos=1 that's
1725 * not too far away from the previously seen picture header. */
1726 if (c.data[3] == 0x01 && num_pic_headers > found &&
1727 (c.offset - last_pic_offset) >= 4 &&
1728 (c.offset - last_pic_offset) <= 64) {
1729 data_scan_ctx_advance (tf, &c, 4);
1736 data_scan_ctx_advance (tf, &c, 1);
1739 if (found > 0 || seen_seq) {
1740 GstTypeFindProbability probability = 0;
1742 GST_LOG ("Found %d pictures, seq:%d, gop:%d", found, seen_seq, seen_gop);
1744 if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq && seen_gop)
1745 probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1;
1746 else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq)
1747 probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9;
1748 else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES)
1749 probability = GST_TYPE_FIND_LIKELY;
1750 else if (seen_seq_at_0 && seen_gop && found > 2)
1751 probability = GST_TYPE_FIND_LIKELY - 10;
1752 else if (seen_seq && seen_gop && found > 2)
1753 probability = GST_TYPE_FIND_LIKELY - 20;
1754 else if (seen_seq_at_0 && found > 0)
1755 probability = GST_TYPE_FIND_POSSIBLE;
1756 else if (seen_seq && found > 0)
1757 probability = GST_TYPE_FIND_POSSIBLE - 5;
1759 probability = GST_TYPE_FIND_POSSIBLE - 10;
1761 probability = GST_TYPE_FIND_POSSIBLE - 20;
1763 gst_type_find_suggest_simple (tf, probability, "video/mpeg",
1764 "systemstream", G_TYPE_BOOLEAN, FALSE,
1765 "mpegversion", G_TYPE_INT, 1, NULL);
1769 /*** audio/x-aiff ***/
1771 static GstStaticCaps aiff_caps = GST_STATIC_CAPS ("audio/x-aiff");
1773 #define AIFF_CAPS gst_static_caps_get(&aiff_caps)
1775 aiff_type_find (GstTypeFind * tf, gpointer unused)
1777 guint8 *data = gst_type_find_peek (tf, 0, 4);
1779 if (data && memcmp (data, "FORM", 4) == 0) {
1781 if (memcmp (data, "AIFF", 4) == 0 || memcmp (data, "AIFC", 4) == 0)
1782 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AIFF_CAPS);
1786 /*** audio/x-svx ***/
1788 static GstStaticCaps svx_caps = GST_STATIC_CAPS ("audio/x-svx");
1790 #define SVX_CAPS gst_static_caps_get(&svx_caps)
1792 svx_type_find (GstTypeFind * tf, gpointer unused)
1794 guint8 *data = gst_type_find_peek (tf, 0, 4);
1796 if (data && memcmp (data, "FORM", 4) == 0) {
1798 if (memcmp (data, "8SVX", 4) == 0 || memcmp (data, "16SV", 4) == 0)
1799 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SVX_CAPS);
1803 /*** audio/x-shorten ***/
1805 static GstStaticCaps shn_caps = GST_STATIC_CAPS ("audio/x-shorten");
1807 #define SHN_CAPS gst_static_caps_get(&shn_caps)
1809 shn_type_find (GstTypeFind * tf, gpointer unused)
1811 guint8 *data = gst_type_find_peek (tf, 0, 4);
1813 if (data && memcmp (data, "ajkg", 4) == 0) {
1814 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS);
1816 data = gst_type_find_peek (tf, -8, 8);
1817 if (data && memcmp (data, "SHNAMPSK", 8) == 0) {
1818 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS);
1822 /*** application/x-ape ***/
1824 static GstStaticCaps ape_caps = GST_STATIC_CAPS ("application/x-ape");
1826 #define APE_CAPS gst_static_caps_get(&ape_caps)
1828 ape_type_find (GstTypeFind * tf, gpointer unused)
1830 guint8 *data = gst_type_find_peek (tf, 0, 4);
1832 if (data && memcmp (data, "MAC ", 4) == 0) {
1833 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, APE_CAPS);
1837 /*** ISO FORMATS ***/
1839 /*** audio/x-m4a ***/
1841 static GstStaticCaps m4a_caps = GST_STATIC_CAPS ("audio/x-m4a");
1843 #define M4A_CAPS (gst_static_caps_get(&m4a_caps))
1845 m4a_type_find (GstTypeFind * tf, gpointer unused)
1847 guint8 *data = gst_type_find_peek (tf, 4, 8);
1850 (memcmp (data, "ftypM4A ", 8) == 0 ||
1851 memcmp (data, "ftypmp42", 8) == 0)) {
1852 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M4A_CAPS);
1856 /*** application/x-3gp ***/
1858 /* The Q is there because variables can't start with a number. */
1861 static GstStaticCaps q3gp_caps = GST_STATIC_CAPS ("application/x-3gp");
1863 #define Q3GP_CAPS (gst_static_caps_get(&q3gp_caps))
1865 q3gp_type_find (GstTypeFind * tf, gpointer unused)
1868 guint32 ftyp_size = 0;
1870 guint8 *data = NULL;
1872 if ((data = gst_type_find_peek (tf, 0, 12)) == NULL) {
1877 if (memcmp (data, "ftyp", 4) != 0) {
1881 /* check major brand */
1883 if (memcmp (data, "3gp", 3) == 0 ||
1884 memcmp (data, "3gr", 3) == 0 ||
1885 memcmp (data, "3gs", 3) == 0 || memcmp (data, "3gg", 3) == 0) {
1886 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, Q3GP_CAPS);
1890 /* check compatible brands */
1891 if ((data = gst_type_find_peek (tf, 0, 4)) != NULL) {
1892 ftyp_size = GST_READ_UINT32_BE (data);
1894 for (offset = 16; offset < ftyp_size; offset += 4) {
1895 if ((data = gst_type_find_peek (tf, offset, 3)) == NULL) {
1898 if (memcmp (data, "3gp", 3) == 0 ||
1899 memcmp (data, "3gr", 3) == 0 ||
1900 memcmp (data, "3gs", 3) == 0 || memcmp (data, "3gg", 3) == 0) {
1901 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, Q3GP_CAPS);
1910 /*** video/quicktime ***/
1912 static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime");
1914 #define QT_CAPS gst_static_caps_get(&qt_caps)
1915 #define STRNCMP(x,y,z) (strncmp ((char*)(x), (char*)(y), z))
1918 qt_type_find (GstTypeFind * tf, gpointer unused)
1925 while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
1926 /* box/atom types that are in common with ISO base media file format */
1927 if (STRNCMP (&data[4], "moov", 4) == 0 ||
1928 STRNCMP (&data[4], "mdat", 4) == 0 ||
1929 STRNCMP (&data[4], "ftyp", 4) == 0 ||
1930 STRNCMP (&data[4], "free", 4) == 0 ||
1931 STRNCMP (&data[4], "uuid", 4) == 0 ||
1932 STRNCMP (&data[4], "skip", 4) == 0) {
1934 tip = GST_TYPE_FIND_LIKELY;
1936 tip = GST_TYPE_FIND_NEARLY_CERTAIN;
1939 /* other box/atom types, apparently quicktime specific */
1940 else if (STRNCMP (&data[4], "pnot", 4) == 0 ||
1941 STRNCMP (&data[4], "PICT", 4) == 0 ||
1942 STRNCMP (&data[4], "wide", 4) == 0 ||
1943 STRNCMP (&data[4], "prfl", 4) == 0) {
1944 tip = GST_TYPE_FIND_MAXIMUM;
1950 size = GST_READ_UINT32_BE (data);
1954 sizedata = gst_type_find_peek (tf, offset + 8, 8);
1955 if (sizedata == NULL)
1958 size = GST_READ_UINT64_BE (sizedata);
1966 gst_type_find_suggest (tf, tip, QT_CAPS);
1971 /*** image/x-quicktime ***/
1973 static GstStaticCaps qtif_caps = GST_STATIC_CAPS ("image/x-quicktime");
1975 #define QTIF_CAPS gst_static_caps_get(&qtif_caps)
1977 /* how many atoms we check before we give up */
1978 #define QTIF_MAXROUNDS 25
1981 qtif_type_find (GstTypeFind * tf, gpointer unused)
1984 gboolean found_idsc = FALSE;
1985 gboolean found_idat = FALSE;
1989 while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) {
1992 size = GST_READ_UINT32_BE (data);
1994 const guint8 *sizedata;
1996 sizedata = gst_type_find_peek (tf, offset + 8, 8);
1997 if (sizedata == NULL)
2000 size = GST_READ_UINT64_BE (sizedata);
2005 if (STRNCMP (data + 4, "idsc", 4) == 0)
2007 if (STRNCMP (data + 4, "idat", 4) == 0)
2010 if (found_idsc && found_idat) {
2011 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, QTIF_CAPS);
2016 if (++rounds > QTIF_MAXROUNDS)
2020 if (found_idsc || found_idat) {
2021 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, QTIF_CAPS);
2026 /*** audio/x-mod ***/
2028 static GstStaticCaps mod_caps = GST_STATIC_CAPS ("audio/x-mod");
2030 #define MOD_CAPS gst_static_caps_get(&mod_caps)
2031 /* FIXME: M15 CheckType to do */
2033 mod_type_find (GstTypeFind * tf, gpointer unused)
2038 if ((data = gst_type_find_peek (tf, 1080, 4)) != NULL) {
2039 /* Protracker and variants */
2040 if ((memcmp (data, "M.K.", 4) == 0) || (memcmp (data, "M!K!", 4) == 0) ||
2042 (memcmp (data, "FLT", 3) == 0 && isdigit (data[3])) ||
2043 (memcmp (data, "EXO", 3) == 0 && isdigit (data[3])) ||
2044 /* Oktalyzer (Amiga) */
2045 (memcmp (data, "OKTA", 4) == 0) ||
2046 /* Oktalyser (Atari) */
2047 (memcmp (data, "CD81", 4) == 0) ||
2049 (memcmp (data + 1, "CHN", 3) == 0 && isdigit (data[0])) ||
2050 /* Fasttracker or Taketracker */
2051 (memcmp (data + 2, "CH", 2) == 0 && isdigit (data[0])
2052 && isdigit (data[1])) || (memcmp (data + 2, "CN", 2) == 0
2053 && isdigit (data[0]) && isdigit (data[1]))) {
2054 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2059 if ((data = gst_type_find_peek (tf, 0, 38)) != NULL) {
2060 if (memcmp (data, "Extended Module: ", 17) == 0 && data[37] == 0x1A) {
2061 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2066 if (data || (data = gst_type_find_peek (tf, 0, 8)) != NULL) {
2067 if (memcmp (data, "OKTASONG", 8) == 0) {
2068 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2072 if (data || (data = gst_type_find_peek (tf, 0, 4)) != NULL) {
2074 if ((memcmp (data, "if", 2) == 0) || (memcmp (data, "JN", 2) == 0)) {
2075 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2079 if ((memcmp (data, "AMF", 3) == 0 && data[3] > 10 && data[3] < 14) ||
2081 (memcmp (data, "IMPM", 4) == 0) ||
2083 (memcmp (data, "MMD0", 4) == 0) || (memcmp (data, "MMD1", 4) == 0) ||
2085 (memcmp (data, "MTM", 3) == 0)) {
2086 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2090 if (memcmp (data, "RIFF", 4) == 0) {
2091 guint8 *data2 = gst_type_find_peek (tf, 8, 4);
2094 if (memcmp (data2, "DSMF", 4) == 0) {
2095 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2101 if (memcmp (data, "FAM\xFE", 4) == 0) {
2102 guint8 *data2 = gst_type_find_peek (tf, 44, 3);
2105 if (memcmp (data2, "compare", 3) == 0) {
2106 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2110 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2115 if (memcmp (data, "GDM\xFE", 4) == 0) {
2116 guint8 *data2 = gst_type_find_peek (tf, 71, 4);
2119 if (memcmp (data2, "GMFS", 4) == 0) {
2120 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2124 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS);
2130 if ((data = gst_type_find_peek (tf, 60, 4)) != NULL) {
2131 if (memcmp (data, "IM10", 4) == 0) {
2132 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2137 if ((data = gst_type_find_peek (tf, 44, 4)) != NULL) {
2138 if (memcmp (data, "SCRM", 4) == 0) {
2139 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS);
2145 /*** application/x-shockwave-flash ***/
2147 static GstStaticCaps swf_caps =
2148 GST_STATIC_CAPS ("application/x-shockwave-flash");
2149 #define SWF_CAPS (gst_static_caps_get(&swf_caps))
2151 swf_type_find (GstTypeFind * tf, gpointer unused)
2153 guint8 *data = gst_type_find_peek (tf, 0, 4);
2155 if (data && (data[0] == 'F' || data[0] == 'C') &&
2156 data[1] == 'W' && data[2] == 'S') {
2157 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SWF_CAPS);
2161 /*** image/jpeg ***/
2163 static GstStaticCaps jpeg_caps = GST_STATIC_CAPS ("image/jpeg");
2165 #define JPEG_CAPS (gst_static_caps_get(&jpeg_caps))
2167 jpeg_type_find (GstTypeFind * tf, gpointer unused)
2169 guint8 *data = gst_type_find_peek (tf, 0, 10);
2170 guint8 header[2] = { 0xFF, 0xD8 };
2172 if (data && memcmp (data, header, 2) == 0) {
2173 if (memcmp (data + 6, "JFIF", 4) == 0) {
2174 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JPEG_CAPS);
2175 } else if (memcmp (data + 6, "Exif", 4) == 0) {
2176 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JPEG_CAPS);
2178 gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, JPEG_CAPS);
2185 static GstStaticCaps bmp_caps = GST_STATIC_CAPS ("image/bmp");
2187 #define BMP_CAPS (gst_static_caps_get(&bmp_caps))
2189 bmp_type_find (GstTypeFind * tf, gpointer unused)
2191 guint8 *data = gst_type_find_peek (tf, 0, 18);
2193 if (data && memcmp (data, "BM", 2) == 0) {
2194 if ((data[14] == 0x0C ||
2196 data[14] == 0xF0) &&
2197 data[15] == 0 && data[16] == 0 && data[17] == 0) {
2198 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, BMP_CAPS);
2203 /*** image/tiff ***/
2204 static GstStaticCaps tiff_caps = GST_STATIC_CAPS ("image/tiff, "
2205 "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }");
2206 #define TIFF_CAPS (gst_static_caps_get(&tiff_caps))
2207 static GstStaticCaps tiff_be_caps = GST_STATIC_CAPS ("image/tiff, "
2208 "endianness = (int) BIG_ENDIAN");
2209 #define TIFF_BE_CAPS (gst_static_caps_get(&tiff_be_caps))
2210 static GstStaticCaps tiff_le_caps = GST_STATIC_CAPS ("image/tiff, "
2211 "endianness = (int) LITTLE_ENDIAN");
2212 #define TIFF_LE_CAPS (gst_static_caps_get(&tiff_le_caps))
2214 tiff_type_find (GstTypeFind * tf, gpointer ununsed)
2216 guint8 *data = gst_type_find_peek (tf, 0, 8);
2217 guint8 le_header[4] = { 0x49, 0x49, 0x2A, 0x00 };
2218 guint8 be_header[4] = { 0x4D, 0x4D, 0x00, 0x2A };
2221 if (memcmp (data, le_header, 4) == 0) {
2222 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_LE_CAPS);
2223 } else if (memcmp (data, be_header, 4) == 0) {
2224 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_BE_CAPS);
2229 static GstStaticCaps sds_caps = GST_STATIC_CAPS ("audio/x-sds");
2231 #define SDS_CAPS (gst_static_caps_get(&sds_caps))
2233 sds_type_find (GstTypeFind * tf, gpointer ununsed)
2235 guint8 *data = gst_type_find_peek (tf, 0, 4);
2236 guint8 mask[4] = { 0xFF, 0xFF, 0x80, 0xFF };
2237 guint8 match[4] = { 0xF0, 0x7E, 0, 0x01 };
2241 for (x = 0; x < 4; x++) {
2242 if ((data[x] & mask[x]) != match[x]) {
2246 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SDS_CAPS);
2250 static GstStaticCaps ircam_caps = GST_STATIC_CAPS ("audio/x-ircam");
2252 #define IRCAM_CAPS (gst_static_caps_get(&ircam_caps))
2254 ircam_type_find (GstTypeFind * tf, gpointer ununsed)
2256 guint8 *data = gst_type_find_peek (tf, 0, 4);
2257 guint8 mask[4] = { 0xFF, 0xFF, 0xF8, 0xFF };
2258 guint8 match[4] = { 0x64, 0xA3, 0x00, 0x00 };
2260 gboolean matched = TRUE;
2265 for (x = 0; x < 4; x++) {
2266 if ((data[x] & mask[x]) != match[x]) {
2271 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, IRCAM_CAPS);
2274 /* now try the reverse version */
2276 for (x = 0; x < 4; x++) {
2277 if ((data[x] & mask[3 - x]) != match[3 - x]) {
2284 /*** video/x-matroska ***/
2285 static GstStaticCaps matroska_caps = GST_STATIC_CAPS ("video/x-matroska");
2287 #define MATROSKA_CAPS (gst_static_caps_get(&matroska_caps))
2289 matroska_type_find (GstTypeFind * tf, gpointer ununsed)
2291 /* 4 bytes for EBML ID, 1 byte for header length identifier */
2292 guint8 *data = gst_type_find_peek (tf, 0, 4 + 1);
2293 gint len_mask = 0x80, size = 1, n = 1, total;
2294 guint8 probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
2300 if (data[0] != 0x1A || data[1] != 0x45 || data[2] != 0xDF || data[3] != 0xA3)
2303 /* length of header */
2305 while (size <= 8 && !(total & len_mask)) {
2311 total &= (len_mask - 1);
2313 total = (total << 8) | data[4 + n++];
2315 /* get new data for full header, 4 bytes for EBML ID,
2316 * EBML length tag and the actual header */
2317 data = gst_type_find_peek (tf, 0, 4 + size + total);
2321 /* the header must contain the document type 'matroska'. For now,
2322 * we don't parse the whole header but simply check for the
2323 * availability of that array of characters inside the header.
2324 * Not fully fool-proof, but good enough. */
2325 for (n = 4 + size; n <= 4 + size + total - sizeof (probe_data); n++)
2326 if (!memcmp (&data[n], probe_data, sizeof (probe_data))) {
2327 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MATROSKA_CAPS);
2332 /*** video/x-dv ***/
2334 static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, "
2335 "systemstream = (boolean) true");
2336 #define DV_CAPS (gst_static_caps_get(&dv_caps))
2338 dv_type_find (GstTypeFind * tf, gpointer private)
2342 data = gst_type_find_peek (tf, 0, 5);
2344 /* check for DIF and DV flag */
2345 if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00)) {
2346 const gchar *format;
2348 if (data[3] & 0x80) {
2354 gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "video/x-dv",
2355 "systemstream", G_TYPE_BOOLEAN, TRUE,
2356 "format", G_TYPE_STRING, format, NULL);
2361 /*** application/ogg and application/x-annodex ***/
2362 static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
2363 static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
2365 #define OGGANX_CAPS (gst_static_caps_get(&annodex_caps))
2368 ogganx_type_find (GstTypeFind * tf, gpointer private)
2370 guint8 *data = gst_type_find_peek (tf, 0, 4);
2372 if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) {
2374 /* Check for an annodex fishbone header */
2375 data = gst_type_find_peek (tf, 28, 8);
2376 if (data && memcmp (data, "fishead\0", 8) == 0)
2377 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGGANX_CAPS);
2379 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
2380 gst_static_caps_get (&ogg_caps));
2384 /*** audio/x-vorbis ***/
2385 static GstStaticCaps vorbis_caps = GST_STATIC_CAPS ("audio/x-vorbis");
2387 #define VORBIS_CAPS (gst_static_caps_get(&vorbis_caps))
2389 vorbis_type_find (GstTypeFind * tf, gpointer private)
2391 guint8 *data = gst_type_find_peek (tf, 0, 30);
2397 /* 1 byte packet type (identification=0x01)
2398 6 byte string "vorbis"
2399 4 byte vorbis version */
2400 if (memcmp (data, "\001vorbis\000\000\000\000", 11) != 0)
2403 /* 1 byte channels must be != 0 */
2407 /* 4 byte samplerate must be != 0 */
2408 if (GST_READ_UINT32_LE (data) == 0)
2411 /* blocksize checks */
2412 blocksize_0 = data[0] & 0x0F;
2413 blocksize_1 = (data[0] & 0xF0) >> 4;
2414 if (blocksize_0 > blocksize_1)
2416 if (blocksize_0 < 6 || blocksize_0 > 13)
2418 if (blocksize_1 < 6 || blocksize_1 > 13)
2422 if ((data[0] & 0x01) != 1)
2424 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VORBIS_CAPS);
2428 /*** video/x-theora ***/
2430 static GstStaticCaps theora_caps = GST_STATIC_CAPS ("video/x-theora");
2432 #define THEORA_CAPS (gst_static_caps_get(&theora_caps))
2434 theora_type_find (GstTypeFind * tf, gpointer private)
2436 guint8 *data = gst_type_find_peek (tf, 0, 7); //42);
2439 if (data[0] != 0x80)
2441 if (memcmp (&data[1], "theora", 6) != 0)
2443 /* FIXME: make this more reliable when specs are out */
2445 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, THEORA_CAPS);
2449 /*** application/x-ogm-video or audio***/
2451 static GstStaticCaps ogmvideo_caps =
2452 GST_STATIC_CAPS ("application/x-ogm-video");
2453 #define OGMVIDEO_CAPS (gst_static_caps_get(&ogmvideo_caps))
2455 ogmvideo_type_find (GstTypeFind * tf, gpointer private)
2457 guint8 *data = gst_type_find_peek (tf, 0, 9);
2460 if (memcmp (data, "\001video\000\000\000", 9) != 0)
2462 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMVIDEO_CAPS);
2466 static GstStaticCaps ogmaudio_caps =
2467 GST_STATIC_CAPS ("application/x-ogm-audio");
2468 #define OGMAUDIO_CAPS (gst_static_caps_get(&ogmaudio_caps))
2470 ogmaudio_type_find (GstTypeFind * tf, gpointer private)
2472 guint8 *data = gst_type_find_peek (tf, 0, 9);
2475 if (memcmp (data, "\001audio\000\000\000", 9) != 0)
2477 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMAUDIO_CAPS);
2481 static GstStaticCaps ogmtext_caps = GST_STATIC_CAPS ("application/x-ogm-text");
2483 #define OGMTEXT_CAPS (gst_static_caps_get(&ogmtext_caps))
2485 ogmtext_type_find (GstTypeFind * tf, gpointer private)
2487 guint8 *data = gst_type_find_peek (tf, 0, 9);
2490 if (memcmp (data, "\001text\000\000\000\000", 9) != 0)
2492 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMTEXT_CAPS);
2496 /*** audio/x-speex ***/
2498 static GstStaticCaps speex_caps = GST_STATIC_CAPS ("audio/x-speex");
2500 #define SPEEX_CAPS (gst_static_caps_get(&speex_caps))
2502 speex_type_find (GstTypeFind * tf, gpointer private)
2504 guint8 *data = gst_type_find_peek (tf, 0, 80);
2507 /* 8 byte string "Speex "
2508 24 byte speex version string + int */
2509 if (memcmp (data, "Speex ", 8) != 0)
2513 /* 4 byte header size >= 80 */
2514 if (GST_READ_UINT32_LE (data) < 80)
2518 /* 4 byte sample rate <= 48000 */
2519 if (GST_READ_UINT32_LE (data) > 48000)
2523 /* currently there are only 3 speex modes. */
2524 if (GST_READ_UINT32_LE (data) > 3)
2528 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SPEEX_CAPS);
2532 /*** audio/x-celt ***/
2534 static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt");
2536 #define CELT_CAPS (gst_static_caps_get(&celt_caps))
2538 celt_type_find (GstTypeFind * tf, gpointer private)
2540 guint8 *data = gst_type_find_peek (tf, 0, 8);
2543 /* 8 byte string "CELT " */
2544 if (memcmp (data, "CELT ", 8) != 0)
2547 /* TODO: Check other values of the CELT header */
2548 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CELT_CAPS);
2552 /*** application/x-ogg-skeleton ***/
2553 static GstStaticCaps ogg_skeleton_caps =
2554 GST_STATIC_CAPS ("application/x-ogg-skeleton, parsed=(boolean)FALSE");
2555 #define OGG_SKELETON_CAPS (gst_static_caps_get(&ogg_skeleton_caps))
2557 oggskel_type_find (GstTypeFind * tf, gpointer private)
2559 guint8 *data = gst_type_find_peek (tf, 0, 12);
2562 /* 8 byte string "fishead\0" for the ogg skeleton stream */
2563 if (memcmp (data, "fishead\0", 8) != 0)
2567 /* Require that the header contains version 3.0 */
2568 if (GST_READ_UINT16_LE (data) != 3)
2571 if (GST_READ_UINT16_LE (data) != 0)
2574 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGG_SKELETON_CAPS);
2578 static GstStaticCaps cmml_caps = GST_STATIC_CAPS ("text/x-cmml");
2580 #define CMML_CAPS (gst_static_caps_get(&cmml_caps))
2582 cmml_type_find (GstTypeFind * tf, gpointer private)
2584 /* Header is 12 bytes minimum (though we don't check the minor version */
2585 guint8 *data = gst_type_find_peek (tf, 0, 12);
2589 /* 8 byte string "CMML\0\0\0\0" for the magic number */
2590 if (memcmp (data, "CMML\0\0\0\0", 8) != 0)
2594 /* Require that the header contains at least version 2.0 */
2595 if (GST_READ_UINT16_LE (data) < 2)
2598 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CMML_CAPS);
2602 /*** application/x-tar ***/
2604 static GstStaticCaps tar_caps = GST_STATIC_CAPS ("application/x-tar");
2606 #define TAR_CAPS (gst_static_caps_get(&tar_caps))
2607 #define OLDGNU_MAGIC "ustar " /* 7 chars and a NUL */
2608 #define NEWGNU_MAGIC "ustar" /* 5 chars and a NUL */
2610 tar_type_find (GstTypeFind * tf, gpointer unused)
2612 guint8 *data = gst_type_find_peek (tf, 257, 8);
2614 /* of course we are not certain, but we don't want other typefind funcs
2615 * to detect formats of files within the tar archive, e.g. mp3s */
2617 if (memcmp (data, OLDGNU_MAGIC, 8) == 0) { /* sic */
2618 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS);
2619 } else if (memcmp (data, NEWGNU_MAGIC, 6) == 0 && /* sic */
2620 g_ascii_isdigit (data[6]) && g_ascii_isdigit (data[7])) {
2621 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS);
2626 /*** application/x-ar ***/
2628 static GstStaticCaps ar_caps = GST_STATIC_CAPS ("application/x-ar");
2630 #define AR_CAPS (gst_static_caps_get(&ar_caps))
2632 ar_type_find (GstTypeFind * tf, gpointer unused)
2634 guint8 *data = gst_type_find_peek (tf, 0, 24);
2636 if (data && memcmp (data, "!<arch>", 7) == 0) {
2639 for (i = 7; i < 24; ++i) {
2640 if (!g_ascii_isprint (data[i]) && data[i] != '\n') {
2641 gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, AR_CAPS);
2645 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, AR_CAPS);
2649 /*** audio/x-au ***/
2651 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
2652 * as it is only possible to register one typefind factory per 'name'
2653 * (which is in this case the caps), and the first one would be replaced by
2654 * the second one. */
2655 static GstStaticCaps au_caps = GST_STATIC_CAPS ("audio/x-au");
2657 #define AU_CAPS (gst_static_caps_get(&au_caps))
2659 au_type_find (GstTypeFind * tf, gpointer unused)
2661 guint8 *data = gst_type_find_peek (tf, 0, 4);
2664 if (memcmp (data, ".snd", 4) == 0 || memcmp (data, "dns.", 4) == 0) {
2665 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AU_CAPS);
2671 /*** video/x-nuv ***/
2673 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
2674 * as it is only possible to register one typefind factory per 'name'
2675 * (which is in this case the caps), and the first one would be replaced by
2676 * the second one. */
2677 static GstStaticCaps nuv_caps = GST_STATIC_CAPS ("video/x-nuv");
2679 #define NUV_CAPS (gst_static_caps_get(&nuv_caps))
2681 nuv_type_find (GstTypeFind * tf, gpointer unused)
2683 guint8 *data = gst_type_find_peek (tf, 0, 11);
2686 if (memcmp (data, "MythTVVideo", 11) == 0
2687 || memcmp (data, "NuppelVideo", 11) == 0) {
2688 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, NUV_CAPS);
2693 /*** audio/x-paris ***/
2694 /* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */
2695 static GstStaticCaps paris_caps = GST_STATIC_CAPS ("audio/x-paris");
2697 #define PARIS_CAPS (gst_static_caps_get(&paris_caps))
2699 paris_type_find (GstTypeFind * tf, gpointer unused)
2701 guint8 *data = gst_type_find_peek (tf, 0, 4);
2704 if (memcmp (data, " paf", 4) == 0 || memcmp (data, "fap ", 4) == 0) {
2705 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, PARIS_CAPS);
2710 /*** audio/iLBC-sh ***/
2711 /* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */
2712 static GstStaticCaps ilbc_caps = GST_STATIC_CAPS ("audio/iLBC-sh");
2714 #define ILBC_CAPS (gst_static_caps_get(&ilbc_caps))
2716 ilbc_type_find (GstTypeFind * tf, gpointer unused)
2718 guint8 *data = gst_type_find_peek (tf, 0, 8);
2721 if (memcmp (data, "#!iLBC30", 8) == 0 || memcmp (data, "#!iLBC20", 8) == 0) {
2722 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, ILBC_CAPS);
2727 /*** application/x-ms-dos-executable ***/
2729 static GstStaticCaps msdos_caps =
2730 GST_STATIC_CAPS ("application/x-ms-dos-executable");
2731 #define MSDOS_CAPS (gst_static_caps_get(&msdos_caps))
2732 /* see http://www.madchat.org/vxdevl/papers/winsys/pefile/pefile.htm */
2734 msdos_type_find (GstTypeFind * tf, gpointer unused)
2736 guint8 *data = gst_type_find_peek (tf, 0, 64);
2738 if (data && data[0] == 'M' && data[1] == 'Z' &&
2739 GST_READ_UINT16_LE (data + 8) == 4) {
2740 guint32 pe_offset = GST_READ_UINT32_LE (data + 60);
2742 data = gst_type_find_peek (tf, pe_offset, 2);
2743 if (data && data[0] == 'P' && data[1] == 'E') {
2744 gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, MSDOS_CAPS);
2749 /*** application/x-mmsh ***/
2751 static GstStaticCaps mmsh_caps = GST_STATIC_CAPS ("application/x-mmsh");
2753 #define MMSH_CAPS gst_static_caps_get(&mmsh_caps)
2755 /* This is to recognise mssh-over-http */
2757 mmsh_type_find (GstTypeFind * tf, gpointer unused)
2759 static const guint8 asf_marker[16] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66,
2760 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
2765 data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16);
2766 if (data && data[0] == 0x24 && data[1] == 0x48 &&
2767 GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 &&
2768 memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) {
2769 gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMSH_CAPS);
2773 /*** video/x-dirac ***/
2775 /* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH,
2776 * as it is only possible to register one typefind factory per 'name'
2777 * (which is in this case the caps), and the first one would be replaced by
2778 * the second one. */
2779 static GstStaticCaps dirac_caps = GST_STATIC_CAPS ("video/x-dirac");
2781 #define DIRAC_CAPS (gst_static_caps_get(&dirac_caps))
2783 dirac_type_find (GstTypeFind * tf, gpointer unused)
2785 guint8 *data = gst_type_find_peek (tf, 0, 8);
2788 if (memcmp (data, "BBCD", 4) == 0 || memcmp (data, "KW-DIRAC", 8) == 0) {
2789 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DIRAC_CAPS);
2794 /*** video/vivo ***/
2796 static GstStaticCaps vivo_caps = GST_STATIC_CAPS ("video/vivo");
2798 #define VIVO_CAPS gst_static_caps_get(&vivo_caps)
2801 vivo_type_find (GstTypeFind * tf, gpointer unused)
2803 static const guint8 vivo_marker[] = { 'V', 'e', 'r', 's', 'i', 'o', 'n',
2804 ':', 'V', 'i', 'v', 'o', '/'
2809 data = gst_type_find_peek (tf, 0, 1024);
2810 if (data == NULL || data[0] != 0x00)
2813 if ((data[1] & 0x80)) {
2814 if ((data[2] & 0x80))
2816 hdr_len = ((guint) (data[1] & 0x7f)) << 7;
2826 /* 1008 = 1022 - strlen ("Version:Vivo/") - 1 */
2827 while (pos < 1008 && data[pos] == '\r' && data[pos + 1] == '\n')
2830 if (memcmp (data + pos, vivo_marker, sizeof (vivo_marker)) == 0) {
2831 gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VIVO_CAPS);
2835 /*** generic typefind for streams that have some data at a specific position***/
2846 start_with_type_find (GstTypeFind * tf, gpointer private)
2848 GstTypeFindData *start_with = (GstTypeFindData *) private;
2851 GST_LOG ("trying to find mime type %s with the first %u bytes of data",
2852 gst_structure_get_name (gst_caps_get_structure (start_with->caps, 0)),
2854 data = gst_type_find_peek (tf, 0, start_with->size);
2855 if (data && memcmp (data, start_with->data, start_with->size) == 0) {
2856 gst_type_find_suggest (tf, start_with->probability, start_with->caps);
2861 sw_data_destroy (GstTypeFindData * sw_data)
2863 if (G_LIKELY (sw_data->caps != NULL))
2864 gst_caps_unref (sw_data->caps);
2868 #define TYPE_FIND_REGISTER_START_WITH(plugin,name,rank,ext,_data,_size,_probability)\
2870 GstTypeFindData *sw_data = g_new (GstTypeFindData, 1); \
2871 sw_data->data = (const guint8 *)_data; \
2872 sw_data->size = _size; \
2873 sw_data->probability = _probability; \
2874 sw_data->caps = gst_caps_new_simple (name, NULL); \
2875 if (!gst_type_find_register (plugin, name, rank, start_with_type_find,\
2876 ext, sw_data->caps, sw_data, \
2877 (GDestroyNotify) (sw_data_destroy))) { \
2878 gst_caps_unref (sw_data->caps); \
2883 /*** same for riff types ***/
2886 riff_type_find (GstTypeFind * tf, gpointer private)
2888 GstTypeFindData *riff_data = (GstTypeFindData *) private;
2889 guint8 *data = gst_type_find_peek (tf, 0, 12);
2891 if (data && memcmp (data, "RIFF", 4) == 0) {
2893 if (memcmp (data, riff_data->data, 4) == 0)
2894 gst_type_find_suggest (tf, riff_data->probability, riff_data->caps);
2898 #define TYPE_FIND_REGISTER_RIFF(plugin,name,rank,ext,_data) \
2900 GstTypeFindData *sw_data = g_new (GstTypeFindData, 1); \
2901 sw_data->data = (gpointer)_data; \
2902 sw_data->size = 4; \
2903 sw_data->probability = GST_TYPE_FIND_MAXIMUM; \
2904 sw_data->caps = gst_caps_new_simple (name, NULL); \
2905 if (!gst_type_find_register (plugin, name, rank, riff_type_find, \
2906 ext, sw_data->caps, sw_data, \
2907 (GDestroyNotify) (sw_data_destroy))) { \
2908 gst_caps_unref (sw_data->caps); \
2914 /*** plugin initialization ***/
2916 #define TYPE_FIND_REGISTER(plugin,name,rank,func,ext,caps,priv,notify) \
2918 if (!gst_type_find_register (plugin, name, rank, func, ext, caps, priv, notify))\
2924 plugin_init (GstPlugin * plugin)
2926 /* can't initialize this via a struct as caps can't be statically initialized */
2928 /* note: asx/wax/wmx are XML files, asf doesn't handle them */
2929 /* FIXME-0.11: these should be const,
2930 this requires gstreamer/gst/gsttypefind::gst_type_find_register()
2931 to have define the parameter as const
2933 static gchar *asf_exts[] = { "asf", "wm", "wma", "wmv", NULL };
2934 static gchar *au_exts[] = { "au", "snd", NULL };
2935 static gchar *avi_exts[] = { "avi", NULL };
2936 static gchar *qcp_exts[] = { "qcp", NULL };
2937 static gchar *cdxa_exts[] = { "dat", NULL };
2938 static gchar *flac_exts[] = { "flac", NULL };
2939 static gchar *flx_exts[] = { "flc", "fli", NULL };
2940 static gchar *id3_exts[] =
2941 { "mp3", "mp2", "mp1", "mpga", "ogg", "flac", "tta", NULL };
2942 static gchar *apetag_exts[] = { "ape", "mpc", "wv", NULL }; /* and mp3 and wav? */
2943 static gchar *tta_exts[] = { "tta", NULL };
2944 static gchar *mod_exts[] = { "669", "amf", "dsm", "gdm", "far", "imf",
2945 "it", "med", "mod", "mtm", "okt", "sam",
2946 "s3m", "stm", "stx", "ult", "xm", NULL
2948 static gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
2949 static gchar *ac3_exts[] = { "ac3", NULL };
2950 static gchar *musepack_exts[] = { "mpc", "mpp", "mp+", NULL };
2951 static gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
2952 static gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
2953 static gchar *mpeg_ts_exts[] = { "ts", NULL };
2954 static gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL };
2955 static gchar *qt_exts[] = { "mov", NULL };
2956 static gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL };
2957 static gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL };
2958 static gchar *swf_exts[] = { "swf", "swfl", NULL };
2959 static gchar *utf8_exts[] = { "txt", NULL };
2960 static gchar *wav_exts[] = { "wav", NULL };
2961 static gchar *aiff_exts[] = { "aiff", "aif", "aifc", NULL };
2962 static gchar *svx_exts[] = { "iff", "svx", NULL };
2963 static gchar *paris_exts[] = { "paf", NULL };
2964 static gchar *nist_exts[] = { "nist", NULL };
2965 static gchar *voc_exts[] = { "voc", NULL };
2966 static gchar *sds_exts[] = { "sds", NULL };
2967 static gchar *ircam_exts[] = { "sf", NULL };
2968 static gchar *w64_exts[] = { "w64", NULL };
2969 static gchar *shn_exts[] = { "shn", NULL };
2970 static gchar *ape_exts[] = { "ape", NULL };
2971 static gchar *uri_exts[] = { "ram", NULL };
2972 static gchar *sdp_exts[] = { "sdp", NULL };
2973 static gchar *smil_exts[] = { "smil", NULL };
2974 static gchar *html_exts[] = { "htm", "html", NULL };
2975 static gchar *xml_exts[] = { "xml", NULL };
2976 static gchar *jpeg_exts[] = { "jpg", "jpe", "jpeg", NULL };
2977 static gchar *gif_exts[] = { "gif", NULL };
2978 static gchar *png_exts[] = { "png", NULL };
2979 static gchar *bmp_exts[] = { "bmp", NULL };
2980 static gchar *tiff_exts[] = { "tif", "tiff", NULL };
2981 static gchar *matroska_exts[] = { "mkv", "mka", NULL };
2982 static gchar *mve_exts[] = { "mve", NULL };
2983 static gchar *dv_exts[] = { "dv", "dif", NULL };
2984 static gchar *amr_exts[] = { "amr", NULL };
2985 static gchar *ilbc_exts[] = { "ilbc", NULL };
2986 static gchar *sid_exts[] = { "sid", NULL };
2987 static gchar *xcf_exts[] = { "xcf", NULL };
2988 static gchar *mng_exts[] = { "mng", NULL };
2989 static gchar *jng_exts[] = { "jng", NULL };
2990 static gchar *xpm_exts[] = { "xpm", NULL };
2991 static gchar *ras_exts[] = { "ras", NULL };
2992 static gchar *bz2_exts[] = { "bz2", NULL };
2993 static gchar *gz_exts[] = { "gz", NULL };
2994 static gchar *zip_exts[] = { "zip", NULL };
2995 static gchar *compress_exts[] = { "Z", NULL };
2996 static gchar *m4a_exts[] = { "m4a", NULL };
2997 static gchar *q3gp_exts[] = { "3gp", NULL };
2998 static gchar *aac_exts[] = { "aac", NULL };
2999 static gchar *spc_exts[] = { "spc", NULL };
3000 static gchar *wavpack_exts[] = { "wv", "wvp", NULL };
3001 static gchar *wavpack_correction_exts[] = { "wvc", NULL };
3002 static gchar *rar_exts[] = { "rar", NULL };
3003 static gchar *tar_exts[] = { "tar", NULL };
3004 static gchar *ar_exts[] = { "a", NULL };
3005 static gchar *msdos_exts[] = { "dll", "exe", "ocx", "sys", "scr",
3006 "msstyles", "cpl", NULL
3008 static gchar *flv_exts[] = { "flv", NULL };
3009 static gchar *m4v_exts[] = { "m4v", NULL };
3010 static gchar *h264_exts[] = { "h264", "x264", "264", NULL };
3011 static gchar *nuv_exts[] = { "nuv", NULL };
3012 static gchar *vivo_exts[] = { "viv", NULL };
3013 static gchar *nsf_exts[] = { "nsf", NULL };
3014 static gchar *mid_exts[] = { "mid", "midi", NULL };
3015 static gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL };
3017 GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions",
3018 GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions");
3020 /* must use strings, macros don't accept initializers */
3021 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-ms-asf", GST_RANK_SECONDARY,
3023 "\060\046\262\165\216\146\317\021\246\331\000\252\000\142\316\154", 16,
3024 GST_TYPE_FIND_MAXIMUM);
3025 TYPE_FIND_REGISTER (plugin, "audio/x-musepack", GST_RANK_PRIMARY,
3026 musepack_type_find, musepack_exts, MUSEPACK_CAPS, NULL, NULL);
3027 TYPE_FIND_REGISTER (plugin, "audio/x-au", GST_RANK_MARGINAL,
3028 au_type_find, au_exts, AU_CAPS, NULL, NULL);
3029 TYPE_FIND_REGISTER_RIFF (plugin, "video/x-msvideo", GST_RANK_PRIMARY,
3031 TYPE_FIND_REGISTER_RIFF (plugin, "audio/qcelp", GST_RANK_PRIMARY,
3033 TYPE_FIND_REGISTER_RIFF (plugin, "video/x-cdxa", GST_RANK_PRIMARY,
3035 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-vcd", GST_RANK_PRIMARY,
3036 cdxa_exts, "\000\377\377\377\377\377\377\377\377\377\377\000", 12,
3037 GST_TYPE_FIND_MAXIMUM);
3038 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-imelody", GST_RANK_PRIMARY,
3039 imelody_exts, "BEGIN:IMELODY", 13, GST_TYPE_FIND_MAXIMUM);
3041 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-smoke", GST_RANK_PRIMARY,
3042 NULL, "\x80smoke\x00\x01\x00", 6, GST_TYPE_FIND_MAXIMUM);
3044 TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find,
3045 mid_exts, MID_CAPS, NULL, NULL);
3046 TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find,
3047 flx_exts, FLX_CAPS, NULL, NULL);
3048 TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103,
3049 id3v2_type_find, id3_exts, ID3_CAPS, NULL, NULL);
3050 TYPE_FIND_REGISTER (plugin, "application/x-id3v1", GST_RANK_PRIMARY + 101,
3051 id3v1_type_find, id3_exts, ID3_CAPS, NULL, NULL);
3052 TYPE_FIND_REGISTER (plugin, "application/x-apetag", GST_RANK_PRIMARY + 102,
3053 apetag_type_find, apetag_exts, APETAG_CAPS, NULL, NULL);
3054 TYPE_FIND_REGISTER (plugin, "audio/x-ttafile", GST_RANK_PRIMARY,
3055 tta_type_find, tta_exts, TTA_CAPS, NULL, NULL);
3056 TYPE_FIND_REGISTER (plugin, "audio/x-mod", GST_RANK_SECONDARY, mod_type_find,
3057 mod_exts, MOD_CAPS, NULL, NULL);
3058 TYPE_FIND_REGISTER (plugin, "audio/mpeg", GST_RANK_PRIMARY, mp3_type_find,
3059 mp3_exts, MP3_CAPS, NULL, NULL);
3060 TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find,
3061 ac3_exts, AC3_CAPS, NULL, NULL);
3062 TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
3063 mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
3064 TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
3065 mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
3066 TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
3067 ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL);
3068 TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL,
3069 mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL,
3071 TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,
3072 mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL);
3073 TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY,
3074 h264_video_type_find, h264_exts, MPEG_VIDEO_CAPS, NULL, NULL);
3075 TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY,
3076 nuv_type_find, nuv_exts, NUV_CAPS, NULL, NULL);
3079 TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find,
3080 m4a_exts, M4A_CAPS, NULL, NULL);
3081 TYPE_FIND_REGISTER (plugin, "application/x-3gp", GST_RANK_PRIMARY,
3082 q3gp_type_find, q3gp_exts, Q3GP_CAPS, NULL, NULL);
3083 TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY,
3084 qt_type_find, qt_exts, QT_CAPS, NULL, NULL);
3085 TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY,
3086 qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL);
3088 TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find,
3089 html_exts, HTML_CAPS, NULL, NULL);
3090 TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia",
3091 GST_RANK_SECONDARY, rm_exts, ".RMF", 4, GST_TYPE_FIND_MAXIMUM);
3092 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-pn-realaudio",
3093 GST_RANK_SECONDARY, rm_exts, ".ra\375", 4, GST_TYPE_FIND_MAXIMUM);
3094 TYPE_FIND_REGISTER (plugin, "application/x-shockwave-flash",
3095 GST_RANK_SECONDARY, swf_type_find, swf_exts, SWF_CAPS, NULL, NULL);
3096 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-flv", GST_RANK_SECONDARY,
3097 flv_exts, "FLV", 3, GST_TYPE_FIND_MAXIMUM);
3098 TYPE_FIND_REGISTER (plugin, "text/plain", GST_RANK_MARGINAL, utf8_type_find,
3099 utf8_exts, UTF8_CAPS, NULL, NULL);
3100 TYPE_FIND_REGISTER (plugin, "text/uri-list", GST_RANK_MARGINAL, uri_type_find,
3101 uri_exts, URI_CAPS, NULL, NULL);
3102 TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY,
3103 sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL);
3104 TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY,
3105 smil_type_find, smil_exts, SMIL_CAPS, NULL, NULL);
3106 TYPE_FIND_REGISTER (plugin, "application/xml", GST_RANK_MARGINAL,
3107 xml_type_find, xml_exts, GENERIC_XML_CAPS, NULL, NULL);
3108 TYPE_FIND_REGISTER_RIFF (plugin, "audio/x-wav", GST_RANK_PRIMARY, wav_exts,
3110 TYPE_FIND_REGISTER (plugin, "audio/x-aiff", GST_RANK_SECONDARY,
3111 aiff_type_find, aiff_exts, AIFF_CAPS, NULL, NULL);
3112 TYPE_FIND_REGISTER (plugin, "audio/x-svx", GST_RANK_SECONDARY, svx_type_find,
3113 svx_exts, SVX_CAPS, NULL, NULL);
3114 TYPE_FIND_REGISTER (plugin, "audio/x-paris", GST_RANK_SECONDARY,
3115 paris_type_find, paris_exts, PARIS_CAPS, NULL, NULL);
3116 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nist", GST_RANK_SECONDARY,
3117 nist_exts, "NIST", 4, GST_TYPE_FIND_MAXIMUM);
3118 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-voc", GST_RANK_SECONDARY,
3119 voc_exts, "Creative", 8, GST_TYPE_FIND_MAXIMUM);
3120 TYPE_FIND_REGISTER (plugin, "audio/x-sds", GST_RANK_SECONDARY, sds_type_find,
3121 sds_exts, SDS_CAPS, NULL, NULL);
3122 TYPE_FIND_REGISTER (plugin, "audio/x-ircam", GST_RANK_SECONDARY,
3123 ircam_type_find, ircam_exts, IRCAM_CAPS, NULL, NULL);
3124 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-w64", GST_RANK_SECONDARY,
3125 w64_exts, "riff", 4, GST_TYPE_FIND_MAXIMUM);
3126 TYPE_FIND_REGISTER (plugin, "audio/x-shorten", GST_RANK_SECONDARY,
3127 shn_type_find, shn_exts, SHN_CAPS, NULL, NULL);
3128 TYPE_FIND_REGISTER (plugin, "application/x-ape", GST_RANK_SECONDARY,
3129 ape_type_find, ape_exts, APE_CAPS, NULL, NULL);
3130 TYPE_FIND_REGISTER (plugin, "image/jpeg", GST_RANK_PRIMARY + 15,
3131 jpeg_type_find, jpeg_exts, JPEG_CAPS, NULL, NULL);
3132 TYPE_FIND_REGISTER_START_WITH (plugin, "image/gif", GST_RANK_PRIMARY,
3133 gif_exts, "GIF8", 4, GST_TYPE_FIND_MAXIMUM);
3134 TYPE_FIND_REGISTER_START_WITH (plugin, "image/png", GST_RANK_PRIMARY + 14,
3135 png_exts, "\211PNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3136 TYPE_FIND_REGISTER (plugin, "image/bmp", GST_RANK_PRIMARY, bmp_type_find,
3137 bmp_exts, BMP_CAPS, NULL, NULL);
3138 TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find,
3139 tiff_exts, TIFF_CAPS, NULL, NULL);
3140 TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY,
3141 matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL);
3142 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY,
3143 mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
3144 GST_TYPE_FIND_MAXIMUM);
3145 TYPE_FIND_REGISTER (plugin, "video/x-dv", GST_RANK_SECONDARY, dv_type_find,
3146 dv_exts, DV_CAPS, NULL, NULL);
3147 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-nb-sh", GST_RANK_PRIMARY,
3148 amr_exts, "#!AMR", 5, GST_TYPE_FIND_LIKELY);
3149 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-wb-sh", GST_RANK_PRIMARY,
3150 amr_exts, "#!AMR-WB", 7, GST_TYPE_FIND_MAXIMUM);
3151 TYPE_FIND_REGISTER (plugin, "audio/iLBC-sh", GST_RANK_PRIMARY,
3152 ilbc_type_find, ilbc_exts, ILBC_CAPS, NULL, NULL);
3153 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-sid", GST_RANK_MARGINAL,
3154 sid_exts, "PSID", 4, GST_TYPE_FIND_MAXIMUM);
3155 TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xcf", GST_RANK_SECONDARY,
3156 xcf_exts, "gimp xcf", 8, GST_TYPE_FIND_MAXIMUM);
3157 TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mng", GST_RANK_SECONDARY,
3158 mng_exts, "\212MNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3159 TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-jng", GST_RANK_SECONDARY,
3160 jng_exts, "\213JNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM);
3161 TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xpixmap", GST_RANK_SECONDARY,
3162 xpm_exts, "/* XPM */", 9, GST_TYPE_FIND_MAXIMUM);
3163 TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-sun-raster",
3164 GST_RANK_SECONDARY, ras_exts, "\131\246\152\225", 4,
3165 GST_TYPE_FIND_MAXIMUM);
3166 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-bzip",
3167 GST_RANK_SECONDARY, bz2_exts, "BZh", 3, GST_TYPE_FIND_LIKELY);
3168 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-gzip",
3169 GST_RANK_SECONDARY, gz_exts, "\037\213", 2, GST_TYPE_FIND_LIKELY);
3170 TYPE_FIND_REGISTER_START_WITH (plugin, "application/zip", GST_RANK_SECONDARY,
3171 zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY);
3172 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress",
3173 GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY);
3174 TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY,
3175 flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL);
3176 TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY,
3177 vorbis_type_find, NULL, VORBIS_CAPS, NULL, NULL);
3178 TYPE_FIND_REGISTER (plugin, "video/x-theora", GST_RANK_PRIMARY,
3179 theora_type_find, NULL, THEORA_CAPS, NULL, NULL);
3180 TYPE_FIND_REGISTER (plugin, "application/x-ogm-video", GST_RANK_PRIMARY,
3181 ogmvideo_type_find, NULL, OGMVIDEO_CAPS, NULL, NULL);
3182 TYPE_FIND_REGISTER (plugin, "application/x-ogm-audio", GST_RANK_PRIMARY,
3183 ogmaudio_type_find, NULL, OGMAUDIO_CAPS, NULL, NULL);
3184 TYPE_FIND_REGISTER (plugin, "application/x-ogm-text", GST_RANK_PRIMARY,
3185 ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL);
3186 TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY,
3187 speex_type_find, NULL, SPEEX_CAPS, NULL, NULL);
3188 TYPE_FIND_REGISTER (plugin, "audio/x-celt", GST_RANK_PRIMARY,
3189 celt_type_find, NULL, CELT_CAPS, NULL, NULL);
3190 TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY,
3191 oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL);
3192 TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find,
3193 NULL, CMML_CAPS, NULL, NULL);
3194 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-executable",
3195 GST_RANK_MARGINAL, NULL, "\177ELF", 4, GST_TYPE_FIND_MAXIMUM);
3196 TYPE_FIND_REGISTER (plugin, "adts_mpeg_stream", GST_RANK_SECONDARY,
3197 aac_type_find, aac_exts, AAC_CAPS, NULL, NULL);
3198 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-spc", GST_RANK_SECONDARY,
3199 spc_exts, "SNES-SPC700 Sound File Data", 27, GST_TYPE_FIND_MAXIMUM);
3200 TYPE_FIND_REGISTER (plugin, "audio/x-wavpack", GST_RANK_SECONDARY,
3201 wavpack_type_find, wavpack_exts, WAVPACK_CAPS, NULL, NULL);
3202 TYPE_FIND_REGISTER (plugin, "audio/x-wavpack-correction", GST_RANK_SECONDARY,
3203 wavpack_type_find, wavpack_correction_exts, WAVPACK_CORRECTION_CAPS, NULL,
3205 TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-rar",
3206 GST_RANK_SECONDARY, rar_exts, "Rar!", 4, GST_TYPE_FIND_LIKELY);
3207 TYPE_FIND_REGISTER (plugin, "application/x-tar", GST_RANK_SECONDARY,
3208 tar_type_find, tar_exts, TAR_CAPS, NULL, NULL);
3209 TYPE_FIND_REGISTER (plugin, "application/x-ar", GST_RANK_SECONDARY,
3210 ar_type_find, ar_exts, AR_CAPS, NULL, NULL);
3211 TYPE_FIND_REGISTER (plugin, "application/x-ms-dos-executable",
3212 GST_RANK_SECONDARY, msdos_type_find, msdos_exts, MSDOS_CAPS, NULL, NULL);
3213 TYPE_FIND_REGISTER (plugin, "video/x-dirac", GST_RANK_PRIMARY,
3214 dirac_type_find, NULL, DIRAC_CAPS, NULL, NULL);
3215 TYPE_FIND_REGISTER (plugin, "multipart/x-mixed-replace", GST_RANK_SECONDARY,
3216 multipart_type_find, NULL, MULTIPART_CAPS, NULL, NULL);
3217 TYPE_FIND_REGISTER (plugin, "application/x-mmsh", GST_RANK_SECONDARY,
3218 mmsh_type_find, NULL, MMSH_CAPS, NULL, NULL);
3219 TYPE_FIND_REGISTER (plugin, "video/vivo", GST_RANK_SECONDARY,
3220 vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL);
3221 TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf",
3222 GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM);
3226 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
3228 "typefindfunctions",
3229 "default typefind functions",
3230 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)