示例#1
0
/* when a timed element restarts, it needs to be removed and reinserted at its proper location */
static void gf_smil_reorder_timing(SMIL_Timing_RTI *rti)
{
	GF_SceneGraph * sg = rti->timed_elt->sgprivate->scenegraph;
	while (sg->parent_scene) sg = sg->parent_scene;
	gf_list_del_item(sg->smil_timed_elements, rti);
	gf_smil_timing_add_to_sg(sg, rti);
}
示例#2
0
void gf_smil_timing_modified(GF_Node *node, GF_FieldInfo *field)
{
	GF_SceneGraph *sg;
	SMILTimingAttributesPointers *timingp = NULL;
	SMIL_Timing_RTI *rti;

	u32 tag = gf_node_get_tag(node);
	
	if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) {
		timingp = ((SVGTimedAnimBaseElement *)node)->timingp;
	} 
#ifdef GPAC_ENABLE_SVG_SA
	else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) {
		timingp = ((SVG_SA_Element *)node)->timingp;
	}
#endif
#ifdef GPAC_ENABLE_SVG_SANI
	else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) {
		timingp = ((SVG_SANI_Element *)node)->timingp;
	}
#endif
	else {
		return;
	}
	
	if (!timingp) return;
	rti = timingp->runtime;
	if (!rti) return;

	/*recompute interval list*/
	rti->scene_time = -1;
	sg = node->sgprivate->scenegraph;
	while (sg->parent_scene) sg = sg->parent_scene;
	sg->update_smil_timing = 1;
	gf_smil_timing_refresh_interval_list(rti);
	if (!rti->current_interval) {
		s32 interval_index;
		interval_index = gf_smil_timing_find_interval_index(rti, GF_MAX_DOUBLE);
		if (interval_index >= 0) {
			rti->current_interval_index = interval_index;
			rti->current_interval = (SMIL_Interval*)gf_list_get(rti->intervals, rti->current_interval_index);
		} 
	}
	gf_smil_timing_add_to_sg(sg, rti);
}
示例#3
0
/* This function notifies the scene time to all the timed elements from the list in the given scene graph.
   It returns the number of active timed elements. If no timed element is active, this means that from the timing
   point of view, the scene has not changed and no rendering refresh is needed, even if the time has changed.
   It uses an additional list of modified timed elements to insure that no timing 
   element was modified by the begin/end/repeat of another timed element.
*/
Bool gf_smil_notify_timed_elements(GF_SceneGraph *sg)
{
	SMIL_Timing_RTI *rti;
	u32 active_count, i;
	s32 ret;
	Bool do_loop;
	if (!sg) return 0;

	active_count = 0;

	/*
		Note: whenever a timed element is active, we trigger a gf_node_dirty_parent_graph so that the parent graph 
		is aware that some modifications may happen in the subtree. This is needed for cases where the subtree
		is in an offscreen surface, to force retraversing of the subtree and thus apply the animation. 

	*/
	
	/* notify the new scene time to the register timed elements 
	   this might modify other timed elements or the element itself 
	   in which case it will be added to the list of modified elements */
	i = 0;
	do_loop = 1;
	while(do_loop && (rti = (SMIL_Timing_RTI *)gf_list_enum(sg->smil_timed_elements, &i))) {
		ret = gf_smil_timing_notify_time(rti, gf_node_get_scene_time((GF_Node*)rti->timed_elt) );
		switch (ret) {
		case -1:
			/* special case for discard element
			   when a discard element is executed, it automatically removes itself from the list of timed element 
			   in the scene graph, we need to fix the index i. */
			i--;
			break;
		case -2:
			/* special return value, -2 means that the tested timed element is waiting to begin
			   Assuming that the timed elements are sorted by begin order, 
			   the next ones don't need to be checked */
			do_loop = 0;
			break;
		case -3:
			/* special case for animation elements which do not need to be notified anymore, 
			   but which require a tree traversal */
			i--;
			active_count ++;
			gf_node_dirty_parent_graph(rti->timed_elt);
			break;
		case 1:
			active_count++;
			gf_node_dirty_parent_graph(rti->timed_elt);
			break;
		case 0:
		default:
			break;
		}
	}

	/* notify the timed elements which have been modified either since the previous frame (updates, scripts) or 
	   because of the start/end/repeat of the previous notifications */
	while (gf_list_count(sg->modified_smil_timed_elements)) {
		/* first remove the modified smil timed element */
		rti = gf_list_get(sg->modified_smil_timed_elements, 0);
		gf_list_rem(sg->modified_smil_timed_elements, 0);

		/* then remove it in the list of non modified (if it was there) */
		gf_list_del_item(sg->smil_timed_elements, rti);

		/* then insert it at its right position (in the sorted list of timed elements) */
		gf_smil_timing_add_to_sg(sg, rti);

		/* finally again notify this timed element */
		rti->force_reevaluation = 1;
		ret = gf_smil_timing_notify_time(rti, gf_node_get_scene_time((GF_Node*)rti->timed_elt) );
		switch (ret) {
		case -1:
			break;
		case -2:
			break;
		case -3:
			active_count++;
			gf_node_dirty_parent_graph(rti->timed_elt);
			break;
		case 1:
			active_count++;
			gf_node_dirty_parent_graph(rti->timed_elt);
			break;
		case 0:
		default:
			break;
		}

	}
	return (active_count>0);
}
示例#4
0
/* Attributes from the timed elements are not easy to use during runtime, 
   the runtime info is a set of easy to use structures. 
   This function initializes them (intervals, status ...) 
   and registers the element with the scenegraph */
GF_EXPORT
void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
{
	GF_SceneGraph *sg;
	SMIL_Timing_RTI *rti;
	SMILTimingAttributesPointers *timingp = NULL;
	u32 tag = gf_node_get_tag(timed_elt);
	SVGAllAttributes all_atts;
	SVGTimedAnimBaseElement *e = (SVGTimedAnimBaseElement *)timed_elt;

	gf_svg_flatten_attributes((SVG_Element *)e, &all_atts);
	e->timingp = gf_malloc(sizeof(SMILTimingAttributesPointers));
	e->timingp->begin		= all_atts.begin;
	e->timingp->clipBegin	= all_atts.clipBegin;
	e->timingp->clipEnd		= all_atts.clipEnd;
	e->timingp->dur			= all_atts.dur;
	e->timingp->end			= all_atts.end;
	e->timingp->fill		= all_atts.smil_fill;
	e->timingp->max			= all_atts.max;
	e->timingp->min			= all_atts.min;
	e->timingp->repeatCount = all_atts.repeatCount;
	e->timingp->repeatDur	= all_atts.repeatDur;
	e->timingp->restart		= all_atts.restart;
	timingp = e->timingp;
	if (!timingp) return;

	if (tag == TAG_SVG_audio || tag == TAG_SVG_video) {
		/* if the dur attribute is not set, then it should be set to media 
		   as this is the default for media elements see 
		   http://www.w3.org/TR/2005/REC-SMIL2-20051213/smil-timing.html#Timing-DurValueSemantics
		   "For simple media elements that specify continuous media (i.e. media with an inherent notion of time), 
		   the implicit duration is the intrinsic duration of the media itself - e.g. video and audio files 
		   have a defined duration."
		TODO: Check if this should work with the animation element */
		if (!e->timingp->dur) {
			GF_FieldInfo info;
			gf_node_get_attribute_by_tag((GF_Node *)e, TAG_SVG_ATT_dur, 1, 0, &info);
			e->timingp->dur = (SMIL_Duration *)info.far_ptr;
			e->timingp->dur->type = SMIL_DURATION_MEDIA;
		}
	}

	GF_SAFEALLOC(rti, SMIL_Timing_RTI)
	timingp->runtime = rti;
	rti->timed_elt = timed_elt;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_SMIL, ("[SMIL Timing   ] Time %f - Timed element %s - Initialization\n", gf_node_get_scene_time((GF_Node *)rti->timed_elt), gf_node_get_log_name((GF_Node *)rti->timed_elt)));

	rti->timingp = timingp;
	rti->status = SMIL_STATUS_WAITING_TO_BEGIN;
	rti->evaluate_status = SMIL_TIMING_EVAL_NONE;	
	rti->evaluate = gf_smil_timing_null_timed_function;
	rti->scene_time = -1;
	rti->force_reevaluation = 0;
	rti->media_duration = -1;

	GF_SAFEALLOC(rti->current_interval, SMIL_Interval);
	gf_smil_timing_get_first_interval(rti);
	GF_SAFEALLOC(rti->next_interval, SMIL_Interval);
	gf_smil_timing_get_next_interval(rti, 0, rti->next_interval, rti->current_interval->begin);

	/* Now that the runtime info for this timed element is initialized, we can tell the scene graph that it can start
	   notifying the scene time to this element. Because of the 'animation' element, we can have many scene graphs
	   sharing the same scene time, we therefore add this timed element to the rootmost scene graph. */
	sg = timed_elt->sgprivate->scenegraph;
	while (sg->parent_scene) sg = sg->parent_scene;
	gf_smil_timing_add_to_sg(sg, rti);
}
示例#5
0
GF_EXPORT
void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
{
	s32 interval_index;
	GF_SceneGraph *sg;
	SMIL_Timing_RTI *rti;
	SMILTimingAttributesPointers *timingp = NULL;
	u32 tag = gf_node_get_tag(timed_elt);

	if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) {
		SVGAllAttributes all_atts;
		SVGTimedAnimBaseElement *e = (SVGTimedAnimBaseElement *)timed_elt;
		gf_svg_flatten_attributes((SVG_Element *)e, &all_atts);
		e->timingp = malloc(sizeof(SMILTimingAttributesPointers));
		e->timingp->begin		= all_atts.begin;
		e->timingp->clipBegin	= all_atts.clipBegin;
		e->timingp->clipEnd		= all_atts.clipEnd;
		e->timingp->dur			= all_atts.dur;
		e->timingp->end			= all_atts.end;
		e->timingp->fill		= all_atts.smil_fill;
		e->timingp->max			= all_atts.max;
		e->timingp->min			= all_atts.min;
		e->timingp->repeatCount = all_atts.repeatCount;
		e->timingp->repeatDur	= all_atts.repeatDur;
		e->timingp->restart		= all_atts.restart;
		timingp = e->timingp;
	} 
#ifdef GPAC_ENABLE_SVG_SA
	else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) {
		SVG_SA_Element *e = (SVG_SA_Element *)timed_elt;
		e->timingp = malloc(sizeof(SMILTimingAttributesPointers));
		e->timingp->begin		= &e->timing->begin;
		e->timingp->clipBegin	= &e->timing->clipBegin;
		e->timingp->clipEnd		= &e->timing->clipEnd;
		e->timingp->dur			= &e->timing->dur;
		e->timingp->end			= &e->timing->end;
		e->timingp->fill		= &e->timing->fill;
		e->timingp->max			= &e->timing->max;
		e->timingp->min			= &e->timing->min;
		e->timingp->repeatCount = &e->timing->repeatCount;
		e->timingp->repeatDur	= &e->timing->repeatDur;
		e->timingp->restart		= &e->timing->restart;
		timingp = e->timingp;
	}
#endif
#ifdef GPAC_ENABLE_SVG_SANI
	else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) {
		SVG_SANI_Element *e = (SVG_SANI_Element *)timed_elt;
		e->timingp = malloc(sizeof(SMILTimingAttributesPointers));
		e->timingp->begin		= &e->timing->begin;
		e->timingp->clipBegin	= &e->timing->clipBegin;
		e->timingp->clipEnd		= &e->timing->clipEnd;
		e->timingp->dur			= &e->timing->dur;
		e->timingp->end			= &e->timing->end;
		e->timingp->fill		= &e->timing->fill;
		e->timingp->max			= &e->timing->max;
		e->timingp->min			= &e->timing->min;
		e->timingp->repeatCount = &e->timing->repeatCount;
		e->timingp->repeatDur	= &e->timing->repeatDur;
		e->timingp->restart		= &e->timing->restart;
		timingp = e->timingp;
	}
#endif
	else {
		return;
	}

	if (!timingp) return;

	GF_SAFEALLOC(rti, SMIL_Timing_RTI)
	timingp->runtime = rti;
	rti->timed_elt = timed_elt;
	rti->timingp = timingp;
	rti->status = SMIL_STATUS_WAITING_TO_BEGIN;
	rti->evaluate_status = SMIL_TIMING_EVAL_NONE;	
	rti->intervals = gf_list_new();
	rti->current_interval = NULL;
	rti->evaluate = gf_smil_timing_null_timed_function;
	rti->scene_time = -1;
	rti->media_duration = -1;

	gf_smil_timing_init_interval_list(rti);
	interval_index = gf_smil_timing_find_interval_index(rti, GF_MAX_DOUBLE);
	if (interval_index >= 0) {
		rti->current_interval_index = interval_index;
		rti->current_interval = (SMIL_Interval*)gf_list_get(rti->intervals, rti->current_interval_index);
	} 

	sg = timed_elt->sgprivate->scenegraph;
	while (sg->parent_scene) sg = sg->parent_scene;
	gf_smil_timing_add_to_sg(sg, rti);
}