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); |
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 |
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 */ |
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])) |
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 |
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); |
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)) |
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, |