GF_Err gf_import_nhml_dims()

in src/media_tools/media_import.c [3107:3795]


GF_Err gf_import_nhml_dims(GF_MediaImporter *import, Bool dims_doc)
{
	GF_Err e;
	GF_DIMSDescription dims;
	Bool destroy_esd, inRootOD, do_compress, use_dict, is_dims;
	u32 i, track, tkID, di, mtype, max_size, count, streamType, oti, timescale, specInfoSize, header_end, dts_inc, par_den, par_num;
	GF_ISOSample *samp;
	GF_XMLAttribute *att;
	s64 media_size, media_done, offset;
	u64 duration, sample_duration;
	FILE *nhml, *mdia, *info;
	char *dictionary = NULL;
	char *ext, szName[1000], szMedia[1000], szMediaTemp[1000], szInfo[1000], szXmlFrom[1000], szXmlTo[1000], szXmlHeaderEnd[1000];
	char *specInfo;
	GF_GenericSampleDescription sdesc;
	GF_DOMParser *parser;
	GF_XMLNode *root, *node, *childnode;
	char *szRootName, *szSampleName, *szImpName;

	szRootName = dims_doc ? "DIMSStream" : "NHNTStream";
	szSampleName = dims_doc ? "DIMSUnit" : "NHNTSample";
	szImpName = dims_doc ? "DIMS" : "NHML";

	if (import->flags & GF_IMPORT_PROBE_ONLY) {
		import->nb_tracks = 1;
		import->tk_info[0].track_num = 1;
		import->tk_info[0].type = 0;
		import->tk_info[0].flags = GF_IMPORT_USE_DATAREF;
		return GF_OK;
	}
	nhml = gf_fopen(import->in_name, "rt");
	if (!nhml) return gf_import_message(import, GF_URL_ERROR, "Cannot find %s file %s", szImpName, import->in_name);

	strcpy(szName, import->in_name);
	ext = strrchr(szName, '.');
	if (ext) ext[0] = 0;

	strcpy(szMedia, szName);
	strcat(szMedia, ".media");
	strcpy(szInfo, szName);
	strcat(szInfo, ".info");

	parser = gf_xml_dom_new();
	e = gf_xml_dom_parse(parser, import->in_name, nhml_on_progress, import);
	if (e) {
		gf_fclose(nhml);
		gf_import_message(import, e, "Error parsing %s file: Line %d - %s", szImpName, gf_xml_dom_get_line(parser), gf_xml_dom_get_error(parser));
		gf_xml_dom_del(parser);
		return e;
	}
	root = gf_xml_dom_get_root(parser);
	if (!root) {
		e = gf_import_message(import, GF_BAD_PARAM, "Error parsing %s file - no root node found", szImpName);
		gf_xml_dom_del(parser);
		return e;
	}

	mdia = NULL;
	destroy_esd = GF_FALSE;
	dts_inc = 0;
	inRootOD = GF_FALSE;
	do_compress = GF_FALSE;
	is_dims = GF_FALSE;
	specInfo = NULL;
	samp = NULL;
	memset(&dims, 0, sizeof(GF_DIMSDescription));
	dims.profile = dims.level = 255;
	dims.streamType = GF_TRUE;
	dims.containsRedundant = 1;

	if (stricmp(root->name, szRootName)) {
		e = gf_import_message(import, GF_BAD_PARAM, "Error parsing %s file - \"%s\" root expected, got \"%s\"", szImpName, szRootName, root->name);
		goto exit;
	}
	use_dict = GF_FALSE;
	memset(&sdesc, 0, sizeof(GF_GenericSampleDescription));
	tkID = mtype = streamType = oti = par_den = par_num = 0;
	timescale = 1000;
	i=0;
	strcpy(szXmlHeaderEnd, "");
	header_end = 0;

	while ((att = (GF_XMLAttribute *)gf_list_enum(root->attributes, &i))) {
		if (!stricmp(att->name, "streamType")) {
			NHML_SCAN_INT("%u", streamType)
		} else if (!stricmp(att->name, "mediaType") && (strlen(att->value)==4)) {
			mtype = GF_4CC(att->value[0], att->value[1], att->value[2], att->value[3]);
		} else if (!stricmp(att->name, "mediaSubType") && (strlen(att->value)==4)) {
			sdesc.codec_tag = GF_4CC(att->value[0], att->value[1], att->value[2], att->value[3]);
		} else if (!stricmp(att->name, "objectTypeIndication")) {
			NHML_SCAN_INT("%u", oti)
		} else if (!stricmp(att->name, "timeScale")) {
			NHML_SCAN_INT("%u", timescale)
		} else if (!stricmp(att->name, "width")) {
			NHML_SCAN_INT("%hu", sdesc.width)
		} else if (!stricmp(att->name, "height")) {
			NHML_SCAN_INT("%hu", sdesc.height)
		} else if (!stricmp(att->name, "parNum")) {
			NHML_SCAN_INT("%u", par_num)
		} else if (!stricmp(att->name, "parDen")) {
			NHML_SCAN_INT("%u", par_den)
		} else if (!stricmp(att->name, "sampleRate")) {
			NHML_SCAN_INT("%u", sdesc.samplerate)
		} else if (!stricmp(att->name, "numChannels")) {
			NHML_SCAN_INT("%hu", sdesc.nb_channels)
		} else if (!stricmp(att->name, "baseMediaFile")) {
			strcpy(szMedia, att->value);
		} else if (!stricmp(att->name, "specificInfoFile")) {
			strcpy(szInfo, att->value);
		} else if (!stricmp(att->name, "headerEnd")) {
			NHML_SCAN_INT("%u", header_end)
		} else if (!stricmp(att->name, "trackID")) {
			NHML_SCAN_INT("%u", tkID)
		} else if (!stricmp(att->name, "inRootOD")) {
			inRootOD = (!stricmp(att->value, "yes") );
		} else if (!stricmp(att->name, "DTS_increment")) {
			NHML_SCAN_INT("%u", dts_inc)
		} else if (!stricmp(att->name, "gzipSamples")) {
			do_compress = (!stricmp(att->value, "yes")) ? GF_TRUE : GF_FALSE;
		} else if (!stricmp(att->name, "gzipDictionary")) {
			u64 d_size;
			if (stricmp(att->value, "self")) {
				FILE *d = gf_fopen(att->value, "rb");
				if (!d) {
					gf_import_message(import, GF_IO_ERR, "Cannot open dictionary file %s", att->value);
					continue;
				}
				gf_fseek(d, 0, SEEK_END);
				d_size = gf_ftell(d);
				dictionary = (char*)gf_malloc(sizeof(char)*(size_t)(d_size+1));
				gf_fseek(d, 0, SEEK_SET);
				d_size = fread(dictionary, sizeof(char), (size_t)d_size, d);
				dictionary[d_size]=0;
			}
			use_dict = GF_TRUE;
		}
		/*unknow desc related*/
		else if (!stricmp(att->name, "compressorName")) {
			strcpy(sdesc.compressor_name, att->value);
		} else if (!stricmp(att->name, "codecVersion")) {
			NHML_SCAN_INT("%hu", sdesc.version)
		} else if (!stricmp(att->name, "codecRevision")) {
			NHML_SCAN_INT("%hu", sdesc.revision)
		} else if (!stricmp(att->name, "codecVendor") && (strlen(att->value)==4)) {
			sdesc.vendor_code = GF_4CC(att->value[0], att->value[1], att->value[2], att->value[3]);
		} else if (!stricmp(att->name, "temporalQuality")) {
			NHML_SCAN_INT("%u", sdesc.temporal_quality)
		} else if (!stricmp(att->name, "spatialQuality")) {
			NHML_SCAN_INT("%u", sdesc.spatial_quality)
		} else if (!stricmp(att->name, "horizontalResolution")) {
			NHML_SCAN_INT("%u", sdesc.h_res)
		} else if (!stricmp(att->name, "verticalResolution")) {
			NHML_SCAN_INT("%u", sdesc.v_res)
		} else if (!stricmp(att->name, "bitDepth")) {
			NHML_SCAN_INT("%hu", sdesc.depth)
		} else if (!stricmp(att->name, "bitsPerSample")) {
			NHML_SCAN_INT("%hu", sdesc.bits_per_sample)
		}
		/*DIMS stuff*/
		else if (!stricmp(att->name, "profile")) {
			NHML_SCAN_INT("%c", dims.profile)
		} else if (!stricmp(att->name, "level")) {
			NHML_SCAN_INT("%c", dims.level)
		} else if (!stricmp(att->name, "pathComponents")) {
			NHML_SCAN_INT("%c", dims.pathComponents)
		} else if (!stricmp(att->name, "useFullRequestHost") && !stricmp(att->value, "yes")) {
			dims.fullRequestHost = GF_TRUE;
		} else if (!stricmp(att->name, "stream_type") && !stricmp(att->value, "secondary")) {
			dims.streamType = GF_FALSE;
		} else if (!stricmp(att->name, "contains_redundant")) {
			if (!stricmp(att->value, "main")) {
				dims.containsRedundant = 1;
			} else if (!stricmp(att->value, "redundant")) {
				dims.containsRedundant = 2;
			} else if (!stricmp(att->value, "main+redundant")) {
				dims.containsRedundant = 3;
			}
		} else if (!stricmp(att->name, "text_encoding")) {
			dims.textEncoding = att->value;
		} else if (!stricmp(att->name, "content_encoding")) {
			if (!strcmp(att->value, "deflate")) {
				dims.contentEncoding = att->value;
				do_compress = GF_TRUE;
			}
		} else if (!stricmp(att->name, "content_script_types")) {
			dims.content_script_types = att->value;
		} else if (!stricmp(att->name, "mime_type")) {
			dims.mime_type = att->value;
		} else if (!stricmp(att->name, "media_namespace")) {
			dims.mime_type = att->value;
		} else if (!stricmp(att->name, "media_schema_location")) {
			dims.xml_schema_loc = att->value;
		} else if (!stricmp(att->name, "xml_namespace")) {
			dims.mime_type = att->value;
		} else if (!stricmp(att->name, "xml_schema_location")) {
			dims.xml_schema_loc = att->value;
		} else if (!stricmp(att->name, "xmlHeaderEnd")) {
			strcpy(szXmlHeaderEnd, att->value);
		}
	}
	if (sdesc.samplerate && !timescale) {
		timescale = sdesc.samplerate;
	} 
	if (!sdesc.bits_per_sample) {
		sdesc.bits_per_sample = 16;
	}

	if (dims_doc || (sdesc.codec_tag==GF_ISOM_SUBTYPE_3GP_DIMS)) {
		mtype = GF_ISOM_MEDIA_DIMS;
		sdesc.codec_tag=GF_ISOM_SUBTYPE_3GP_DIMS;
		is_dims = GF_TRUE;
		streamType = 0;
		import->flags &= ~GF_IMPORT_USE_DATAREF;
	}

	mdia = gf_fopen(szMedia, "rb");

	specInfoSize = 0;
	if (!streamType && !mtype && !sdesc.codec_tag) {
		e = gf_import_message(import, GF_NOT_SUPPORTED, "Error parsing %s file - StreamType or MediaType not specified", szImpName);
		goto exit;
	}

	info = gf_fopen(szInfo, "rb");
	if (info) {
		gf_fseek(info, 0, SEEK_END);
		specInfoSize = (u32) gf_ftell(info);
		specInfo = (char*)gf_malloc(sizeof(char) * specInfoSize);
		gf_fseek(info, 0, SEEK_SET);
		specInfoSize = (u32) fread(specInfo, sizeof(char), specInfoSize, info);
		gf_fclose(info);
	} else if (header_end) {
		/* for text based streams, the decoder specific info can be at the beginning of the file */
		specInfoSize = header_end;
		specInfo = (char*)gf_malloc(sizeof(char) * (specInfoSize+1));
		specInfoSize = (u32) fread(specInfo, sizeof(char), specInfoSize, mdia);		
		specInfo[specInfoSize] = 0;
		header_end = specInfoSize;
	} else if (strlen(szXmlHeaderEnd)) {
		/* for XML based streams, the decoder specific info can be up to some element in the file */
		samp = gf_isom_sample_new();
		max_size = 0;
		strcpy(szXmlFrom, "doc.start");
		e = gf_import_sample_from_xml(import, samp, szMedia, szXmlFrom, szXmlHeaderEnd, &max_size);
		if (e) {
			gf_isom_sample_del(&samp);
			goto exit;
		}
		specInfo = (char*)gf_malloc(sizeof(char) * (samp->dataLength+1));
		memcpy(specInfo, samp->data, samp->dataLength);
		specInfoSize = samp->dataLength;
		specInfo[specInfoSize] = 0;
		gf_isom_sample_del(&samp);
	}

	i=0;
	while ((node = (GF_XMLNode *) gf_list_enum(root->content, &i))) {
		if (node->type) continue;
		if (stricmp(node->name, "DecoderSpecificInfo") ) continue;

		e = gf_xml_parse_bit_sequence(node, &specInfo, &specInfoSize);
		break;
	}


	/*compressing samples, remove data ref*/
	if (do_compress) import->flags &= ~GF_IMPORT_USE_DATAREF;

	if (streamType) {
		if (!import->esd) {
			import->esd = gf_odf_desc_esd_new(2);
			destroy_esd = GF_TRUE;
			import->esd->ESID = tkID;
		}
		/*update stream type/oti*/
		if (!import->esd->decoderConfig) import->esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
		if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
		import->esd->decoderConfig->streamType = streamType;
		import->esd->decoderConfig->objectTypeIndication = oti;

		if (import->esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) import->esd->decoderConfig->decoderSpecificInfo);
		import->esd->decoderConfig->decoderSpecificInfo = NULL;

		import->esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
		import->esd->decoderConfig->decoderSpecificInfo->dataLength = specInfoSize;
		import->esd->decoderConfig->decoderSpecificInfo->data = specInfo;
		specInfo = NULL;
		specInfoSize = 0;
		import->esd->slConfig->timestampResolution = timescale;


		switch (import->esd->decoderConfig->streamType) {
		case GF_STREAM_SCENE:
			mtype = GF_ISOM_MEDIA_SCENE;
			break;
		case GF_STREAM_VISUAL:
			mtype = GF_ISOM_MEDIA_VISUAL;
#ifndef GPAC_DISABLE_AV_PARSERS
			if (import->esd->decoderConfig->objectTypeIndication==GPAC_OTI_VIDEO_MPEG4_PART2) {
				GF_M4VDecSpecInfo dsi;
				if (!import->esd->decoderConfig->decoderSpecificInfo) {
					e = GF_NON_COMPLIANT_BITSTREAM;
					goto exit;
				}
				e = gf_m4v_get_config(import->esd->decoderConfig->decoderSpecificInfo->data, import->esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
				sdesc.width = dsi.width;
				sdesc.height = dsi.height;
				if (e) goto exit;
			}
#endif
			break;
		case GF_STREAM_AUDIO:
			mtype = GF_ISOM_MEDIA_AUDIO;
			if (!sdesc.samplerate) sdesc.samplerate = 44100;
			if (!sdesc.nb_channels) sdesc.nb_channels = 2;
			break;
		case GF_STREAM_MPEG7:
			mtype = GF_ISOM_MEDIA_MPEG7;
			break;
		case GF_STREAM_IPMP:
			mtype = GF_ISOM_MEDIA_IPMP;
			break;
		case GF_STREAM_OCI:
			mtype = GF_ISOM_MEDIA_OCI;
			break;
		case GF_STREAM_MPEGJ:
			mtype = GF_ISOM_MEDIA_MPEGJ;
			break;
		/*note we cannot import OD from NHNT*/
		case GF_STREAM_OD:
			e = GF_NOT_SUPPORTED;
			goto exit;
		case GF_STREAM_INTERACT:
			mtype = GF_ISOM_MEDIA_SCENE;
			break;
		default:
			if (!mtype) mtype = GF_ISOM_MEDIA_ESM;
			break;
		}

		track = gf_isom_new_track(import->dest, import->esd->ESID, mtype, timescale);
		if (!track) {
			e = gf_isom_last_error(import->dest);
			goto exit;
		}
		e = gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? szMedia : NULL, NULL, &di);
		if (e) goto exit;

		gf_import_message(import, GF_OK, "NHML import - Stream Type %s - ObjectTypeIndication 0x%02x", gf_odf_stream_type_name(import->esd->decoderConfig->streamType), import->esd->decoderConfig->objectTypeIndication);

	} else if (is_dims) {
		track = gf_isom_new_track(import->dest, tkID, mtype, timescale);
		if (!track) {
			e = gf_isom_last_error(import->dest);
			goto exit;
		}
		e = gf_isom_new_dims_description(import->dest, track, &dims, NULL, NULL, &di);
		if (e) goto exit;

		gf_import_message(import, GF_OK, "3GPP DIMS import");
	} else if (mtype == GF_ISOM_MEDIA_MPEG_SUBT || mtype == GF_ISOM_MEDIA_SUBT || mtype == GF_ISOM_MEDIA_TEXT) {
		track = gf_isom_new_track(import->dest, tkID, mtype, timescale);
		if (!track) {
			e = gf_isom_last_error(import->dest);
			goto exit;
		}
		if(sdesc.codec_tag == GF_ISOM_SUBTYPE_STPP) {
			e = gf_isom_new_xml_subtitle_description(import->dest, track,
													 dims.mime_type, dims.xml_schema_loc, NULL,
													 &di);
		} else if (sdesc.codec_tag == GF_ISOM_SUBTYPE_SBTT) {
			e = gf_isom_new_stxt_description(import->dest, track, GF_ISOM_SUBTYPE_SBTT,
											 dims.mime_type, dims.textEncoding, specInfo,
											 &di);
		} else if (sdesc.codec_tag == GF_ISOM_SUBTYPE_STXT) {
			e = gf_isom_new_stxt_description(import->dest, track, GF_ISOM_SUBTYPE_STXT,
											 dims.mime_type, dims.textEncoding, specInfo,
											 &di);
		} else {
			e = GF_NOT_SUPPORTED;
		}
		if (e) goto exit;
	} else if (mtype == GF_ISOM_MEDIA_META) {
		track = gf_isom_new_track(import->dest, tkID, mtype, timescale);
		if (!track) {
			e = gf_isom_last_error(import->dest);
			goto exit;
		}
		if(sdesc.codec_tag == GF_ISOM_SUBTYPE_METX) {
			e = gf_isom_new_xml_metadata_description(import->dest, track,
													 dims.mime_type, dims.xml_schema_loc, dims.textEncoding, 
													 &di);
		} else if (sdesc.codec_tag == GF_ISOM_SUBTYPE_METT) {
			e = gf_isom_new_stxt_description(import->dest, track, GF_ISOM_SUBTYPE_METT,
											 dims.mime_type, dims.textEncoding, specInfo,
											 &di);
		} else {
			e = GF_NOT_SUPPORTED;
		}
		if (e) goto exit;
	} else {
		char szT[5];
		sdesc.extension_buf = specInfo;
		sdesc.extension_buf_size = specInfoSize;
		if (!sdesc.vendor_code) sdesc.vendor_code = GF_4CC('G', 'P', 'A', 'C');

		track = gf_isom_new_track(import->dest, tkID, mtype, timescale);
		if (!track) {
			e = gf_isom_last_error(import->dest);
			goto exit;
		}

		e = gf_isom_new_generic_sample_description(import->dest, track, (import->flags & GF_IMPORT_USE_DATAREF) ? szMedia : NULL, NULL, &sdesc, &di);
		if (e) goto exit;

		strcpy(szT, gf_4cc_to_str(mtype));
		gf_import_message(import, GF_OK, "NHML import - MediaType \"%s\" - SubType \"%s\"", szT, gf_4cc_to_str(sdesc.codec_tag));
	}

	gf_isom_set_track_enabled(import->dest, track, 1);
	import->final_trackID = gf_isom_get_track_id(import->dest, track);
	if (import->esd && !import->esd->ESID) import->esd->ESID = import->final_trackID;

	if (sdesc.width && sdesc.height) {
		gf_isom_set_visual_info(import->dest, track, di, sdesc.width, sdesc.height);
		if (par_den && par_num) {
			gf_media_change_par(import->dest, track, par_num, par_den);
		} else {
			gf_media_update_par(import->dest, track);
		}
	}
	else if (sdesc.samplerate && sdesc.nb_channels) {
		gf_isom_set_audio_info(import->dest, track, di, sdesc.samplerate, sdesc.nb_channels, (u8) sdesc.bits_per_sample);
	}

	duration = (u64) ( ((Double) import->duration)/ 1000 * timescale);

	samp = gf_isom_sample_new();
	samp->data = (char*)gf_malloc(sizeof(char) * 1024);
	max_size = 1024;
	count = 0;
	media_size = 0;
	if (mdia) {
		gf_fseek(mdia, 0, SEEK_END);
		media_size = gf_ftell(mdia);
		gf_fseek(mdia, 0, SEEK_SET);
	}
	/* if we've read the header from the same file, mark the header data as used */
	media_done = header_end;

	samp->IsRAP = RAP;
	i=0;
	while ((node = (GF_XMLNode *) gf_list_enum(root->content, &i))) {
		u32 j, dims_flags;
		Bool append, compress, has_subbs;
		if (node->type) continue;
		if (stricmp(node->name, szSampleName) ) continue;

		strcpy(szMediaTemp, "");
		strcpy(szXmlFrom, "");
		strcpy(szXmlTo, "");

		/*by default handle all samples as contigous*/
		offset = 0;
		samp->dataLength = 0;
		dims_flags = 0;
		append = GF_FALSE;
		compress = do_compress;
		sample_duration = 0;

		j=0;
		while ( (att = (GF_XMLAttribute *)gf_list_enum(node->attributes, &j))) {
			if (!stricmp(att->name, "DTS") || !stricmp(att->name, "time")) {
				u32 h, m, s, ms;
				u64 dst_val;
				if (strchr(att->value, ':') && sscanf(att->value, "%u:%u:%u.%u", &h, &m, &s, &ms) == 4) {
					samp->DTS = (u64) ( (Double) ( ((h*3600.0 + m*60.0 + s)*1000 + ms) / 1000.0) * timescale );
				} else if (sscanf(att->value, ""LLU, &dst_val)==1) {
					samp->DTS = dst_val;
				}
			}
			else if (!stricmp(att->name, "CTSOffset")) samp->CTS_Offset = atoi(att->value);
			else if (!stricmp(att->name, "isRAP") && !samp->IsRAP) {
				samp->IsRAP = (!stricmp(att->value, "yes")) ? RAP : RAP_NO;
			}
			else if (!stricmp(att->name, "isSyncShadow")) samp->IsRAP = !stricmp(att->value, "yes") ? RAP_REDUNDANT : RAP_NO;
			else if (!stricmp(att->name, "mediaOffset")) offset = (s64) atof(att->value) ;
			else if (!stricmp(att->name, "dataLength")) samp->dataLength = atoi(att->value);
			else if (!stricmp(att->name, "mediaFile")) strcpy(szMediaTemp, att->value);
			else if (!stricmp(att->name, "xmlFrom")) strcpy(szXmlFrom, att->value);
			else if (!stricmp(att->name, "xmlTo")) strcpy(szXmlTo, att->value);
			/*DIMS flags*/
			else if (!stricmp(att->name, "is-Scene") && !stricmp(att->value, "yes"))
				dims_flags |= GF_DIMS_UNIT_S;
			else if (!stricmp(att->name, "is-RAP") && !stricmp(att->value, "yes")) {
				dims_flags |= GF_DIMS_UNIT_M;
				samp->IsRAP = RAP;
			}
			else if (!stricmp(att->name, "is-redundant") && !stricmp(att->value, "yes"))
				dims_flags |= GF_DIMS_UNIT_I;
			else if (!stricmp(att->name, "redundant-exit") && !stricmp(att->value, "yes"))
				dims_flags |= GF_DIMS_UNIT_D;
			else if (!stricmp(att->name, "priority") && !stricmp(att->value, "high"))
				dims_flags |= GF_DIMS_UNIT_P;
			else if (!stricmp(att->name, "compress") && !stricmp(att->value, "yes"))
				dims_flags |= GF_DIMS_UNIT_C;
			else if (!stricmp(att->name, "duration") )
				sscanf(att->value, ""LLU, &sample_duration);
		}
		if (samp->IsRAP==RAP)
			dims_flags |= GF_DIMS_UNIT_M;
		if (!count && samp->DTS) samp->DTS = 0;

		if (!(dims_flags & GF_DIMS_UNIT_C)) compress = GF_FALSE;
		count++;

		has_subbs = GF_FALSE;
		j=0;
		while ((childnode = (GF_XMLNode *) gf_list_enum(node->content, &j))) {
			if (childnode->type) continue;
			if (stricmp(childnode->name, "BS") ) continue;
			has_subbs = GF_TRUE;
			break;
		}


		if (import->flags & GF_IMPORT_USE_DATAREF) {
			if (offset) offset = media_done;
			e = gf_isom_add_sample_reference(import->dest, track, di, samp, offset);
		} else if (strlen(szXmlFrom) && strlen(szXmlTo)) {
			char *xml_file;
			if (strlen(szMediaTemp)) xml_file = szMediaTemp;
			else xml_file = szMedia;
			samp->dataLength = max_size;
			e = gf_import_sample_from_xml(import, samp, xml_file, szXmlFrom, szXmlTo, &max_size);
		} else if (is_dims && !strlen(szMediaTemp)) {
			GF_BitStream *bs;
			char *content = gf_xml_dom_serialize(node, GF_TRUE);

			samp->dataLength = 3 + (u32) strlen(content);

			if (samp->dataLength>max_size) {
				samp->data = (char*)gf_realloc(samp->data, sizeof(char) * samp->dataLength);
				max_size = samp->dataLength;
			}

			bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_WRITE);
			gf_bs_write_u16(bs, samp->dataLength-2);
			gf_bs_write_u8(bs, (u8) dims_flags);
			gf_bs_write_data(bs, content, (samp->dataLength-3));
			gf_free(content);
			gf_bs_del(bs);
			/*same DIMS unit*/
			if (gf_isom_get_sample_from_dts(import->dest, track, samp->DTS))
				append = GF_TRUE;

		} else if (has_subbs) {
			if (samp->data) gf_free(samp->data );
			samp->data = 0;
			samp->dataLength = 0;
			e = gf_xml_parse_bit_sequence(node, &samp->data, &samp->dataLength);
			max_size = samp->dataLength;
		} else {
			Bool close = GF_FALSE;
			FILE *f = mdia;
			if (strlen(szMediaTemp)) {
				f = gf_fopen(szMediaTemp, "rb");
				close = GF_TRUE;
				if (offset) gf_fseek(f, offset, SEEK_SET);
			} else {
				if (!offset) offset = media_done;
			}
			if (!f) {
				e = gf_import_message(import, GF_BAD_PARAM, "%s import failure: file %s not found", szImpName, close ? szMediaTemp : szMedia);
				goto exit;
			}

			if (!samp->dataLength) {
				u64 cur_pos = gf_ftell(f);
				gf_fseek(f, 0, SEEK_END);
				assert(gf_ftell(f) < 1<<31);
				samp->dataLength = (u32) gf_ftell(f);
				gf_fseek(f, cur_pos, SEEK_SET);
			}

			gf_fseek(f, offset, SEEK_SET);
			if (is_dims) {
				GF_BitStream *bs;
				if (samp->dataLength+3>max_size) {
					samp->data = (char*)gf_realloc(samp->data, sizeof(char) * (samp->dataLength+3));
					max_size = samp->dataLength+3;
				}
				bs = gf_bs_new(samp->data, samp->dataLength+3, GF_BITSTREAM_WRITE);
				gf_bs_write_u16(bs, samp->dataLength+1);
				gf_bs_write_u8(bs, (u8) dims_flags);
				if (samp->dataLength != fread( samp->data+3, sizeof(char), samp->dataLength, f)) {
					GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[NHML import dims] Failed to fully read samp->dataLength\n"));
				}
				gf_bs_del(bs);
				samp->dataLength+=3;

				/*same DIMS unit*/
				if (gf_isom_get_sample_from_dts(import->dest, track, samp->DTS))
					append = GF_TRUE;
			} else {
				if (samp->dataLength>max_size) {
					samp->data = (char*)gf_realloc(samp->data, sizeof(char) * samp->dataLength);
					max_size = samp->dataLength;
				}
				if (samp->dataLength != fread( samp->data, sizeof(char), samp->dataLength, f)) {
					GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[NHML import] Failed to fully read samp->dataLength\n"));
				}
			}
			if (close) gf_fclose(f);
		}
		if (e) goto exit;

		if (is_dims) {
			if (strstr(samp->data+3, "svg ")) dims_flags |= GF_DIMS_UNIT_S;
			if (dims_flags & GF_DIMS_UNIT_S) dims_flags |= GF_DIMS_UNIT_P;
			samp->data[2] = dims_flags;
		}

		if (compress) {
#ifndef GPAC_DISABLE_ZLIB
			e = compress_sample_data(samp, &max_size, use_dict ? &dictionary : NULL, is_dims ? 3 : 0);
			if (e) goto exit;
			if (is_dims) {
				GF_BitStream *bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_WRITE);
				gf_bs_write_u16(bs, samp->dataLength-2);
				gf_bs_del(bs);
			}
#else
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: your version of GPAC was compile with no libz support. Abort."));
			e = GF_NOT_SUPPORTED;
			goto exit;
#endif
		}
		if (is_dims && (samp->dataLength > 0xFFFF)) {
			e = gf_import_message(import, GF_BAD_PARAM, "DIMS import failure: sample data is too long - maximum size allowed: 65532 bytes");
			goto exit;
		}


		if ((samp->IsRAP==RAP_REDUNDANT) && !is_dims) {
			e = gf_isom_add_sample_shadow(import->dest, track, samp);
		} else if (append) {
			e = gf_isom_append_sample_data(import->dest, track, samp->data, samp->dataLength);
		} else {
			e = gf_isom_add_sample(import->dest, track, di, samp);
		}
		if (e) goto exit;
		samp->IsRAP = RAP_NO;
		samp->CTS_Offset = 0;
		if (sample_duration)
			samp->DTS += sample_duration;
		else
			samp->DTS += dts_inc;
		media_done += samp->dataLength;
		gf_set_progress(is_dims ? "Importing DIMS" : "Importing NHML", (u32) media_done, (u32) (media_size ? media_size : media_done+1) );
		if (duration && (samp->DTS > duration)) break;
		if (import->flags & GF_IMPORT_DO_ABORT) break;
	}

	if (sample_duration) {
		gf_isom_set_last_sample_duration(import->dest, track, (u32) sample_duration);
	}

	if (media_done!=media_size) gf_set_progress(is_dims ? "Importing DIMS" : "Importing NHML", (u32) media_size, (u32) media_size);
	gf_media_update_bitrate(import->dest, track);

	if (inRootOD) gf_isom_add_track_to_root_od(import->dest, track);

exit:
	gf_fclose(nhml);
	if (samp) {
		samp->dataLength = 1;
		gf_isom_sample_del(&samp);
	}
	if (mdia) gf_fclose(mdia);
	if (import->esd && destroy_esd) {
		gf_odf_desc_del((GF_Descriptor *) import->esd);
		import->esd = NULL;
	}
	gf_xml_dom_del(parser);
	if (specInfo) gf_free(specInfo);
	if (dictionary) gf_free(dictionary);
	return e;
}