LCOV - code coverage report
Current view: top level - compositor - scene_ns.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 167 268 62.3 %
Date: 2021-04-29 23:48:07 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2018
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/compositor_dev.h>
      27             : #include <gpac/network.h>
      28             : 
      29             : 
      30           0 : void scene_ns_on_setup_error(GF_Filter *failed_filter, void *udta, GF_Err err)
      31             : {
      32             :         GF_SceneNamespace *scene_ns;
      33             :         GF_Scene *scene;
      34             :         GF_ObjectManager *root = (GF_ObjectManager *)udta;
      35             :         assert(root);
      36           0 :         scene_ns = root->scene_ns;
      37             :         assert(scene_ns);
      38           0 :         scene = root->subscene ? root->subscene : root->parentscene;
      39             :         assert(scene);
      40             : 
      41           0 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Service connection failure received from %s - %s\n", scene_ns->url, gf_error_to_string(err) ));
      42             : 
      43           0 :         if (root->scene_ns->owner != root) {
      44           0 :                 gf_scene_message(scene, scene_ns->url, "Incompatible module type", GF_SERVICE_ERROR);
      45           0 :                 return;
      46             :         }
      47             :         /*this is service connection*/
      48           0 :         gf_odm_service_media_event(root, GF_EVENT_MEDIA_SETUP_DONE);
      49             : 
      50           0 :         scene_ns->connect_ack = GF_TRUE;
      51           0 :         if (err) {
      52             :                 char msg[5000];
      53           0 :                 snprintf(msg, sizeof(msg), "Cannot open %s", scene_ns->url);
      54           0 :                 gf_scene_message(scene, scene_ns->url, msg, err);
      55             : 
      56           0 :                 if (root->mo) root->mo->connect_failure = GF_TRUE;
      57           0 :                 gf_odm_service_media_event(root, GF_EVENT_ERROR);
      58             : 
      59             :                 /*destroy service only if attached*/
      60             :                 if (root) {
      61             :                         GF_Scene *top_scene;
      62             :                         //notify before disconnecting
      63           0 :                         if (root->subscene) gf_scene_notify_event(root->subscene, GF_EVENT_SCENE_ATTACHED, NULL, NULL, err, GF_FALSE);
      64             : 
      65             :                         //detach clocks before destroying namspace
      66           0 :                         root->ck = NULL;
      67           0 :                         if (root->subscene) {
      68           0 :                                 u32 i, count = gf_list_count(root->subscene->resources);
      69           0 :                                 for (i=0; i<count; i++) {
      70           0 :                                         GF_ObjectManager *anodm = gf_list_get(root->subscene->resources, i);
      71           0 :                                         anodm->ck = NULL;
      72           0 :                                         if (anodm->scene_ns==root->scene_ns)
      73           0 :                                                 anodm->scene_ns = NULL;
      74             :                                 }
      75             :                         }
      76             : 
      77           0 :                         root->scene_ns = NULL;
      78           0 :                         if (scene_ns->owner && scene_ns->nb_odm_users) scene_ns->nb_odm_users--;
      79           0 :                         scene_ns->owner = NULL;
      80             : 
      81           0 :                         top_scene = gf_scene_get_root_scene(scene);
      82             : 
      83             :                         //source filter no longer exists
      84           0 :                         scene_ns->source_filter = NULL;
      85           0 :                         gf_scene_ns_del(scene_ns, top_scene);
      86             : 
      87           0 :                         if (!root->parentscene) {
      88             :                                 GF_Event evt;
      89           0 :                                 evt.type = GF_EVENT_CONNECT;
      90           0 :                                 evt.connect.is_connected = 0;
      91           0 :                                 gf_filter_send_gf_event(scene->compositor->filter, &evt);
      92             :                         } else {
      93             :                                 /*try to reinsert OD for VRML/X3D with multiple URLs:
      94             :                                 1- first remove from parent scene without destroying object, this will trigger a re-setup
      95             :                                         if other URLs are present
      96             :                                         2- then destroy object*/
      97           0 :                                 gf_scene_remove_object(root->parentscene, root, 0);
      98           0 :                                 gf_odm_disconnect(root, 1);
      99             :                         }
     100           0 :                         return;
     101             :                 }
     102             :         }
     103             : }
     104             : 
     105             : 
     106             : 
     107             : #ifdef FILTER_FIXME
     108             : static void term_on_disconnect(GF_ClientService *service, LPNETCHANNEL netch, GF_Err response)
     109             : {
     110             :         GF_ObjectManager *root;
     111             :         GF_Channel *ch;
     112             :         GF_Terminal *term = service->term;
     113             : 
     114             :         /*may be null upon destroy*/
     115             :         root = service->owner;
     116             :         if (root && (root->net_service != service)) {
     117             :                 if (root->net_service) gf_term_message(term, service->url, "Incompatible module type", GF_SERVICE_ERROR);
     118             :                 return;
     119             :         }
     120             :         //reset global seek time
     121             :         if (term->root_scene && term->root_scene->root_od)
     122             :                 term->root_scene->root_od->media_start_time = 0;
     123             : 
     124             :         /*this is service disconnect*/
     125             :         if (!netch) {
     126             :                 if (service->subservice_disconnect) {
     127             :                         if (service->owner && service->subservice_disconnect==1) {
     128             :                                 GF_Scene *scene = service->owner->subscene ? service->owner->subscene : service->owner->parentscene;
     129             :                                 /*destroy all media*/
     130             :                                 gf_scene_disconnect(scene, GF_TRUE);
     131             :                         }
     132             :                         return;
     133             :                 }
     134             :                 /*unregister from valid services*/
     135             :                 if (gf_list_del_item(term->net_services, service)>=0) {
     136             :                         /*and queue for destroy*/
     137             :                         gf_list_add(term->net_services_to_remove, service);
     138             :                 }
     139             :                 return;
     140             :         }
     141             :         /*this is channel disconnect*/
     142             : 
     143             :         /*no notif in case of failure for disconnection*/
     144             :         ch = gf_term_get_channel(service, netch);
     145             :         if (!ch) return;
     146             :         /*signal channel state*/
     147             :         ch->es_state = GF_ESM_ES_DISCONNECTED;
     148             : }
     149             : #endif
     150             : 
     151         887 : void gf_scene_insert_pid(GF_Scene *scene, GF_SceneNamespace *sns, GF_FilterPid *pid, Bool is_in_iod)
     152             : {
     153             :         u32 i, min_od_id;
     154             :         GF_MediaObject *the_mo;
     155             :         GF_ObjectManager *odm, *root;
     156             :         const GF_PropertyValue *v;
     157             :         u32 mtype=0;
     158             :         u32 pid_odid=0;
     159             :         u32 pid_id=0;
     160             :         u32 ServiceID=0;
     161             : 
     162         887 :         root = sns->owner;
     163         887 :         if (!root) {
     164           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] has no root, aborting !\n", sns->url));
     165             :                 return;
     166             :         }
     167         887 :         if (root->flags & GF_ODM_DESTROYED) {
     168           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Service %s] root has been scheduled for destruction - aborting !\n", sns->url));
     169             :                 return;
     170             :         }
     171         887 :         scene = root->subscene ? root->subscene : root->parentscene;
     172         887 :         if (scene->root_od->addon && (scene->root_od->addon->addon_type == GF_ADDON_TYPE_MAIN)) {
     173           0 :                 scene->root_od->flags |= GF_ODM_REGENERATE_SCENE;
     174             :         }
     175             : 
     176         887 :         if (scene->is_dynamic_scene) {
     177         209 :                 if (!root->ID)
     178         207 :                         root->ID = 1;
     179             :         }
     180             : 
     181         887 :         v = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
     182         887 :         if (!v) return;
     183         887 :         mtype = v->value.uint;
     184             : 
     185         887 :         v = gf_filter_pid_get_property(pid, GF_PROP_PID_SERVICE_ID);
     186         887 :         if (v) ServiceID = v->value.uint;
     187             : 
     188         887 :         v = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     189         887 :         if (v) pid_id = v->value.uint;
     190             : 
     191         887 :         if (scene->compositor->autofps && (mtype==GF_STREAM_VISUAL) ) {
     192         345 :                 v = gf_filter_pid_get_property(pid, GF_PROP_PID_FPS);
     193         345 :                 if (v && v->value.frac.den && v->value.frac.num && (v->value.frac.den!=v->value.frac.num)) {
     194         180 :                         scene->compositor->autofps = GF_FALSE;
     195         180 :                         gf_sc_set_fps(scene->compositor, v->value.frac);
     196             :                 }
     197             :         }
     198             : 
     199         887 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Service %s] Adding new media\n", sns->url));
     200             : 
     201             :         /*object declared this way are not part of an OD stream and are considered as dynamic*/
     202             :         /*      od->objectDescriptorID = GF_MEDIA_EXTERNAL_ID; */
     203             : 
     204             :         /*check if we have a mediaObject in the scene not attached and matching this object*/
     205             :         the_mo = NULL;
     206             :         odm = NULL;
     207             :         min_od_id = 0;
     208         139 :         for (i=0; i<gf_list_count(scene->scene_objects); i++) {
     209             : #if FILTER_FIXME
     210             :                 char *frag = NULL;
     211             : #endif
     212             :                 char *ext, *url;
     213             :                 u32 match_esid = 0;
     214             :                 Bool type_matched = GF_FALSE;
     215         310 :                 GF_MediaObject *mo = gf_list_get(scene->scene_objects, i);
     216             : 
     217         310 :                 if ((mo->OD_ID != GF_MEDIA_EXTERNAL_ID) && (min_od_id<mo->OD_ID))
     218             :                         min_od_id = mo->OD_ID;
     219             : 
     220             :                 //got the service, check the type
     221             :                 /*match type*/
     222         310 :                 switch (mtype) {
     223         256 :                 case GF_STREAM_VISUAL:
     224         256 :                         if (mo->type == GF_MEDIA_OBJECT_VIDEO) type_matched = GF_TRUE;
     225             :                         break;
     226          21 :                 case GF_STREAM_AUDIO:
     227          21 :                         if (mo->type == GF_MEDIA_OBJECT_AUDIO) type_matched = GF_TRUE;
     228             :                         break;
     229          29 :                 case GF_STREAM_SCENE:
     230          29 :                         if (mo->type == GF_MEDIA_OBJECT_UPDATES) type_matched = GF_TRUE;
     231             :                         break;
     232             :                 default:
     233             :                         break;
     234             :                 }
     235         310 :                 if (!mo->odm) {
     236             :                         u32 j;
     237             :                         //if not external OD, look for ODM with same ID
     238          14 :                         if (mo->OD_ID != GF_MEDIA_EXTERNAL_ID) {
     239           6 :                                 for (j=0; j<gf_list_count(scene->resources); j++) {
     240          20 :                                         GF_ObjectManager *an_odm = gf_list_get(scene->resources, j);
     241          20 :                                         if (an_odm->ID == mo->OD_ID) {
     242          14 :                                                 mo->odm = an_odm;
     243          14 :                                                 break;
     244             :                                         }
     245             :                                 }
     246             :                         }
     247          14 :                         if (!mo->odm) {
     248           0 :                                 continue;
     249             :                         }
     250             :                 }
     251             :                 /*if object is attached to a service, don't bother looking in a different one*/
     252         310 :                 if (mo->odm->scene_ns && (mo->odm->scene_ns != sns)) {
     253             :                         Bool mine = 0;
     254         284 :                         if (mo->odm->scene_ns->source_filter) {
     255         217 :                                 mine = gf_filter_pid_is_filter_in_parents(pid, mo->odm->scene_ns->source_filter);
     256             :                         }
     257             :                         //passthrough ODM not yet assigned, consider it ours
     258          67 :                         else if (!mo->odm->pid && (mo->odm->flags & GF_ODM_PASSTHROUGH)) {
     259             :                                 mine = GF_TRUE;
     260             :                         }
     261         327 :                         if (!mine) continue;
     262             : 
     263         174 :                         if (type_matched) {
     264             :                                 the_mo = mo;
     265         171 :                                 odm = mo->odm;
     266         171 :                                 pid_odid = odm->ID = mo->OD_ID;
     267         171 :                                 break;
     268             :                         }
     269             :                 }
     270             : 
     271             :                 /*already assigned object*/
     272          29 :                 if (mo->odm->ID) continue;
     273             : 
     274             :                 /*we cannot match yet the object, we need the OD command for that*/
     275           0 :                 if (mo->OD_ID != GF_MEDIA_EXTERNAL_ID) {
     276           0 :                         continue;
     277             :                 }
     278           0 :                 if (!mo->URLs.count || !mo->URLs.vals[0].url) continue;
     279             : 
     280           0 :                 ext = strrchr(mo->URLs.vals[0].url, '#');
     281           0 :                 if (ext) {
     282             : #if FILTER_FIXME
     283             :                         frag = strchr(ext, '=');
     284             : #endif
     285           0 :                         ext[0] = 0;
     286             :                 }
     287           0 :                 url = mo->URLs.vals[0].url;
     288           0 :                 if (!strnicmp(url, "file://localhost", 16)) url += 16;
     289           0 :                 else if (!strnicmp(url, "file://", 7)) url += 7;
     290           0 :                 else if (!strnicmp(url, "gpac://", 7)) url += 7;
     291           0 :                 else if (!strnicmp(url, "pid://", 6)) match_esid = atoi(url+6);
     292             : 
     293           0 :                 if (!match_esid && mo->odm->scene_ns && !strstr(mo->odm->scene_ns->url, url)) {
     294           0 :                         if (ext) ext[0] = '#';
     295           0 :                         continue;
     296             :                 }
     297           0 :                 if (ext) ext[0] = '#';
     298             : 
     299           0 :                 if (match_esid && (pid_id != match_esid))
     300           0 :                         continue;
     301             : 
     302             :                 /*match type*/
     303           0 :                 switch (mtype) {
     304           0 :                 case GF_STREAM_VISUAL:
     305           0 :                         if (mo->type != GF_MEDIA_OBJECT_VIDEO) continue;
     306             :                         break;
     307           0 :                 case GF_STREAM_AUDIO:
     308           0 :                         if (mo->type != GF_MEDIA_OBJECT_AUDIO) continue;
     309             :                         break;
     310           0 :                 case GF_STREAM_SCENE:
     311           0 :                         if (mo->type != GF_MEDIA_OBJECT_UPDATES) continue;
     312             :                         break;
     313           0 :                 default:
     314           0 :                         continue;
     315             :                 }
     316             : #if FILTER_FIXME
     317             :                 if (frag) {
     318             :                         u32 frag_id = 0;
     319             :                         u32 ID = od->objectDescriptorID;
     320             :                         if (ID==GF_MEDIA_EXTERNAL_ID) ID = esd->ESID;
     321             :                         frag++;
     322             :                         frag_id = atoi(frag);
     323             :                         if (ID!=frag_id) continue;
     324             :                 }
     325             : #endif
     326             :                 the_mo = mo;
     327           0 :                 odm = mo->odm;
     328           0 :                 pid_odid = odm->ID = mo->OD_ID;
     329           0 :                 if (mo->OD_ID == GF_MEDIA_EXTERNAL_ID)
     330           0 :                         odm->flags |= GF_ODM_NOT_IN_OD_STREAM;
     331             :                 break;
     332             :         }
     333             : 
     334             :         /*add a pass on scene->resource to check for min_od_id,
     335             :         otherwise we may have another modules declaring an object with ID 0 from
     336             :         another thread, which will assert (only one object with a givne OD ID)*/
     337        1241 :         for (i=0; i<gf_list_count(scene->resources); i++) {
     338         371 :                 GF_ObjectManager *an_odm = gf_list_get(scene->resources, i);
     339             : 
     340         371 :                 if (an_odm->ID == GF_MEDIA_EXTERNAL_ID) continue;
     341             : 
     342         274 :                 if (min_od_id < an_odm->ID)
     343             :                         min_od_id = an_odm->ID;
     344             : 
     345         274 :                 if (odm) continue;
     346             :                 //check for OD replacement, look for ODMs with no PID assigned and a source filter origin for this pid
     347          65 :                 if (an_odm->pid) continue;
     348             : 
     349          24 :                 if (!an_odm->scene_ns->source_filter) continue;
     350          17 :                 if (! gf_filter_pid_is_filter_in_parents(pid, an_odm->scene_ns->source_filter))
     351           0 :                         continue;
     352             : 
     353             :                 odm = an_odm;
     354          17 :                 pid_odid = an_odm->ID;
     355          17 :                 break;
     356             :         }
     357             : 
     358         887 :         if (is_in_iod) {
     359         479 :                 odm = scene->root_od;
     360             :                 //for inline cases, the media object may already be setup
     361         479 :                 the_mo = odm->mo;
     362         479 :                 if (the_mo) pid_odid = the_mo->OD_ID;
     363             :         }
     364             : 
     365         887 :         if (!odm) {
     366         220 :                 odm = gf_odm_new();
     367         220 :                 odm->parentscene = scene;
     368         220 :                 gf_list_add(scene->resources, odm);
     369             :         }
     370         887 :         odm->flags |= GF_ODM_NOT_SETUP;
     371         887 :         if (!pid_odid) {
     372         658 :                 pid_odid = min_od_id + 1;
     373             :         }
     374         887 :         odm->ID = pid_odid;
     375         887 :         odm->mo = the_mo;
     376         887 :         odm->ServiceID = ServiceID;
     377         887 :         if (!odm->pid) {
     378         881 :                 odm->type = mtype;
     379         881 :                 if (mtype == GF_STREAM_AUDIO) {
     380          18 :                         scene->compositor->audio_renderer->nb_audio_objects++;
     381          18 :                         scene->compositor->audio_renderer->scene_ready = GF_FALSE;
     382             :                 }
     383             :         }
     384             : 
     385             :         //register PID with ODM, but don't call setup object
     386         887 :         gf_odm_register_pid(odm, pid, GF_TRUE);
     387             : 
     388         887 :         gf_filter_pid_set_udta(pid, odm);
     389             : 
     390         887 :         v = gf_filter_pid_get_property(pid, GF_PROP_PID_PLAYBACK_MODE);
     391         887 :         if (!v || !v->value.uint) odm->flags |= GF_ODM_NO_TIME_CTRL;
     392             : 
     393         887 :         if (the_mo) the_mo->OD_ID = odm->ID;
     394         887 :         if (!scene->selected_service_id)
     395         887 :                 scene->selected_service_id = ServiceID;
     396             : 
     397         887 :         if (odm->parentscene && odm->parentscene->is_dynamic_scene)
     398         209 :                 odm->flags |= GF_ODM_NOT_IN_OD_STREAM;
     399             : 
     400             :         //we insert right away the PID as a new object if the scene is dynamic
     401             :         //if the scene is not dynamic, we wait for the corresponding OD update
     402             :         //FILTER_FIXME: needs rework to enable attaching subtitle to a non-dynamic scene
     403             :         //otherwise if subscene, this is an IOD
     404         887 :         if (odm->subscene || (odm->flags & GF_ODM_NOT_IN_OD_STREAM) ) {
     405         876 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] setup object - MO %08x\n", odm->ID, odm->mo));
     406         876 :                 gf_odm_setup_object(odm, sns, pid);
     407             :         } else {
     408             :                 //cannot setup until we get the associated OD_Update
     409          11 :                 odm->ID = 0;
     410             :         }
     411             : 
     412         887 :         if (scene->is_dynamic_scene && !root->scene_ns->connect_ack) {
     413             :                 /*othewise send a connect ack for top level*/
     414             :                 GF_Event evt;
     415         209 :                 root->scene_ns->connect_ack = GF_TRUE;
     416             : 
     417         209 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Root object connected (%s) !\n", root->scene_ns->url));
     418             : 
     419         209 :                 evt.type = GF_EVENT_CONNECT;
     420         209 :                 evt.connect.is_connected = GF_TRUE;
     421         209 :                 gf_sc_send_event(scene->compositor, &evt);
     422             :         }
     423             : }
     424             : 
     425         906 : GF_SceneNamespace *gf_scene_ns_new(GF_Scene *scene, GF_ObjectManager *owner, const char *url, const char *parent_url)
     426             : {
     427             :         char *frag;
     428             :         GF_SceneNamespace *sns;
     429             : 
     430         906 :         GF_SAFEALLOC(sns, GF_SceneNamespace);
     431         906 :         if (!sns) {
     432           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Compose] Failed to allocate namespace\n"));
     433             :                 return NULL;
     434             :         }
     435         906 :         sns->owner = owner;
     436         906 :         sns->url = gf_url_concatenate(parent_url, url);
     437         906 :         sns->clocks = gf_list_new();
     438         906 :         frag = strchr(sns->url, '#');
     439         906 :         if (frag) {
     440           0 :                 sns->url_frag = gf_strdup(frag+1);
     441           0 :                 frag[0] = 0;
     442             :         }
     443             : 
     444             :         //move to top scene
     445         906 :         scene = gf_scene_get_root_scene(scene);
     446         906 :         gf_list_add(scene->namespaces, sns);
     447             : 
     448         906 :         return sns;
     449             : }
     450             : 
     451             : 
     452             : 
     453         906 : void gf_scene_ns_del(GF_SceneNamespace *sns, GF_Scene *root_scene)
     454             : {
     455         906 :         gf_list_del_item(root_scene->namespaces, sns);
     456             : 
     457         906 :         if (sns->source_filter) {
     458         230 :                 gf_filter_remove_src(root_scene->compositor->filter, sns->source_filter);
     459             :         }
     460         906 :         if (sns->clocks) {
     461        1747 :                 while (gf_list_count(sns->clocks)) {
     462         841 :                         GF_Clock *ck = gf_list_pop_back(sns->clocks);
     463         841 :                         gf_clock_del(ck);
     464             :                 }
     465         906 :                 gf_list_del(sns->clocks);
     466             :         }
     467         906 :         if (sns->url) gf_free(sns->url);
     468         906 :         if (sns->url_frag) gf_free(sns->url_frag);
     469         906 :         gf_free(sns);
     470         906 : }
     471             : 
     472             : 
     473           3 : Bool scene_ns_remove_object(GF_Filter *filter, void *callback, u32 *reschedule_ms)
     474             : {
     475             :         GF_ObjectManager *odm = (GF_ObjectManager *)callback;
     476           3 :         gf_odm_disconnect(odm, 2);
     477           3 :         return GF_FALSE;
     478             : }
     479             : 
     480             : /*connects given OD manager to its URL*/
     481         274 : void gf_scene_ns_connect_object(GF_Scene *scene, GF_ObjectManager *odm, char *serviceURL, char *parent_url)
     482             : {
     483             :         GF_Err e;
     484             :         char *frag;
     485             :         Bool reloc_result=GF_FALSE;
     486             : 
     487             :         /*check cache*/
     488         274 :         if (parent_url) {
     489             :                 u32 i, count;
     490         260 :                 count = gf_opts_get_section_count();
     491        2454 :                 for (i=0; i<count; i++) {
     492             :                         u32 exp, sec, frac;
     493             :                         const char *opt, *service_cache;
     494        2194 :                         const char *name = gf_opts_get_section_name(i);
     495        4388 :                         if (strncmp(name, "@cache=", 7)) continue;
     496           0 :                         opt = gf_opts_get_key(name, "serviceURL");
     497           0 :                         if (!opt || stricmp(opt, parent_url)) continue;
     498           0 :                         opt = gf_opts_get_key(name, "cacheName");
     499           0 :                         if (!opt || stricmp(opt, serviceURL)) continue;
     500             : 
     501           0 :                         service_cache = (char*)gf_opts_get_key(name, "cacheFile");
     502           0 :                         opt = gf_opts_get_key(name, "expireAfterNTP");
     503           0 :                         if (opt) {
     504           0 :                                 sscanf(opt, "%u", &exp);
     505           0 :                                 gf_net_get_ntp(&sec, &frac);
     506           0 :                                 if (exp && (exp<sec)) {
     507           0 :                                         opt = gf_opts_get_key(name, "cacheFile");
     508           0 :                                         if (opt) gf_file_delete((char*) opt);
     509           0 :                                         gf_opts_del_section(name);
     510             :                                         service_cache = NULL;
     511             :                                 }
     512             :                         }
     513           0 :                         if (service_cache) serviceURL = (char *)service_cache;
     514           0 :                         break;
     515             :                 }
     516             :         }
     517             : 
     518         274 :         frag = strchr(serviceURL, '#');
     519         274 :         if (frag) {
     520          10 :                 frag[0] = 0;
     521          10 :                 u32 i, count = gf_list_count(scene->compositor->root_scene->namespaces);
     522          21 :                 for (i=0; i<count; i++) {
     523          11 :                         GF_SceneNamespace *sns = gf_list_get(scene->compositor->root_scene->namespaces, i);
     524          11 :                         if (sns->url && !strcmp(sns->url, serviceURL)) {
     525           0 :                                 frag[0] = '#';
     526           0 :                                 odm->scene_ns = sns;
     527           0 :                                 sns->nb_odm_users++;
     528           3 :                                 return;
     529             :                         }
     530             :                 }
     531             :         }
     532             : 
     533         274 :         odm->scene_ns = gf_scene_ns_new(scene->compositor->root_scene, odm, serviceURL, (odm->addon || reloc_result) ? NULL : parent_url);
     534             : 
     535         274 :         if (!odm->scene_ns) {
     536           0 :                 gf_scene_message(scene, serviceURL, "Cannot create scene service", GF_OUT_OF_MEM);
     537           0 :                 gf_odm_disconnect(odm, 1);
     538           0 :                 if (frag) frag[0] = '#';
     539             :                 return;
     540             :         }
     541         274 :         odm->scene_ns->nb_odm_users++;
     542             :         assert(odm->scene_ns->owner == odm);
     543             : 
     544         274 :         if (frag && !odm->scene_ns->url_frag) {
     545          10 :                 odm->scene_ns->url_frag = gf_strdup(frag+1);
     546             :         }
     547             : 
     548         274 :         if (!strncmp(serviceURL, "gpid://", 7)) {
     549           0 :                 gf_odm_service_media_event(odm, GF_EVENT_MEDIA_SETUP_BEGIN);
     550           0 :                 gf_odm_service_media_event(odm, GF_EVENT_MEDIA_SETUP_DONE);
     551           0 :                 odm->scene_ns->connect_ack = GF_TRUE;
     552           0 :                 odm->flags |= GF_ODM_NOT_IN_OD_STREAM | GF_ODM_PASSTHROUGH;
     553           0 :                 if (frag) frag[0] = '#';
     554             :                 return;
     555             :         }
     556         274 :         if (!parent_url && odm->parentscene && odm->parentscene->root_od->scene_ns)
     557           7 :                 parent_url = odm->parentscene->root_od->scene_ns->url;
     558             : 
     559         274 :         odm->scene_ns->source_filter = gf_filter_connect_source(scene->compositor->filter, serviceURL, parent_url, GF_FALSE, &e);
     560             : 
     561         274 :         if (frag) frag[0] = '#';
     562         274 :         if (!odm->scene_ns->source_filter) {
     563             :                 Bool remove_scene=GF_FALSE;
     564           3 :                 GF_Scene *target_scene = odm->subscene ? NULL : odm->parentscene;
     565           3 :                 if (odm->mo) odm->mo->connect_failure = GF_TRUE;
     566           3 :                 odm->skip_disconnect_state = 1;
     567             :                 //prevent scene from being disconnected - this can happen if a script catches the event and triggers a disonnection of the parent scene
     568           3 :                 if (target_scene) target_scene->root_od->skip_disconnect_state = 1;
     569           3 :                 gf_scene_notify_event(scene, GF_EVENT_SCENE_ATTACHED, NULL, NULL, e, GF_TRUE);
     570           3 :                 gf_scene_message(scene, serviceURL, "Cannot find filter for service", e);
     571           3 :                 odm->skip_disconnect_state = 0;
     572             : 
     573           3 :                 if (target_scene) {
     574           2 :                         if (target_scene->root_od->skip_disconnect_state==2) remove_scene = GF_TRUE;
     575           2 :                         target_scene->root_od->skip_disconnect_state = 0;
     576             :                 }
     577           2 :                 if (remove_scene) {
     578           0 :                         gf_filter_post_task(scene->compositor->filter, scene_ns_remove_object, target_scene->root_od, "remove_odm");
     579             :                 } else {
     580           3 :                         gf_filter_post_task(scene->compositor->filter, scene_ns_remove_object, odm, "remove_odm");
     581             :                 }
     582             :                 return;
     583             :         }
     584             :     //make sure we only connect this filter to ourselves 
     585         271 :     gf_filter_set_source_restricted(scene->compositor->filter, odm->scene_ns->source_filter, NULL);
     586             :     
     587         271 :         gf_filter_set_setup_failure_callback(scene->compositor->filter, odm->scene_ns->source_filter, scene_ns_on_setup_error, odm);
     588             : 
     589             :         /*OK connect*/
     590         271 :         gf_odm_service_media_event(odm, GF_EVENT_MEDIA_SETUP_BEGIN);
     591             : }
     592             : 
     593             : 
     594             : GF_EXPORT
     595           2 : Bool gf_term_is_supported_url(GF_Terminal *term, const char *fileName, Bool use_parent_url, Bool no_mime_check)
     596             : {
     597             : #ifdef FILTER_FIXME
     598             :         GF_InputService *ifce;
     599             :         GF_Err e;
     600             :         char *sURL;
     601             :         char *mime=NULL;
     602             :         char *parent_url = NULL;
     603             :         if (use_parent_url && term->root_scene) parent_url = term->root_scene->root_od->net_service->url;
     604             : 
     605             :         ifce = gf_term_can_handle_service(term, fileName, parent_url, no_mime_check, &sURL, &e, NULL, &mime);
     606             :         if (!ifce) return 0;
     607             :         gf_modules_close_interface((GF_BaseInterface *) ifce);
     608             :         gf_free(sURL);
     609             :         if (mime) gf_free(mime);
     610             : #endif
     611           2 :         return 1;
     612             : }

Generated by: LCOV version 1.13