⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smil_timing.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Authors: Cyril Concolato - Jean Le Feuvre *    Copyright (c)2004-200X ENST - All rights reserved * *  This file is part of GPAC / SVG Scene Graph sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details.	 * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/scenegraph_dev.h>#include <gpac/events.h>#include <gpac/nodes_svg_sa.h>#include <gpac/nodes_svg_sani.h>#include <gpac/nodes_svg_da.h>static void gf_smil_timing_null_timed_function(SMIL_Timing_RTI *rti, Fixed normalized_scene_time, u32 state){}static s32 gf_smil_timing_find_interval_index(SMIL_Timing_RTI *rti, Double scene_time){	s32 index = -1;	u32 i, count;	count = gf_list_count(rti->intervals);	if (rti->current_interval) i = rti->current_interval_index + 1;	else i = 0;	for (; i<count; i++) {		SMIL_Interval *interval = (SMIL_Interval *)gf_list_get(rti->intervals, i);		if (interval->begin <= scene_time) {			index = i;			break;		}	}	return index;}/* computes the active duration for the given interval,   assumes that the values of begin and end have been set   and that begin is defined (i.e. a positive value)*/static void gf_smil_timing_compute_active_duration(SMIL_Timing_RTI *rti, SMIL_Interval *interval){	Bool clamp_active_duration;	Bool isDurDefined, isRepeatCountDefined, isRepeatDurDefined, isMinDefined, isMaxDefined, isRepeatDurIndefinite, isRepeatCountIndefinite, isMediaDuration;	SMILTimingAttributesPointers *timingp = rti->timingp;	if (!timingp) return;		switch (gf_node_get_tag((GF_Node *)rti->timed_elt)) {#ifdef GPAC_ENABLE_SVG_SA	case TAG_SVG_SA_discard:#endif#ifdef GPAC_ENABLE_SVG_SANI	case TAG_SVG_SANI_discard:#endif	case TAG_SVG_discard:		interval->active_duration = -1;		return;	}	isDurDefined = (timingp->dur && timingp->dur->type == SMIL_DURATION_DEFINED);	isMediaDuration = (timingp->dur && (timingp->dur->type == SMIL_DURATION_MEDIA) && (rti->media_duration>=0) );	isRepeatCountDefined = (timingp->repeatCount && timingp->repeatCount->type == SMIL_REPEATCOUNT_DEFINED);	isRepeatCountIndefinite = (timingp->repeatCount && timingp->repeatCount->type == SMIL_REPEATCOUNT_INDEFINITE);	isRepeatDurDefined = (timingp->repeatDur && timingp->repeatDur->type == SMIL_DURATION_DEFINED);	isRepeatDurIndefinite = (timingp->repeatDur && timingp->repeatDur->type == SMIL_DURATION_INDEFINITE);	/* Step 1: Computing active duration using repeatDur and repeatCount */	if (isDurDefined || isMediaDuration) {		interval->simple_duration = isMediaDuration ? rti->media_duration : timingp->dur->clock_value;		if (isRepeatCountDefined && !isRepeatDurDefined) {			interval->active_duration = FIX2FLT(timingp->repeatCount->count) * interval->simple_duration;		} else if (!isRepeatCountDefined && isRepeatDurDefined) {			interval->active_duration = timingp->repeatDur->clock_value;		} else if (!isRepeatCountDefined && !isRepeatDurDefined) {			if (isRepeatDurIndefinite || isRepeatCountIndefinite) {				interval->active_duration = -1;			} else {				interval->active_duration = interval->simple_duration;			}		} else {			interval->active_duration = MIN(timingp->repeatDur->clock_value, 										FIX2FLT(timingp->repeatCount->count) * interval->simple_duration);		}				} else {		/* simple_duration is indefinite */		interval->simple_duration = -1;				/* we can ignore repeatCount to compute active_duration */		if (!isRepeatDurDefined) {			interval->active_duration = -1;		} else {			interval->active_duration = timingp->repeatDur->clock_value;		}	}	/* Step 2: clamp the active duration with min and max */	clamp_active_duration = 1;	/* testing for presence of min and max because some elements may not have them: eg SVG audio */	isMinDefined = (timingp->min && timingp->min->type == SMIL_DURATION_DEFINED);	isMaxDefined = (timingp->max && timingp->max->type == SMIL_DURATION_DEFINED);	if (isMinDefined && isMaxDefined && 		timingp->max->clock_value < timingp->min->clock_value) {		clamp_active_duration = 0;	}	if (clamp_active_duration) {		if (isMinDefined) {			if (interval->active_duration >= 0 && interval->active_duration <= timingp->min->clock_value) {				interval->active_duration = timingp->min->clock_value;			}		}		if (isMaxDefined) {			if ((interval->active_duration >= 0 && interval->active_duration >= timingp->max->clock_value) ||				interval->active_duration == -1) {				interval->active_duration = timingp->max->clock_value;			}		}	}	/* Step 3: if end is defined in the document, clamp active duration to end-begin 	otherwise return*/	if (interval->end < 0) {		/* interval->active_duration stays as is */	} else {		if (interval->active_duration >= 0)			interval->active_duration = MIN(interval->active_duration, interval->end - interval->begin);		else 			interval->active_duration = interval->end - interval->begin;	}}GF_EXPORTvoid gf_smil_set_media_duration(SMIL_Timing_RTI *rti, Double media_duration){	rti->media_duration = media_duration;	gf_smil_timing_compute_active_duration(rti, rti->current_interval);}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);}/* 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);	}}/* To reduce the process of notifying the time to each timed element, we add to the scene graph    only the timed elements which have a resolved current interval, other timed elements will be    added at runtime when an event leads to the creation of a new interval.   We also insert the new timed element in the order of the current_interval begin value, to stop    the notification of time earlier */static void gf_smil_timing_add_to_sg(GF_SceneGraph *sg, SMIL_Timing_RTI *rti){	if (rti->current_interval) {		SMIL_Timing_RTI *cur_rti = NULL;		u32 i, count;		count = gf_list_count(sg->smil_timed_elements);		for (i = 0; i < count; i++) {			cur_rti = (SMIL_Timing_RTI *)gf_list_get(sg->smil_timed_elements, i);			if (cur_rti->current_interval->begin > rti->current_interval->begin) break;		}		gf_list_insert(sg->smil_timed_elements, rti, i);	}}/* 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);}GF_EXPORTvoid 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);}void gf_smil_timing_delete_runtime_info(GF_Node *timed_elt, SMIL_Timing_RTI *rti){	GF_SceneGraph *sg;	u32 i;	if (!rti || !timed_elt) return;	for (i = 0; i<gf_list_count(rti->intervals); i++) {		SMIL_Interval *interval = (SMIL_Interval *)gf_list_get(rti->intervals, i);		free(interval);	}	gf_list_del(rti->intervals);	sg = timed_elt->sgprivate->scenegraph;	while (sg->parent_scene) sg = sg->parent_scene;	gf_list_del_item(sg->smil_timed_elements, rti);	free(rti);}GF_EXPORTBool gf_smil_timing_is_active(GF_Node *node) {	SMILTimingAttributesPointers *timingp = NULL;	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 0;	}	if (!timingp || !timingp->runtime) return 0;	return (timingp->runtime->status == SMIL_STATUS_ACTIVE);}void gf_smil_timing_end_notif(SMIL_Timing_RTI *rti, Double clock){	if (rti->current_interval && (rti->current_interval_index>=0) && (rti->current_interval->active_duration<0) ) {		rti->current_interval->end = clock;		rti->current_interval->active_duration = rti->current_interval->end - rti->current_interval->begin;	}}/* 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);	}}#if 0static void gf_smil_timing_print_interval(SMIL_Interval *interval){	fprintf(stdout, "Current Interval - ");	fprintf(stdout, "Begin: %f", interval->begin);	fprintf(stdout, " - End: %f", interval->end);	fprintf(stdout, "\n");	fprintf(stdout, "Duration - Simple %f, Active %f\n",interval->simple_duration, interval->active_duration);	fprintf(stdout, "\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -