From 2a84cf0941ebf65504599ea42f6fe4ffbb0e8da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 22 Jan 2010 01:49:38 +0000 Subject: [PATCH] typefinding: add PNM typefinder Add PNM typefinder, so we can remove the one that's in the PNM plugin in -bad (which btw uses different/wrong media types that don't match the ones used by gdkpixbufdec) and people don't make fun of us for loading image decoders when typefinding and playing back audio files. --- gst/typefind/gsttypefindfunctions.c | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index c7b46dc50f..a6d9674b66 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -2580,6 +2580,104 @@ tiff_type_find (GstTypeFind * tf, gpointer ununsed) } } +/*** PNM ***/ + +static GstStaticCaps pnm_caps = GST_STATIC_CAPS ("image/x-portable-bitmap; " + "image/x-portable-graymap; image/x-portable-pixmap; " + "image/x-portable-anymap"); + +#define PNM_CAPS (gst_static_caps_get(&pnm_caps)) + +#define IS_PNM_WHITESPACE(c) \ + ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == 't') + +static void +pnm_type_find (GstTypeFind * tf, gpointer ununsed) +{ + const gchar *media_type = NULL; + DataScanCtx c = { 0, NULL, 0 }; + guint h = 0, w = 0; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 16))) + return; + + /* see http://en.wikipedia.org/wiki/Netpbm_format */ + if (c.data[0] != 'P' || c.data[1] < '1' || c.data[1] > '7' || + !IS_PNM_WHITESPACE (c.data[2]) || + (c.data[3] != '#' && c.data[3] < '0' && c.data[3] > '9')) + return; + + switch (c.data[1]) { + case '1': + media_type = "image/x-portable-bitmap"; /* ASCII */ + break; + case '2': + media_type = "image/x-portable-graymap"; /* ASCII */ + break; + case '3': + media_type = "image/x-portable-pixmap"; /* ASCII */ + break; + case '4': + media_type = "image/x-portable-bitmap"; /* Raw */ + break; + case '5': + media_type = "image/x-portable-graymap"; /* Raw */ + break; + case '6': + media_type = "image/x-portable-pixmap"; /* Raw */ + break; + case '7': + media_type = "image/x-portable-anymap"; + break; + default: + g_return_if_reached (); + } + + /* try to extract width and height as well */ + if (c.data[1] != '7') { + gchar s[64] = { 0, } + , sep1, sep2; + + /* need to skip any comment lines first */ + data_scan_ctx_advance (tf, &c, 3); + while (c.data[0] == '#') { /* we know there's still data left */ + data_scan_ctx_advance (tf, &c, 1); + while (c.data[0] != '\n' && c.data[0] != '\r') { + if (!data_scan_ctx_ensure_data (tf, &c, 4)) + return; + data_scan_ctx_advance (tf, &c, 1); + } + data_scan_ctx_advance (tf, &c, 1); + GST_LOG ("skipped comment line in PNM header"); + } + + if (!data_scan_ctx_ensure_data (tf, &c, 32) && + !data_scan_ctx_ensure_data (tf, &c, 4)) { + return; + } + + /* need to NUL-terminate data for sscanf */ + memcpy (s, c.data, MIN (sizeof (s) - 1, c.size)); + if (sscanf (s, "%u%c%u%c", &w, &sep1, &h, &sep2) == 4 && + IS_PNM_WHITESPACE (sep1) && IS_PNM_WHITESPACE (sep2) && + w > 0 && w < G_MAXINT && h > 0 && h < G_MAXINT) { + GST_LOG ("extracted PNM width and height: %dx%d", w, h); + } else { + w = 0; + h = 0; + } + } else { + /* FIXME: extract width + height for anymaps too */ + } + + if (w > 0 && h > 0) { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, media_type, + "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL); + } else { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, media_type, NULL); + } +} + static GstStaticCaps sds_caps = GST_STATIC_CAPS ("audio/x-sds"); #define SDS_CAPS (gst_static_caps_get(&sds_caps)) @@ -3486,6 +3584,7 @@ plugin_init (GstPlugin * plugin) static gchar *mng_exts[] = { "mng", NULL }; static gchar *jng_exts[] = { "jng", NULL }; static gchar *xpm_exts[] = { "xpm", NULL }; + static gchar *pnm_exts[] = { "pnm", "ppm", "pgm", "pbm", NULL }; static gchar *ras_exts[] = { "ras", NULL }; static gchar *bz2_exts[] = { "bz2", NULL }; static gchar *gz_exts[] = { "gz", NULL }; @@ -3659,6 +3758,8 @@ plugin_init (GstPlugin * plugin) bmp_exts, BMP_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find, tiff_exts, TIFF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/x-portable-pixmap", GST_RANK_SECONDARY, + pnm_type_find, pnm_exts, PNM_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY, matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL); TYPE_FIND_REGISTER (plugin, "application/mxf", GST_RANK_PRIMARY,