mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
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:
parent
66615a8a6a
commit
497d87061d
1 changed files with 109 additions and 14 deletions
|
@ -3589,32 +3589,126 @@ 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 ***/
|
||||
static GstStaticCaps vorbis_caps = GST_STATIC_CAPS ("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,
|
||||
|
|
Loading…
Reference in a new issue