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

📄 time_node.cpp

📁 彩信浏览器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}common::playable *time_node::create_playable() {	assert(is_playable());	if(m_ffwd_mode) return 0;	AM_DBG m_logger->debug("%s[%s].create()", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str());	return m_context->create_playable(m_node);}time_node::time_type time_node::get_playable_dur() {	common::duration dur_pair = m_context->get_dur(m_node);	if(dur_pair.first && dur_pair.second>0)		return secs_to_time_type(dur_pair.second)();#if 0	// Attempted fix by Jack: if we're fast-forwarding we return zero for	// things we can't figure out the duration for.	if (m_ffwd_mode) {		m_logger->trace("fast-forward: ignoring unknown duration for %s", get_sig().c_str());		return secs_to_time_type(0)();	}#endif	return time_type::unresolved;}// Prepare children playables without recursionvoid time_node::prepare_playables() {#ifdef WITH_AGGRESSIVE_PRELOADING	// Note by Jack: this code is temporarily disabled. It has some serious	// drawbacks, such as starting all playables for children of a <seq>, which	// could (in some documents) cause an incredible number of playables to	// be created long before they're actually needed. We need to come up	// with a better preloading scheme at some point.	if(m_ffwd_mode) return;	std::list<time_node*> children;	get_children(children);	std::list<time_node*>::iterator it;	for(it = children.begin(); it != children.end(); it++) {		if((*it)->is_playable()) (*it)->create_playable();	}#endif}//////////////////////////// Driver shellvoid time_node::get_pending_events(std::map<time_type, std::list<time_node*> >& events) {	if(!is_alive() || paused() || deferred()) return;	if(m_interval.is_valid()) {		if(!is_active()) {			// If we are not active we schedule our own begin			qtime_type timestamp(sync_node(), m_interval.begin);			time_type doctime = timestamp.to_doc();			AM_DBG m_logger->debug("get_pending_events(0x%x %s): schedule begin for %d", this, get_sig().c_str(), doctime());			events[doctime].push_back(this);		} else if(m_interval.end.is_definite()) {			// If we are active and our end is known we schedule our own end			qtime_type timestamp(sync_node(), get_interval_end());			time_type doctime = timestamp.to_doc();			AM_DBG m_logger->debug("get_pending_events(0x%x %s): schedule end for %d", this, get_sig().c_str(), doctime());			events[doctime].push_back(this);						bool repeats = m_attrs.specified_rdur() || m_attrs.specified_rcount();			repeats = repeats && (m_last_cdur.is_definite() && m_last_cdur() != 0);			if(repeats) {				// And we also schedule our repeat, if applicable				qtime_type ts(this, m_last_cdur);				time_type dt = ts.to_doc();				AM_DBG m_logger->debug("get_pending_events(0x%x %s): schedule repeat for %d", this, get_sig().c_str(), dt());				events[dt].push_back(this);			}		}	}		if(m_update_event.first) {		// Jack thinks (but not sure:-) this one has to do with multiple		// begin/end times.		qtime_type timestamp = m_update_event.second;		time_type doctime = timestamp.to_doc();		AM_DBG m_logger->debug("get_pending_events(0x%x %s): schedule update_event for %d", this, get_sig().c_str(), doctime());		events[doctime].push_back(this);	}	if(m_transout_sr && !m_ffwd_mode) {		// We schedule the start of our outtransition, if applicable		time_mset set;		m_transout_sr->get_instance_times(set);		if(!set.empty()) {			qtime_type timestamp(sync_node(), *set.begin());			time_type doctime = timestamp.to_doc();			AM_DBG m_logger->debug("get_pending_events(0x%x %s): schedule transout for %d", this, get_sig().c_str(), doctime());			events[doctime].push_back(this);		}	}		std::list<time_node*> children;	get_children(children);	std::list<time_node*>::iterator it;	for(it = children.begin(); it != children.end(); it++) {		// Finally we recursively get all events for our childen.		(*it)->get_pending_events(events);	}	AM_DBG lib::logger::get_logger()->debug(" time_node::get_pending_events: 0x%x", &events);}void time_node::exec(qtime_type timestamp) {	AM_DBG m_logger->debug("time_node::exec(%ld) for %s ffwd %d is_alive()=%d is_active()=%d", timestamp.second(), get_sig().c_str(), (int)m_ffwd_mode, is_alive(), is_active());	if(!is_alive()) {		// check for transOut		return;	}		if(m_update_event.first) {		sync_update(m_update_event.second);		m_update_event.first = false;	}		timestamp.to_node(sync_node());	assert(timestamp.first == sync_node());		if(!is_active()) {		// in this state, activation is the only interesting activity		AM_DBG m_logger->debug("time_node::exec(%ld) for %s m_interval=(%ld,%ld) deferred=%d", timestamp.second(), get_sig().c_str(), m_interval.begin(), m_interval.end(), deferred());		if(begin_cond(timestamp)) {			if(deferred()) defer_interval(timestamp);			else set_state_ex(ts_active, timestamp);		}		return;	}	// The following code applies to active nodes	assert(is_active());		if(m_transout_sr) {		// timestamp.second >= m_interval.end		time_mset set;		m_transout_sr->get_instance_times(set);		if(!set.empty()) {			qtime_type ts(sync_node(), *set.begin());			if(timestamp.second >= ts.second) {				// start trasnition				AM_DBG m_logger->debug("%s[%s].start_transition() at %ld (end:%ld)", 					m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(),					ts.second(),  m_interval.end());				const lib::transition_info *trans_out = m_attrs.get_trans_out();				m_context->start_transition(m_node, trans_out, false);				m_transout_sr->reset(0);			}		}	}		// Check for the EOI event	if(end_cond(timestamp)) {		// This node should go postactive		time_type reftime;		if(m_interval.end.is_definite()) reftime = m_interval.end;		else reftime = timestamp.second;		qtime_type qt(sync_node(), reftime);		set_state_ex(ts_postactive, qt);		return;	}		// Check for the EOSD event	AM_DBG m_logger->debug("%s[%s] checking for end-of-sd (cdur=%ld)", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), m_last_cdur());	if(m_last_cdur.is_definite() && m_last_cdur() != 0 && timestamp.as_time_value_down_to(this) >= m_last_cdur())		on_eosd(timestamp);}// Returns true when the end conditions of this node evaluate to true// e.g. the node should be deactivated// Assumes the node is activebool time_node::end_cond(qtime_type timestamp) {	assert(timestamp.first == sync_node());	assert(is_active());	bool ec = end_sync_cond_applicable() && end_sync_cond();	bool tc = !end_sync_cond_applicable() && timestamp.second >= get_interval_end();		if(is_time_container() && (ec || tc)) {		AM_DBG m_logger->debug("%s[%s].end_cond() true [%s]", m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), (ec?"end_sync_cond":"interval_end"));	}		// The "tc" condition is not sufficient when needs_implicit_dur()is true	// for example: 	// a) a video has returned its implicit dur	// b) calcs have been done based on this value	// c) m_interval.end may have assumed this vale	// d) the interval has not been updated yet	// e) due to not controled delays the video is still playing		bool specified_dur = m_attrs.specified_dur() || m_attrs.specified_rdur();	if(is_cmedia() && !is_animation() && tc && !specified_dur && m_time_calc->uses_dur()) {		if(m_context->wait_for_eom() && !m_eom_flag) {			tc = false;			AM_DBG m_logger->debug("%s[%s].end_cond() waiting media end", 				m_attrs.get_tag().c_str(), m_attrs.get_id().c_str());		}	}		return ec || tc;}// Returns true when the begin conditions of this node evaluate to true// e.g. the node should be activatedbool time_node::begin_cond(qtime_type timestamp) {	return m_interval.is_valid() && m_interval.contains(timestamp.second);}//////////////////////////// Notifications// The clock used by the argument timestamp can be any// Convert it if possible to this sync_node clock timevoid time_node::sync_update(qtime_type timestamp) {	time_type pt = timestamp.as_node_time(sync_node());	if(pt.is_resolved()) {		timestamp = qtime_type(sync_node(), pt);		m_state->sync_update(timestamp);	}}// Called on the end of simple duration eventvoid time_node::on_eosd(qtime_type timestamp) {	AM_DBG m_logger->debug("%s[%s].on_eosd() ST:%ld, PT:%ld, DT:%ld (sdur=%ld)", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), 		timestamp.as_time_value_down_to(this),		timestamp.second(), 		timestamp.as_doc_time_value(),		m_last_cdur()		);		// update repeat registers	m_rad += m_last_cdur();	m_precounter++;			// Should this node repeat?	if(m_attrs.specified_rdur()) {		time_type rdur = m_attrs.get_rdur();		if(rdur == time_type::indefinite || rdur > m_rad) {			repeat(timestamp);			return;		}	}		if(m_attrs.specified_rcount()) {		double rcount = m_attrs.get_rcount();		if(m_attrs.is_rcount_indefinite() || rcount > double(m_precounter)) {			repeat(timestamp);			return;		}	}}// Begin of media notification// Currently this notification is not used.// Could be used to define the slip sync offset.void time_node::on_bom(qtime_type timestamp) {	m_eom_flag = false;	if(!is_discrete()) {		qtime_type pt = timestamp.as_qtime_down_to(sync_node());		qtime_type st = pt.as_qtime_down_to(this);		AM_DBG m_logger->debug("%s[%s].on_bom() ST:%ld, PT:%ld, DT:%ld", 			m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), 			st.second(),			pt.second(),			timestamp.second()); 	}	if(m_timer) m_timer->resume();}// Notification from the playable that has paused for fetching bitsvoid time_node::on_pom(qtime_type timestamp) {	if(m_timer) m_timer->pause();}// Notification from the playable that has resumed playbackvoid time_node::on_rom(qtime_type timestamp) {	if(m_timer) m_timer->resume();}// End of nedia notification// This notification is taken into account when this node is still active// and the implicit duration is involved in timing calculations.void time_node::on_eom(qtime_type timestamp) {	AM_DBG m_logger->debug("%s[%s].on_eom()", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str());	m_eom_flag = true;	if(is_playable() && !is_discrete()) {		if(m_impldur == time_type::unresolved) {			time_type pt = timestamp.as_node_time(sync_node());			m_impldur = pt - m_interval.begin();		}		if (m_state->ident() == ts_active) {			raise_update_event(timestamp);			sync_node()->raise_update_event(timestamp);		}		qtime_type pt = timestamp.as_qtime_down_to(sync_node());		qtime_type st = pt.as_qtime_down_to(this);		AM_DBG m_logger->debug("%s[%s].on_eom() ST:%ld, PT:%ld, DT:%ld", 			m_attrs.get_tag().c_str(), 			m_attrs.get_id().c_str(), 			st.second(),			pt.second(),			timestamp.second()); 	}}// Return true if we want on on_eom callback.// This is a hack, really. The problem it tries to solve is that sometimes the// on_eom notification comes in late (because it goes through the event processor)// and by the time we get to on_eom we've already started with a next iteration.// The on_eom callback will then erronuously terminte the new iteration.// But: this solution is a hack, it would be much better if we (a) could make sure// this situation could never occur or (b) could detect this situation in on_eom().bool time_node::want_on_eom(){	return is_active() && !m_eom_flag;}// End of transition// This notification is sent when a transition ends. It is sent to// all nodes that overlap the transition that just finished.void time_node::on_transitioned(qtime_type timestamp) {	AM_DBG m_logger->debug("%s[%s].on_transitioned() DT:%ld", 		m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), 		timestamp.second());	// If this node is not in fill=fill_transition state we do nothing	if (m_active || !m_needs_remove) return;	const time_attrs* ta = get_time_attrs();	fill_behavior fb = ta->get_fill();	if (fb == fill_transition)		remove(timestamp);}//////////////////////////// Node activities (see also activate())// The following function is called when the node should repeat.// It is responsible to execute the repeat actions for this node. void time_node::repeat(qtime_type timestamp) {	AM_DBG m_logger->debug("%s[%s].repeat() ST:%ld, PT:%ld, DT:%ld", m_attrs.get_tag().c_str(), 		m_attrs.get_id().c_str(), 		timestamp.as_time_value_down_to(this),		timestamp.second(), 		timestamp.as_doc_time_value());		// raise_repeat_event async	raise_repeat_event(timestamp);				if(down()) {		// The reset_children op ends all active children		// In consequence for excl empties its pause queue		reset_children(timestamp, this);		startup_children(timestamp);	} 		if(!is_time_container()) {		repeat_playable();	}}// Pauses this node.// Excl element handling.void time_node::pause(qtime_type timestamp, pause_display d) {	if(!is_active()) return;	time_type self_simple_time = timestamp.as_time_down_to(this);	qtime_type qt(this, self_simple_time);		if(is_playable()) pause_playable(d);	if(m_timer) m_timer->pause();		m_paused_sync_time = timestamp.as_time_down_to(sync_node());		// could deduce this from the fact that the node 	// is active and the timer is nor running	set_paused(true); 		// Recalculate the interval of this node as if its dur was indefinite	// The interval semantics are applicable when paused	interval_type i1 = m_interval;	m_time_calc->set_paused_mode(true);	time_type iend = calc_current_interval_end();	if(iend != m_interval.end) {		update_interval_end(timestamp, iend);	}		// Report changed interval	AM_DBG m_logger->debug("%s[%s].pause(): %s -> %s at %ld", 		m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), 		::repr(i1).c_str(), ::repr(m_interval).c_str(), self_simple_time());			// Pause playable active children	time_node::iterator nit;	time_node::iterator end_nit = end();	for(nit=begin(); nit != end_nit; nit++) {		if(!(*nit).first && (*nit).second->is_playable() && (*nit).second->is_active()) 			(*nit).second->pause_playable(d);

⌨️ 快捷键说明

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