static void ODS_SetupOD(GF_Scene *scene, GF_ObjectDescriptor *od) { GF_ObjectManager *odm; odm = gf_scene_find_odm(scene, od->objectDescriptorID); /*remove the old OD*/ if (odm) gf_odm_disconnect(odm, 1); odm = gf_odm_new(); odm->OD = od; odm->term = scene->root_od->term; odm->parentscene = scene; gf_list_add(scene->resources, odm); /*locate service owner*/ gf_odm_setup_object(odm, scene->root_od->net_service); }
static void ODS_SetupOD(GF_InlineScene *is, GF_ObjectDescriptor *od) { GF_ObjectManager *odm; odm = gf_is_find_odm(is, od->objectDescriptorID); /*remove the old OD*/ if (odm) gf_odm_disconnect(odm, 1); odm = gf_odm_new(); odm->OD = od; odm->term = is->root_od->term; odm->parentscene = is; gf_list_add(is->ODlist, odm); /*locate service owner*/ gf_odm_setup_object(odm, is->root_od->net_service); }
static void term_on_media_add(void *user_priv, GF_ClientService *service, GF_Descriptor *media_desc, Bool no_scene_check) { u32 i, min_od_id; GF_MediaObject *the_mo; GF_Scene *scene; GF_ObjectManager *odm, *root; GF_ObjectDescriptor *od; GET_TERM(); root = service->owner; if (!root) { GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] has not root, aborting !\n", service->url)); return; } if (root->flags & GF_ODM_DESTROYED) { GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] root has been scheduled for destruction - aborting !\n", service->url)); return; } scene = root->subscene ? root->subscene : root->parentscene; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Service %s] %s\n", service->url, media_desc ? "Adding new media object" : "Regenerating scene graph")); if (!media_desc) { if (!no_scene_check) gf_scene_regenerate(scene); return; } switch (media_desc->tag) { case GF_ODF_OD_TAG: case GF_ODF_IOD_TAG: if (root && (root->net_service == service)) { od = (GF_ObjectDescriptor *) media_desc; break; } default: gf_odf_desc_del(media_desc); return; } gf_term_lock_net(term, 1); /*object declared this way are not part of an OD stream and are considered as dynamic*/ /* od->objectDescriptorID = GF_MEDIA_EXTERNAL_ID; */ /*check if we have a mediaObject in the scene not attached and matching this object*/ the_mo = NULL; odm = NULL; min_od_id = 0; for (i=0; i<gf_list_count(scene->scene_objects); i++) { char *frag, *ext; GF_ESD *esd; char *url; u32 match_esid = 0; GF_MediaObject *mo = gf_list_get(scene->scene_objects, i); if ((mo->OD_ID != GF_MEDIA_EXTERNAL_ID) && (min_od_id<mo->OD_ID)) min_od_id = mo->OD_ID; if (!mo->odm) continue; /*if object is attached to a service, don't bother looking in a different one*/ if (mo->odm->net_service && (mo->odm->net_service != service)) continue; /*already assigned object - this may happen since the compositor has no control on when objects are declared by the service, therefore opening file#video and file#audio may result in the objects being declared twice if the service doesn't keep track of declared objects*/ if (mo->odm->OD) { if (od->objectDescriptorID && is_same_od(mo->odm->OD, od)) { /*reassign OD ID*/ mo->OD_ID = od->objectDescriptorID; gf_odf_desc_del(media_desc); gf_term_lock_net(term, 0); return; } continue; } if (mo->OD_ID != GF_MEDIA_EXTERNAL_ID) { if (mo->OD_ID == od->objectDescriptorID) { the_mo = mo; odm = mo->odm; break; } continue; } if (!mo->URLs.count || !mo->URLs.vals[0].url) continue; frag = NULL; ext = strrchr(mo->URLs.vals[0].url, '#'); if (ext) { frag = strchr(ext, '='); ext[0] = 0; } url = mo->URLs.vals[0].url; if (!strnicmp(url, "file://localhost", 16)) url += 16; else if (!strnicmp(url, "file://", 7)) url += 7; else if (!strnicmp(url, "gpac://", 7)) url += 7; else if (!strnicmp(url, "pid://", 6)) match_esid = atoi(url+6); if (!match_esid && !strstr(service->url, url)) { if (ext) ext[0] = '#'; continue; } if (ext) ext[0] = '#'; esd = gf_list_get(od->ESDescriptors, 0); if (match_esid && (esd->ESID != match_esid)) continue; /*match type*/ switch (esd->decoderConfig->streamType) { case GF_STREAM_VISUAL: if (mo->type != GF_MEDIA_OBJECT_VIDEO) continue; break; case GF_STREAM_AUDIO: if (mo->type != GF_MEDIA_OBJECT_AUDIO) continue; break; case GF_STREAM_PRIVATE_MEDIA: if ((mo->type != GF_MEDIA_OBJECT_AUDIO) && (mo->type != GF_MEDIA_OBJECT_VIDEO)) continue; break; case GF_STREAM_SCENE: if (mo->type != GF_MEDIA_OBJECT_UPDATES) continue; break; default: continue; } if (frag) { u32 frag_id = 0; u32 ID = od->objectDescriptorID; if (ID==GF_MEDIA_EXTERNAL_ID) ID = esd->ESID; frag++; frag_id = atoi(frag); if (ID!=frag_id) continue; } the_mo = mo; odm = mo->odm; break; } /*add a pass on scene->resource to check for min_od_id, otherwise we may have another modules declaring an object with ID 0 from another thread, which will assert (only one object with a givne OD ID)*/ for (i=0; i<gf_list_count(scene->resources); i++) { GF_ObjectManager *an_odm = gf_list_get(scene->resources, i); if (an_odm->OD && (an_odm->OD->objectDescriptorID != GF_MEDIA_EXTERNAL_ID) && (min_od_id < an_odm->OD->objectDescriptorID)) min_od_id = an_odm->OD->objectDescriptorID; } if (!odm) { odm = gf_odm_new(); odm->term = term; odm->parentscene = scene; gf_list_add(scene->resources, odm); } odm->OD = od; odm->mo = the_mo; odm->flags |= GF_ODM_NOT_IN_OD_STREAM; if (!od->objectDescriptorID) { od->objectDescriptorID = min_od_id + 1; } if (the_mo) the_mo->OD_ID = od->objectDescriptorID; if (!scene->selected_service_id) scene->selected_service_id = od->ServiceID; /*net is unlocked before seting up the object as this might trigger events going into JS and deadlocks with the compositor*/ gf_term_lock_net(term, 0); GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] setup object - MO %08x\n", odm->OD->objectDescriptorID, odm->mo)); gf_odm_setup_object(odm, service); /*OD inserted by service: resetup scene*/ if (!no_scene_check && scene->is_dynamic_scene) gf_scene_regenerate(scene); }