~ubuntu-branches/ubuntu/raring/gpac/raring

« back to all changes in this revision

Viewing changes to src/terminal/object_manager.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2007-01-24 23:34:57 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070124233457-zzlls8afkt0nyakj
Tags: 0.4.2~rc2-0ubuntu1
* New upstream release
  * Most notably MP4 tagging support via MP4Box -itags
* debian/patches/01_64bits.dpatch: dropped; included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
void gf_odm_del(GF_ObjectManager *odm)
55
55
{
56
 
        u32 i, count;
57
 
        count = gf_list_count(odm->ms_stack);
58
 
        for (i = 0; i<count; i++) {
59
 
                MediaSensorStack *media_sens = gf_list_get(odm->ms_stack, i);
 
56
        u32 i;
 
57
        MediaSensorStack *media_sens;
 
58
        i=0;
 
59
        while ((media_sens = gf_list_enum(odm->ms_stack, &i))) {
60
60
                MS_Stop(media_sens);
61
61
                /*and detach from stream object*/
62
62
                media_sens->is_init = 0;
90
90
        /*no destroy*/
91
91
        if (!do_remove) return;
92
92
 
93
 
        /*then delete all the OD channels associated with this service*/
 
93
        /*unload the decoders before deleting the channels to prevent any access fault*/
 
94
        if (odm->codec) gf_mm_remove_codec(odm->term->mediaman, odm->codec);
 
95
        if (odm->ocr_codec) gf_mm_remove_codec(odm->term->mediaman, odm->ocr_codec);
 
96
        if (odm->oci_codec) gf_mm_remove_codec(odm->term->mediaman, odm->oci_codec);
 
97
 
 
98
        /*then delete all the channels in this OD */
94
99
        while (gf_list_count(odm->channels)) {
95
100
                ch = gf_list_get(odm->channels, 0);
 
101
#if 0
 
102
                if (ch->clock->mc && ch->clock->mc->stream && ch->clock->mc->stream->odm==odm) {
 
103
                        ch->clock->mc->stream = NULL;
 
104
                        ch->clock->mc = NULL;
 
105
                }
 
106
#endif
96
107
                ODM_DeleteChannel(odm, ch);
97
108
        }
98
109
 
 
110
        /*delete the decoders*/
 
111
        if (odm->codec) gf_codec_del(odm->codec);
 
112
        if (odm->ocr_codec) gf_codec_del(odm->ocr_codec);
 
113
        if (odm->oci_codec) gf_codec_del(odm->oci_codec);
 
114
 
 
115
        /*then detach from network service*/
99
116
        if (odm->net_service) {
100
117
                if (odm->net_service->owner == odm) {
101
118
                        if (odm->net_service->nb_odm_users) odm->net_service->nb_odm_users--;
103
120
                        odm->net_service->owner = NULL;
104
121
                        /*try to assign a new root in case this is not scene shutdown*/
105
122
                        if (odm->net_service->nb_odm_users && odm->parentscene) {
106
 
                                u32 i;
107
 
                                for (i=0; i<gf_list_count(odm->parentscene->ODlist); i++) {
108
 
                                        GF_ObjectManager *new_root = gf_list_get(odm->parentscene->ODlist, i);
 
123
                                GF_ObjectManager *new_root;
 
124
                                u32 i = 0;
 
125
                                while ((new_root = gf_list_enum(odm->parentscene->ODlist, &i)) ) {
 
126
                                        while (new_root->remote_OD) new_root = new_root->remote_OD;
109
127
                                        if (new_root == odm) continue;
110
 
                                        while (new_root->remote_OD) new_root = new_root->remote_OD;
111
128
                                        if (new_root->net_service != odm->net_service) continue;
112
129
                                        new_root->net_service->owner = new_root;
113
130
                                        break;
118
135
                odm->net_service = NULL;
119
136
        }
120
137
 
121
 
        /*last thing to do, unload the decoders if no channels associated*/
122
 
        if (odm->codec) {
123
 
                assert(!gf_list_count(odm->codec->inChannels));
124
 
                gf_mm_remove_codec(odm->term->mediaman, odm->codec);
125
 
                gf_codec_del(odm->codec);
126
 
        }
127
 
        if (odm->ocr_codec) {
128
 
                assert(!gf_list_count(odm->ocr_codec->inChannels));
129
 
                gf_mm_remove_codec(odm->term->mediaman, odm->ocr_codec);
130
 
                gf_codec_del(odm->ocr_codec);
131
 
        }
132
 
        if (odm->oci_codec) {
133
 
                assert(!gf_list_count(odm->oci_codec->inChannels));
134
 
                gf_mm_remove_codec(odm->term->mediaman, odm->oci_codec);
135
 
                gf_codec_del(odm->oci_codec);
136
 
        }
137
 
 
138
138
        /*delete from the parent scene.*/
139
139
        if (odm->parentscene) {
140
 
                gf_is_remove_object(odm->parentscene, odm);
 
140
                gf_is_remove_object(odm->parentscene, odm, do_remove);
141
141
                if (odm->subscene) gf_is_del(odm->subscene);
142
142
                if (odm->parent_OD) odm->parent_OD->remote_OD = NULL;
143
143
                gf_odm_del(odm);
162
162
}
163
163
 
164
164
/*setup service for OD (extract IOD and go)*/
165
 
void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *sub_url)
 
165
void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url)
166
166
{
167
167
        u32 od_type;
 
168
        char *sub_url = (char *) service_sub_url;
168
169
        GF_ObjectManager *par;
169
170
        GF_Terminal *term;
170
171
        GF_Descriptor *desc;
173
174
        assert(odm->OD==NULL);
174
175
 
175
176
        odm->net_service->nb_odm_users++;
176
 
        od_type = GF_MEDIA_OBJECT_UNDEF;
 
177
        if (odm->subscene) od_type = GF_MEDIA_OBJECT_SCENE;
 
178
        else od_type = GF_MEDIA_OBJECT_UNDEF;
177
179
 
178
180
        /*for remote ODs, get expected OD type in case the service needs to generate the IOD on the fly*/
179
181
        par = odm;
180
182
        while (par->parent_OD) par = par->parent_OD;
181
183
        if (par->parentscene && par->OD && par->OD->URLString) {
182
184
                GF_MediaObject *mo;
 
185
                char *ext;
183
186
                mo = gf_is_find_object(par->parentscene, par->OD->objectDescriptorID, par->OD->URLString);
184
187
                if (mo) od_type = mo->type;
 
188
                ext = strchr(par->OD->URLString, '#');
 
189
                if (ext) sub_url = ext;
185
190
        }
186
191
 
187
192
        desc = odm->net_service->ifce->GetServiceDescriptor(odm->net_service->ifce, od_type, sub_url); 
188
 
        if (!desc) {
189
 
                gf_term_message(odm->term, odm->net_service->url, "Service Entry Point not found", GF_SERVICE_ERROR);
190
 
                goto err_exit;
 
193
 
 
194
        /*create empty service descriptor, this will automatically create a dynamic scene*/
 
195
        if (!desc) desc = gf_odf_desc_new(GF_ODF_OD_TAG);
 
196
 
 
197
        if (!gf_list_count( ((GF_ObjectDescriptor*)desc)->ESDescriptors)) {
 
198
                /*new subscene*/
 
199
                if (!odm->subscene) {
 
200
                        assert(odm->parentscene);
 
201
                        odm->subscene = gf_is_new(odm->parentscene);
 
202
                        odm->subscene->root_od = odm;
 
203
                        gf_sg_set_javascript_api(odm->subscene->graph, &odm->term->js_ifce);
 
204
                }
191
205
        }
192
206
 
193
207
        toolList = NULL;
222
236
        if (toolList) {
223
237
                Bool ipmp_failed = 0;
224
238
/*
225
 
                for (i=0; i<gf_list_count(toolList->ipmp_tools); i++) {
226
 
                        GF_IPMP_Tool *ipmpt = gf_list_get(toolList->ipmp_tools, i);
 
239
                GF_IPMP_Tool *ipmpt;
 
240
                i=0;
 
241
                while ((ipmpt = gf_list_enum(toolList->ipmp_tools, &i))) {
227
242
                        if (!Term_CheckIPMPTool(odm->term, ipmpt)) {
228
243
                                ipmp_failed = 1;
229
244
                                break;
236
251
                        goto err_exit;
237
252
                }
238
253
        }
 
254
 
239
255
        /*keep track of term since the setup may fail and the OD may be destroyed*/
240
256
        term = odm->term;
241
257
        gf_term_lock_net(term, 1);
258
274
/*locate ESD by ID*/
259
275
static GF_ESD *od_get_esd(GF_ObjectDescriptor *OD, u16 ESID)
260
276
{
261
 
        u32 i;
262
277
        GF_ESD *esd;
263
 
        for (i=0; i<gf_list_count(OD->ESDescriptors); i++) {
264
 
                esd = gf_list_get(OD->ESDescriptors, i);
 
278
        u32 i = 0;
 
279
        while ((esd = gf_list_enum(OD->ESDescriptors, &i)) ) {
265
280
                if (esd->ESID==ESID) return esd;
266
281
        }
267
282
        return NULL;
270
285
static void ODM_SelectAlternateStream(GF_ObjectManager *odm, u32 lang_code, u8 stream_type)
271
286
{
272
287
        u32 i;
 
288
        GF_ESD *esd;
273
289
        u16 def_id, es_id;
274
290
 
275
291
        def_id = 0;
276
 
        for (i=0; i<gf_list_count(odm->OD->ESDescriptors); i++) {
277
 
                GF_ESD *esd = gf_list_get(odm->OD->ESDescriptors, i);
 
292
        i=0;
 
293
        while ( (esd = gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
278
294
                if (esd->decoderConfig->streamType != stream_type) continue;
279
295
 
280
296
                if (!esd->langDesc) {
290
306
        }
291
307
 
292
308
        /*remove all other media streams*/
293
 
        for (i=0; i<gf_list_count(odm->OD->ESDescriptors); i++) {
294
 
                GF_ESD *esd = (GF_ESD *)gf_list_get(odm->OD->ESDescriptors, i);
 
309
        i=0;
 
310
        while ((esd = gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
295
311
                if (esd->decoderConfig->streamType != stream_type) continue;
296
312
 
297
313
                /*get base stream ID for this stream*/
333
349
        *externalClock = 0;
334
350
 
335
351
        /*step 1: validate OD*/
336
 
        for (i = 0; i < gf_list_count(odm->OD->ESDescriptors); i++) {
337
 
                esd = (GF_ESD *)gf_list_get(odm->OD->ESDescriptors, i);
 
352
        i=0;
 
353
        while ((esd = gf_list_enum(odm->OD->ESDescriptors, &i))) {
338
354
                /*check external clock refs*/
339
355
                if (esd->OCRESID && (esd->OCRESID!=esd->ESID) && (od_get_esd(odm->OD, esd->OCRESID) == NULL) ) {
340
356
                        *externalClock = 1;
341
357
                }
342
358
                switch (esd->decoderConfig->streamType) {
343
 
                case GF_STREAM_OD:
344
 
                        nb_od++;
345
 
                        if (esd->decoderConfig->objectTypeIndication == GPAC_STATIC_OD_OTI) nb_scene++;
346
 
                        break;
 
359
                case GF_STREAM_OD: nb_od++; break;
347
360
                case GF_STREAM_OCR: nb_ocr++; break;
348
361
                case GF_STREAM_SCENE: nb_scene++; break;
349
362
                case GF_STREAM_MPEG7: nb_mp7++; break;
370
383
        /*the rest should be OK*/
371
384
 
372
385
        /*select independant streams - check language and (TODO) bitrate & term caps*/
373
 
        sOpt = gf_cfg_get_key(odm->term->user->config, "Systems", "Language");
 
386
        sOpt = gf_cfg_get_key(odm->term->user->config, "Systems", "Language3CC");
374
387
        if (!sOpt) {
375
 
                gf_cfg_set_key(odm->term->user->config, "Systems", "Language", "und");
 
388
                gf_cfg_set_key(odm->term->user->config, "Systems", "Language3CC", "und");
376
389
                sOpt = "und";
377
390
        }
378
391
        lang = (sOpt[0]<<16) | (sOpt[1]<<8) | sOpt[2];
392
405
        /*check if inline or animation stream*/
393
406
        *hasInline = 1;
394
407
        base_scene = NULL;
395
 
        for (i=0; i<gf_list_count(odm->OD->ESDescriptors); i++) {
396
 
                esd = (GF_ESD *)gf_list_get(odm->OD->ESDescriptors, i);
 
408
        i=0;
 
409
        while ( (esd = gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
397
410
                switch (esd->decoderConfig->streamType) {
398
411
                case GF_STREAM_PRIVATE_SCENE:
399
412
                case GF_STREAM_SCENE: 
436
449
        Bool hasInline, externalClock;
437
450
        u32 i, numOK;
438
451
        GF_Err e;
 
452
        GF_ESD *esd;
439
453
 
440
454
        if (!odm->net_service) odm->net_service = serv;
441
455
        
483
497
        }
484
498
 
485
499
        numOK = odm->pending_channels = 0;
486
 
        /*avoid channels PLAY request when confirming connection (sync network service)*/
487
 
        odm->is_open = 2;
488
 
 
489
 
        for (i=0; i<gf_list_count(odm->OD->ESDescriptors); i++) {
490
 
                GF_ESD *esd = gf_list_get(odm->OD->ESDescriptors, i);
491
 
                e = gf_odm_setup_es(odm, esd, serv);
492
 
                /*notify error but still go on, all streams are not so usefull*/
493
 
                if (e==GF_OK) 
494
 
                        numOK++;
495
 
                else
496
 
                        gf_term_message(odm->term, odm->net_service->url, "Stream Setup Failure", e);
497
 
 
 
500
 
 
501
        /*empty IOD, use a dynamic scene*/
 
502
        if (!gf_list_count(odm->OD->ESDescriptors) && odm->subscene && (odm->subscene->root_od==odm)) {
 
503
                odm->subscene->is_dynamic_scene = 1;
 
504
                gf_odm_start(odm);
 
505
        } else {
 
506
                /*avoid channels PLAY request when confirming connection (sync network service)*/
 
507
                odm->is_open = 2;
 
508
 
 
509
                i=0;
 
510
                while ((esd = gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
 
511
                        e = gf_odm_setup_es(odm, esd, serv);
 
512
                        /*notify error but still go on, all streams are not so usefull*/
 
513
                        if (e==GF_OK) {
 
514
                                numOK++;
 
515
                        } else {
 
516
                                gf_term_message(odm->term, odm->net_service->url, "Stream Setup Failure", e);
 
517
                        }
 
518
                }
 
519
                odm->is_open = 0;
498
520
        }
499
 
        odm->is_open = 0;
500
521
 
501
522
        /*special case for ODs only having OCRs: force a START since they're never refered to by media nodes*/
502
523
        if (odm->ocr_codec) gf_odm_start(odm);
528
549
                if (root == odm) gf_odm_start(odm);
529
550
        }
530
551
 
 
552
        if (odm->codec && odm->codec->ck && odm->codec->ck->no_time_ctrl) gf_odm_start(odm);
531
553
        
532
554
        /*for objects inserted by user (subs & co), auto select*/
533
555
        if (odm->term->root_scene->is_dynamic_scene && odm->parent_OD) {
557
579
        in_scene = odm->parentscene;
558
580
        if (odm->subscene && odm->subscene->root_od == odm) {
559
581
                in_scene = odm->subscene;
560
 
                for (j=0; j<gf_list_count(odm->channels); j++) {
561
 
                        ch = gf_list_get(odm->channels, j);
 
582
                i=0;
 
583
                while ((ch = gf_list_enum(odm->channels, &i)) ) {
562
584
                        if (ch->clock->no_time_ctrl) {
563
585
                                odm->no_time_ctrl = 1;
564
586
                                break;
566
588
                }
567
589
        }
568
590
 
569
 
        for (i=0; i<gf_list_count(in_scene->ODlist); i++) {
570
 
                test_od = gf_list_get(in_scene->ODlist, i);
 
591
        i=0;
 
592
        while ((test_od = gf_list_enum(in_scene->ODlist, &i)) ) {
571
593
                if (odm==test_od) continue;
572
 
                for (j=0; j<gf_list_count(test_od->channels); j++) {
573
 
                        ch = gf_list_get(test_od->channels, j);
 
594
                j=0;
 
595
                while ((ch = gf_list_enum(test_od->channels, &j)) ) {
574
596
                        if (ch->clock->no_time_ctrl) {
575
597
                                test_od->no_time_ctrl = 1;
576
598
                                break;
596
618
        GF_Codec *dec;
597
619
        s8 flag;
598
620
        u16 clockID;
 
621
        Bool emulated_od = 0;
599
622
        GF_Err e;
600
623
        GF_InlineScene *is;
601
624
 
676
699
                        e = GF_NON_COMPLIANT_BITSTREAM;
677
700
                        break;
678
701
                }
679
 
 
680
702
                /*OD codec acts as main scene codec when used to generate scene graph*/
681
 
                if (esd->decoderConfig->objectTypeIndication==GPAC_STATIC_OD_OTI) {
682
 
                        dec = odm->subscene->scene_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
683
 
                        gf_mm_add_codec(odm->term->mediaman, odm->subscene->scene_codec);
684
 
                        odm->subscene->is_dynamic_scene = 1;
685
 
                        dec->flags |= GF_ESM_CODEC_IS_STATIC_OD;
686
 
                } else if (! odm->subscene->od_codec) {
687
 
                        dec = odm->subscene->od_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
 
703
                if (! odm->subscene->od_codec) {
 
704
                        odm->subscene->od_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
688
705
                        gf_mm_add_codec(odm->term->mediaman, odm->subscene->od_codec);
689
 
                }
 
706
                } 
 
707
                dec = odm->subscene->od_codec;
690
708
                break;
691
709
        case GF_STREAM_OCR:
692
710
                /*OD codec acts as main scene codec when used to generate scene graph*/
706
724
                else {
707
725
                        if (! odm->subscene->scene_codec) {
708
726
                                odm->subscene->scene_codec = gf_codec_new(odm, esd, odm->Scene_PL, &e);
709
 
                                gf_mm_add_codec(odm->term->mediaman, odm->subscene->scene_codec);
 
727
                                if (!e) gf_mm_add_codec(odm->term->mediaman, odm->subscene->scene_codec);
710
728
                        }
711
729
                        dec = odm->subscene->scene_codec;
712
730
                }
744
762
                        }
745
763
                }
746
764
                dec = odm->codec;
 
765
                if ((esd->ESID==esd->OCRESID) &&(esd->ESID>=65530)) {
 
766
                        emulated_od = 1;
 
767
                }
747
768
                break;
748
769
 
749
770
        case GF_STREAM_PRIVATE_SCENE:
790
811
        ch->es_state = GF_ESM_ES_SETUP;
791
812
        ch->odm = odm;
792
813
 
793
 
        /*one more channel to wait for*/
794
 
        odm->pending_channels++;
795
 
 
796
814
        /*get media padding BEFORE channel setup, since we use it on channel connect ack*/
797
815
        if (dec) {
798
816
                cap.CapCode = GF_CODEC_PADDING_BYTES;
804
822
                ch->codec_resilient = cap.cap.valueInt;
805
823
        }
806
824
 
 
825
        if (emulated_od) {
 
826
                ch->service = NULL;
 
827
        }
 
828
 
 
829
        /*one more channel to wait for*/
 
830
        odm->pending_channels++;
 
831
 
807
832
        /*service redirection*/
808
833
        if (esd->URLString) {
809
834
                GF_ChannelSetup *cs;
814
839
                cs = malloc(sizeof(GF_ChannelSetup));
815
840
                cs->ch = ch;
816
841
                cs->dec = dec;
 
842
 
 
843
                /*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/
 
844
                if ((ch->esd->decoderConfig->streamType==GF_STREAM_OD) && strstr(ch->esd->URLString, "data:application/mpeg4-od-au;") ) 
 
845
                        dec->flags |= GF_ESM_CODEC_IS_STATIC_OD;
 
846
 
817
847
                gf_term_lock_net(odm->term, 1);
818
848
                gf_list_add(odm->term->channels_pending, cs);
819
849
                e = gf_term_connect_remote_channel(odm->term, ch, esd->URLString);
844
874
{
845
875
        char szURL[2048];
846
876
        GF_Err e;
 
877
        GF_NetworkCommand com;
847
878
 
848
879
        e = had_err;
849
880
        if (e) {
850
881
                ch->odm->pending_channels--;
851
882
                goto err_exit;
852
883
        }
853
 
        if (ch->esd->URLString) {
854
 
                strcpy(szURL, ch->esd->URLString);
855
 
        } else {
856
 
                sprintf(szURL, "ES_ID=%d", ch->esd->ESID);
857
 
        }
858
 
 
859
884
 
860
885
        /*insert channel*/
861
886
        if (dec) gf_list_insert(ch->odm->channels, ch, 0);
862
887
 
863
 
        ch->es_state = GF_ESM_ES_WAIT_FOR_ACK;
 
888
        if (ch->service) {
 
889
                ch->es_state = GF_ESM_ES_WAIT_FOR_ACK;
 
890
                if (ch->esd->URLString) {
 
891
                        strcpy(szURL, ch->esd->URLString);
 
892
                } else {
 
893
                        sprintf(szURL, "ES_ID=%d", ch->esd->ESID);
 
894
                }
864
895
 
865
 
        /*connect before setup: this is needed in case the decoder cfg is wrong, we may need to get it from
866
 
        network config...*/
867
 
        e = ch->service->ifce->ConnectChannel(ch->service->ifce, ch, szURL, ch->esd->decoderConfig->upstream);
 
896
                /*connect before setup: this is needed in case the decoder cfg is wrong, we may need to get it from
 
897
                network config...*/
 
898
                e = ch->service->ifce->ConnectChannel(ch->service->ifce, ch, szURL, ch->esd->decoderConfig->upstream);
 
899
        } else {
 
900
                ch->es_state = GF_ESM_ES_CONNECTED;
 
901
                ch->odm->pending_channels--;
 
902
        }
868
903
 
869
904
        if (e) {
870
905
                if (dec) gf_list_rem(ch->odm->channels, 0);
891
926
        }
892
927
 
893
928
        /*in case a channel is inserted in a running OD, open and play if not in queue*/
894
 
        if (ch->odm->is_open==1) {
 
929
        if ( (ch->odm->is_open==1) 
 
930
                /*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/
 
931
                ||      (dec && (dec->flags & GF_ESM_CODEC_IS_STATIC_OD)) 
 
932
        ) {
 
933
 
895
934
                gf_term_lock_net(ch->odm->term, 1);
 
935
                gf_list_del_item(ch->odm->term->od_pending, ch->odm);
 
936
 
896
937
                gf_es_start(ch);
897
 
                if (gf_list_find(ch->odm->term->od_pending, ch->odm)<0) {
898
 
                        GF_NetworkCommand com;
899
 
                        com.command_type = GF_NET_CHAN_PLAY;
900
 
                        com.base.on_channel = ch;
901
 
                        com.play.speed = FIX2FLT(ch->clock->speed);
902
 
                        com.play.start_range = gf_clock_time(ch->clock);
903
 
                        com.play.start_range /= 1000;
904
 
                        com.play.end_range = -1.0;
905
 
                        gf_term_service_command(ch->service, &com);
906
 
                }
 
938
                com.command_type = GF_NET_CHAN_PLAY;
 
939
                com.base.on_channel = ch;
 
940
                com.play.speed = FIX2FLT(ch->clock->speed);
 
941
                com.play.start_range = gf_clock_time(ch->clock);
 
942
                com.play.start_range /= 1000;
 
943
                com.play.end_range = -1.0;
 
944
                gf_term_service_command(ch->service, &com);
907
945
                if (dec && (dec->Status!=GF_ESM_CODEC_PLAY)) gf_mm_start_codec(dec);
908
946
                gf_term_lock_net(ch->odm->term, 0);
909
947
        }
910
 
 
911
948
        return GF_OK;
912
949
 
913
950
err_exit:
957
994
                if (!count) count = gf_codec_remove_channel(odm->subscene->od_codec, ch);
958
995
        }
959
996
        assert(count);
960
 
 
961
 
        ch->service->ifce->DisconnectChannel(ch->service->ifce, ch); 
962
 
        if (ch->esd->URLString) ch->service->nb_ch_users--;
963
 
        ODM_CheckChannelService(ch);
 
997
        
 
998
        if (ch->service) {
 
999
                ch->service->ifce->DisconnectChannel(ch->service->ifce, ch); 
 
1000
                if (ch->esd->URLString) ch->service->nb_ch_users--;
 
1001
                ODM_CheckChannelService(ch);
 
1002
        }
964
1003
 
965
1004
        //and delete
966
1005
        gf_es_del(ch);
970
1009
{
971
1010
        GF_ESD *esd;
972
1011
        GF_Channel *ch;
973
 
        u32 i;
974
 
        for (i=0; i<gf_list_count(odm->OD->ESDescriptors); i++) {
975
 
                esd = gf_list_get(odm->OD->ESDescriptors, i);
 
1012
        u32 i = 0;
 
1013
        while ((esd = gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
976
1014
                if (esd->ESID==ES_ID) goto esd_found;
977
1015
        }
978
1016
        return;
979
1017
 
980
1018
esd_found:
981
1019
        /*remove esd*/
982
 
        gf_list_rem(odm->OD->ESDescriptors, i);
 
1020
        gf_list_rem(odm->OD->ESDescriptors, i-1);
983
1021
        /*locate channel*/
984
1022
        ch = NULL;
985
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
986
 
                ch = gf_list_get(odm->channels, i);
 
1023
        i=0;
 
1024
        while ((ch = gf_list_enum(odm->channels, &i)) ) {
987
1025
                if (ch->esd->ESID == ES_ID) break;
988
1026
                ch = NULL;
989
1027
        }
998
1036
void gf_odm_start(GF_ObjectManager *odm)
999
1037
{
1000
1038
        gf_term_lock_net(odm->term, 1);
 
1039
 
1001
1040
        /*only if not open & ready (not waiting for ACK on channel setup)*/
1002
1041
        if (!odm->is_open && !odm->pending_channels) {
1003
 
                u32 i;
 
1042
                GF_Channel *ch;
 
1043
                u32 i = 0;
1004
1044
                odm->is_open = 1;
1005
1045
                /*start all channels and postpone play - this assures that all channels of a multiplexed are setup
1006
1046
                before one starts playing*/
1007
 
                for (i=0; i<gf_list_count(odm->channels); i++) {
1008
 
                        GF_Channel *ch = gf_list_get(odm->channels, i);
 
1047
                while ( (ch = gf_list_enum(odm->channels, &i)) ) {
1009
1048
                        gf_es_start(ch);
1010
1049
                }
1011
1050
                if (gf_list_find(odm->term->od_pending, odm)<0) gf_list_add(odm->term->od_pending, odm);
1015
1054
 
1016
1055
void gf_odm_play(GF_ObjectManager *odm)
1017
1056
{
 
1057
        GF_Channel *ch;
1018
1058
        u32 i;
1019
1059
        Bool skip_od_st;
1020
1060
        GF_NetworkCommand com;
1021
1061
        MediaControlStack *ctrl;
 
1062
        GF_Clock *parent_ck = NULL;
 
1063
 
 
1064
        if (odm->parentscene) {
 
1065
                parent_ck = gf_odm_get_media_clock(odm->parentscene->root_od);
 
1066
                if (!gf_odm_shares_clock(odm, parent_ck)) parent_ck = NULL;
 
1067
        }
1022
1068
 
1023
1069
        skip_od_st = (odm->subscene && odm->subscene->static_media_ressources) ? 1 : 0;
1024
1070
 
1025
1071
        /*send play command*/
1026
1072
        com.command_type = GF_NET_CHAN_PLAY;
1027
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
 
1073
        i=0;
 
1074
        while ( (ch = gf_list_enum(odm->channels, &i)) ) {
1028
1075
                Double ck_time;
1029
 
                GF_Channel *ch = gf_list_get(odm->channels, i);
1030
1076
 
1031
1077
                com.base.on_channel = ch;
1032
1078
                com.play.speed = 1.0;
1033
 
                /*plays from current time*/
1034
 
                ck_time = gf_clock_time(ch->clock);
1035
 
                ck_time /= 1000;
1036
 
                /*handle initial start - MPEG-4 is a bit annoying here, streams are not started through OD but through
1037
 
                scene nodes. If the stream runs on the BIFS/OD clock, the clock is already started at this point and we're 
1038
 
                sure to get at least a one-frame delay in PLAY, so just remove it - note we're generous (one second)
1039
 
                but this shouldn't hurt*/
1040
 
                if (ck_time<=1.0) ck_time = 0;
 
1079
                /*play from requested time (seeking or non-mpeg4 media control)*/
 
1080
                if (odm->media_start_time && !ch->clock->clock_init) {
 
1081
                        ck_time = (Double) (s64) odm->media_start_time;
 
1082
                        ck_time /= 1000;
 
1083
                }
 
1084
                /*play from current time*/
 
1085
                else {
 
1086
                        ck_time = gf_clock_time(ch->clock);
 
1087
                        ck_time /= 1000;
 
1088
                        /*handle initial start - MPEG-4 is a bit annoying here, streams are not started through OD but through
 
1089
                        scene nodes. If the stream runs on the BIFS/OD clock, the clock is already started at this point and we're 
 
1090
                        sure to get at least a one-frame delay in PLAY, so just remove it - note we're generous but this shouldn't hurt*/
 
1091
                        if (ck_time<=0.5) ck_time = 0;
 
1092
                }
1041
1093
                com.play.start_range = ck_time;
1042
1094
                com.play.end_range = -1;
1043
 
                /*override range and speed with MC - here we don't adjust since mediaControl is here to give us the exact
1044
 
                media start time*/
1045
 
                ctrl = ODM_GetMediaControl(odm);
 
1095
                /*if object shares parent scene clock, do not use media control*/
 
1096
                ctrl = parent_ck ? NULL : ODM_GetMediaControl(odm);
 
1097
                /*override range and speed with MC*/
1046
1098
                if (ctrl) {
1047
1099
                        MC_GetRange(ctrl, &com.play.start_range, &com.play.end_range);
1048
1100
                        com.play.speed = FIX2FLT(ctrl->control->mediaSpeed);
1051
1103
                                com.play.start_range = ck_time;
1052
1104
                        }
1053
1105
                        gf_clock_set_speed(ch->clock, ctrl->control->mediaSpeed);
1054
 
                }
1055
 
                /*user-defined seek on top scene*/
1056
 
                else if (odm->term->root_scene->root_od==odm) {
1057
 
                        com.play.start_range = odm->term->restart_time;
1058
 
                        com.play.start_range /= 1000.0;
 
1106
                        /*if requested seek time AND media control, adjust start range to current play time*/
 
1107
                        if (odm->media_start_time) {
 
1108
                                if ((com.play.start_range>=0) && (com.play.end_range>com.play.start_range)) {
 
1109
                                        if (ctrl->control->loop) {
 
1110
                                                Double active_dur = com.play.end_range - com.play.start_range;
 
1111
                                                while (ck_time>active_dur) ck_time -= active_dur;
 
1112
                                        } else {
 
1113
                                                ck_time = 0;
 
1114
                                                //com.play.start_range = com.play.end_range;
 
1115
                                        }
 
1116
                                }
 
1117
                                com.play.start_range += ck_time;
 
1118
                        }
1059
1119
                }
1060
1120
                /*full object playback*/
1061
1121
                if (com.play.end_range<=0) {
1062
 
                        odm->range_end = odm->duration;
 
1122
                        odm->range_end = (u32) odm->duration;
1063
1123
                } else {
1064
1124
                        /*segment playback - since our timing is in ms whereas segment ranges are double precision, 
1065
1125
                        make sure we have a LARGER range in ms, otherwise media sensors won't deactivate properly*/
1067
1127
                }
1068
1128
 
1069
1129
                /*don't replay OD channel, only init clock if needed*/
1070
 
                if (skip_od_st && (ch->esd->decoderConfig->streamType==GF_STREAM_OD)) {
 
1130
                if (!ch->service || (skip_od_st && (ch->esd->decoderConfig->streamType==GF_STREAM_OD))) {
1071
1131
                        Bool gf_es_owns_clock(GF_Channel *ch);
1072
1132
 
1073
1133
                        if (gf_es_owns_clock(ch) ) 
1082
1142
                        gf_term_service_command(ch->service, &com);
1083
1143
                }
1084
1144
        }
1085
 
        /*if root OD reset the global seek time*/       
1086
 
        if (odm->term->root_scene->root_od==odm) odm->term->restart_time = 0;
1087
 
 
 
1145
        odm->media_start_time = 0;
1088
1146
 
1089
1147
        /*start codecs last (otherwise we end up pulling data from channels not yet connected->pbs when seeking)*/
1090
1148
        if (odm->codec) {
1091
1149
                /*reset*/
1092
1150
                if (odm->codec->CB) {
1093
 
                        CB_SetStatus(odm->codec->CB, CB_STOP);
 
1151
                        gf_cm_set_status(odm->codec->CB, CB_STOP);
1094
1152
                        odm->codec->CB->HasSeenEOS = 0;
1095
1153
                }
1096
1154
                gf_mm_start_codec(odm->codec);
1105
1163
 
1106
1164
void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
1107
1165
{
1108
 
        u32 i, count;
 
1166
        GF_Channel *ch;
 
1167
        u32 i;
1109
1168
        MediaControlStack *ctrl;
 
1169
        MediaSensorStack *media_sens;
1110
1170
        GF_NetworkCommand com;
1111
1171
        
 
1172
        if (!odm->is_open) return;
 
1173
 
 
1174
#if 0
 
1175
        /*Handle broadcast environment, do not stop the object if no time control and instruction
 
1176
        comes from the scene*/
 
1177
        if (odm->no_time_ctrl && !force_close) {
 
1178
                //fprintf(stdout, "OD%d - broadcast detected, ignoring Stop from scene\n", odm->OD->objectDescriptorID);
 
1179
                return;
 
1180
        }
 
1181
#endif
 
1182
 
1112
1183
        gf_list_del_item(odm->term->od_pending, odm);
1113
1184
 
1114
 
        if (!odm->is_open) return;
1115
 
 
1116
1185
        /*little opt for image codecs: don't actually stop the OD*/
1117
1186
        if (!force_close && odm->codec && odm->codec->CB) {
1118
1187
                if (odm->codec->CB->Capacity==1) return;
1128
1197
        if (odm->ocr_codec) gf_mm_stop_codec(odm->ocr_codec);
1129
1198
        if (odm->oci_codec) gf_mm_stop_codec(odm->oci_codec);
1130
1199
 
 
1200
        gf_term_lock_net(odm->term, 1);
 
1201
 
 
1202
        /*send stop command*/
 
1203
        com.command_type = GF_NET_CHAN_STOP;
 
1204
        i=0;
 
1205
        while ((ch = gf_list_enum(odm->channels, &i)) ) {
 
1206
                if (ch->service) {
 
1207
                        com.base.on_channel = ch;
 
1208
                        gf_term_service_command(ch->service, &com);
 
1209
                }
 
1210
        }
 
1211
 
1131
1212
        /*stop channels*/
1132
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1133
 
                GF_Channel *ch = gf_list_get(odm->channels, i);
 
1213
        i=0;
 
1214
        while ((ch = gf_list_enum(odm->channels, &i)) ) {
1134
1215
                gf_es_stop(ch);
1135
1216
        }
1136
1217
 
1137
 
        /*send stop command*/
1138
 
        com.command_type = GF_NET_CHAN_STOP;
1139
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1140
 
                GF_Channel *ch = gf_list_get(odm->channels, i);
1141
 
                com.base.on_channel = ch;
1142
 
                gf_term_service_command(ch->service, &com);
1143
 
        }
 
1218
        gf_term_lock_net(odm->term, 0);
1144
1219
 
1145
1220
        odm->is_open = 0;
1146
1221
        odm->current_time = 0;
1147
1222
 
1148
1223
        /*reset media sensor(s)*/
1149
 
        count = gf_list_count(odm->ms_stack);
1150
 
        for (i = 0; i<count; i++) {
1151
 
                MediaSensorStack *media_sens = gf_list_get(odm->ms_stack, i);
1152
 
                MS_Stop(media_sens);
 
1224
        if (force_close!=2) {
 
1225
                i = 0;
 
1226
                while ((media_sens = gf_list_enum(odm->ms_stack, &i))){
 
1227
                        MS_Stop(media_sens);
 
1228
                }
1153
1229
        }
1154
1230
        /*reset media control state*/
1155
1231
        ctrl = ODM_GetMediaControl(odm);
1156
1232
        if (ctrl) ctrl->current_seg = 0;
1157
 
 
1158
1233
}
1159
1234
 
1160
1235
void gf_odm_on_eos(GF_ObjectManager *odm, GF_Channel *on_channel)
1186
1261
        }
1187
1262
}
1188
1263
 
1189
 
void gf_odm_set_duration(GF_ObjectManager *odm, GF_Channel *ch, u32 stream_duration)
 
1264
void gf_odm_set_duration(GF_ObjectManager *odm, GF_Channel *ch, u64 stream_duration)
1190
1265
{
1191
1266
        if (odm->codec) {
1192
1267
                if (ch->esd->decoderConfig->streamType == odm->codec->type)
1212
1287
        if (odm->codec) return odm->codec->ck;
1213
1288
        if (odm->ocr_codec) return odm->ocr_codec->ck;
1214
1289
        if (odm->subscene && odm->subscene->scene_codec) return odm->subscene->scene_codec->ck;
 
1290
        if (odm->subscene && odm->subscene->dyn_ck) return odm->subscene->dyn_ck;
1215
1291
        return NULL;
1216
1292
}
1217
1293
 
1225
1301
        if (ctrl && (gf_list_find(odm->mc_stack, ctrl) < 0)) gf_list_add(odm->mc_stack, ctrl);
1226
1302
        if (ctrl && !ctrl->control->enabled) return;
1227
1303
 
1228
 
        /*for each clock in the controled OD*/
1229
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1230
 
                ch = gf_list_get(odm->channels, i);
1231
 
                if (ch->clock->mc != ctrl) {
 
1304
        if (odm->subscene && odm->subscene->is_dynamic_scene) {
 
1305
                if (odm->subscene->dyn_ck) {
1232
1306
                        /*deactivate current control*/
1233
 
                        if (ctrl && ch->clock->mc) {
1234
 
                                ch->clock->mc->control->enabled = 0;
1235
 
                                gf_node_event_out_str((GF_Node *)ch->clock->mc->control, "enabled");
1236
 
                        }
1237
 
                        /*and attach this control to the clock*/
1238
 
                        ch->clock->mc = ctrl;
 
1307
                        if (ctrl && odm->subscene->dyn_ck->mc) {
 
1308
                                odm->subscene->dyn_ck->mc->control->enabled = 0;
 
1309
                                gf_node_event_out_str((GF_Node *)odm->subscene->dyn_ck->mc->control, "enabled");
 
1310
                        }
 
1311
                        odm->subscene->dyn_ck->mc = ctrl;
 
1312
                }
 
1313
        } else {
 
1314
                /*for each clock in the controled OD*/
 
1315
                i=0;
 
1316
                while ((ch = gf_list_enum(odm->channels, &i))) {
 
1317
                        if (ch->clock->mc != ctrl) {
 
1318
                                /*deactivate current control*/
 
1319
                                if (ctrl && ch->clock->mc) {
 
1320
                                        ch->clock->mc->control->enabled = 0;
 
1321
                                        gf_node_event_out_str((GF_Node *)ch->clock->mc->control, "enabled");
 
1322
                                }
 
1323
                                /*and attach this control to the clock*/
 
1324
                                ch->clock->mc = ctrl;
 
1325
                        }
1239
1326
                }
1240
1327
        }
1241
1328
        /*store active control on media*/
1271
1358
Bool ODM_SwitchMediaControl(GF_ObjectManager *odm, MediaControlStack *ctrl)
1272
1359
{
1273
1360
        u32 i;
 
1361
        MediaControlStack *st2;
1274
1362
        if (!ctrl->control->enabled) return 0;
1275
1363
 
1276
1364
        /*for all media controls other than this one force enable to false*/
1277
 
        for (i=0; i<gf_list_count(odm->mc_stack); i++) {
1278
 
                MediaControlStack *st2 = gf_list_get(odm->mc_stack, i);
 
1365
        i=0;
 
1366
        while ((st2 = gf_list_enum(odm->mc_stack, &i))) {
1279
1367
                if (st2 == ctrl) continue;
1280
1368
                if (st2->control->enabled) {
1281
1369
                        st2->control->enabled = 0;
1290
1378
 
1291
1379
Bool gf_odm_shares_clock(GF_ObjectManager *odm, GF_Clock *ck)
1292
1380
{
1293
 
        u32 i;
 
1381
        u32 i = 0;
1294
1382
        GF_Channel *ch;
1295
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1296
 
                ch = gf_list_get(odm->channels, i);
 
1383
        while ((ch = gf_list_enum(odm->channels, &i))) {
1297
1384
                if (ch->clock == ck) return 1;
1298
1385
        }
1299
1386
        return 0;
1305
1392
{
1306
1393
        u32 i;
1307
1394
        GF_NetworkCommand com;
 
1395
        MediaSensorStack *media_sens;
1308
1396
        GF_Channel *ch;
1309
1397
 
1310
1398
        if (odm->no_time_ctrl) return;
1325
1413
        if (odm->oci_codec) gf_mm_stop_codec(odm->oci_codec);
1326
1414
 
1327
1415
        com.command_type = GF_NET_CHAN_PAUSE;
1328
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1329
 
                ch = gf_list_get(odm->channels, i); 
 
1416
        i=0;
 
1417
        while ((ch = gf_list_enum(odm->channels, &i))) {
1330
1418
                gf_clock_pause(ch->clock);
1331
1419
                com.base.on_channel = ch;
1332
1420
                gf_term_service_command(ch->service, &com);
1333
1421
        }
1334
1422
 
1335
1423
        /*mediaSensor  shall generate isActive false when paused*/
1336
 
        for (i = 0; i<gf_list_count(odm->ms_stack); i++) {
1337
 
                MediaSensorStack *media_sens = gf_list_get(odm->ms_stack, i);
 
1424
        i=0;
 
1425
        while ((media_sens = gf_list_enum(odm->ms_stack, &i)) ) {
1338
1426
                if (media_sens && media_sens->sensor->isActive) {
1339
1427
                        media_sens->sensor->isActive = 0;
1340
1428
                        gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive");
1347
1435
        u32 i;
1348
1436
        GF_NetworkCommand com;
1349
1437
        GF_Channel *ch;
 
1438
        MediaSensorStack *media_sens;
1350
1439
 
1351
1440
        if (odm->no_time_ctrl) return;
1352
1441
 
1366
1455
        if (odm->oci_codec) gf_mm_start_codec(odm->oci_codec);
1367
1456
        
1368
1457
        com.command_type = GF_NET_CHAN_RESUME;
1369
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1370
 
                ch = gf_list_get(odm->channels, i); 
 
1458
        i=0;
 
1459
        while ((ch = gf_list_enum(odm->channels, &i)) ){
1371
1460
                gf_clock_resume(ch->clock);
1372
1461
                com.base.on_channel = ch;
1373
1462
                gf_term_service_command(ch->service, &com);
1374
1463
        }
1375
1464
 
1376
1465
        /*mediaSensor shall generate isActive TRUE when resumed*/
1377
 
        for (i = 0; i<gf_list_count(odm->ms_stack); i++) {
1378
 
                MediaSensorStack *media_sens = gf_list_get(odm->ms_stack, i);
 
1466
        i=0;
 
1467
        while ((media_sens = gf_list_enum(odm->ms_stack, &i)) ){
1379
1468
                if (media_sens && !media_sens->sensor->isActive) {
1380
1469
                        media_sens->sensor->isActive = 1;
1381
1470
                        gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive");
1393
1482
 
1394
1483
        com.command_type = GF_NET_CHAN_SET_SPEED;
1395
1484
        com.play.speed = FIX2FLT(speed);
1396
 
        for (i=0; i<gf_list_count(odm->channels); i++) {
1397
 
                ch = gf_list_get(odm->channels, i); 
 
1485
        i=0;
 
1486
        while ((ch = gf_list_enum(odm->channels, &i)) ) {
1398
1487
                gf_clock_set_speed(ch->clock, speed);
1399
1488
                com.play.on_channel = ch;
1400
1489
                gf_term_service_command(ch->service, &com);
1403
1492
 
1404
1493
GF_Segment *ODM_GetSegment(GF_ObjectManager *odm, char *descName)
1405
1494
{
1406
 
        u32 i;
1407
 
        for (i=0; i<gf_list_count(odm->OD->OCIDescriptors); i++) {
1408
 
                GF_Segment *desc = gf_list_get(odm->OD->OCIDescriptors, i);
 
1495
        GF_Segment *desc;
 
1496
        u32 i = 0;
 
1497
        while ( (desc = gf_list_enum(odm->OD->OCIDescriptors, &i)) ){
1409
1498
                if (desc->tag != GF_ODF_SEGMENT_TAG) continue;
1410
1499
                if (!stricmp(desc->SegmentName, descName)) return desc;
1411
1500
        }
1416
1505
{
1417
1506
        /*this reorders segments when inserting into list - I believe this is not compliant*/
1418
1507
#if 0
1419
 
        u32 i;
1420
 
        for (i=0; i<gf_list_count(list); i++) {
1421
 
                GF_Segment *desc = gf_list_get(list, i);
 
1508
        GF_Segment *desc;
 
1509
        u32 i = 0;
 
1510
        while ((desc = gf_list_enum(list, &i))) {
1422
1511
                if (desc == seg) return;
1423
1512
                if (seg->startTime + seg->Duration <= desc->startTime) {
1424
1513
                        gf_list_insert(list, seg, i);
1434
1523
{
1435
1524
        char *str, *sep;
1436
1525
        char seg1[1024], seg2[1024], seg_url[4096];
1437
 
        GF_Segment *first_seg, *last_seg;
 
1526
        GF_Segment *first_seg, *last_seg, *seg;
1438
1527
        u32 i, j;
1439
1528
 
1440
1529
        /*browse all URLs*/
1470
1559
                }
1471
1560
                /*segment range process*/
1472
1561
                ODM_InsertSegment(odm, first_seg, list);
1473
 
                for (j=0; j<gf_list_count(odm->OD->OCIDescriptors); j++) {
1474
 
                        GF_Segment *seg = gf_list_get(odm->OD->OCIDescriptors, j);
 
1562
                j=0;
 
1563
                while ( (seg = gf_list_enum(odm->OD->OCIDescriptors, &j)) ) {
1475
1564
                        if (seg->tag != GF_ODF_SEGMENT_TAG) continue;
1476
1565
                        if (seg==first_seg) continue;
1477
1566
                        if (seg->startTime + seg->Duration <= first_seg->startTime) continue;
1499
1588
        if (!odm->codec || ((odm->codec->type!=GF_STREAM_VISUAL) && (odm->codec->type!=GF_STREAM_AUDIO))) {
1500
1589
                GF_Clock *ck = gf_odm_get_media_clock(odm);
1501
1590
                u32 now = gf_clock_time(ck);
1502
 
                u32 dur = odm->subscene ? odm->subscene->duration : odm->duration;
 
1591
                u64 dur = odm->subscene ? odm->subscene->duration : odm->duration;
1503
1592
                cur = gf_list_get(ctrl->seg, ctrl->current_seg);
1504
1593
                if (odm->subscene && odm->subscene->needs_restart) return 0;
1505
1594
                if (cur) dur = (u32) ((cur->Duration+cur->startTime)*1000);