static const char *ctxload_probe_data(const u8 *probe_data, u32 size, GF_FilterProbeScore *score)
{
	const char *mime_type = NULL;
	char *dst = NULL;
	GF_Err e;
	char *res=NULL;

	/* check gzip magic header */
	if ((size>2) && (probe_data[0] == 0x1f) && (probe_data[1] == 0x8b)) {
		*score = GF_FPROBE_EXT_MATCH;
		return "btz|bt.gz|xmt.gz|xmtz|wrl.gz|x3dv.gz|x3dvz|x3d.gz|x3dz";
	}

	e = gf_utf_get_utf8_string_from_bom(probe_data, size, &dst, &res);
	if (e) return NULL;

	//strip all spaces and \r\n
	while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
		probe_data ++;

	//for XML, strip doctype, <?xml and comments
	while (1) {
		if (!strncmp(probe_data, "<!DOCTYPE", 9)) {
			probe_data = strchr(probe_data, '>');
			if (!probe_data) goto exit;
			probe_data++;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		}
		//for XML, strip xml header
		else if (!strncmp(probe_data, "<?xml", 5)) {
			probe_data = strstr(probe_data, "?>");
			if (!probe_data) goto exit;

			probe_data += 2;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		}
		else if (!strncmp(probe_data, "<!--", 4)) {
			probe_data = strstr(probe_data, "-->");
			if (!probe_data) goto exit;
			probe_data += 3;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		} else {
			break;
		}
	}
	//probe_data is now the first element of the document, if XML
	//we should refin by getting the xmlns attribute value rather than searching for its value...

	if (!strncmp(probe_data, "<XMT-A", strlen("<XMT-A"))
		|| strstr(probe_data, "urn:mpeg:mpeg4:xmta:schema:2002")
	) {
		mime_type = "application/x-xmt";
	} else if (strstr(probe_data, "<X3D")
		|| strstr(probe_data, "http://www.web3d.org/specifications/x3d-3.0.xsd")
	) {
		mime_type = "model/x3d+xml";
	} else if (strstr(probe_data, "<saf")
		|| strstr(probe_data, "urn:mpeg:mpeg4:SAF:2005")
		|| strstr(probe_data, "urn:mpeg:mpeg4:LASeR:2005")
	) {
		mime_type = "application/x-LASeR+xml";
	} else if (!strncmp(probe_data, "<DIMSStream", strlen("<DIMSStream") ) ) {
		mime_type = "application/dims";
	} else if (!strncmp(probe_data, "<svg", 4) || strstr(probe_data, "http://www.w3.org/2000/svg") ) {
		mime_type = "image/svg+xml";
	} else if (!strncmp(probe_data, "<widget", strlen("<widget") ) ) {
		mime_type = "application/widget";
	} else if (!strncmp(probe_data, "<NHNTStream", strlen("<NHNTStream") ) ) {
		mime_type = "application/x-nhml";
	} else if (!strncmp(probe_data, "<TextStream", strlen("<TextStream") ) ) {
		mime_type = "text/ttxt";
	} else if (!strncmp(probe_data, "<text3GTrack", strlen("<text3GTrack") ) ) {
		mime_type = "quicktime/text";
	}
	//BT/VRML with no doc header
	else {
		//get first keyword
		while (1) {
			//strip all spaces and \r\n
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;

			//VRML / XRDV files
			if (!strncmp(probe_data, "#VRML V2.0", strlen("#VRML V2.0"))) {
				mime_type = "model/vrml";
				goto exit;
			}
			if (!strncmp(probe_data, "#X3D V3.0", strlen("#X3D V3.0"))) {
				mime_type = "model/x3d+vrml";
				goto exit;
			}

			//skip comment lines and some specific X3D keyword (we want to fetch a group
			if ((probe_data[0] != '#')
				&& strncmp(probe_data, "PROFILE", strlen("PROFILE"))
				&& strncmp(probe_data, "COMPONENT", strlen("COMPONENT"))
				&& strncmp(probe_data, "META", strlen("META"))
				&& strncmp(probe_data, "IMPORT", strlen("IMPORT"))
				&& strncmp(probe_data, "EXPORT", strlen("EXPORT"))
			) {
				break;
			}
			//skip line and go one
			probe_data = strchr(probe_data, '\n');
			if (!probe_data) goto exit;
		}
		
		if (!strncmp(probe_data, "InitialObjectDescriptor", strlen("InitialObjectDescriptor"))
			|| !strncmp(probe_data, "EXTERNPROTO", strlen("EXTERNPROTO"))
			|| !strncmp(probe_data, "PROTO", strlen("PROTO"))
			|| !strncmp(probe_data, "Group", strlen("Group"))
			|| !strncmp(probe_data, "OrderedGroup", strlen("OrderedGroup"))
			|| !strncmp(probe_data, "Layer2D", strlen("Layer2D"))
			|| !strncmp(probe_data, "Layer3D", strlen("Layer3D"))
		) {
			if (strstr(probe_data, "children"))
				mime_type = "application/x-bt";
		}
	}


exit:

	if (dst) gf_free(dst);
	if (mime_type) {
		*score = GF_FPROBE_MAYBE_SUPPORTED;
		return mime_type;
	}

	*score = GF_FPROBE_NOT_SUPPORTED;
	return NULL;
}
static const char *ctxload_probe_data(const u8 *probe_data, u32 size, GF_FilterProbeScore *score)
{
	const char *mime_type = NULL;
	char *dst = NULL;
	GF_Err e;
	char *res=NULL;

	 
	if ((size>2) && (probe_data[0] == 0x1f) && (probe_data[1] == 0x8b)) {
		*score = GF_FPROBE_EXT_MATCH;
		return "btz|bt.gz|xmt.gz|xmtz|wrl.gz|x3dv.gz|x3dvz|x3d.gz|x3dz";
	}

	e = gf_utf_get_utf8_string_from_bom(probe_data, size, &dst, &res);
	if (e) return NULL;

	 
	while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
		probe_data ++;

	 
	while (1) {
		if (!strncmp(probe_data, "<!DOCTYPE", 9)) {
			probe_data = strchr(probe_data, '>');
			if (!probe_data) goto exit;
			probe_data++;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		}
		 
		else if (!strncmp(probe_data, "<?xml", 5)) {
			probe_data = strstr(probe_data, "?>");
			if (!probe_data) goto exit;

			probe_data += 2;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		}
		else if (!strncmp(probe_data, "<!--", 4)) {
			probe_data = strstr(probe_data, "-->");
			if (!probe_data) goto exit;
			probe_data += 3;
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;
		} else {
			break;
		}
	}
	 
	 

	if (!strncmp(probe_data, "<XMT-A", strlen("<XMT-A"))
		|| strstr(probe_data, "urn:mpeg:mpeg4:xmta:schema:2002")
	) {
		mime_type = "application/x-xmt";
	} else if (strstr(probe_data, "<X3D")
		|| strstr(probe_data, "http://www.web3d.org/specifications/x3d-3.0.xsd")
	) {
		mime_type = "model/x3d+xml";
	} else if (strstr(probe_data, "<saf")
		|| strstr(probe_data, "urn:mpeg:mpeg4:SAF:2005")
		|| strstr(probe_data, "urn:mpeg:mpeg4:LASeR:2005")
	) {
		mime_type = "application/x-LASeR+xml";
	} else if (!strncmp(probe_data, "<DIMSStream", strlen("<DIMSStream") ) ) {
		mime_type = "application/dims";
	} else if (!strncmp(probe_data, "<svg", 4) || strstr(probe_data, "http://www.w3.org/2000/svg") ) {
		mime_type = "image/svg+xml";
	} else if (!strncmp(probe_data, "<widget", strlen("<widget") ) ) {
		mime_type = "application/widget";
	} else if (!strncmp(probe_data, "<NHNTStream", strlen("<NHNTStream") ) ) {
		mime_type = "application/x-nhml";
	} else if (!strncmp(probe_data, "<TextStream", strlen("<TextStream") ) ) {
		mime_type = "text/ttxt";
	} else if (!strncmp(probe_data, "<text3GTrack", strlen("<text3GTrack") ) ) {
		mime_type = "quicktime/text";
	}
	 
	else {
		 
		while (1) {
			 
			while (probe_data[0] && strchr("\n\r\t ", (char) probe_data[0]))
				probe_data ++;

			 
			if (!strncmp(probe_data, "#VRML V2.0", strlen("#VRML V2.0"))) {
				mime_type = "model/vrml";
				goto exit;
			}
			if (!strncmp(probe_data, "#X3D V3.0", strlen("#X3D V3.0"))) {
				mime_type = "model/x3d+vrml";
				goto exit;
			}

			 
			if ((probe_data[0] != '#')
				&& strncmp(probe_data, "PROFILE", strlen("PROFILE"))
				&& strncmp(probe_data, "COMPONENT", strlen("COMPONENT"))
				&& strncmp(probe_data, "META", strlen("META"))
				&& strncmp(probe_data, "IMPORT", strlen("IMPORT"))
				&& strncmp(probe_data, "EXPORT", strlen("EXPORT"))
			) {
				break;
			}
			 
			probe_data = strchr(probe_data, '\n');
			if (!probe_data) goto exit;
		}
		
		if (!strncmp(probe_data, "InitialObjectDescriptor", strlen("InitialObjectDescriptor"))
			|| !strncmp(probe_data, "EXTERNPROTO", strlen("EXTERNPROTO"))
			|| !strncmp(probe_data, "PROTO", strlen("PROTO"))
			|| !strncmp(probe_data, "Group", strlen("Group"))
			|| !strncmp(probe_data, "OrderedGroup", strlen("OrderedGroup"))
			|| !strncmp(probe_data, "Layer2D", strlen("Layer2D"))
			|| !strncmp(probe_data, "Layer3D", strlen("Layer3D"))
		) {
			if (strstr(probe_data, "children"))
				mime_type = "application/x-bt";
		}
	}


exit:

	if (dst) gf_free(dst);
	if (mime_type) {
		*score = GF_FPROBE_MAYBE_SUPPORTED;
		return mime_type;
	}

	*score = GF_FPROBE_NOT_SUPPORTED;
	return NULL;
}