/* the end value of this interval needs to be initialized before computing the active duration the begin value must be >= 0 The result can be: - a positive value meaning that a resolved and non-indefinite value was found - the value -1 meaning indefinite or unresolved TODO: we should make a difference between indefinite and unresolved because if an interval is created with a value of indefinite, this value should not be replaced by a resolved event. (Not sure ?!!) - the value -2 meaning that a valid end value (including indefinite) could not be found */ static void gf_smil_timing_get_interval_end(SMIL_Timing_RTI *rti, SMIL_Interval *interval) { u32 end_count, j; /* we set the value to indicate that this is an illegal end, if it stays like that after searching through the values, then the whole interval must be discarded */ interval->end = -2; end_count = (rti->timingp->end ? gf_list_count(*rti->timingp->end) : 0); /* trying to find a matching end */ if (end_count > 0) { for (j = 0; j < end_count; j++) { SMIL_Time *end = (SMIL_Time*)gf_list_get(*rti->timingp->end, j); if ( GF_SMIL_TIME_IS_CLOCK(end->type) ) { if( end->clock >= interval->begin) { interval->end = end->clock; break; } } else { /* an unresolved or indefinite value is always good */ interval->end = -1; break; } } } else { interval->end = -1; } }
static Bool gf_smil_timing_get_next_interval(SMIL_Timing_RTI *rti, Bool current, SMIL_Interval *interval, Double scene_time) { u32 i, count; memset(interval, 0, sizeof(SMIL_Interval)); interval->begin = -1; count = (rti->timingp->begin ? gf_list_count(*rti->timingp->begin) : 0); for (i = 0; i < count; i ++) { SMIL_Time *begin = (SMIL_Time*)gf_list_get(*rti->timingp->begin, i); if (GF_SMIL_TIME_IS_CLOCK(begin->type)) { if (rti->current_interval->begin != -1 && begin->clock <= rti->current_interval->begin) continue; // if (rti->current_interval->begin == -1 || begin->clock <= scene_time) { interval->begin = begin->clock; break; // } } } if (interval->begin != -1) { gf_smil_timing_get_interval_end(rti, interval); if (interval->end == -2) { /* this is a wrong interval see first animation in animate-elem-201-t.svg */ GF_LOG(GF_LOG_DEBUG, GF_LOG_SMIL, ("[SMIL Timing ] Time %f - Timed element %s - Wrong Interval\n", gf_node_get_scene_time((GF_Node *)rti->timed_elt), gf_node_get_log_name((GF_Node *)rti->timed_elt))); interval->begin = -1; interval->end = -1; return 0; } gf_smil_timing_compute_active_duration(rti, interval); gf_smil_timing_print_interval(rti, current, interval); return 1; } else { return 0; } }
/* assumes that the list of time values is sorted */ static void gf_smil_timing_refresh_interval_list(SMIL_Timing_RTI *rti) { u32 i, count, j, count2; SMIL_Time *begin; SMILTimingAttributesPointers *timingp = rti->timingp; if (!timingp) return; count = (timingp->begin ? gf_list_count(*timingp->begin) : 0); if (!count) { if (rti->current_interval) gf_smil_timing_add_new_interval(rti, rti->current_interval, rti->current_interval->begin, 0); return; } for (i = 0; i < count; i ++) { SMIL_Interval *existing_interval = NULL; begin = (SMIL_Time*)gf_list_get(*timingp->begin, i); /* this is not an acceptable value for a begin */ if (! GF_SMIL_TIME_IS_CLOCK(begin->type) ) continue; count2 = gf_list_count(rti->intervals); for (j=0; j<count2; j++) { existing_interval = (SMIL_Interval *)gf_list_get(rti->intervals, j); if (existing_interval->begin==begin->clock) break; existing_interval = NULL; } /* we create an acceptable only if begin is unspecified or defined (clock or wallclock) */ gf_smil_timing_add_new_interval(rti, existing_interval, begin->clock, i); } }
/* assumes that the list of time values is sorted */ static void gf_smil_timing_init_interval_list(SMIL_Timing_RTI *rti) { u32 i, count; SMIL_Time *begin; SMILTimingAttributesPointers *timingp = rti->timingp; if (!timingp) return; count = gf_list_count(rti->intervals); for (i = 0; i<count; i++) { SMIL_Interval *interval = (SMIL_Interval *)gf_list_get(rti->intervals, i); free(interval); } gf_list_reset(rti->intervals); count = (timingp->begin ? gf_list_count(*timingp->begin) : 0); if (count) { for (i = 0; i < count; i ++) { begin = (SMIL_Time*)gf_list_get(*timingp->begin, i); if (GF_SMIL_TIME_IS_CLOCK(begin->type) ) { /* we create an acceptable only if begin is unspecified or defined (clock or wallclock) */ gf_smil_timing_add_new_interval(rti, NULL, begin->clock, i); } else { /* this is not an acceptable value for a begin */ } } } /*conditional has a default begin value of indefinite*/ else if (rti->timed_elt->sgprivate->tag != TAG_SVG_conditional) { gf_smil_timing_add_new_interval(rti, NULL, 0, 0); } }
static void gf_smil_timing_add_new_interval(SMIL_Timing_RTI *rti, SMIL_Interval *interval, Double begin, u32 index) { u32 j, end_count; SMIL_Time *end; SMILTimingAttributesPointers *timingp = rti->timingp; if (!timingp) return; if (!interval) { GF_SAFEALLOC(interval, SMIL_Interval) interval->begin = begin; gf_list_add(rti->intervals, interval); } end_count = (timingp->end ? gf_list_count(*timingp->end) : 0); /* trying to find a matching end */ if (end_count > index) { for (j = index; j < end_count; j++) { end = (SMIL_Time*)gf_list_get(*timingp->end, j); if ( GF_SMIL_TIME_IS_CLOCK(end->type) ) { if( end->clock >= interval->begin) { interval->end = end->clock; break; } } else { /* an unresolved or indefinite value is always good */ interval->end = -1; break; } } } else { interval->end = -1; } gf_smil_timing_compute_active_duration(rti, interval); }
static Bool gf_smil_discard(SMIL_Timing_RTI *rti, Fixed scene_time) { u32 nb_inst; SMIL_Time *begin; SMILTimingAttributesPointers *timingp = rti->timingp; GF_Node *target; u32 tag = gf_node_get_tag(rti->timed_elt); if (!timingp) return 0; if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) { target = ((SVGTimedAnimBaseElement *)rti->timed_elt)->xlinkp->href->target; } #ifdef GPAC_ENABLE_SVG_SA else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) { target = ((SVG_SA_Element *)rti->timed_elt)->xlinkp->href->target; } #endif #ifdef GPAC_ENABLE_SVG_SANI else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) { target = ((SVG_SANI_Element *)rti->timed_elt)->xlinkp->href->target; } #endif else { return 0; } begin = (timingp->begin ? (SMIL_Time *)gf_list_get(*timingp->begin, 0) : NULL); if (!begin) return 0; if (!GF_SMIL_TIME_IS_CLOCK(begin->type) ) return 0; if (!target) return 0; if (begin->clock > scene_time) return 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Composer] discarding element %s at time %f\n", gf_node_get_name(target), scene_time)); /*this takes care of cases where discard is a child of its target*/ gf_node_register(rti->timed_elt, NULL); nb_inst = gf_node_get_num_instances(rti->timed_elt); gf_node_replace(target, NULL, 0); if (nb_inst == gf_node_get_num_instances(rti->timed_elt)) { gf_node_unregister(rti->timed_elt, NULL); /*after this the stack may be free'd*/ gf_node_replace(rti->timed_elt, NULL, 0); } else { gf_node_unregister(rti->timed_elt, NULL); } return 1; }
static void gf_smil_timing_get_first_interval(SMIL_Timing_RTI *rti) { u32 i, count; memset(rti->current_interval, 0, sizeof(SMIL_Interval)); rti->current_interval->begin = -1; count = (rti->timingp->begin ? gf_list_count(*rti->timingp->begin) : 0); for (i = 0; i < count; i ++) { SMIL_Time *begin = (SMIL_Time*)gf_list_get(*rti->timingp->begin, i); if (GF_SMIL_TIME_IS_CLOCK(begin->type)) { rti->current_interval->begin = begin->clock; break; } } /*In SVG, if no 'begin' is specified, the default timing of the time container is equivalent to an offset value of '0'.*/ if (rti->current_interval->begin == -1 && count == 0) { /* except for LASeR Conditional element*/ if (rti->timed_elt->sgprivate->tag != TAG_LSR_conditional) { rti->current_interval->begin = 0; } else { return; } } /* this is the first time we check the interval */ gf_smil_timing_get_interval_end(rti, rti->current_interval); if (0 && rti->current_interval->end == -2) { /* TODO: check if the interval can be discarded (i.e. if end is specified with an invalid end value (return -2)), probably yes, but next time we call the evaluation of interval, we should call get_first_interval */ GF_LOG(GF_LOG_DEBUG, GF_LOG_SMIL, ("[SMIL Timing ] Time %f - Timed element %s - Wrong Interval\n", gf_node_get_scene_time((GF_Node *)rti->timed_elt), gf_node_get_log_name((GF_Node *)rti->timed_elt))); rti->current_interval->begin = -1; rti->current_interval->end = -1; return; } gf_smil_timing_compute_active_duration(rti, rti->current_interval); gf_smil_timing_print_interval(rti, 1, rti->current_interval); }
/* evaluation function for the discard element returns 1 if the discard was executed 0 otherwise */ static Bool gf_smil_discard(SMIL_Timing_RTI *rti, Fixed scene_time) { u32 nb_inst; SMIL_Time *begin; SVGTimedAnimBaseElement *tb = (SVGTimedAnimBaseElement *)rti->timed_elt; SMILTimingAttributesPointers *timingp = (SMILTimingAttributesPointers *)rti->timingp; GF_Node *target; if (!timingp) return 0; target = tb->xlinkp->href ? tb->xlinkp->href->target : NULL; begin = (timingp->begin ? (SMIL_Time *)gf_list_get(*timingp->begin, 0) : NULL); if (!begin) return 0; if (!GF_SMIL_TIME_IS_CLOCK(begin->type) ) return 0; if (begin->clock > scene_time) return 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_SMIL, ("[SVG Composer] discarding element %s at time %f\n", target ? gf_node_get_log_name(target) : "None", scene_time)); gf_smil_mark_modified(rti, 1); /*this takes care of cases where discard is a child of its target*/ gf_node_register(rti->timed_elt, NULL); nb_inst = gf_node_get_num_instances(rti->timed_elt); if (target) gf_node_replace(target, NULL, 0); if (nb_inst == gf_node_get_num_instances(rti->timed_elt)) { gf_node_unregister(rti->timed_elt, NULL); /*after this the stack may be free'd*/ gf_node_replace(rti->timed_elt, NULL, 0); } else { gf_node_unregister(rti->timed_elt, NULL); } return 1; }