From a7bba83ded997f15e4e8851fecd7c229bbcd385d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 1 May 2024 18:05:35 +0300 Subject: [PATCH] typefind: Add typefinders for formats that were previously available via ffmpeg Co-Authored-By: Matthew Waters Part-of: --- .../gst-docs/symbols/symbol_index.json | 1 + .../gst-libav/docs/gst_plugins_cache.json | 45 +- .../gst-libav/ext/libav/gstavcodecmap.c | 48 ++ .../gst/typefind/gsttypefindfunctions.c | 734 ++++++++++++++++++ .../gst/typefind/gsttypefindfunctionsplugin.c | 10 + .../gst/typefind/gsttypefindfunctionsplugin.h | 24 + .../gst/typefind/gsttypefindfunctionsriff.c | 4 + .../typefind/gsttypefindfunctionsstartwith.c | 4 + 8 files changed, 850 insertions(+), 20 deletions(-) diff --git a/subprojects/gst-docs/symbols/symbol_index.json b/subprojects/gst-docs/symbols/symbol_index.json index fd704e74cd..2690a4b33b 100644 --- a/subprojects/gst-docs/symbols/symbol_index.json +++ b/subprojects/gst-docs/symbols/symbol_index.json @@ -34154,6 +34154,7 @@ "avmux_f4v:maxdelay", "avmux_f4v:preload", "avmux_film_cpk", + "avmux_film_cpk!audio_%u", "avmux_film_cpk!src", "avmux_film_cpk!video_%u", "avmux_film_cpk:maxdelay", diff --git a/subprojects/gst-libav/docs/gst_plugins_cache.json b/subprojects/gst-libav/docs/gst_plugins_cache.json index da3e728cba..c2bd322857 100644 --- a/subprojects/gst-libav/docs/gst_plugins_cache.json +++ b/subprojects/gst-libav/docs/gst_plugins_cache.json @@ -27140,7 +27140,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-avs:\n", + "caps": "video/x-avs:\n", "direction": "sink", "presence": "always" }, @@ -27268,7 +27268,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-dsf:\n", + "caps": "audio/x-dsf:\n", "direction": "sink", "presence": "always" }, @@ -27300,7 +27300,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-ea:\n", + "caps": "video/x-ea:\n", "direction": "sink", "presence": "always" }, @@ -27332,7 +27332,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-film_cpk:\n", + "caps": "video/x-film-cpk:\n", "direction": "sink", "presence": "always" }, @@ -27428,7 +27428,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-idcin:\n", + "caps": "video/x-idcin:\n", "direction": "sink", "presence": "always" }, @@ -27460,7 +27460,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-iff:\n", + "caps": "application/x-iff:\n", "direction": "sink", "presence": "always" }, @@ -27492,7 +27492,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-ipmovie:\n", + "caps": "video/x-ipmovie:\n", "direction": "sink", "presence": "always" }, @@ -27556,7 +27556,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-mm:\n", + "caps": "application/x-mm:\n", "direction": "sink", "presence": "always" }, @@ -27588,7 +27588,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-mmf:\n", + "caps": "application/vnd.smaf:\n", "direction": "sink", "presence": "always" }, @@ -27748,7 +27748,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-nut:\n", + "caps": "application/x-nut:\n", "direction": "sink", "presence": "always" }, @@ -27876,7 +27876,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-smk:\n", + "caps": "application/x-smk:\n", "direction": "sink", "presence": "always" }, @@ -27908,7 +27908,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-sol:\n", + "caps": "application/x-sol:\n", "direction": "sink", "presence": "always" }, @@ -27972,7 +27972,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-vmd:\n", + "caps": "application/x-vmd:\n", "direction": "sink", "presence": "always" }, @@ -28036,7 +28036,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-wc3movie:\n", + "caps": "application/x-wc3movie:\n", "direction": "sink", "presence": "always" }, @@ -28068,7 +28068,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-wsaud:\n", + "caps": "application/x-wsaud:\n", "direction": "sink", "presence": "always" }, @@ -28100,7 +28100,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-wsvqa:\n", + "caps": "application/x-wsvqa:\n", "direction": "sink", "presence": "always" }, @@ -28132,7 +28132,7 @@ "presence": "sometimes" }, "sink": { - "caps": "application/x-gst-av-xwma:\n", + "caps": "audio/x-xwma:\n", "direction": "sink", "presence": "always" }, @@ -137075,8 +137075,13 @@ "klass": "Codec/Muxer", "long-name": "libav Sega FILM / CPK muxer", "pad-templates": { + "audio_%%u": { + "caps": "audio/x-raw:\n channels: [ 1, 2 ]\n rate: [ 4000, 96000 ]\n format: S16BE\n layout: interleaved\n", + "direction": "sink", + "presence": "request" + }, "src": { - "caps": "application/x-gst-av-film_cpk:\n", + "caps": "video/x-film-cpk:\n", "direction": "src", "presence": "always" }, @@ -138227,7 +138232,7 @@ "presence": "request" }, "src": { - "caps": "application/x-gst-av-mmf:\n", + "caps": "application/vnd.smaf:\n", "direction": "src", "presence": "always" } @@ -138911,7 +138916,7 @@ "long-name": "libav NUT muxer", "pad-templates": { "src": { - "caps": "application/x-gst-av-nut:\n", + "caps": "application/x-nut:\n", "direction": "src", "presence": "always" }, diff --git a/subprojects/gst-libav/ext/libav/gstavcodecmap.c b/subprojects/gst-libav/ext/libav/gstavcodecmap.c index c9c0a0fa77..9176bb1952 100644 --- a/subprojects/gst-libav/ext/libav/gstavcodecmap.c +++ b/subprojects/gst-libav/ext/libav/gstavcodecmap.c @@ -3833,6 +3833,42 @@ gst_ffmpeg_formatid_to_caps (const gchar * format_name) caps = gst_caps_from_string ("audio/x-brstm"); } else if (!strcmp (format_name, "bfstm")) { caps = gst_caps_from_string ("audio/x-bfstm"); + } else if (!strcmp (format_name, "avs")) { + caps = gst_caps_from_string ("video/x-avs"); + } else if (!strcmp (format_name, "dsf")) { + caps = gst_caps_from_string ("audio/x-dsf"); + } else if (!strcmp (format_name, "ea")) { + caps = gst_caps_from_string ("video/x-ea"); + } else if (!strcmp (format_name, "film_cpk")) { + caps = gst_caps_from_string ("video/x-film-cpk"); + } else if (!strcmp (format_name, "xwma")) { + caps = gst_caps_from_string ("audio/x-xwma"); + } else if (!strcmp (format_name, "iff")) { + caps = gst_caps_from_string ("application/x-iff"); + } else if (!strcmp (format_name, "idcin")) { + caps = gst_caps_new_empty_simple ("video/x-idcin"); + } else if (!strcmp (format_name, "ipmovie")) { + caps = gst_caps_new_empty_simple ("video/x-ipmovie"); + } else if (!strcmp (format_name, "mm")) { + caps = gst_caps_new_empty_simple ("application/x-mm"); + } else if (!strcmp (format_name, "mmf")) { + caps = gst_caps_new_empty_simple ("application/vnd.smaf"); + } else if (!strcmp (format_name, "nut")) { + caps = gst_caps_new_empty_simple ("application/x-nut"); + } else if (!strcmp (format_name, "pxstr")) { + caps = gst_caps_new_empty_simple ("application/x-pxstr"); + } else if (!strcmp (format_name, "smk")) { + caps = gst_caps_new_empty_simple ("application/x-smk"); + } else if (!strcmp (format_name, "sol")) { + caps = gst_caps_new_empty_simple ("application/x-sol"); + } else if (!strcmp (format_name, "vmd")) { + caps = gst_caps_new_empty_simple ("application/x-vmd"); + } else if (!strcmp (format_name, "wc3movie")) { + caps = gst_caps_new_empty_simple ("application/x-wc3movie"); + } else if (!strcmp (format_name, "wsaud")) { + caps = gst_caps_new_empty_simple ("application/x-wsaud"); + } else if (!strcmp (format_name, "wsvqa")) { + caps = gst_caps_new_empty_simple ("application/x-wsvqa"); } else { gchar *name; @@ -4029,6 +4065,18 @@ gst_ffmpeg_formatid_get_codecids (const gchar * format_name, *video_codec_list = ivf_video_list; *audio_codec_list = ivf_audio_list; + } else if ((!strcmp (format_name, "film_cpk"))) { + static enum AVCodecID cpk_video_list[] = { + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_NONE + }; + static enum AVCodecID cpk_audio_list[] = { + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_NONE + }; + + *video_codec_list = cpk_video_list; + *audio_codec_list = cpk_audio_list; } else if ((plugin->audio_codec != AV_CODEC_ID_NONE) || (plugin->video_codec != AV_CODEC_ID_NONE)) { tmp_vlist[0] = plugin->video_codec; diff --git a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctions.c b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctions.c index 805cb0a301..f7f7f75bb7 100644 --- a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctions.c +++ b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctions.c @@ -5512,6 +5512,699 @@ tap_type_find (GstTypeFind * tf, gpointer unused) } } +/*** audio/x-brstm ***/ + +static GstStaticCaps brstm_caps = GST_STATIC_CAPS ("audio/x-brstm"); + +#define BRSTM_CAPS (gst_static_caps_get(&brstm_caps)) +static void +brstm_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + if (GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('R', 'S', 'T', 'M')) + return; + if (GST_READ_UINT32_LE (data + 4) != 0xfffe + && GST_READ_UINT32_LE (data + 4) != 0xfeff) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, BRSTM_CAPS); + } +} + +/*** audio/x-bfstm ***/ + +static GstStaticCaps bfstm_caps = GST_STATIC_CAPS ("audio/x-bfstm"); + +#define BFSTM_CAPS (gst_static_caps_get(&bfstm_caps)) +static void +bfstm_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + if (GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('F', 'S', 'T', 'M') && + GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('C', 'S', 'T', 'M')) + return; + if (GST_READ_UINT32_LE (data + 4) != 0xfffe + && GST_READ_UINT32_LE (data + 4) != 0xfeff) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, BFSTM_CAPS); + } +} + +/*** audio/x-dsf ***/ + +static GstStaticCaps dsf_caps = GST_STATIC_CAPS ("audio/x-dsf"); + +#define DSF_CAPS (gst_static_caps_get(&dsf_caps)) +static void +dsf_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 12); + + if (data) { + if (memcmp (data, "DSD ", 4) != 0) + return; + if (GST_READ_UINT64_BE (data + 4) == 28) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DSF_CAPS); + } +} + +/*** video/x-ea ***/ + +static GstStaticCaps ea_caps = GST_STATIC_CAPS ("video/x-ea"); + +#define EA_CAPS (gst_static_caps_get(&ea_caps)) +static void +ea_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + static const guint32 ea_fourccs[] = { + GST_MAKE_FOURCC ('I', 'S', 'N', 'h'), + GST_MAKE_FOURCC ('S', 'C', 'H', 'l'), + GST_MAKE_FOURCC ('S', 'E', 'A', 'D'), + GST_MAKE_FOURCC ('S', 'H', 'E', 'N'), + GST_MAKE_FOURCC ('k', 'V', 'G', 'T'), + GST_MAKE_FOURCC ('M', 'A', 'D', 'k'), + GST_MAKE_FOURCC ('M', 'P', 'C', 'h'), + GST_MAKE_FOURCC ('M', 'V', 'h', 'd'), + GST_MAKE_FOURCC ('M', 'V', 'I', 'h'), + GST_MAKE_FOURCC ('A', 'V', 'P', '6'), + }; + + guint32 fourcc = GST_READ_UINT32_LE (data); + gboolean found = FALSE; + + for (gsize i = 0; i < G_N_ELEMENTS (ea_fourccs); i++) { + if (fourcc == ea_fourccs[i]) { + found = TRUE; + break; + } + } + if (!found) + return; + + guint32 size = GST_READ_UINT32_LE (data + 4); + gboolean big_endian = size > 0x000fffff; + if (big_endian) + size = GUINT32_SWAP_LE_BE (size); + if (size > 0xfffff || size < 8) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, EA_CAPS); + } +} + +/*** video/x-film-cpk ***/ + +static GstStaticCaps film_cpk_caps = GST_STATIC_CAPS ("video/x-film-cpk"); + +#define FILM_CPK_CAPS (gst_static_caps_get(&film_cpk_caps)) +static void +film_cpk_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 20); + + if (data) { + if (GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('F', 'I', 'L', 'M')) + return; + if (GST_READ_UINT32_LE (data + 16) != GST_MAKE_FOURCC ('F', 'D', 'S', 'C')) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FILM_CPK_CAPS); + } +} + +/*** application/gxf ***/ + +static GstStaticCaps gxf_caps = GST_STATIC_CAPS ("application/gxf"); + +#define GXF_CAPS (gst_static_caps_get(&gxf_caps)) +static void +gxf_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 16); + + if (data) { + if (memcmp (data, "\x00\x00\x00\x00\x01\xbc", 6) != 0) + return; + if (memcmp (data + 10, "\x00\x00\x00\x00\xe1\xe2", 6) != 0) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, GXF_CAPS); + } +} + +/*** application/x-iff ***/ + +static GstStaticCaps iff_caps = GST_STATIC_CAPS ("application/x-iff"); + +#define IFF_CAPS (gst_static_caps_get(&iff_caps)) +static void +iff_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 16); + + if (data) { + if (GST_READ_UINT32_LE (data) == GST_MAKE_FOURCC ('F', 'O', 'R', 'M') && + (GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('8', 'S', 'V', 'X') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('1', '6', 'S', + 'V') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('M', 'A', 'U', + 'D') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('P', 'B', 'M', + ' ') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('A', 'C', 'B', + 'M') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('D', 'E', 'E', + 'P') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('I', 'L', 'B', + 'M') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('R', 'G', 'B', + '8') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('A', 'N', 'I', + 'M') + || GST_READ_UINT32_LE (data + 8) == GST_MAKE_FOURCC ('R', 'G', 'B', + 'N'))) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, IFF_CAPS); + return; + } + + if (GST_READ_UINT32_LE (data) == GST_MAKE_FOURCC ('F', 'R', 'M', '8') + && GST_READ_UINT32_LE (data + 12) == GST_MAKE_FOURCC ('D', 'S', 'D', + ' ')) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, IFF_CAPS); + return; + } + } +} + +/*** video/x-idcin ***/ + +static GstStaticCaps idcin_caps = GST_STATIC_CAPS ("video/x-idcin"); + +#define IDCIN_CAPS (gst_static_caps_get(&idcin_caps)) +static void +idcin_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 20 + 64 * 1024 + 4); + if (!data) + return; + + // See ffmpeg/libavformat/idcin.c:idcin_probe() for details + + guint number, sample_rate; + guint w, h; + gint i; + + w = GST_READ_UINT32_LE (data); + if (w == 0 || w > 1024) + return; + + h = GST_READ_UINT32_LE (data + 4); + if (h == 0 || h > 1024) + return; + + sample_rate = GST_READ_UINT32_LE (data + 8); + if (sample_rate && (sample_rate < 8000 || sample_rate > 48000)) + return; + + number = GST_READ_UINT32_LE (data + 12); + if (number > 2 || (sample_rate && !number)) + return; + + number = GST_READ_UINT32_LE (data + 16); + if (number > 2 || (sample_rate && !number)) + return; + + i = 20 + 64 * 1024; + if (GST_READ_UINT32_LE (data + i) == 1) + i += 768; + + data = gst_type_find_peek (tf, 0, 20 + 64 * 1024 + 768 + 12); + if (!data) + return; + + if (GST_READ_UINT32_LE (data + i + 8) != w * h) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, IDCIN_CAPS); +} + +/*** video/x-idcin ***/ + +static GstStaticCaps mm_caps = GST_STATIC_CAPS ("application/x-mm"); + +#define MM_CAPS (gst_static_caps_get(&mm_caps)) +static void +mm_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 24 + 6); + if (!data) + return; + + // See ffmpeg/libavformat/mm.c:probe() for details + gint len, type, fps, w, h; + + if (GST_READ_UINT16_LE (&data[0]) != 0x00) + return; + len = GST_READ_UINT32_LE (&data[2]); + if (len != 22 && len != 24) + return; + fps = GST_READ_UINT16_LE (&data[8]); + w = GST_READ_UINT16_LE (&data[12]); + h = GST_READ_UINT16_LE (&data[14]); + if (!fps || fps > 60 || !w || w > 2048 || !h || h > 2048) + return; + type = GST_READ_UINT16_LE (&data[len]); + if (!type || type > 0x31) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, MM_CAPS); +} + +/*** video/x-ipmovie ***/ + +static GstStaticCaps ipmovie_caps = GST_STATIC_CAPS ("video/x-ipmovie"); + +#define IPMOVIE_CAPS (gst_static_caps_get(&ipmovie_caps)) +static void +ipmovie_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 4096) + length = 4096; + + static const char signature[] = "Interplay MVE File\x1A\0\x1A"; + if (length < sizeof (signature)) + return; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + for (gsize i = 0; i < length - sizeof (signature); i++) { + if (memcmp (data + i, signature, sizeof (signature)) != 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, IPMOVIE_CAPS); + return; + } + } +} + +/*** application/vnd.smaf ***/ + +static GstStaticCaps mmf_caps = GST_STATIC_CAPS ("application/vnd.smaf"); + +#define MMF_CAPS (gst_static_caps_get(&mmf_caps)) +static void +mmf_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data = gst_type_find_peek (tf, 0, 12); + if (!data) + return; + + if (data[0] == 'M' && data[1] == 'M' && + data[2] == 'M' && data[3] == 'D' && + data[8] == 'C' && data[9] == 'N' && data[10] == 'T' && data[11] == 'I') + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMF_CAPS); +} + +/*** video/x-nsv ***/ + +static GstStaticCaps nsv_caps = GST_STATIC_CAPS ("video/x-nsv"); + +#define NSV_CAPS (gst_static_caps_get(&nsv_caps)) +static void +nsv_type_find (GstTypeFind * tf, gpointer unused) +{ + static const guint8 marker[4] = { 'N', 'S', 'V', 's', }; + const guint8 *data; + guint64 length; + gsize i; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 4096) + length = 4096; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 4) + return; + + if (data[0] == 'N' && data[1] == 'S' && + data[2] == 'V' && (data[3] == 'f' || data[3] == 's')) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, NSV_CAPS); + return; + } + + if (length < 24) + return; + + for (i = 1; i < length - 23; i++) { + if (memcmp (&data[i], marker, sizeof (marker)) == 0) { + gsize offset = i + 23; + if (offset < length) { + guint32 vsize = GST_READ_UINT24_LE (&data[i + 19]) >> 4; + guint32 asize = GST_READ_UINT16_LE (&data[i + 22]) >> 4; + offset += asize + vsize; + if (offset + 1 < length && GST_READ_UINT16_LE (&data[offset]) == 0xBEEF) { + gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, NSV_CAPS); + return; + } + } + gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, NSV_CAPS); + return; + } + } +} + +/*** application/x-nut ***/ + +static GstStaticCaps nut_caps = GST_STATIC_CAPS ("application/x-nut"); + +#define NUT_CAPS (gst_static_caps_get(&nut_caps)) +static void +nut_type_find (GstTypeFind * tf, gpointer unused) +{ + guint64 marker = (0x7A561F5F04ADULL + (((guint64) ('N' << 8) + 'M') << 48)); + const guint8 *data; + guint64 length; + gsize i; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 4096) + length = 4096; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 8) + return; + + for (i = 0; i < length - 8; i++) { + if (GST_READ_UINT64_BE (&data[i]) == marker) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, NUT_CAPS); + return; + } + } +} + +/*** application/x-pxstr ***/ + +static GstStaticCaps pxstr_caps = GST_STATIC_CAPS ("application/x-pxstr"); + +#define PXSTR_CAPS (gst_static_caps_get(&pxstr_caps)) +static void +pxstr_type_find (GstTypeFind * tf, gpointer unused) +{ + static const guint8 sync_header[] = + { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00 + }; + static const gsize raw_cd_sector_size = 2352; + const guint8 *data; + guint64 length; + int n_vid = 0, n_aud = 0; + gsize i; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > raw_cd_sector_size * 5) + length = raw_cd_sector_size * 5; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 12) + return; + + if (GST_READ_UINT32_LE (data) == GST_MAKE_FOURCC ('R', 'I', 'F', 'F') + && GST_READ_UINT32_LE (&data[8]) == GST_MAKE_FOURCC ('C', 'D', 'X', 'A')) { + length -= 0x2C; + data = &data[0x2C]; + } + + // minimum CD sector size + if (length < raw_cd_sector_size) + return; + + for (i = 0; i < length;) { + if (length - i > 0x25) + break; + + if (memcmp (&data[i], sync_header, sizeof (sync_header)) != 0) + return; + + if (data[i + 0x11] >= 32) + return; + + switch (data[i + 0x12] & 0x0E) { + /* data and video */ + case 0x08: + case 0x02:{ + gint16 current_sector = (gint16) GST_READ_UINT16_LE (&data[i + 0x1C]); + gint16 sector_count = (gint16) GST_READ_UINT16_LE (&data[i + 0x1E]); + gint16 frame_size = (gint16) GST_READ_UINT16_LE (&data[i + 0x24]); + + if (!(frame_size > 0 + && current_sector < sector_count + && sector_count * 0x780 >= frame_size)) + return; + + n_vid++; + break; + } + /* audio */ + case 0x04:{ + if (data[i + 0x13] & 0x2A) + return; + n_aud++; + break; + } + default: + if (data[i + 0x12] & 0x0E) + return; + break; + } + i += raw_cd_sector_size; + } + + if (n_aud + n_vid > 3) + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, PXSTR_CAPS); + else if (n_aud + n_vid) + gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, PXSTR_CAPS); +} + +/*** application/x-smk ***/ + +static GstStaticCaps smk_caps = GST_STATIC_CAPS ("application/x-smk"); + +#define SMK_CAPS (gst_static_caps_get(&smk_caps)) +static void +smk_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 12) + length = 12; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 12) + return; + + if (GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('S', 'M', 'K', '2') + && GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('S', 'M', 'K', '4')) { + return; + } + + if (GST_READ_UINT32_LE (&data[4]) > 32768 + || GST_READ_UINT32_LE (&data[8]) > 32768) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, SMK_CAPS); + } else { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SMK_CAPS); + } +} + +/*** application/x-sol ***/ + +static GstStaticCaps sol_caps = GST_STATIC_CAPS ("application/x-sol"); + +#define SOL_CAPS (gst_static_caps_get(&sol_caps)) +static void +sol_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + guint16 magic; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 8) + length = 8; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 8) + return; + + magic = (guint16) GST_READ_UINT32_LE (data); + if (magic != 0x0b8d && magic != 0x0c0d && magic != 0x0c8d) + return; + + if (GST_READ_UINT32_BE (&data[4]) != GST_MAKE_FOURCC ('S', 'O', 'L', 0)) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SOL_CAPS); +} + +/*** application/x-vmd ***/ + +static GstStaticCaps vmd_caps = GST_STATIC_CAPS ("application/x-vmd"); + +#define VMD_CAPS (gst_static_caps_get(&vmd_caps)) +static void +vmd_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + int w, h, rate; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 806) + length = 806; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 806) + return; + + if (GST_READ_UINT16_LE (data) != 0x0330 - 2) + return; + + w = GST_READ_UINT16_LE (&data[12]); + h = GST_READ_UINT16_LE (&data[14]); + rate = GST_READ_UINT16_LE (&data[804]); + if ((!w || w > 2048 || !h || h > 2048) + && rate != 22050) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, VMD_CAPS); +} + +/*** application/x-wc3movie ***/ + +static GstStaticCaps wc3movie_caps = GST_STATIC_CAPS ("application/x-wc3movie"); + +#define WC3MOVIE_CAPS (gst_static_caps_get(&wc3movie_caps)) +static void +wc3movie_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 12) + length = 12; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 12) + return; + + if (GST_READ_UINT32_LE (data) != GST_MAKE_FOURCC ('F', 'O', 'R', 'M') + || GST_READ_UINT32_LE (&data[8]) != GST_MAKE_FOURCC ('M', 'O', 'V', 'E')) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, WC3MOVIE_CAPS); +} + +/*** application/x-wsaud ***/ + +static GstStaticCaps wsaud_caps = GST_STATIC_CAPS ("application/x-wsaud"); + +#define WSAUD_CAPS (gst_static_caps_get(&wsaud_caps)) +static void +wsaud_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + int rate; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 20) + length = 20; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 20) + return; + + rate = GST_READ_UINT16_LE (data); + if (rate < 8000 || rate > 48000) + return; + + if (data[10] & 0xfc) + return; + + if (data[11] != 99 && data[11] != 1) + return; + + if (GST_READ_UINT32_LE (&data[16]) != 0x0000DEAF) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, WSAUD_CAPS); +} + +/*** application/x-wsvqa ***/ + +static GstStaticCaps wsvqa_caps = GST_STATIC_CAPS ("application/x-wsvqa"); + +#define WSVQA_CAPS (gst_static_caps_get(&wsvqa_caps)) +static void +wsvqa_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + guint64 length; + + length = gst_type_find_get_length (tf); + if (length == 0 || length > 12) + length = 12; + + data = gst_type_find_peek (tf, 0, length); + if (!data) + return; + + if (length < 12) + return; + + if (GST_READ_UINT32_BE (data) != GST_MAKE_FOURCC ('F', 'O', 'R', 'M') + || GST_READ_UINT32_BE (&data[8]) != GST_MAKE_FOURCC ('W', 'V', 'Q', 'A')) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, WSVQA_CAPS); +} + /*** video/vivo ***/ static GstStaticCaps vivo_caps = GST_STATIC_CAPS ("video/vivo"); @@ -6212,3 +6905,44 @@ GST_TYPE_FIND_REGISTER_DEFINE (aa, "audio/audible", GST_RANK_MARGINAL, aa_type_find, "aa,aax", AA_CAPS, NULL, NULL); GST_TYPE_FIND_REGISTER_DEFINE (tap, "audio/x-tap-tap", GST_RANK_PRIMARY, tap_type_find, "tap", TAP_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (brstm, "audio/x-brstm", GST_RANK_SECONDARY, + brstm_type_find, "brstm", BRSTM_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (bfstm, "audio/x-bfstm", GST_RANK_SECONDARY, + bfstm_type_find, "bfstm,bcstm", BFSTM_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (dsf, "audio/x-dsf", GST_RANK_PRIMARY, + dsf_type_find, NULL, DSF_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (ea, "video/x-ea", GST_RANK_SECONDARY, + ea_type_find, NULL, EA_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (film_cpk, "video/x-film-cpk", GST_RANK_SECONDARY, + film_cpk_type_find, "cpk", FILM_CPK_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (gxf, "application/gxf", GST_RANK_SECONDARY, + gxf_type_find, NULL, GXF_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (iff, "application/x-iff", GST_RANK_SECONDARY, + iff_type_find, NULL, IFF_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (ipmovie, "application/x-ipmovie", + GST_RANK_SECONDARY, ipmovie_type_find, NULL, IPMOVIE_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (idcin, "video/x-idcin", GST_RANK_MARGINAL, + idcin_type_find, NULL, IDCIN_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (mm, "application/x-mm", GST_RANK_MARGINAL, + mm_type_find, NULL, MM_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (mmf, "application/vnd.smaf", GST_RANK_SECONDARY, + mmf_type_find, "mmf", MMF_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (nsv, "video/x-nsv", GST_RANK_MARGINAL, + nsv_type_find, "nsv", NSV_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (nut, "application/x-nut", GST_RANK_MARGINAL, + nut_type_find, "nut", NUT_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (pxstr, "application/x-pxstr", GST_RANK_MARGINAL, + pxstr_type_find, "pxstr", PXSTR_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (smk, "application/x-smk", GST_RANK_MARGINAL, + smk_type_find, "smk", SMK_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (sol, "application/x-sol", GST_RANK_MARGINAL, + sol_type_find, "sol", SOL_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (vmd, "application/x-vmd", GST_RANK_MARGINAL, + vmd_type_find, "vmd", VMD_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (wc3movie, "application/x-wc3movie", + GST_RANK_MARGINAL, wc3movie_type_find, "wc3movie", WC3MOVIE_CAPS, NULL, + NULL); +GST_TYPE_FIND_REGISTER_DEFINE (wsaud, "application/x-wsaud", GST_RANK_MARGINAL, + wsaud_type_find, "wsaud", WSAUD_CAPS, NULL, NULL); +GST_TYPE_FIND_REGISTER_DEFINE (wsvqa, "application/x-wsvqa", GST_RANK_MARGINAL, + wsvqa_type_find, "wsvqa", WSVQA_CAPS, NULL, NULL); diff --git a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.c b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.c index c0e386aa2a..998cfd4cf7 100644 --- a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.c +++ b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.c @@ -42,15 +42,18 @@ plugin_init (GstPlugin * plugin) /* must use strings, macros don't accept initializers */ /*Riff Type find register */ + GST_TYPE_FIND_REGISTER (fourxm, plugin); GST_TYPE_FIND_REGISTER (avi, plugin); GST_TYPE_FIND_REGISTER (qcp, plugin); GST_TYPE_FIND_REGISTER (cdxa, plugin); GST_TYPE_FIND_REGISTER (riff_mid, plugin); GST_TYPE_FIND_REGISTER (wav, plugin); GST_TYPE_FIND_REGISTER (webp, plugin); + GST_TYPE_FIND_REGISTER (xwma, plugin); /*'Start with' Type find register */ GST_TYPE_FIND_REGISTER (asf, plugin); + GST_TYPE_FIND_REGISTER (avs, plugin); GST_TYPE_FIND_REGISTER (vcd, plugin); GST_TYPE_FIND_REGISTER (imelody, plugin); GST_TYPE_FIND_REGISTER (scc, plugin); @@ -203,6 +206,13 @@ plugin_init (GstPlugin * plugin) GST_TYPE_FIND_REGISTER (pva, plugin); GST_TYPE_FIND_REGISTER (aa, plugin); GST_TYPE_FIND_REGISTER (tap, plugin); + GST_TYPE_FIND_REGISTER (brstm, plugin); + GST_TYPE_FIND_REGISTER (bfstm, plugin); + GST_TYPE_FIND_REGISTER (dsf, plugin); + GST_TYPE_FIND_REGISTER (ea, plugin); + GST_TYPE_FIND_REGISTER (film_cpk, plugin); + GST_TYPE_FIND_REGISTER (gxf, plugin); + GST_TYPE_FIND_REGISTER (iff, plugin); return TRUE; } diff --git a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.h b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.h index 0dfbc700b0..f23b99e458 100644 --- a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.h +++ b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsplugin.h @@ -41,9 +41,12 @@ GST_TYPE_FIND_REGISTER_DECLARE (cdxa); GST_TYPE_FIND_REGISTER_DECLARE (riff_mid); GST_TYPE_FIND_REGISTER_DECLARE (wav); GST_TYPE_FIND_REGISTER_DECLARE (webp); +GST_TYPE_FIND_REGISTER_DECLARE (fourxm); +GST_TYPE_FIND_REGISTER_DECLARE (xwma); /*'Start with' type find declaration */ GST_TYPE_FIND_REGISTER_DECLARE (asf); +GST_TYPE_FIND_REGISTER_DECLARE (avs); GST_TYPE_FIND_REGISTER_DECLARE (vcd); GST_TYPE_FIND_REGISTER_DECLARE (imelody); GST_TYPE_FIND_REGISTER_DECLARE (scc); @@ -91,6 +94,7 @@ GST_TYPE_FIND_REGISTER_DECLARE (ds_store); GST_TYPE_FIND_REGISTER_DECLARE (psd); GST_TYPE_FIND_REGISTER_DECLARE (xi); GST_TYPE_FIND_REGISTER_DECLARE (dmp); +GST_TYPE_FIND_REGISTER_DECLARE (yuv4mpeg); /*Type find declaration by functions */ GST_TYPE_FIND_REGISTER_DECLARE (musepack); @@ -195,5 +199,25 @@ GST_TYPE_FIND_REGISTER_DECLARE (ssa); GST_TYPE_FIND_REGISTER_DECLARE (pva); GST_TYPE_FIND_REGISTER_DECLARE (aa); GST_TYPE_FIND_REGISTER_DECLARE (tap); +GST_TYPE_FIND_REGISTER_DECLARE (brstm); +GST_TYPE_FIND_REGISTER_DECLARE (bfstm); +GST_TYPE_FIND_REGISTER_DECLARE (dsf); +GST_TYPE_FIND_REGISTER_DECLARE (ea); +GST_TYPE_FIND_REGISTER_DECLARE (film_cpk); +GST_TYPE_FIND_REGISTER_DECLARE (gxf); +GST_TYPE_FIND_REGISTER_DECLARE (iff); +GST_TYPE_FIND_REGISTER_DECLARE (idcin); +GST_TYPE_FIND_REGISTER_DECLARE (ipmovie); +GST_TYPE_FIND_REGISTER_DECLARE (mm); +GST_TYPE_FIND_REGISTER_DECLARE (mmf); +GST_TYPE_FIND_REGISTER_DECLARE (nsv); +GST_TYPE_FIND_REGISTER_DECLARE (nut); +GST_TYPE_FIND_REGISTER_DECLARE (pxstr); +GST_TYPE_FIND_REGISTER_DECLARE (smk); +GST_TYPE_FIND_REGISTER_DECLARE (sol); +GST_TYPE_FIND_REGISTER_DECLARE (vmd); +GST_TYPE_FIND_REGISTER_DECLARE (wc3movie); +GST_TYPE_FIND_REGISTER_DECLARE (wsaud); +GST_TYPE_FIND_REGISTER_DECLARE (wsvqa); #endif //__GST_TYPE_FIND_FUNCTIONS_PLUGIN_H__ diff --git a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsriff.c b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsriff.c index ba55219611..98823c4370 100644 --- a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsriff.c +++ b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsriff.c @@ -81,3 +81,7 @@ TYPE_FIND_REGISTER_RIFF_DEFINE (wav, "audio/x-wav", GST_RANK_PRIMARY, "wav", "WAVE"); TYPE_FIND_REGISTER_RIFF_DEFINE (webp, "image/webp", GST_RANK_PRIMARY, "webp", "WEBP"); +TYPE_FIND_REGISTER_RIFF_DEFINE (fourxm, "video/x-4xm", GST_RANK_PRIMARY, + NULL, "4XMV"); +TYPE_FIND_REGISTER_RIFF_DEFINE (xwma, "audio/x-xwma", GST_RANK_PRIMARY, + NULL, "XWMA"); diff --git a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsstartwith.c b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsstartwith.c index 6109e9c9ab..c3e3e286db 100644 --- a/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsstartwith.c +++ b/subprojects/gst-plugins-base/gst/typefind/gsttypefindfunctionsstartwith.c @@ -177,3 +177,7 @@ TYPE_FIND_REGISTER_START_WITH_DEFINE (xi, "audio/x-xi", GST_RANK_SECONDARY, "xi", "Extended Instrument: ", 21, GST_TYPE_FIND_MAXIMUM); TYPE_FIND_REGISTER_START_WITH_DEFINE (dmp, "audio/x-tap-dmp", GST_RANK_SECONDARY, "dmp", "DC2N-TAP-RAW", 12, GST_TYPE_FIND_LIKELY); +TYPE_FIND_REGISTER_START_WITH_DEFINE (avs, "video/x-avs", + GST_RANK_SECONDARY, NULL, "wW\x10\x00", 4, GST_TYPE_FIND_LIKELY); +TYPE_FIND_REGISTER_START_WITH_DEFINE (yuv4mpeg, "application/x-yuv4mpeg", + GST_RANK_MARGINAL, NULL, "YUV4MPEG2", 9, GST_TYPE_FIND_MAXIMUM);