コード例 #1
0
ファイル: mpeg4_inline.c プロジェクト: DmitrySigaev/gpac-sf
void gf_inline_on_modified(GF_Node *node)
{
	u32 ODID;
	GF_MediaObject *mo;
	M_Inline *pInline = (M_Inline *) node;
	GF_Scene *scene = (GF_Scene *)gf_node_get_private(node);

	ODID = gf_mo_get_od_id(&pInline->url);
	if (scene) {
		mo = (scene->root_od) ? scene->root_od->mo : NULL;

		/*disconnect current inline if we're the last one using it (same as regular OD session leave/join)*/
		if (mo) {
			Bool changed = GF_TRUE;
			if (ODID != GF_MEDIA_EXTERNAL_ID) {
				if (ODID && (ODID==scene->root_od->OD->objectDescriptorID)) changed = GF_FALSE;
			} else {
				if (gf_mo_is_same_url(mo, &pInline->url, NULL, 0) ) changed = GF_FALSE;
			}
			if (mo->num_open) {
				if (!changed) return;

				gf_scene_notify_event(scene, GF_EVENT_UNLOAD, node, NULL, GF_OK, GF_TRUE);
				gf_node_dirty_parents(node);
				gf_mo_event_target_remove_by_node(mo, node);

				/*reset the scene pointer as it may get destroyed*/
				switch (gf_node_get_tag(node)) {
				case TAG_MPEG4_Inline:
#ifndef GPAC_DISABLE_X3D
				case TAG_X3D_Inline:
#endif
					gf_node_set_private(node, NULL);
					break;
				}

				mo->num_open --;
				if (!mo->num_open) {
					if (ODID == GF_MEDIA_EXTERNAL_ID) {
						GF_Scene *parent = scene->root_od->parentscene;
						/*!!! THIS WILL DESTROY THE INLINE SCENE OBJECT !!!*/
						gf_odm_disconnect(scene->root_od, GF_TRUE);
						/*and force removal of the media object*/
						if (parent) {
							if (gf_list_del_item(parent->scene_objects, mo)>=0) {
								gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL);
								gf_mo_del(mo);
							}
						}
					} else {
						gf_term_lock_media_queue(scene->root_od->term, GF_TRUE);

						/*external media are completely unloaded, except addons which are only declared once */
						if (!scene->root_od->addon && (scene->root_od->OD->objectDescriptorID==GF_MEDIA_EXTERNAL_ID)) {
							scene->root_od->action_type = GF_ODM_ACTION_DELETE;
						} else {
							scene->root_od->action_type = GF_ODM_ACTION_STOP;
						}
						if (gf_list_find(scene->root_od->term->media_queue, scene->root_od)<0)
							gf_list_add(scene->root_od->term->media_queue, scene->root_od);

						gf_term_lock_media_queue(scene->root_od->term, GF_FALSE);
					}
				}
			}
		}
	}
	/*force a redraw and load scene at next pass - we cannot load the scene now because
		- we can be in a JS call (eg JS mutex blocked)
		- locating scene objects matching the new url needs exclusive access to the MediaObject list, achieved with the term net mutex
		- another service may already be setting up objects (eg exclusive access to the net mutex grabbed), which can trigger event forwarding
		- some event forwarders may request JS context (eg access to JS mutex)

		In such a case we would end up in a deadlock - this needs urgent fixing ...
	*/
	if (ODID) {
		/*if no parent we must process the url change as we may not be traversed later on (not in the scene tree)*/
		if (gf_node_get_parent(node, 0)==NULL) {
			gf_inline_set_scene(pInline);
		} else {
			gf_node_dirty_parents(node);
		}
	}
}
コード例 #2
0
ファイル: media_object.c プロジェクト: Bevara/GPAC
void gf_mo_unregister(GF_Node *node, GF_MediaObject *mo)
{
	if (mo && node) {
		gf_mo_event_target_remove_by_node(mo, node);
	}
}
コード例 #3
0
ファイル: mpeg4_inline.c プロジェクト: DmitrySigaev/gpac-sf
static void gf_inline_traverse(GF_Node *n, void *rs, Bool is_destroy)
{
	MFURL *current_url;
	GF_Scene *scene = (GF_Scene *)gf_node_get_private(n);

	if (is_destroy) {
		GF_MediaObject *mo;
		if (!scene) return;
		mo = scene->root_od ? scene->root_od->mo : NULL;

		gf_scene_notify_event(scene, GF_EVENT_UNLOAD, n, NULL, GF_OK, GF_TRUE);
		if (!mo) return;
		gf_mo_event_target_remove_by_node(mo, n);

		/*disconnect current inline if we're the last one using it (same as regular OD session leave/join)*/
		if (mo->num_open) {
			mo->num_open --;
			if (!mo->num_open) {
				gf_term_lock_media_queue(scene->root_od->term, GF_TRUE);

				/*this is unspecified in the spec: whenever an inline not using the
				OD framework is destroyed, destroy the associated resource*/
				if (mo->OD_ID == GF_MEDIA_EXTERNAL_ID) {
					/*get parent scene and remove MediaObject in case the ressource
					gets re-requested later on*/
					GF_Scene *parent_scene = (GF_Scene *)gf_sg_get_private(gf_node_get_graph((GF_Node *) n) );
					if (gf_list_del_item(parent_scene->scene_objects, mo)>=0) {
						gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL);
						if (mo->odm) {
							gf_odm_reset_media_control(mo->odm, 1);
							mo->odm->mo = NULL;
						}
						gf_mo_del(mo);
					}
					scene->root_od->action_type = GF_ODM_ACTION_DELETE;
					gf_list_add(scene->root_od->term->media_queue, scene->root_od);
				} else {
					scene->root_od->action_type = GF_ODM_ACTION_SCENE_DISCONNECT;
					gf_list_add(scene->root_od->term->media_queue, scene->root_od);
				}
				gf_term_lock_media_queue(scene->root_od->term, GF_FALSE);
			}
		}
		return;
	}


	//if no private scene is associated	get the node parent graph, retrieve the IS and find the OD
	if (!scene) {
		M_Inline *inl = (M_Inline *)n;
		gf_inline_set_scene(inl);
		scene = (GF_Scene *)gf_node_get_private(n);
		if (!scene) {
			/*just like protos, we must invalidate parent graph until attached*/
			if (inl->url.count) {
				if (!inl->url.vals[0].OD_ID && (!inl->url.vals[0].url || !strlen(inl->url.vals[0].url) ) ) {
					gf_sg_vrml_mf_reset(&inl->url, GF_SG_VRML_MFURL);
				} else {
					gf_node_dirty_set(n, 0, GF_TRUE);
				}
			}
			return;
		}
	}

	/*if not attached return (attaching the graph cannot be done in render since render is not called while unattached :) */
	if (!scene->graph_attached) {
		/*just like protos, we must invalidate parent graph until attached*/
		gf_node_dirty_set(n, 0, GF_TRUE);
		return;
	}
	/*clear dirty flags for any sub-inlines, bitmaps or protos*/
	gf_node_dirty_clear(n, 0);

	current_url = scene->current_url;
	scene->current_url = & ((M_Inline*)n)->url;
	gf_sc_traverse_subscene(scene->root_od->term->compositor, n, scene->graph, rs);
	scene->current_url = current_url;

	//do we have to restart for next frame ? If so let's do it
	gf_inline_check_restart(scene);

	/*if we need to restart, shutdown graph and do it*/
	if (scene->needs_restart) {
		/*special case: scene change*/
		if (scene->needs_restart==2) {
			scene->needs_restart = 0;
			gf_inline_on_modified(n);
			return;
		}

		scene->needs_restart = 0;
		gf_term_lock_media_queue(scene->root_od->term, GF_TRUE);
		scene->root_od->action_type = GF_ODM_ACTION_SCENE_INLINE_RESTART;
		gf_list_add(scene->root_od->term->media_queue, scene->root_od);
		gf_term_lock_media_queue(scene->root_od->term, GF_FALSE);

		gf_node_dirty_set(n, 0, GF_TRUE);
		return;
	}

}