Example #1
0
/*render : setup media sensor and update timing in case of inline scenes*/
void RenderMediaSensor(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	GF_Clock *ck;
	Bool do_update_clock = 1;
	MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node);

	if (is_destroy) {
		/*unlink from OD*/
		if (st->stream && st->stream->odm)
			gf_list_del_item(st->stream->odm->ms_stack, st);

		gf_list_del(st->seg);
		gf_free(st);
		return;
	}
	//we need to disable culling otherwise we may never be called back again ...
	tr_state->disable_cull = 1;

	if (!st->stream) st->stream = gf_mo_register(node, &st->sensor->url, 0, 0);
	if (!st->stream || !st->stream->odm) return;

	if (!st->is_init) {
		gf_list_add(st->stream->odm->ms_stack, st);
		gf_odm_init_segments(st->stream->odm, st->seg, &st->sensor->url);
		st->is_init = 1;
		st->active_seg = 0;

	}
	/*media sensor bound to natural media (audio, video) is updated when fetching the stream
	data for rendering.*/

	ck = NULL;
	/*check inline scenes - if the scene is set to restart DON'T MODIFY SENSOR: since we need a 2 render
	passes to restart inline, scene is considered as not running*/
	if (st->stream->odm->subscene && !st->stream->odm->subscene->needs_restart) {
		if (st->stream->odm->subscene->scene_codec) ck = st->stream->odm->subscene->scene_codec->ck;
		/*dynamic scene*/
		else ck = st->stream->odm->subscene->dyn_ck;
		if (st->stream->odm->subscene->is_dynamic_scene) do_update_clock = 0;
	}
	/*check anim streams*/
	else if (st->stream->odm->codec && (st->stream->odm->codec->type==GF_STREAM_SCENE)) ck = st->stream->odm->codec->ck;
	/*check OCR streams*/
	else if (st->stream->odm->ocr_codec) ck = st->stream->odm->ocr_codec->ck;

	if (ck && gf_clock_is_started(ck) ) {
		if (do_update_clock)
			st->stream->odm->media_current_time = gf_clock_media_time(ck);
		mediasensor_update_timing(st->stream->odm, 0);
	}
	//if main addon is VoD and selected and clock is paused, fire a timeshift update
	else if (st->stream->odm->subscene && st->stream->odm->subscene->sys_clock_at_main_activation) {
		GF_Event evt;
		memset(&evt, 0, sizeof(evt));
		evt.type = GF_EVENT_TIMESHIFT_UPDATE;
		gf_term_send_event(st->stream->odm->term, &evt);
	}
}
Example #2
0
GF_EXPORT
void gf_service_download_update_stats(GF_DownloadSession * sess)
{
	GF_ClientService *serv;
	const char *szURI;
	u32 total_size, bytes_done, bytes_per_sec;
	GF_NetIOStatus net_status;

	if (!sess) return;

	gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status);
	serv = (GF_ClientService *)gf_dm_sess_get_private(sess);
	switch (net_status) {
	case GF_NETIO_SETUP:
		gf_term_message(serv->term, serv->url, "Connecting", GF_OK);
		break;
	case GF_NETIO_CONNECTED:
		gf_term_message(serv->term, serv->url, "Connected", GF_OK);
		break;
	case GF_NETIO_WAIT_FOR_REPLY:
		gf_term_message(serv->term, serv->url, "Waiting for reply...", GF_OK);
		break;
	case GF_NETIO_PARSE_REPLY:
		gf_term_message(serv->term, serv->url, "Starting download...", GF_OK);
		break;
	case GF_NETIO_DATA_EXCHANGE:
		/*notify some connection / ...*/
		if (total_size) {
			GF_Event evt;
			evt.type = GF_EVENT_PROGRESS;
			evt.progress.progress_type = 1;
			evt.progress.service = szURI;
			evt.progress.total = total_size;
			evt.progress.done = bytes_done;
			evt.progress.bytes_per_seconds = bytes_per_sec;
			gf_term_send_event(serv->term, &evt);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size));
		gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec);
		break;
	case GF_NETIO_DATA_TRANSFERED:
		gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE);
		if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			if (!gf_clock_is_started(ck)) {
				GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n"));
				if (serv->is_paused) {
					serv->is_paused = 0;
#ifndef GPAC_DISABLE_VRML
					mediacontrol_resume(serv->owner, 0);
#endif
				}
			}
		}
		break;
	default:
		break;
	}
}
static void check_keyboard(GF_Terminal *term)
{
	if (gf_prompt_has_input()) {
		switch (gf_prompt_get_char()) {
		case 'q':
			{
				GF_Event evt;
				memset(&evt, 0, sizeof(GF_Event));
				evt.type = GF_EVENT_QUIT;
				gf_term_send_event(term, &evt);
			}
			break;
		}
	}
}
Example #4
0
JSBool SMJS_FUNCTION(widget_open_url)
{
	GF_Event evt;
	SMJS_OBJ
	SMJS_ARGS
	GF_WidgetInstance *wid = (GF_WidgetInstance *)SMJS_GET_PRIVATE(c, obj);
	if (!wid || !argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;

	memset(&evt, 0, sizeof(GF_Event));
	evt.type = GF_EVENT_NAVIGATE;
	evt.navigate.to_url = SMJS_CHARS(c, argv[0]);
	gf_term_send_event(wid->widget->wm->term, &evt);
	SMJS_FREE(c, (char *)evt.navigate.to_url);

	return JS_TRUE;
}
Example #5
0
static void anchor_activation(GF_Node *node, AnchorStack *st, GF_Compositor *compositor)
{
	GF_Event evt;
	u32 i;
	MFURL *url = NULL;
	switch (gf_node_get_tag(node)) {
	case TAG_MPEG4_Anchor:
		url = & ((M_Anchor *)node)->url;
		evt.navigate.param_count = ((M_Anchor *)node)->parameter.count;
		evt.navigate.parameters = (const char **) ((M_Anchor *)node)->parameter.vals;
		break;
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Anchor:
		url = & ((X_Anchor *)node)->url;
		evt.navigate.param_count = ((X_Anchor *)node)->parameter.count;
		evt.navigate.parameters = (const char **) ((X_Anchor *)node)->parameter.vals;
		break;
#endif
	}
	evt.type = GF_EVENT_NAVIGATE;
	i=0;
	while (url && i<url->count) {
		evt.navigate.to_url = url->vals[i].url;
		if (!evt.navigate.to_url) break;
		/*current scene navigation*/
		if (evt.navigate.to_url[0] == '#') {
			GF_Node *bindable;
			evt.navigate.to_url++;
			bindable = gf_sg_find_node_by_name(gf_node_get_graph(node), (char *) evt.navigate.to_url);
			if (bindable) {
				Bindable_SetSetBind(bindable, 1);
				break;
			}
		} else if (compositor->term) {
			if (gf_scene_process_anchor(node, &evt))
				break;
		} else if (gf_term_send_event(compositor->term, &evt)) {
			break;
		}
		i++;
	}
}
Example #6
0
static Bool OnAnchor(GF_SensorHandler *sh, Bool is_over, Bool is_cancel, GF_Event *ev, GF_Compositor *compositor)
{
	GF_Event evt;
	MFURL *url = NULL;
	AnchorStack *st = (AnchorStack *) gf_node_get_private(sh->sensor);

	if ((ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) st->active = 1;
	else if ((ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) st->active = 1;
	else if (st->active && (
	             /*mouse*/ ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT))
	             || /*mouse*/((ev->type==GF_EVENT_KEYUP) && (ev->key.key_code==GF_KEY_ENTER))
	         ) ) {
		if (!is_cancel) anchor_activation(sh->sensor, st, compositor);
	} else if (is_over && !st->over) {
		st->over = 1;
		if (compositor->user->EventProc) {
			evt.type = GF_EVENT_NAVIGATE_INFO;
			switch (gf_node_get_tag(sh->sensor)) {
			case TAG_MPEG4_Anchor:
				evt.navigate.to_url = ((M_Anchor *)sh->sensor)->description.buffer;
				url = & ((M_Anchor *)sh->sensor)->url;
				break;
#ifndef GPAC_DISABLE_X3D
			case TAG_X3D_Anchor:
				evt.navigate.to_url = ((X_Anchor *)sh->sensor)->description.buffer;
				url = & ((X_Anchor *)sh->sensor)->url;
				break;
#endif
			}
			if (url && (!evt.navigate.to_url || !strlen(evt.navigate.to_url))) evt.navigate.to_url = url->vals[0].url;
			gf_term_send_event(compositor->term, &evt);
		}
	} else if (!is_over) {
		st->over = 0;
	}
	return 0;
}
Example #7
0
static void term_on_connect(void *user_priv, GF_ClientService *service, LPNETCHANNEL netch, GF_Err err)
{
	GF_Channel *ch;
	GF_ObjectManager *root;
	GET_TERM();

	GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] %s connection ACK received from %s - %s\n", netch ? "Channel" : "Service", service->url, gf_error_to_string(err) ));

	root = service->owner;
	if (root && (root->net_service != service)) {
		gf_term_message(term, service->url, "Incompatible module type", GF_SERVICE_ERROR);
		return;
	}
	/*this is service connection*/
	if (!netch) {
		gf_term_service_media_event(service->owner, GF_EVENT_MEDIA_SETUP_DONE);
		if (err) {
			char msg[5000];
			snprintf(msg, sizeof(msg)-1, "Cannot open %s", service->url);
			gf_term_message(term, service->url, msg, err);

			gf_term_service_media_event(service->owner, GF_EVENT_ERROR);

			/*destroy service only if attached*/
			if (root) {
				gf_term_lock_media_queue(term, 1);
				service->ifce->CloseService(service->ifce);
				root->net_service = NULL;
				if (service->owner && service->nb_odm_users) service->nb_odm_users--;
				service->owner = NULL;
				/*depends on module: some module could forget to call gf_term_on_disconnect */
				if ( gf_list_del_item(term->net_services, service) >= 0) {
					/*and queue for destroy*/
					gf_list_add(term->net_services_to_remove, service);
				}
				gf_term_lock_media_queue(term, 0);

				if (!root->parentscene) {
					GF_Event evt;
					evt.type = GF_EVENT_CONNECT;
					evt.connect.is_connected = 0;
					gf_term_send_event(term, &evt);
				} else {
					if (root->subscene) gf_scene_notify_event(root->subscene, GF_EVENT_SCENE_ATTACHED, NULL, NULL, err);
					/*try to reinsert OD for VRML/X3D with multiple URLs:
					1- first remove from parent scene without destroying object, this will trigger a re-setup
					if other URLs are present
					2- then destroy object*/
					gf_scene_remove_object(root->parentscene, root, 0);
					gf_odm_disconnect(root, 1);
				}
				return;
			}
		}

		if (!root) {
			/*channel service connect*/
			u32 i;
			GF_ChannelSetup *cs;
			GF_List *ODs;

			if (!gf_list_count(term->channels_pending)) {
				return;
			}
			ODs = gf_list_new();
			gf_term_lock_net(term, 1);
			i=0;
			while ((cs = (GF_ChannelSetup*)gf_list_enum(term->channels_pending, &i))) {
				if (cs->ch->service != service) continue;
				gf_list_rem(term->channels_pending, i-1);
				i--;
				/*even if error do setup (channel needs to be deleted)*/
				if (gf_odm_post_es_setup(cs->ch, cs->dec, err) == GF_OK) {
					if (cs->ch->odm && (gf_list_find(ODs, cs->ch->odm)==-1) ) gf_list_add(ODs, cs->ch->odm);
				}
				gf_free(cs);
			}
			gf_term_lock_net(term, 0);
			/*finally setup all ODs concerned (we do this later in case of scalability)*/
			while (gf_list_count(ODs)) {
				GF_ObjectManager *odm = (GF_ObjectManager*)gf_list_get(ODs, 0);
				gf_list_rem(ODs, 0);
				/*force re-setup*/
				gf_scene_setup_object(odm->parentscene, odm);
			}
			gf_list_del(ODs);
		} else {
			/*setup od*/
			gf_odm_setup_entry_point(root, service->url);
		}
		/*load cache if requested*/
		if (!err && term->enable_cache) {
			err = gf_term_service_cache_load(service);
			/*not a fatal error*/
			if (err) gf_term_message(term, "GPAC Cache", "Cannot load cache", err);
		}
		return;
	}

	/*this is channel connection*/
	ch = gf_term_get_channel(service, netch);
	if (!ch) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Terminal] Channel connection ACK error: channel not found\n"));
		return;
	}

	/*confirm channel connection even if error - this allow playback of objects even if not all streams are setup*/
	gf_term_lock_net(term, 1);
	gf_es_on_connect(ch);
	gf_term_lock_net(term, 0);

	if (err && ((err!=GF_STREAM_NOT_FOUND) || (ch->esd->decoderConfig->streamType!=GF_STREAM_INTERACT))) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Terminal] Channel %d connection error: %s\n", ch->esd->ESID, gf_error_to_string(err) ));
		ch->es_state = GF_ESM_ES_UNAVAILABLE;
/*		return;*/
	}

	if (ch->odm->mo) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Channel %d connected - %d objects opened\n", ch->esd->ESID, ch->odm->mo->num_open ));
	} else {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Channel %d connected - not attached to the scene\n", ch->esd->ESID));
	}
	/*Plays request are skiped until all channels are connected. We send a PLAY on the objecy in case
		1-OD user has requested a play
		2-this is a channel of the root OD
	*/
	if ( (ch->odm->mo && ch->odm->mo->num_open)
		|| !ch->odm->parentscene
	) {
		gf_odm_start(ch->odm, 0);
	}
#if 0
	else if (ch->odm->codec && ch->odm->codec->ck && ch->odm->codec->ck->no_time_ctrl) {
		gf_odm_play(ch->odm);
	}
#endif
}
Example #8
0
static void term_on_command(void *user_priv, GF_ClientService *service, GF_NetworkCommand *com, GF_Err response)
{
	GF_Channel *ch;
	GET_TERM();

	if (com->command_type==GF_NET_BUFFER_QUERY) {
		GF_List *od_list;
		u32 i;
		GF_ObjectManager *odm;
		com->buffer.max = 0;
		com->buffer.min = com->buffer.occupancy = (u32) -1;
		if (!service->owner) {
			com->buffer.occupancy = 0;
			return;
		}

		/*browse all channels in the scene, running on this service, and get buffer info*/
		od_list = NULL;
		if (service->owner->subscene) {
			od_list = service->owner->subscene->resources;
		} else if (service->owner->parentscene) {
			od_list = service->owner->parentscene->resources;
		}
		if (!od_list) {
			com->buffer.occupancy = 0;
			return;
		}
		/*get exclusive access to media scheduler, to make sure ODs are not being
		manipulated*/
		gf_mx_p(term->mm_mx);
		if (!gf_list_count(od_list))
			GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM] No object manager found for the scene (URL: %s), buffer occupancy will remain unchanged\n", service->url));
		i=0;
		while ((odm = (GF_ObjectManager*)gf_list_enum(od_list, &i))) {
			u32 j, count;
			if (!odm->codec) continue;
			count = gf_list_count(odm->channels);
			for (j=0; j<count; j++) {
				GF_Channel *ch = (GF_Channel *)gf_list_get(odm->channels, j);
				if (ch->service != service) continue;
				if (ch->es_state != GF_ESM_ES_RUNNING) continue;
				if (/*!ch->MaxBuffer || */ch->dispatch_after_db || ch->bypass_sl_and_db || ch->IsEndOfStream) continue;
				//perform buffer management only on base layer  -this is because we don't signal which ESs are on/off in the underlying service ...
				if (ch->esd->dependsOnESID) continue;
				if (ch->MaxBuffer>com->buffer.max) com->buffer.max = ch->MaxBuffer;
				if (ch->MinBuffer<com->buffer.min) com->buffer.min = ch->MinBuffer;
				if (ch->IsClockInit && (u32) ch->BufferTime  < com->buffer.occupancy) {
					/*if we don't have more units (compressed or not) than requested max for the composition memory, request more data*/
					if (odm->codec->CB->UnitCount + ch->AU_Count <= odm->codec->CB->Capacity) {
//						com->buffer.occupancy = 0;
						com->buffer.occupancy = ch->BufferTime;
					} else {
						com->buffer.occupancy = ch->BufferTime;
					}
				}
			}
		}
		gf_mx_v(term->mm_mx);
//		fprintf(stderr, "Buffer occupancy %d\n", com->buffer.occupancy);
		if (com->buffer.occupancy==(u32) -1) com->buffer.occupancy = 0;
		return;
	}
	if (com->command_type==GF_NET_SERVICE_INFO) {
		GF_Event evt;
		evt.type = GF_EVENT_METADATA;
		gf_term_send_event(term, &evt);
		return;
	}


	if (!com->base.on_channel) return;


	ch = gf_term_get_channel(service, com->base.on_channel);
	if (!ch) return;

	switch (com->command_type) {
	/*SL reconfiguration*/
	case GF_NET_CHAN_RECONFIG:
		gf_term_lock_net(term, 1);
		gf_es_reconfig_sl(ch, &com->cfg.sl_config, com->cfg.use_m2ts_sections);
		gf_term_lock_net(term, 0);
		return;
	/*time mapping (TS to media-time)*/
	case GF_NET_CHAN_MAP_TIME:

		if (ch->esd->dependsOnESID) {
			//ignore everything
		} else {
			u32 i;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: before mapping: seed TS %d - TS offset %d\n", ch->esd->ESID, ch->seed_ts, ch->ts_offset));
			ch->seed_ts = com->map_time.timestamp;
			ch->ts_offset = (u32) (com->map_time.media_time*1000);
			GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: mapping TS "LLD" to media time %f - current time %d\n", ch->esd->ESID, com->map_time.timestamp, com->map_time.media_time, gf_clock_time(ch->clock)));
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: after mapping: seed TS %d - TS offset %d\n", ch->esd->ESID, ch->seed_ts, ch->ts_offset));

			if (com->map_time.reset_buffers) {
				gf_es_reset_buffers(ch);
			}
			/*if we were reassembling an AU, do not perform clock init check when dispatching it since we computed its timestamps
			according to the previous clock origin*/
			else {
				gf_mx_p(ch->mx);
				ch->skip_time_check_for_pending = 1;
				gf_mx_v(ch->mx);
			}
			/*if the channel is the clock, force a re-init*/
			if (gf_es_owns_clock(ch)) {
				ch->IsClockInit = 0;
				gf_clock_reset(ch->clock);
			}
			else if (ch->odm->flags & GF_ODM_INHERIT_TIMELINE) {
				ch->IsClockInit = 0;
//				ch->ts_offset -= ch->seed_ts*1000/ch->ts_res;
			}

			for (i=0; i<gf_list_count(ch->odm->channels); i++) {
				GF_Channel *a_ch = gf_list_get(ch->odm->channels, i);
				if (ch==a_ch) continue;
				if (! a_ch->esd->dependsOnESID) continue;
				a_ch->seed_ts = ch->seed_ts;
				a_ch->IsClockInit = 0;
				a_ch->ts_offset = ch->ts_offset;
			}
		}
		break;
	/*duration changed*/
	case GF_NET_CHAN_DURATION:
		gf_odm_set_duration(ch->odm, ch, (u32) (1000*com->duration.duration));
		break;
	case GF_NET_CHAN_BUFFER_QUERY:
		if (ch->IsEndOfStream) {
			com->buffer.max = com->buffer.min = com->buffer.occupancy = 0;
		} else {
			com->buffer.max = ch->MaxBuffer;
			com->buffer.min = ch->MinBuffer;
			com->buffer.occupancy = ch->BufferTime;
		}
		break;
	case GF_NET_CHAN_DRM_CFG:
		gf_term_lock_net(term, 1);
		gf_es_config_drm(ch, &com->drm_cfg);
		gf_term_lock_net(term, 0);
		return;
	case GF_NET_CHAN_GET_ESD:
		gf_term_lock_net(term, 1);
		com->cache_esd.esd = ch->esd;
		com->cache_esd.is_iod_stream = (ch->odm->subscene /*&& (ch->odm->subscene->root_od==ch->odm)*/) ? 1 : 0;
		gf_term_lock_net(term, 0);
		return;
	default:
		return;
	}
}
Example #9
0
GF_EXPORT
void gf_term_download_update_stats(GF_DownloadSession * sess)
{
	GF_ClientService *serv;
	const char *szURI;
	u32 total_size, bytes_done, net_status, bytes_per_sec;

	if (!sess) return;

	gf_dm_sess_get_stats(sess, NULL, &szURI, &total_size, &bytes_done, &bytes_per_sec, &net_status);
	serv = (GF_ClientService *)gf_dm_sess_get_private(sess);
	switch (net_status) {
	case GF_NETIO_SETUP:
		gf_term_on_message(serv, GF_OK, "Connecting");
		break;
	case GF_NETIO_CONNECTED:
		gf_term_on_message(serv, GF_OK, "Connected");
		break;
	case GF_NETIO_WAIT_FOR_REPLY:
		gf_term_on_message(serv, GF_OK, "Waiting for reply...");
		break;
	case GF_NETIO_PARSE_REPLY:
		gf_term_on_message(serv, GF_OK, "Starting download...");
		break;
	case GF_NETIO_DATA_EXCHANGE:
		/*notify some connection / ...*/
		if (total_size) {
			GF_Event evt;
			evt.type = GF_EVENT_PROGRESS;
			evt.progress.progress_type = 1;
			evt.progress.service = szURI;
			evt.progress.total = total_size;
			evt.progress.done = bytes_done;
			evt.progress.bytes_per_seconds = bytes_per_sec;
			gf_term_send_event(serv->term, &evt);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_NETWORK, ("[HTTP] %s received %d / %d\n", szURI, bytes_done, total_size));
		gf_term_service_media_event_with_download(serv->owner, GF_EVENT_MEDIA_PROGRESS, bytes_done, total_size, bytes_per_sec);

		/*JLF fix this*/
		if (0&& (serv->download_rebuffer || serv->auto_rebuffer) && serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			Double download_percent, playback_percent, adj_percent;
			download_percent = 100 * bytes_done;
			download_percent /= total_size;

			playback_percent = 100 * serv->owner->current_time;
			playback_percent /= serv->owner->duration;
			if (serv->auto_rebuffer)
				adj_percent = 0.0;
			else
				adj_percent = 100.0 * serv->download_rebuffer / serv->owner->duration;

			if (playback_percent >= download_percent) {
				if (gf_clock_is_started(ck)) {
					GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% but downloaded %d %% - Pausing\n", (u32) playback_percent, (u32) download_percent));
					if (!serv->is_paused) {
						serv->is_paused = 1;
						mediacontrol_pause(serv->owner);
					}
					gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_WAITING);
					gf_term_on_message(serv, GF_OK, "HTTP Buffering ...");
				}
			} else if (playback_percent + adj_percent <= download_percent) {
				Double time_to_play = 0;
				Double time_to_download = 0;
				/*automatic rebuffer: make sure we can finish playback before resuming*/
				if (serv->auto_rebuffer) {
					if (bytes_per_sec) {
						time_to_download = 1000.0*(total_size - bytes_done);
						time_to_download /= bytes_per_sec;
					}
					time_to_play = (Double) serv->owner->duration;
					time_to_play -= serv->owner->current_time;
				}
				if ((time_to_download<=time_to_play) && !gf_clock_is_started(ck)) {
					GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Played %d %% and downloaded %d %% - Resuming\n", (u32) playback_percent, (u32) download_percent));
					if (serv->auto_rebuffer) {
						GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Auto-rebuffer done: should be done downloading in %d ms and remains %d ms to play\n", (u32) time_to_download, (u32) (serv->owner->duration - serv->owner->current_time) ));
					}
					gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_PLAYING);
					if (serv->is_paused) {
						serv->is_paused = 0;
						mediacontrol_resume(serv->owner);
					}
					gf_term_on_message(serv, GF_OK, "HTTP Resuming playback");
				}
			}
		}
		break;
	case GF_NETIO_DATA_TRANSFERED:
		gf_term_service_media_event(serv->owner, GF_EVENT_MEDIA_LOAD_DONE);
		if (serv->owner && !(serv->owner->flags & GF_ODM_DESTROYED) && serv->owner->duration) {
			GF_Clock *ck = gf_odm_get_media_clock(serv->owner);
			if (!gf_clock_is_started(ck)) {
				GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[HTTP Resource] Done retrieving file - resuming playback\n"));
				if (serv->is_paused) {
					serv->is_paused = 0;
					mediacontrol_resume(serv->owner);
				}
			}
		}
		break;
	}
}
Example #10
0
static void term_on_command(GF_ClientService *service, GF_NetworkCommand *com, GF_Err response)
{
	GF_Channel *ch;
	GF_Terminal *term = service->term;

	if (com->command_type==GF_NET_BUFFER_QUERY) {
		GF_Scene *scene;

		u32 i, max_buffer_time;
		GF_ObjectManager *odm;
		com->buffer.max = 0;
		com->buffer.min = com->buffer.occupancy = (u32) -1;
		com->buffer.buffering = GF_FALSE;
		if (!service->owner) {
			com->buffer.occupancy = 0;
			return;
		}

		/*browse all channels in the scene, running on this service, and get buffer info*/
		scene = NULL;
		if (service->owner->subscene) {
			scene = service->owner->subscene;
		} else if (service->owner->parentscene) {
			scene = service->owner->parentscene;
		}
		if (!scene) {
			com->buffer.occupancy = 0;
			return;
		}
		/*get exclusive access to scene resources , to make sure ODs are not being inserted/remove*/
		gf_mx_p(scene->mx_resources);

		max_buffer_time=0;
		if (!gf_list_count(scene->resources))
			GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ODM] No object manager found for the scene (URL: %s), buffer occupancy will remain unchanged\n", service->url));
		i=0;
		while ((odm = (GF_ObjectManager*)gf_list_enum(scene->resources, &i))) {
			gather_buffer_level(odm, service, com, &max_buffer_time);
		}
		gf_mx_v(scene->mx_resources);
		if (com->buffer.occupancy==(u32) -1) com->buffer.occupancy = 0;

		//in bench mode return the 1 if one of the buffer is full (eg sleep until all buffers are not full), 0 otherwise
		if (term->bench_mode) {
			com->buffer.occupancy = (max_buffer_time>com->buffer.max) ? 2 : 0;
			com->buffer.max = 1;
			com->buffer.min = 0;
		}
		return;
	}
	if (com->command_type==GF_NET_SERVICE_INFO) {
		GF_Event evt;
		evt.type = GF_EVENT_METADATA;
		gf_term_send_event(term, &evt);
		return;
	}
	if (com->command_type==GF_NET_SERVICE_MEDIA_CAP_QUERY) {
		gf_sc_get_av_caps(term->compositor, &com->mcaps.width, &com->mcaps.height, &com->mcaps.display_bit_depth, &com->mcaps.audio_bpp, &com->mcaps.channels, &com->mcaps.sample_rate);
		return;
	}
	if (com->command_type==GF_NET_SERVICE_EVENT) {
		/*check for UDP timeout*/
		if (com->send_event.evt.message.error == GF_IP_UDP_TIMEOUT) {
			const char *sOpt = gf_cfg_get_key(term->user->config, "Network", "AutoReconfigUDP");
			if (sOpt && !stricmp(sOpt, "yes")) {
				char szMsg[1024];
				sprintf(szMsg, "!! UDP down (%s) - Retrying with TCP !!\n", com->send_event.evt.message.message);
				gf_term_message(term, service->url, szMsg, GF_IP_NETWORK_FAILURE);

				/*reload scene - FIXME this shall work on inline nodes, not on the root !*/
				if (term->reload_url) gf_free(term->reload_url);
				term->reload_state = 1;
				term->reload_url = gf_strdup(term->root_scene->root_od->net_service->url);
				gf_cfg_set_key(term->user->config, "Network", "UDPNotAvailable", "yes");
				return;
			}
		}

		com->send_event.res = 0;
		gf_term_send_event(term, &com->send_event.evt);
		return;
	}

	if (com->command_type==GF_NET_ASSOCIATED_CONTENT_LOCATION) {
		GF_Scene *scene = NULL;
		if (service->owner->subscene) {
			scene = service->owner->subscene;
		} else if (service->owner->parentscene) {
			scene = service->owner->parentscene;
		}
		if (scene)
			gf_scene_register_associated_media(scene, &com->addon_info);
		return;
	}
	if (com->command_type==GF_NET_ASSOCIATED_CONTENT_TIMING) {
		GF_Scene *scene = NULL;
		if (service->owner->subscene) {
			scene = service->owner->subscene;
		} else if (service->owner->parentscene) {
			scene = service->owner->parentscene;
		}
		if (scene)
			gf_scene_notify_associated_media_timeline(scene, &com->addon_time);
		return;
	}
	if (com->command_type==GF_NET_SERVICE_SEEK) {
		GF_Scene *scene = NULL;
		if (service->owner->subscene) {
			scene = service->owner->subscene;
		} else if (service->owner->parentscene) {
			scene = service->owner->parentscene;
		}
		if (scene && scene->is_dynamic_scene) {
			gf_sc_lock(term->compositor, 1);
			gf_scene_restart_dynamic(scene, (u64) (com->play.start_range*1000), 0, 0);
			gf_sc_lock(term->compositor, 0);
		}
		return;
	}

	if (com->command_type == GF_NET_SERVICE_CODEC_STAT_QUERY) {
		GF_List *od_list;
		u32 i;
		GF_ObjectManager *odm;

		com->codec_stat.avg_dec_time = 0;
		com->codec_stat.max_dec_time = 0;
		com->codec_stat.irap_avg_dec_time = 0;
		com->codec_stat.irap_max_dec_time = 0;

		if (!service->owner) return;
		/*browse all channels in the scene, running on this service, and get codec stat*/
		od_list = NULL;
		if (service->owner->subscene) {
			od_list = service->owner->subscene->resources;
		} else if (service->owner->parentscene) {
			od_list = service->owner->parentscene->resources;
		}
		if (!od_list) return;

		/*get exclusive access to media scheduler, to make sure ODs are not being manipulated*/
		i=0;
		while ((odm = (GF_ObjectManager*)gf_list_enum(od_list, &i))) {
			u32 avg_dec_time;
			/*the decoder statistics are reliable only if we decoded at least 1s*/
			if (!odm->codec || !odm->codec->nb_dec_frames ||
			        (odm->codec->ck->speed > 0 ? odm->codec->stat_start + 1000 > odm->codec->last_unit_dts : odm->codec->stat_start - 1000 < odm->codec->last_unit_dts))
				continue;
			avg_dec_time = (u32) (odm->codec->total_dec_time / odm->codec->nb_dec_frames);
			if (avg_dec_time > com->codec_stat.avg_dec_time) {
				com->codec_stat.avg_dec_time = avg_dec_time;
				com->codec_stat.max_dec_time = odm->codec->max_dec_time;
				com->codec_stat.irap_avg_dec_time = odm->codec->nb_iframes ? (u32) (odm->codec->total_iframes_time / odm->codec->nb_iframes) : 0;
				com->codec_stat.irap_max_dec_time = odm->codec->max_iframes_time;
			}
			if (odm->codec->codec_reset) {
				com->codec_stat.codec_reset = GF_TRUE;
				odm->codec->codec_reset = GF_FALSE;
			}
			com->codec_stat.decode_only_rap = odm->codec->decode_only_rap ? GF_TRUE : GF_FALSE;
		}

		return;
	}

	if (!com->base.on_channel) return;

	ch = gf_term_get_channel(service, com->base.on_channel);
	if (!ch) return;

	switch (com->command_type) {
	/*SL reconfiguration*/
	case GF_NET_CHAN_RECONFIG:
		gf_term_lock_net(term, 1);
		gf_es_reconfig_sl(ch, &com->cfg.sl_config, com->cfg.use_m2ts_sections);
		gf_term_lock_net(term, 0);
		return;
	case GF_NET_CHAN_SET_MEDIA_TIME:
		if (gf_es_owns_clock(ch) || !ch->clock->has_media_time_shift) {
			Double mtime = com->map_time.media_time;
			if (ch->clock->clock_init) {
				Double t = (Double) com->map_time.timestamp;
				t /= ch->esd->slConfig->timestampResolution;
				t -= ((Double) ch->clock->init_time) /1000;
				mtime += t;
			}
			ch->clock->media_time_at_init = (u32) (1000*mtime);
			ch->clock->has_media_time_shift = 1;
		}
		return;
	/*time mapping (TS to media-time)*/
	case GF_NET_CHAN_MAP_TIME:

		if (ch->esd->dependsOnESID) {
			//ignore everything
		} else {
			u32 i;
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: before mapping: seed TS %d - TS offset %d\n", ch->esd->ESID, ch->seed_ts, ch->ts_offset));
			ch->seed_ts = com->map_time.timestamp;
			ch->ts_offset = (u32) (com->map_time.media_time*1000);
			GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[SyncLayer] ES%d: mapping TS "LLD" to media time %f - current time %d\n", ch->esd->ESID, com->map_time.timestamp, com->map_time.media_time, gf_clock_time(ch->clock)));
			GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: after mapping: seed TS %d - TS offset %d\n", ch->esd->ESID, ch->seed_ts, ch->ts_offset));

			if (com->map_time.reset_buffers) {
				gf_es_reset_buffers(ch);
			}
			/*if we were reassembling an AU, do not perform clock init check when dispatching it since we computed its timestamps
			according to the previous clock origin*/
			else {
				gf_mx_p(ch->mx);
				ch->skip_time_check_for_pending = 1;
				gf_mx_v(ch->mx);
			}
			/*if the channel is the clock, force a re-init*/
			if (gf_es_owns_clock(ch)) {
				ch->IsClockInit = 0;
				gf_clock_reset(ch->clock);
			}
			else if (ch->odm->flags & GF_ODM_INHERIT_TIMELINE) {
				ch->IsClockInit = 0;
//				ch->ts_offset -= ch->seed_ts*1000/ch->ts_res;
			}

			for (i=0; i<gf_list_count(ch->odm->channels); i++) {
				GF_Channel *a_ch = gf_list_get(ch->odm->channels, i);
				if (ch==a_ch) continue;
				if (! a_ch->esd->dependsOnESID) continue;
				a_ch->seed_ts = ch->seed_ts;
				a_ch->IsClockInit = 0;
				a_ch->ts_offset = ch->ts_offset;
			}
		}
		break;
	/*duration changed*/
	case GF_NET_CHAN_DURATION:
		gf_odm_set_duration(ch->odm, ch, (u32) (1000*com->duration.duration));
		break;
	case GF_NET_CHAN_BUFFER_QUERY:
		if (ch->IsEndOfStream) {
			com->buffer.max = com->buffer.min = com->buffer.occupancy = 0;
		} else {
			com->buffer.max = ch->MaxBuffer;
			com->buffer.min = ch->MinBuffer;
			com->buffer.occupancy = (u32) (ch->BufferTime / FIX2FLT(ch->clock->speed) );
		}
		break;
	case GF_NET_CHAN_DRM_CFG:
		gf_term_lock_net(term, 1);
		gf_es_config_drm(ch, &com->drm_cfg);
		gf_term_lock_net(term, 0);
		return;
	case GF_NET_CHAN_GET_ESD:
		gf_term_lock_net(term, 1);
		com->cache_esd.esd = ch->esd;
		com->cache_esd.is_iod_stream = (ch->odm->subscene /*&& (ch->odm->subscene->root_od==ch->odm)*/) ? 1 : 0;
		gf_term_lock_net(term, 0);
		return;
	case GF_NET_CHAN_RESET:
		gf_es_reset_buffers(ch);
		break;
	case GF_NET_CHAN_PAUSE:
		ch->MaxBuffer = com->buffer.max;
		ch->MinBuffer = com->buffer.min;
		ch->BufferTime = com->buffer.max;
		gf_es_buffer_on(ch);
		break;
	case GF_NET_CHAN_RESUME:
		ch->BufferTime = ch->MaxBuffer;
		gf_es_update_buffering(ch, 1);
		gf_es_buffer_off(ch);
		break;
	case GF_NET_CHAN_BUFFER:
		ch->MaxBuffer = com->buffer.max;
		ch->MinBuffer = com->buffer.min;
		ch->BufferTime = com->buffer.occupancy;
		gf_es_update_buffering(ch, 1);
		break;
	default:
		return;
	}
}
Example #11
0
static void svg_a_handle_event(GF_Node *handler, GF_DOM_Event *event, GF_Node *observer)
{
	GF_Compositor *compositor;
	GF_Event evt;
	SVG_Element *a;
	SVGAllAttributes all_atts;

	if (event->event_phase & GF_DOM_EVENT_PHASE_PREVENT) return;

	assert(gf_node_get_tag((GF_Node*)event->currentTarget->ptr)==TAG_SVG_a);
	a = (SVG_Element *) event->currentTarget->ptr;
	gf_svg_flatten_attributes(a, &all_atts);

	compositor = (GF_Compositor *)gf_node_get_private((GF_Node *)handler);

	if (!compositor->user->EventProc) return;
	if (!all_atts.xlink_href) return;

	if (event->type==GF_EVENT_MOUSEOVER) {
		evt.type = GF_EVENT_NAVIGATE_INFO;
		
		if (all_atts.xlink_title) evt.navigate.to_url = *all_atts.xlink_title;
		else if (all_atts.xlink_href->string) evt.navigate.to_url = all_atts.xlink_href->string;
		else {
			evt.navigate.to_url = gf_node_get_name(all_atts.xlink_href->target);
			if (!evt.navigate.to_url) evt.navigate.to_url = "document internal link";
		}

		gf_term_send_event(compositor->term, &evt);
		return;
	}

	evt.type = GF_EVENT_NAVIGATE;
	
	if (all_atts.xlink_href->type == XMLRI_STRING) {
		evt.navigate.to_url = gf_term_resolve_xlink(handler, all_atts.xlink_href->string);
		if (evt.navigate.to_url) {
			if (all_atts.target) {
				evt.navigate.parameters = (const char **) &all_atts.target;
				evt.navigate.param_count = 1;
			} else {
				evt.navigate.parameters = NULL;
				evt.navigate.param_count = 0;
			}

			if (evt.navigate.to_url[0] != '#') {
				if (compositor->term) {
					gf_scene_process_anchor(handler, &evt);
				} else {
					gf_term_send_event(compositor->term, &evt);
				}
				gf_free((char *)evt.navigate.to_url);
				return;
			}
			all_atts.xlink_href->target = gf_sg_find_node_by_name(gf_node_get_graph(handler), (char *) evt.navigate.to_url+1);
			if (all_atts.xlink_href->target) {
				all_atts.xlink_href->type = XMLRI_ELEMENTID;
				gf_free((char *)evt.navigate.to_url);
			} else {
				svg_a_set_view(handler, compositor, evt.navigate.to_url + 1);
				gf_free((char *)evt.navigate.to_url);
				return;
			}
		}
	}
	if (!all_atts.xlink_href->target) {
		return;
	} 
	/*this is a time event*/
	if (is_timing_target(all_atts.xlink_href->target)) {
		gf_smil_timing_insert_clock(all_atts.xlink_href->target, 0, gf_node_get_scene_time((GF_Node *)handler) );
	} 
	/*this is an implicit SVGView event*/
	else {
		svg_a_set_view(handler, compositor, gf_node_get_name(all_atts.xlink_href->target));
	}
}