Пример #1
0
static GF_Err ISOW_Open(GF_StreamingCache *mc, GF_ClientService *serv, const char *location_and_name, Bool keep_existing_files)
{
	char szRoot[GF_MAX_PATH], szPath[GF_MAX_PATH], *ext;
	ISOMReader *cache = (ISOMReader *)mc->priv;
	if (cache->mov || cache->service) return GF_BAD_PARAM;

	strcpy(szRoot, location_and_name);
	ext = strrchr(szRoot, '.');
	if (ext) ext[0] = 0;
	strcpy(szPath, szRoot);
	strcat(szPath, ".mp4");
	if (keep_existing_files) {
		FILE *f = gf_fopen(szPath, "rb");
		if (f) {
			u32 i=0;
			gf_fclose(f);
			while (1) {
				sprintf(szPath, "%s_%04d.mp4", szRoot, i);
				f = gf_fopen(szPath, "rb");
				if (!f) break;
				gf_fclose(f);
				i++;
			}
		}
	}

	/*create a new movie in write mode (eg no editing)*/
	cache->mov = gf_isom_open(szPath, GF_ISOM_OPEN_WRITE, NULL);
	if (!cache->mov) return gf_isom_last_error(NULL);
	cache->service = serv;
	return GF_OK;
}
Пример #2
0
GF_EXPORT
GF_Err gf_webvtt_dump_iso_track(GF_MediaExporter *dumper, char *szName, u32 track, Bool merge, Bool box_dump)
{
#ifdef GPAC_DISABLE_MEDIA_IMPORT
	return GF_NOT_SUPPORTED;
#else
	GF_Err  e;
	u32     i;
	u32     count;
	u32     timescale;
	FILE    *out;
	u32     di;
	u64     duration;
	GF_WebVTTParser *parser;

	out = szName ? gf_fopen(szName, "wt") : (dumper->dump_file ? dumper->dump_file : stdout);
	if (!out) return GF_IO_ERR;// gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName);

	parser = gf_webvtt_parser_new();
	parser->user = out;
	parser->on_cue_read = gf_webvtt_dump_cue;

	if (box_dump)
		fprintf(out, "<WebVTTTrack trackID=\"%d\">\n", gf_isom_get_track_id(dumper->file, track) );

	e = gf_webvtt_dump_header(out, dumper->file, track, box_dump, 1);
	if (e) goto exit;

	timescale = gf_isom_get_media_timescale(dumper->file, track);

	count = gf_isom_get_sample_count(dumper->file, track);
	for (i=0; i<count; i++) {
		GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di);
		if (!samp) {
			e = gf_isom_last_error(dumper->file);
			goto exit;
		}
		e = gf_webvtt_parse_iso_sample(parser, timescale, samp, merge, box_dump);
		if (e) {
			goto exit;
		}
		gf_isom_sample_del(&samp);
	}
	duration = gf_isom_get_media_duration(dumper->file, track);
	gf_webvtt_parser_dump_finalize(parser, duration);

	if (box_dump)
		fprintf(out, "</WebVTTTrack>\n");

exit:
	gf_webvtt_parser_del(parser);
	if (szName) gf_fclose(out);
	return e;
#endif
}
Пример #3
0
GF_Err gf_webvtt_dump_iso_track(GF_MediaExporter *dumper, char *szName, u32 track, Bool merge)
{
	GF_Err  e;
	u32     i;
	u32     count;
	u32     timescale;
	FILE    *out;
	u32     di;
	u64     duration;
	GF_WebVTTParser *parser;

	out = szName ? gf_fopen(szName, "wt") : stdout;
	if (!out) return GF_IO_ERR;// gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName);

	parser = gf_webvtt_parser_new();
	parser->user = out;
	parser->on_cue_read = gf_webvtt_dump_cue;

	e = gf_webvtt_dump_header(out, dumper->file, track, 1);
	if (e) goto exit;

	timescale = gf_isom_get_media_timescale(dumper->file, track);

	count = gf_isom_get_sample_count(dumper->file, track);
	for (i=0; i<count; i++) {
		GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di);
		if (!samp) {
			e = gf_isom_last_error(dumper->file);
			goto exit;
		}
		e = gf_webvtt_parse_iso_sample(parser, timescale, samp, merge);
		if (e) goto exit;
		//gf_webvtt_dump_iso_sample(out, timescale, samp);
	}
	duration = gf_isom_get_media_duration(dumper->file, track);
	gf_webvtt_parser_dump_finalize(parser, duration);

exit:
	gf_webvtt_parser_del(parser);
	if (szName) gf_fclose(out);
	return e;
}
Пример #4
0
GF_Err TTIn_LoadFile(GF_InputService *plug, const char *url, Bool is_cache)
{
    GF_Err e;
    GF_MediaImporter import;
    char szFILE[GF_MAX_PATH];
    TTIn *tti = (TTIn *)plug->priv;
    const char *cache_dir;
    if (!tti || !url)
        return GF_BAD_PARAM;
    cache_dir = gf_modules_get_option((GF_BaseInterface *)plug, "General", "CacheDirectory");
    if (cache_dir && strlen(cache_dir)) {
        if (cache_dir[strlen(cache_dir)-1] != GF_PATH_SEPARATOR) {
            sprintf(szFILE, "%s%csrt_%p_mp4", cache_dir, GF_PATH_SEPARATOR, tti);
        } else {
            sprintf(szFILE, "%ssrt_%p_mp4", cache_dir, tti);
        }
    } else {
        sprintf(szFILE, "%p_temp_mp4", tti);
    }
    tti->mp4 = gf_isom_open(szFILE, GF_ISOM_OPEN_WRITE, NULL);
    if (!tti->mp4) return gf_isom_last_error(NULL);
    if (tti->szFile)
        gf_free(tti->szFile);
    tti->szFile = gf_strdup(szFILE);

    memset(&import, 0, sizeof(GF_MediaImporter));
    import.dest = tti->mp4;
    /*override layout from sub file*/
    import.flags = GF_IMPORT_SKIP_TXT_BOX;
    import.in_name = gf_strdup(url);

    e = gf_media_import(&import);
    if (!e) {
        tti->tt_track = 1;
        gf_isom_text_set_streaming_mode(tti->mp4, 1);
    }
    if (import.in_name)
        gf_free(import.in_name);
    return e;
}
Пример #5
0
static void process_samples_from_track(GF_ISOFile *movie, u32 track_id, u32 *sample_index)
{
	u32 track_number;
	u32 sample_count;
	/* Error indicator */
	GF_Err e;
	/* Number of bytes required to finish the current ISO Box reading */
	u64 missing_bytes;

	track_number = gf_isom_get_track_by_id(movie, track_id);
	if (track_number == 0) {
		fprintf(stdout, "Could not find track ID=%u. Ignore segment.\n", track_id);
		return;
	}

	sample_count = gf_isom_get_sample_count(movie, track_number);
	while (*sample_index <= sample_count) {
		GF_ISOSample *iso_sample;
		u32 sample_description_index;

		iso_sample = gf_isom_get_sample(movie, track_number, *sample_index, &sample_description_index);
		if (iso_sample) {
			fprintf(stdout, "Found sample #%5d/%5d of length %8d, RAP: %d, DTS: "LLD", CTS: "LLD"\n", *sample_index, sample_count, iso_sample->dataLength, iso_sample->IsRAP, iso_sample->DTS, iso_sample->DTS+iso_sample->CTS_Offset);
			(*sample_index)++;

			/* Release the sample data, once you're done with it*/
			gf_isom_sample_del(&iso_sample);
		} else {
			e = gf_isom_last_error(movie);
			if (e == GF_ISOM_INCOMPLETE_FILE) {
				missing_bytes = gf_isom_get_missing_bytes(movie, track_number);
				fprintf(stdout, "Missing "LLU" bytes on input file\n", missing_bytes);
				gf_sleep(1000);
			}
		}
	}
}
Пример #6
0
GF_Err gf_isom_setup_hint_track(GF_ISOFile *movie, u32 trackNumber, u32 HintType)
{
	GF_Err e;
	GF_TrackBox *trak;
	GF_TrackReferenceBox *tref;
	GF_TrackReferenceTypeBox *dpnd;
	GF_HintMediaHeaderBox *hmhd;
	//UDTA related ...
	GF_UserDataBox *udta;


	//what do we support
	switch (HintType) {
	case GF_ISOM_HINT_RTP:
		break;
	default:
		return GF_NOT_SUPPORTED;
	}
	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
	if (e) return e;

	trak = gf_isom_get_track_from_file(movie, trackNumber);
	if (!trak) return gf_isom_last_error(movie);

	//check we have a hint ...
	if ( !IsHintTrack(trak)) {
		return GF_BAD_PARAM;
	}
	hmhd = (GF_HintMediaHeaderBox *)trak->Media->information->InfoHeader;
	//make sure the subtype was not already defined
	if (hmhd->subType) return GF_BAD_PARAM;
	//store the HintTrack format for later use...
	hmhd->subType = HintType;

	
	//hint tracks always have a tref and everything ...
	if (!trak->References) {
		if (!trak->References) {
			tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF);
			e = trak_AddBox((GF_Box*)trak, (GF_Box *)tref);
			if (e) return e;
		}
	}
	tref = trak->References;

	//do we have a hint reference on this trak ???
	e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_HINT, &dpnd);
	if (e) return e;
	//if yes, return false (existing hint track...)
	if (dpnd) return GF_BAD_PARAM;

	//create our dep
	dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_REFT);
	dpnd->reference_type = GF_ISOM_BOX_TYPE_HINT;
	e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd);
	if (e) return e;

	//for RTP, we need to do some UDTA-related stuff...
	if (HintType != GF_ISOM_HINT_RTP) return GF_OK;

	if (!trak->udta) {
		//create one
		udta = (GF_UserDataBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_UDTA);
		e = trak_AddBox((GF_Box*)trak, (GF_Box *) udta);
		if (e) return e;
	}
	udta = trak->udta;

	//HNTI
	e = udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HNTI));
	if (e) return e;

/*
	//NAME
	e = udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_NAME));
	if (e) return e;
	//HINF
	return udta_AddBox(udta, gf_isom_box_new(GF_ISOM_BOX_TYPE_HINF));
*/
	return GF_OK;
}
Пример #7
0
GF_EXPORT
GF_ISOMRTPStreamer *gf_isom_streamer_new(const char *file_name, const char *ip_dest, u16 port, Bool loop, Bool force_mpeg4, u32 path_mtu, u32 ttl, char *ifce_addr)
{
	GF_ISOMRTPStreamer *streamer;
	GF_Err e = GF_OK;
	const char *opt = NULL;
	/*GF_Config *configFile = NULL;	*/
	u32 i, max_ptime, au_sn_len;	
	u8 payt;			
	GF_ISOFile *file;
	GF_RTPTrack *track, *prev_track;
	u16 first_port;
	u32 nb_tracks;
	u32 sess_data_size;

	if (!ip_dest) ip_dest = "127.0.0.1";
	if (!port) port = 7000;
	if (!path_mtu) path_mtu = 1450;

	GF_SAFEALLOC(streamer, GF_ISOMRTPStreamer);
	streamer->dest_ip = gf_strdup(ip_dest);

	payt = 96;
	max_ptime = au_sn_len = 0;

	file = gf_isom_open(file_name, GF_ISOM_OPEN_READ, NULL);
	if (!file) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("Error opening file %s: %s\n", opt, gf_error_to_string(gf_isom_last_error(NULL))));
		return NULL;
	}

	streamer->isom = file;
	streamer->loop = loop;
	streamer->force_mpeg4_generic = force_mpeg4;
	first_port = port;

	sess_data_size = 0;
	prev_track = NULL;
	
	nb_tracks = gf_isom_get_track_count(streamer->isom);
	for (i=0; i<nb_tracks; i++) {
		u32 mediaSize, mediaDuration, flags, MinSize, MaxSize, avgTS, streamType, oti, const_dur, nb_ch, samplerate, maxDTSDelta, TrackMediaSubType, TrackMediaType, bandwidth, IV_length, KI_length, dsi_len;
		const char *url, *urn;
		char *dsi;
		Bool is_crypted;
		
		dsi_len = samplerate = streamType = oti = nb_ch = IV_length = KI_length = 0;
		is_crypted = 0;
		dsi = NULL;

		flags = 0;

		/*we only support self-contained files for hinting*/
		gf_isom_get_data_reference(streamer->isom, i+1, 1, &url, &urn);
		if (url || urn) continue;

		TrackMediaType = gf_isom_get_media_type(streamer->isom, i+1);
		TrackMediaSubType = gf_isom_get_media_subtype(streamer->isom, i+1, 1);

		switch (TrackMediaType) {
		case GF_ISOM_MEDIA_TEXT:
			break;
		case GF_ISOM_MEDIA_VISUAL:
		case GF_ISOM_MEDIA_AUDIO:
		case GF_ISOM_MEDIA_SUBT:
		case GF_ISOM_MEDIA_OD:
		case GF_ISOM_MEDIA_SCENE:
			if (gf_isom_get_sample_description_count(streamer->isom, i+1) > 1) continue;
			break;
		default:
			continue;
		}

		GF_SAFEALLOC(track, GF_RTPTrack);
		if (prev_track) prev_track->next = track;
		else streamer->stream = track;
		prev_track = track;

		track->track_num = i+1;

		track->nb_aus = gf_isom_get_sample_count(streamer->isom, track->track_num);
		track->timescale = gf_isom_get_media_timescale(streamer->isom, track->track_num);
		mediaDuration = (u32)(gf_isom_get_media_duration(streamer->isom, track->track_num)*1000/track->timescale); // ms
		mediaSize = (u32)gf_isom_get_media_data_size(streamer->isom, track->track_num);

		sess_data_size += mediaSize;
		if (mediaDuration > streamer->duration_ms) streamer->duration_ms = mediaDuration;

		track->port = check_next_port(streamer, first_port);
		first_port = track->port+2;

		/*init packetizer*/
		if (streamer->force_mpeg4_generic) flags = GP_RTP_PCK_SIGNAL_RAP | GP_RTP_PCK_FORCE_MPEG4;


		switch (TrackMediaSubType) {
		case GF_ISOM_SUBTYPE_MPEG4_CRYP: 
			is_crypted = 1;
		case GF_ISOM_SUBTYPE_MPEG4:
		{	
			GF_ESD *esd = gf_isom_get_esd(streamer->isom, track->track_num, 1);
			if (esd) {
				streamType = esd->decoderConfig->streamType;
				oti = esd->decoderConfig->objectTypeIndication;

				/*systems streams*/
				if (streamType==GF_STREAM_AUDIO) {
					gf_isom_get_audio_info(streamer->isom, track->track_num, 1, &samplerate, &nb_ch, NULL);
				}
				/*systems streams*/
				else if (streamType==GF_STREAM_SCENE) {
					if (gf_isom_has_sync_shadows(streamer->isom, track->track_num) || gf_isom_has_sample_dependency(streamer->isom, track->track_num))
						flags |= GP_RTP_PCK_SYSTEMS_CAROUSEL;
				}
				
				if (esd->decoderConfig->decoderSpecificInfo) {
					dsi = esd->decoderConfig->decoderSpecificInfo->data;
					dsi_len = esd->decoderConfig->decoderSpecificInfo->dataLength;
					esd->decoderConfig->decoderSpecificInfo->data = NULL;
					esd->decoderConfig->decoderSpecificInfo->dataLength = 0;
				}
				gf_odf_desc_del((GF_Descriptor*)esd);
			}
		}
			break;
		case GF_ISOM_SUBTYPE_AVC_H264:
		case GF_ISOM_SUBTYPE_AVC2_H264:
		case GF_ISOM_SUBTYPE_SVC_H264:
		{
			GF_AVCConfig *avcc = gf_isom_avc_config_get(streamer->isom, track->track_num, 1);
			track->avc_nalu_size = avcc->nal_unit_size;
			gf_odf_avc_cfg_del(avcc);
			streamType = GF_STREAM_VISUAL;
			oti = GPAC_OTI_VIDEO_AVC;
		}
			break;
		default:
			streamType = GF_STREAM_4CC;
			oti = TrackMediaSubType;
			break;
		}
		
		/*get sample info*/
		gf_media_get_sample_average_infos(streamer->isom, track->track_num, &MinSize, &MaxSize, &avgTS, &maxDTSDelta, &const_dur, &bandwidth);

		if (is_crypted) {
			Bool use_sel_enc;
			gf_isom_get_ismacryp_info(streamer->isom, track->track_num, 1, NULL, NULL, NULL, NULL, NULL, &use_sel_enc, &IV_length, &KI_length);
			if (use_sel_enc) flags |= GP_RTP_PCK_SELECTIVE_ENCRYPTION;
		}

		track->rtp = gf_rtp_streamer_new_extended(streamType, oti, track->timescale, 
									(char *) streamer->dest_ip, track->port, path_mtu, ttl, ifce_addr, 
									flags, dsi, dsi_len, 								 
									 payt, samplerate, nb_ch,
									 is_crypted, IV_length, KI_length,
									 MinSize, MaxSize, avgTS, maxDTSDelta, const_dur, bandwidth, max_ptime, au_sn_len);

		if (!track->rtp) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("Could not initialize RTP streamer: %s\n", gf_error_to_string(e)));
			goto exit;
		}		

		payt++;
		track->microsec_ts_scale = 1000000;
		track->microsec_ts_scale /= gf_isom_get_media_timescale(streamer->isom, track->track_num);
	}
	return streamer;

exit:
	gf_free(streamer);
	return NULL;
} 
Пример #8
0
Файл: main.c Проект: Bevara/GPAC
int main (int argc, char **argv)
{
	Double fps_dump;
	u32 i;
	char rad[500];
	s32 frameID, h, m, s, f;
	Float fps;
	u32 dump_type;
	s32 dump_time;
	u32 dump_w, dump_h;
	Bool copy;
	char szConfigFile[4096];
	char *dump_out;
	char *inName, *arg;
	GF_ISOFile *file;

	if (argc < 2) {
		PrintUsage();
		return 0;
	}

	dump_type = 0;
	fps_dump = 0.0f;
	dump_w = dump_h = 0;
	dump_out = NULL;
	inName = NULL;
	frameID = -1;
	dump_time = -1;
	szConfigFile[0] = 0;

	for (i = 1; i < (u32) argc ; i++) {
		arg = argv[i];
		if (arg[0] != '-') {
			inName = arg;
			break;
		}
		if (!stricmp(arg, "-h")) {
			PrintUsage();
			return 0;
		} else if (!stricmp(arg, "-version")) {
			PrintVersion();
			return 0;
		} else if (!stricmp(arg, "-size")) {
			sscanf(argv[i+1], "%dx%d", &dump_w, &dump_h);
			i++;
		} else if (!stricmp(arg, "-raw")) {
			dump_type = 2;
			if ((i+1<(u32)argc) && (argv[i+1][0]!='-')) {
				if (strstr(argv[i+1], "T")) {
					if (strstr(argv[i+1], "F")) {
						sscanf(argv[i+1], "T%d:%d:%d:%dF%f", &h, &m, &s, &f, &fps);
						dump_time = (s32) ((3600*h + 60*m + s)*1000 + 1000*f/fps);
					} else {
						sscanf(argv[i+1], "T%d:%d:%d", &h, &m, &s);
						dump_time = (s32) ((3600*h + 60*m + s)*1000);
					}
				} else {
					frameID = atoi(argv[i+1]);
				}
				i++;
			}
		} else if (!stricmp(arg, "-bmp")) {
			dump_type = 1;
			if ((i+1<(u32)argc) && (argv[i+1][0]!='-')) {
				if (strstr(argv[i+1], "T")) {
					if (strstr(argv[i+1], "F")) {
						sscanf(argv[i+1], "T%d:%d:%d:%dF%f", &h, &m, &s, &f, &fps);
						dump_time = (s32) ((3600*h + 60*m + s)*1000 + 1000*f/fps);
					} else {
						sscanf(argv[i+1], "T%d:%d:%d", &h, &m, &s);
						dump_time = (s32) ((3600*h + 60*m + s)*1000);
					}
				} else {
					frameID = atoi(argv[i+1]);
				}
				i++;
			}
		} else if (!stricmp(arg, "-3d")) {
			dump_type = 3;
		} else if (!stricmp(arg, "-outpath")) {
			dump_out = argv[i+1];
			i++;
		} else if (!stricmp(arg, "-fps")) {
			fps_dump = atof(argv[i+1]);
			i++;
		} else if (!stricmp(arg, "-copy")) {
			copy = 1;
		} else if (!stricmp(arg, "-cfg")) {
			strcpy(szConfigFile, argv[i+1]);
			i += 1;
		} else {
			PrintUsage();
			return (0);
		}
	}
	if (!inName) {
		PrintUsage();
		return 0;
	}
	gf_sys_init();

	file = gf_isom_open(inName, GF_ISOM_OPEN_READ, NULL);
	if (!file) {
		printf("Error opening file: %s\n", gf_error_to_string(gf_isom_last_error(NULL)));
		return 0;
	}

	if (dump_out) {
		arg = strrchr(inName, GF_PATH_SEPARATOR);
		if (arg) {
			strcpy(rad, arg + 1);
		} else {
			strcpy(rad, inName);
		}
	} else {
		strcpy(rad, inName);
	}
	while (rad[strlen(rad)-1] != '.') rad[strlen(rad)-1] = 0;
	rad[strlen(rad)-1] = 0;
	if (dump_type == 3) {
		bifs3d_viewpoints_merger(file, szConfigFile, dump_w, dump_h, rad, dump_type, dump_out, fps_dump, frameID, dump_time);
	}
	else bifs_to_vid(file, szConfigFile, dump_w, dump_h, rad, dump_type, dump_out, fps_dump, frameID, dump_time);
	printf("\ndone\n");
	gf_isom_delete(file);
	return 0;

}
Пример #9
0
GF_Err gf_sm_load_init_isom(GF_SceneLoader *load)
{
	u32 i;
	GF_BIFSConfig *bc;
	GF_ESD *esd;
	GF_Err e;
	char *scene_msg = "MPEG-4 BIFS Scene Parsing";
	if (!load->isom) return GF_BAD_PARAM;

	/*load IOD*/
	load->ctx->root_od = (GF_ObjectDescriptor *) gf_isom_get_root_od(load->isom);
	if (!load->ctx->root_od) {
		e = gf_isom_last_error(load->isom);
		if (e) return e;
	} else if ((load->ctx->root_od->tag != GF_ODF_OD_TAG) && (load->ctx->root_od->tag != GF_ODF_IOD_TAG)) {
		gf_odf_desc_del((GF_Descriptor *) load->ctx->root_od);
		load->ctx->root_od = NULL;
	}

	esd = NULL;

	/*get root scene stream*/
	for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
		u32 type = gf_isom_get_media_type(load->isom, i+1);
		if (type != GF_ISOM_MEDIA_SCENE) continue;
		if (! gf_isom_is_track_in_root_od(load->isom, i+1) ) continue;
		esd = gf_isom_get_esd(load->isom, i+1, 1);

		if (esd && esd->URLString) {
			gf_odf_desc_del((GF_Descriptor *)esd);
			esd = NULL;
			continue;
		}

		/*make sure we load the root BIFS stream first*/
		if (esd && esd->dependsOnESID && (esd->dependsOnESID!=esd->ESID) ) {
			u32 track = gf_isom_get_track_by_id(load->isom, esd->dependsOnESID);
			if (gf_isom_get_media_type(load->isom, track) != GF_ISOM_MEDIA_OD) {
				gf_odf_desc_del((GF_Descriptor *)esd);
				esd = NULL;
				continue;
			}
		}
		if (esd->decoderConfig->objectTypeIndication==0x09) scene_msg = "MPEG-4 LASeR Scene Parsing";
		break;
	}
	if (!esd) return GF_OK;

	e = GF_OK;
	GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("%s\n", scene_msg));

	/*BIFS: update size & pixel metrics info*/
	if (esd->decoderConfig->objectTypeIndication<=2) {
		bc = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication);
		if (!bc->elementaryMasks && bc->pixelWidth && bc->pixelHeight) {
			load->ctx->scene_width = bc->pixelWidth;
			load->ctx->scene_height = bc->pixelHeight;
			load->ctx->is_pixel_metrics = bc->pixelMetrics;
		}
		gf_odf_desc_del((GF_Descriptor *) bc);
		/*note we don't load the first BIFS AU to avoid storing the BIFS decoder, needed to properly handle quantization*/
	}
	/*LASeR*/
	else if (esd->decoderConfig->objectTypeIndication==0x09) {
		load->ctx->is_pixel_metrics = 1;
	}
	gf_odf_desc_del((GF_Descriptor *) esd);
	esd = NULL;

	load->process = gf_sm_load_run_isom;
	load->done = gf_sm_load_done_isom;
	load->suspend = gf_sm_isom_suspend;
	return GF_OK;
}
Пример #10
0
static GF_Err gf_sm_load_run_isom(GF_SceneLoader *load)
{
	GF_Err e;
	FILE *logs;
	u32 i, j, di, nbBifs, nbLaser, nb_samp, samp_done, init_offset;
	GF_StreamContext *sc;
	GF_ESD *esd;
	GF_ODCodec *od_dec;
#ifndef GPAC_DISABLE_BIFS
	GF_BifsDecoder *bifs_dec;
#endif
#ifndef GPAC_DISABLE_LASER
	GF_LASeRCodec *lsr_dec;
#endif

	if (!load || !load->isom) return GF_BAD_PARAM;

	nbBifs = nbLaser = 0;
	e = GF_OK;
#ifndef GPAC_DISABLE_BIFS
	bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1);
	gf_bifs_decoder_set_extraction_path(bifs_dec, load->localPath, load->fileName);
#endif
	od_dec = gf_odf_codec_new();
	logs = NULL;
#ifndef GPAC_DISABLE_LASER
	lsr_dec = gf_laser_decoder_new(load->scene_graph);
#endif
	esd = NULL;
	/*load each stream*/
	nb_samp = 0;
	for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
		u32 type = gf_isom_get_media_type(load->isom, i+1);
		switch (type) {
		case GF_ISOM_MEDIA_SCENE:
		case GF_ISOM_MEDIA_OD:
			nb_samp += gf_isom_get_sample_count(load->isom, i+1);
			break;
		default:
			break;
		}
	}
	samp_done = 1;
	gf_isom_text_set_streaming_mode(load->isom, 1);

	for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
		u32 type = gf_isom_get_media_type(load->isom, i+1);
		switch (type) {
		case GF_ISOM_MEDIA_SCENE:
		case GF_ISOM_MEDIA_OD:
			break;
		default:
			continue;
		}
		esd = gf_isom_get_esd(load->isom, i+1, 1);
		if (!esd) continue;


		if ((esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_AFX) ||
		        (esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE)
		   ) {
			nb_samp += gf_isom_get_sample_count(load->isom, i+1);
			continue;
		}
		sc = gf_sm_stream_new(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
		sc->streamType = esd->decoderConfig->streamType;
		sc->ESID = esd->ESID;
		sc->objectType = esd->decoderConfig->objectTypeIndication;
		sc->timeScale = gf_isom_get_media_timescale(load->isom, i+1);

		/*we still need to reconfig the BIFS*/
		if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
#ifndef GPAC_DISABLE_BIFS
			/*BIFS*/
			if (esd->decoderConfig->objectTypeIndication<=2) {
				if (!esd->dependsOnESID && nbBifs && !i)
					mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
				if (!esd->decoderConfig->decoderSpecificInfo) {
					/* Hack for T-DMB non compliant streams */
					e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, NULL, 0, esd->decoderConfig->objectTypeIndication);
				} else {
					e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
				}
				if (e) goto exit;
				nbBifs++;
			}
#endif

#ifndef GPAC_DISABLE_LASER
			/*LASER*/
			if (esd->decoderConfig->objectTypeIndication==0x09) {
				if (!esd->dependsOnESID && nbBifs && !i)
					mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
				e = gf_laser_decoder_configure_stream(lsr_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
				if (e) goto exit;
				nbLaser++;
			}
#endif
		}

		init_offset = 0;
		/*dump all AUs*/
		for (j=0; j<gf_isom_get_sample_count(load->isom, i+1); j++) {
			GF_AUContext *au;
			GF_ISOSample *samp = gf_isom_get_sample(load->isom, i+1, j+1, &di);
			if (!samp) {
				mp4_report(load, gf_isom_last_error(load->isom), "Unable to fetch sample %d from track ID %d - aborting track import", j+1, gf_isom_get_track_id(load->isom, i+1));
				break;
			}
			/*check if track has initial offset*/
			if (!j && gf_isom_get_edit_segment_count(load->isom, i+1)) {
				u64 EditTime, dur, mtime;
				u8 mode;
				gf_isom_get_edit_segment(load->isom, i+1, 1, &EditTime, &dur, &mtime, &mode);
				if (mode==GF_ISOM_EDIT_EMPTY) {
					init_offset = (u32) (dur * sc->timeScale / gf_isom_get_timescale(load->isom) );
				}
			}
			samp->DTS += init_offset;

			au = gf_sm_stream_au_new(sc, samp->DTS, ((Double)(s64) samp->DTS) / sc->timeScale, (samp->IsRAP==RAP) ? 1 : 0);

			if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
#ifndef GPAC_DISABLE_BIFS
				if (esd->decoderConfig->objectTypeIndication<=2)
					e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
#endif
#ifndef GPAC_DISABLE_LASER
				if (esd->decoderConfig->objectTypeIndication==0x09)
					e = gf_laser_decode_command_list(lsr_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
#endif
			} else {
				e = gf_odf_codec_set_au(od_dec, samp->data, samp->dataLength);
				if (!e) e = gf_odf_codec_decode(od_dec);
				if (!e) {
					while (1) {
						GF_ODCom *odc = gf_odf_codec_get_com(od_dec);
						if (!odc) break;
						/*update ESDs if any*/
						UpdateODCommand(load->isom, odc);
						gf_list_add(au->commands, odc);
					}
				}
			}
			gf_isom_sample_del(&samp);
			if (e) {
				mp4_report(load, gf_isom_last_error(load->isom), "decoding sample %d from track ID %d failed", j+1, gf_isom_get_track_id(load->isom, i+1));
				goto exit;
			}

			samp_done++;
			gf_set_progress("MP4 Loading", samp_done, nb_samp);
		}
		gf_odf_desc_del((GF_Descriptor *) esd);
		esd = NULL;
	}
	gf_isom_text_set_streaming_mode(load->isom, 0);

exit:
#ifndef GPAC_DISABLE_BIFS
	gf_bifs_decoder_del(bifs_dec);
#endif
	gf_odf_codec_del(od_dec);
#ifndef GPAC_DISABLE_LASER
	gf_laser_decoder_del(lsr_dec);
#endif
	if (esd) gf_odf_desc_del((GF_Descriptor *) esd);
	if (logs) gf_fclose(logs);
	return e;
}
Пример #11
0
Файл: main.c Проект: erelh/gpac
int main(int argc, char **argv)
{
	GF_ISOFile *movie;
	GF_ESD *esd;
	GF_Err e;
	Double gb_size = 5.0;
	u8 store_mode;
	u32 track, di, i, nb_samp;
	GF_ISOSample *samp;

	store_mode = GF_ISOM_OPEN_WRITE;
	for (i=1; i<argc; i++) {
		if (!strcmp(argv[i], "-flat")) store_mode = GF_ISOM_OPEN_WRITE;
		else if (!strcmp(argv[i], "-inter")) store_mode = GF_ISOM_WRITE_EDIT;
		else if (!strcmp(argv[i], "-size") && (i+1<argc)) {
			gb_size = atof(argv[i+1]);
			i++;
		}
		else if (!strcmp(argv[i], "-h")) {
			PrintUsage();
			return 0;
		}
	}

	nb_samp = (u32) (gb_size*1024);
	fprintf(stdout, "Creating test file %s - %g GBytes - %d samples - %s mode\n", TEST_FILE_NAME, gb_size, nb_samp, (store_mode == GF_ISOM_OPEN_WRITE) ? "Flat" : "Interleaved");

	movie = gf_isom_open(TEST_FILE_NAME, store_mode, NULL);
	if (!movie) {
		fprintf(stdout, "Error creating file: %s\n", gf_error_to_string(gf_isom_last_error(NULL)));
		return 1;
	}

	track = gf_isom_new_track(movie, 1, GF_ISOM_MEDIA_VISUAL, 25);
	esd = gf_odf_desc_esd_new(2);
	esd->decoderConfig->streamType = 4;
	gf_isom_new_mpeg4_description(movie, track, esd, NULL, NULL, &di);

	samp = gf_isom_sample_new();
	samp->dataLength = 1024*1024;
	samp->data = gf_malloc(sizeof(char)*samp->dataLength);
  memset(samp->data, 0, sizeof(char)*samp->dataLength);

	for (i=0; i<nb_samp; i++) {
		if (samp->DTS % 25) samp->IsRAP = 0;
		else samp->IsRAP = 1;
		e = gf_isom_add_sample(movie, track, di, samp);
		samp->DTS += 1;

		fprintf(stdout, "Writing sample %d / %d \r", i+1, nb_samp);
		if (e) break;
	}
	gf_isom_sample_del(&samp);

	if (e) {
		fprintf(stdout, "\nError writing sample %d\n", i);
		gf_isom_delete(movie);
		return 1;
	}

	fprintf(stdout, "\nDone writing samples\n");
	e = gf_isom_close(movie);
	if (e) {
		fprintf(stdout, "Error writing file\n");
		return 1;
	}
	return 0;
}
Пример #12
0
/*fixme, this doesn't work properly with respect to @expect_type*/
static GF_Descriptor *ISOR_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
{
    u32 count, nb_st, i, trackID;
    GF_ESD *esd;
    ISOMReader *read;
    GF_InitialObjectDescriptor *iod;
    if (!plug || !plug->priv) return NULL;
    read = (ISOMReader *) plug->priv;
    if (!read->mov) return NULL;

    /*no matter what always read text as TTUs*/
    gf_isom_text_set_streaming_mode(read->mov, 1);

    trackID = 0;
    if (!sub_url) {
        trackID = read->base_track_id;
        read->base_track_id = 0;
    } else {
        char *ext = strrchr(sub_url, '#');
        if (!ext) {
            trackID = 0;
        } else {
            if (!strnicmp(ext, "#trackID=", 9)) trackID = atoi(ext+9);
            else if (!stricmp(ext, "#video")) trackID = get_track_id(read->mov, GF_ISOM_MEDIA_VISUAL, 0);
            else if (!strnicmp(ext, "#video", 6)) {
                trackID = atoi(ext+6);
                trackID = get_track_id(read->mov, GF_ISOM_MEDIA_VISUAL, trackID);
            }
            else if (!stricmp(ext, "#audio")) trackID = get_track_id(read->mov, GF_ISOM_MEDIA_AUDIO, 0);
            else if (!strnicmp(ext, "#audio", 6)) {
                trackID = atoi(ext+6);
                trackID = get_track_id(read->mov, GF_ISOM_MEDIA_AUDIO, trackID);
            }
            else trackID = atoi(ext+1);

            /*if trackID is 0, assume this is a fragment identifier*/
        }
    }

    if (!trackID && (expect_type!=GF_MEDIA_OBJECT_SCENE) && (expect_type!=GF_MEDIA_OBJECT_UNDEF)) {
        for (i=0; i<gf_isom_get_track_count(read->mov); i++) {
            u32 type = gf_isom_get_media_type(read->mov, i+1);
            if (
                ((type==GF_ISOM_MEDIA_VISUAL) && (expect_type==GF_MEDIA_OBJECT_VIDEO))
                || ((type==GF_ISOM_MEDIA_AUDIO) && (expect_type==GF_MEDIA_OBJECT_AUDIO)) ) {
                trackID = gf_isom_get_track_id(read->mov, i+1);
                break;
            }

        }
    }
    if (trackID && (expect_type!=GF_MEDIA_OBJECT_SCENE) ) {
        u32 track = gf_isom_get_track_by_id(read->mov, trackID);
        if (!track) return NULL;
        esd = gf_media_map_esd(read->mov, track);
        esd->OCRESID = 0;
        iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(read->mov);
        if (!iod) {
            iod = (GF_InitialObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
            iod->OD_profileAndLevel = iod->audio_profileAndLevel = iod->graphics_profileAndLevel = iod->scene_profileAndLevel = iod->visual_profileAndLevel = 0xFE;
        } else {
            while (gf_list_count(iod->ESDescriptors)) {
                GF_ESD *old = (GF_ESD *)gf_list_get(iod->ESDescriptors, 0);
                gf_odf_desc_del((GF_Descriptor *) old);
                gf_list_rem(iod->ESDescriptors, 0);
            }
        }
        gf_list_add(iod->ESDescriptors, esd);
        isor_emulate_chapters(read->mov, iod);
        return (GF_Descriptor *) iod;
    }

    iod = NULL;
    if (check_mpeg4_systems(plug, read->mov)) {
        iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(read->mov);
        if (!iod) {
#ifndef GPAC_DISABLE_LOG
            GF_Err e = gf_isom_last_error(read->mov);
            if (e) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IsoMedia] Cannot fetch MPEG-4 IOD (error %s) - generating one\n", gf_error_to_string(e) ));
            } else {
                GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[IsoMedia] No MPEG-4 IOD found in file - generating one\n"));
            }
#endif
        }
    }
    if (!iod) return isor_emulate_iod(read);

    count = gf_list_count(iod->ESDescriptors);
    if (!count) {
        gf_odf_desc_del((GF_Descriptor*) iod);
        return isor_emulate_iod(read);
    }
    if (count==1) {
        esd = (GF_ESD *)gf_list_get(iod->ESDescriptors, 0);
        switch (esd->decoderConfig->streamType) {
        case GF_STREAM_SCENE:
        case GF_STREAM_PRIVATE_SCENE:
            break;
        case GF_STREAM_VISUAL:
            if (expect_type!=GF_MEDIA_OBJECT_VIDEO) {
                gf_odf_desc_del((GF_Descriptor*) iod);
                return isor_emulate_iod(read);
            }
            break;
        case GF_STREAM_AUDIO:
            /*we need a fake scene graph*/
            if (expect_type!=GF_MEDIA_OBJECT_AUDIO) {
                gf_odf_desc_del((GF_Descriptor*) iod);
                return isor_emulate_iod(read);
            }
            break;
        default:
            gf_odf_desc_del((GF_Descriptor*) iod);
            return NULL;
        }
    }
    /*check IOD is not badly formed (eg mixing audio, video or text streams)*/
    nb_st = 0;
    for (i=0; i<count; i++) {
        esd = (GF_ESD *)gf_list_get(iod->ESDescriptors, i);
        switch (esd->decoderConfig->streamType) {
        case GF_STREAM_VISUAL:
            nb_st |= 1;
            break;
        case GF_STREAM_AUDIO:
            nb_st |= 2;
            break;
        case GF_STREAM_TEXT:
            nb_st |= 4;
            break;
        }
    }
    if ( (nb_st & 1) + (nb_st & 2) + (nb_st & 4) > 1) {
        gf_odf_desc_del((GF_Descriptor*) iod);
        return isor_emulate_iod(read);
    }

    isor_emulate_chapters(read->mov, iod);
    return (GF_Descriptor *) iod;
}
Пример #13
0
void isor_net_io(void *cbk, GF_NETIO_Parameter *param)
{
    GF_Err e;
    u32 size = 0;
    char *local_name;
    ISOMReader *read = (ISOMReader *) cbk;

    /*handle service message*/
    gf_term_download_update_stats(read->dnload);

    if (param->msg_type==GF_NETIO_DATA_TRANSFERED) {
        e = GF_EOS;
    } else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) {
        e = GF_OK;
        size = param->size;
    } else {
        e = param->error;
    }

    if (e<GF_OK) {
        /*error opening service*/
        if (!read->mov) gf_term_on_connect(read->service, NULL, e);
        return;
    }

    /*open file if not done yet (bad interleaving)*/
    if (e==GF_EOS) {
        const char *local_name;
        if (read->mov) return;
        local_name = gf_dm_sess_get_cache_name(read->dnload);
        if (!local_name) {
            gf_term_on_connect(read->service, NULL, GF_SERVICE_ERROR);
            return;
        }
        e = GF_OK;
        read->mov = gf_isom_open(local_name, GF_ISOM_OPEN_READ, NULL);
        if (!read->mov) e = gf_isom_last_error(NULL);
        else read->time_scale = gf_isom_get_timescale(read->mov);
        gf_term_on_connect(read->service, NULL, GF_OK);
        if (read->no_service_desc) isor_declare_objects(read);
    }

    if (!size) return;

    /*service is opened, nothing to do*/
    if (read->mov) return;

    /*try to open the service*/
    local_name = (char *)gf_dm_sess_get_cache_name(read->dnload);
    if (!local_name) {
        gf_term_on_connect(read->service, NULL, GF_SERVICE_ERROR);
        return;
    }

    /*not enogh data yet*/
    if (read->missing_bytes && (read->missing_bytes > size) ) {
        read->missing_bytes -= size;
        return;
    }

    e = gf_isom_open_progressive(local_name, 0, 0, &read->mov, &read->missing_bytes);
    switch (e) {
    case GF_ISOM_INCOMPLETE_FILE:
        return;
    case GF_OK:
        break;
    default:
        gf_term_on_connect(read->service, NULL, e);
        return;
    }
    read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0;

    /*ok let's go*/
    read->time_scale = gf_isom_get_timescale(read->mov);
    gf_term_on_connect(read->service, NULL, GF_OK);
    if (read->no_service_desc) isor_declare_objects(read);
}
Пример #14
0
void isor_net_io(void *cbk, GF_NETIO_Parameter *param)
{
	GF_Err e;
	u32 size = 0;
	char *local_name;
	ISOMReader *read = (ISOMReader *) cbk;

	/*handle service message*/
	if (!read->buffering)
		gf_service_download_update_stats(read->dnload);

	if (param->msg_type==GF_NETIO_DATA_TRANSFERED) {
		e = GF_EOS;
	} else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) {
		e = GF_OK;
		size = param->size;
	} else {
		e = param->error;
	}

	if (e<GF_OK) {
		/*error opening service*/
		if (!read->mov) {
			/* if there is an intermediate between this module and the terminal, report to it */
			if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
				send_proxy_command(read, GF_FALSE, GF_FALSE, e, NULL, NULL);
			} else {
				gf_service_connect_ack(read->service, NULL, e);
			}
		}
		return;
	}

	/*open file if not done yet (bad interleaving)*/
	if (e==GF_EOS) {
		const char *local_name;
		if (read->mov) return;
		local_name = gf_dm_sess_get_cache_name(read->dnload);
		if (!local_name) {
			if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
				send_proxy_command(read, GF_FALSE, GF_FALSE, GF_SERVICE_ERROR, NULL, NULL);
			} else {
				gf_service_connect_ack(read->service, NULL, GF_SERVICE_ERROR);
			}
			return;
		}
		e = GF_OK;
		read->mov = gf_isom_open(local_name, GF_ISOM_OPEN_READ, NULL);
		if (!read->mov) e = gf_isom_last_error(NULL);
		else read->time_scale = gf_isom_get_timescale(read->mov);
		read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0;
		if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
			send_proxy_command(read, GF_FALSE, GF_FALSE, GF_OK, NULL, NULL);
		} else {
			gf_service_connect_ack(read->service, NULL, GF_OK);
		}
		if (read->no_service_desc) isor_declare_objects(read);
	}

	if (!size) return;

	/*service is opened, nothing to do*/
	if (read->mov) {
		isor_check_buffer_level(read);

		/*end of chunk*/
		if (read->frag_type && (param->reply==1) ) {
			u64 bytesMissing = 0;
			gf_mx_p(read->segment_mutex);
			e = gf_isom_refresh_fragmented(read->mov, &bytesMissing, NULL);
			gf_mx_v(read->segment_mutex);
		}
		return;
	}

	/*try to open the service*/
	local_name = (char *)gf_dm_sess_get_cache_name(read->dnload);
	if (!local_name) {
		if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
			send_proxy_command(read, GF_FALSE, GF_FALSE, GF_SERVICE_ERROR, NULL, NULL);
		} else {
			gf_service_connect_ack(read->service, NULL, GF_SERVICE_ERROR);
		}
		return;
	}

	/*not enogh data yet*/
	if (read->missing_bytes && (read->missing_bytes > size) ) {
		read->missing_bytes -= size;
		return;
	}

	e = gf_isom_open_progressive(local_name, 0, 0, &read->mov, &read->missing_bytes);
	switch (e) {
	case GF_ISOM_INCOMPLETE_FILE:
		return;
	case GF_OK:
		break;
	default:
		if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
			send_proxy_command(read, GF_FALSE, GF_FALSE, e, NULL, NULL);
		} else {
			gf_service_connect_ack(read->service, NULL, e);
		}
		return;
	}
	read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0;

	/*ok let's go, we can setup the decoders */
	read->time_scale = gf_isom_get_timescale(read->mov);
	if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) {
		send_proxy_command(read, GF_FALSE, GF_FALSE, GF_OK, NULL, NULL);
	} else {
		gf_service_connect_ack(read->service, NULL, GF_OK);
	}

	if (read->no_service_desc) isor_declare_objects(read);
}
Пример #15
0
static u32 iso_progressive_read_thread(void *param)
{
	ISOProgressiveReader *reader = (ISOProgressiveReader *)param;
	u32 track_number;
	GF_ISOSample *iso_sample;
	u32 samples_processed;
	u32 sample_index;
	u32 sample_count;

	samples_processed = 0;
	sample_count = 0;
	track_number = 0;
	/* samples are numbered starting from 1 */
	sample_index = 1;

	while (reader->do_run == GF_TRUE) {

		/* we can only parse if there is a movie */
		if (reader->movie) {

			/* block the data input until we are done in the parsing */
			gf_mx_p(reader->mutex);

			/* get the track number we want */
			if (track_number == 0) {
				track_number = gf_isom_get_track_by_id(reader->movie, reader->track_id);
			}

			/* only if we have the track number can we try to get the sample data */
			if (track_number != 0) {
				u32 new_sample_count;
				u32 di; /*descriptor index*/

				/* let's see how many samples we have since the last parsed */
				new_sample_count = gf_isom_get_sample_count(reader->movie, track_number);
				if (new_sample_count > sample_count) {
					/* New samples have been added to the file */
					fprintf(stdout, "Found %d new samples (total: %d)\n", new_sample_count - sample_count, new_sample_count);
					if (sample_count == 0) {
						sample_count = new_sample_count;
					}
				}
				if (sample_count == 0) {
					/*let the reader push new data */
					gf_mx_v(reader->mutex);
					//gf_sleep(1000);
				} else {
					/* let's analyze the samples we have parsed so far one by one */
					iso_sample = gf_isom_get_sample(reader->movie, track_number, sample_index, &di);
					if (iso_sample) {
						/* if you want the sample description data, you can call:
						   GF_Descriptor *desc = gf_isom_get_decoder_config(reader->movie, reader->track_handle, di);
						*/

						samples_processed++;
						/*here we dump some sample info: samp->data, samp->dataLength, samp->isRAP, samp->DTS, samp->CTS_Offset */
						fprintf(stdout, "Found sample #%5d (#%5d) of length %8d, RAP: %d, DTS: "LLD", CTS: "LLD"\r", sample_index, samples_processed, iso_sample->dataLength, iso_sample->IsRAP, iso_sample->DTS, iso_sample->DTS+iso_sample->CTS_Offset);
						sample_index++;

						/*release the sample data, once you're done with it*/
						gf_isom_sample_del(&iso_sample);

						/* once we have read all the samples, we can release some data and force a reparse of the input buffer */
						if (sample_index > sample_count) {
							u64 new_buffer_start;
							u64 missing_bytes;

							fprintf(stdout, "\nReleasing unnecessary buffers\n");
							/* release internal structures associated with the samples read so far */
							gf_isom_reset_tables(reader->movie, GF_TRUE);

#if 1
							/* release the associated input data as well */
							gf_isom_reset_data_offset(reader->movie, &new_buffer_start);
							if (new_buffer_start) {
								u32 offset = (u32)new_buffer_start;
								memmove(reader->data, reader->data+offset, reader->data_size-offset);
								reader->valid_data_size -= offset;
							}
							sprintf(reader->data_url, "gmem://%d@%p", reader->valid_data_size, reader->data);
							gf_isom_refresh_fragmented(reader->movie, &missing_bytes, reader->data_url);
#endif

							/* update the sample count and sample index */
							sample_count = new_sample_count - sample_count;
							assert(sample_count == 0);
							sample_index = 1;
						}
					} else {
						GF_Err e = gf_isom_last_error(reader->movie);
						fprintf(stdout, "Could not get sample %s\r", gf_error_to_string(e));
					}
					/* and finally, let the data reader push more data */
					gf_mx_v(reader->mutex);
				}
			}
		} else {
			//gf_sleep(1);
		}
	}
	return 0;
}