typefinding: more fine-grained ogg typefinding

Typefind to audio/ogg, video/ogg, etc. Also change
application/x-annodex to application/annodex.

See http://wiki.xiph.org/MIME_Types_and_File_Extensions
This commit is contained in:
Tim-Philipp Müller 2012-04-15 22:32:06 +01:00
parent 66615a8a6a
commit 497d87061d

View file

@ -3589,30 +3589,124 @@ dv_type_find (GstTypeFind * tf, gpointer private)
}
/*** application/ogg and application/x-annodex ***/
static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg");
static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex");
/*** Ogg and Annodex variants ***/
static GstStaticCaps ogg_annodex_caps =
GST_STATIC_CAPS ("application/ogg;application/x-annodex");
GST_STATIC_CAPS ("application/ogg;video/ogg;audio/ogg;"
"application/annodex;audio/annodex;video/annodex;application/kate");
#define OGGANX_CAPS (gst_static_caps_get(&ogg_annodex_caps))
typedef enum
{
OGG_AUDIO = 0,
OGG_VIDEO,
OGG_KATE,
OGG_OTHER,
OGG_SKELETON,
OGG_ANNODEX,
OGG_NUM
} GstOggStreamType;
static void
ogganx_type_find (GstTypeFind * tf, gpointer private)
{
const guint8 *data = gst_type_find_peek (tf, 0, 4);
const gchar *media_type;
DataScanCtx c = { 0, NULL, 0 };
guint ogg_syncs = 0;
guint hdr_count[OGG_NUM] = { 0, };
static const struct
{
const gchar marker[10];
guint8 marker_size;
GstOggStreamType stream_type;
} markers[] = {
{
"\001vorbis", 7, OGG_AUDIO}, {
"\200theora", 7, OGG_VIDEO}, {
"fLaC", 4, OGG_AUDIO}, {
"\177FLAC", 5, OGG_AUDIO}, {
"Speex", 5, OGG_AUDIO}, {
"CMML\0\0\0\0", 8, OGG_OTHER}, {
"PCM ", 8, OGG_AUDIO}, {
"Annodex", 7, OGG_ANNODEX}, {
"fishead", 7, OGG_SKELETON}, {
"AnxData", 7, OGG_ANNODEX}, {
"CELT ", 8, OGG_AUDIO}, {
"\200kate\0\0\0", 8, OGG_KATE}, {
"BBCD\0", 5, OGG_VIDEO}, {
"OVP80\1\1", 7, OGG_VIDEO}, {
"OpusHead", 8, OGG_AUDIO}, {
"\001audio\0\0\0", 9, OGG_AUDIO}, {
"\001video\0\0\0", 9, OGG_VIDEO}, {
"\001text\0\0\0", 9, OGG_OTHER}
};
if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) {
while (c.offset < 4096 && data_scan_ctx_ensure_data (tf, &c, 64)) {
guint size, i;
/* Check for an annodex fishbone header */
data = gst_type_find_peek (tf, 28, 8);
if (data && memcmp (data, "fishead\0", 8) == 0)
gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
gst_static_caps_get (&annodex_caps));
if (memcmp (c.data, "OggS", 5) != 0)
break;
gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
gst_static_caps_get (&ogg_caps));
++ogg_syncs;
/* check if BOS */
if (c.data[5] != 0x02)
break;
/* headers should only have one segment */
if (c.data[26] != 1)
break;
size = c.data[27];
if (size < 8)
break;
data_scan_ctx_advance (tf, &c, 28);
if (!data_scan_ctx_ensure_data (tf, &c, MAX (size, 8)))
break;
for (i = 0; i < G_N_ELEMENTS (markers); ++i) {
if (memcmp (c.data, markers[i].marker, markers[i].marker_size) == 0) {
++hdr_count[markers[i].stream_type];
break;
}
}
if (i == G_N_ELEMENTS (markers)) {
GST_MEMDUMP ("unknown Ogg stream marker", c.data, size);
++hdr_count[OGG_OTHER];
}
data_scan_ctx_advance (tf, &c, size);
}
if (ogg_syncs == 0)
return;
/* FIXME: what about XSPF? */
if (hdr_count[OGG_ANNODEX] > 0) {
if (hdr_count[OGG_VIDEO] > 0)
media_type = "video/annodex";
else if (hdr_count[OGG_AUDIO] > 0)
media_type = "audio/annodex";
else
media_type = "application/annodex";
} else if (hdr_count[OGG_VIDEO] > 0) {
media_type = "video/ogg";
} else if (hdr_count[OGG_AUDIO] > 0) {
media_type = "audio/ogg";
} else if (hdr_count[OGG_KATE] > 0 && hdr_count[OGG_OTHER] == 0) {
media_type = "application/kate";
} else {
media_type = "application/ogg";
}
GST_INFO ("found %s (audio:%u, video:%u, annodex:%u, skeleton:%u, other:%u)",
media_type, hdr_count[OGG_AUDIO], hdr_count[OGG_VIDEO],
hdr_count[OGG_ANNODEX], hdr_count[OGG_SKELETON], hdr_count[OGG_OTHER]);
gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, media_type, NULL);
}
/*** audio/x-vorbis ***/
@ -4455,7 +4549,8 @@ plugin_init (GstPlugin * plugin)
TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
mpeg_ts_type_find, "ts,mts", MPEGTS_CAPS, NULL, NULL);
TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
ogganx_type_find, "anx,ogg,ogm", OGGANX_CAPS, NULL, NULL);
ogganx_type_find, "ogg,oga,ogv,ogm,ogx,spx,anx,axa,axv", OGGANX_CAPS,
NULL, NULL);
TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL,
mpeg_video_stream_type_find, "mpv,mpeg,mpg", MPEG_VIDEO_CAPS, NULL, NULL);
TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY,