2
* GPAC - Multimedia Framework C SDK
4
* Copyright (c) Jean Le Feuvre 2000-2005
7
* This file is part of GPAC / Media terminal sub-project
9
* GPAC is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation; either version 2, or (at your option)
14
* GPAC is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with this library; see the file COPYING. If not, write to
21
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
#include <gpac/internal/terminal_dev.h>
27
#include <gpac/constants.h>
28
#include "media_memory.h"
29
#include "media_control.h"
31
#include "input_sensor.h"
33
/*removes the channel ressources and destroy it*/
34
void ODM_DeleteChannel(GF_ObjectManager *odm, struct _es_channel *ch);
37
GF_ObjectManager *gf_odm_new()
39
GF_ObjectManager *tmp;
40
GF_SAFEALLOC(tmp, GF_ObjectManager);
41
if (!tmp) return NULL;
42
tmp->channels = gf_list_new();
44
tmp->Audio_PL = (u8) -1;
45
tmp->Graphics_PL = (u8) -1;
47
tmp->Scene_PL = (u8) -1;
48
tmp->Visual_PL = (u8) -1;
49
tmp->mx = gf_mx_new("ODM");
50
#ifndef GPAC_DISABLE_VRML
51
tmp->ms_stack = gf_list_new();
52
tmp->mc_stack = gf_list_new();
57
void gf_odm_del(GF_ObjectManager *odm)
60
#ifndef GPAC_DISABLE_VRML
62
MediaSensorStack *media_sens;
63
MediaControlStack *media_ctrl;
66
/*make sure we are not in the media queue*/
67
gf_term_lock_media_queue(odm->term, 1);
68
gf_list_del_item(odm->term->media_queue, odm);
69
gf_term_lock_media_queue(odm->term, 0);
71
lock = gf_mx_try_lock(odm->mx);
73
#ifndef GPAC_DISABLE_VRML
75
while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i))) {
77
/*and detach from stream object*/
78
media_sens->stream = NULL;
80
gf_list_del(odm->ms_stack);
83
while ((media_ctrl = (MediaControlStack *)gf_list_enum(odm->mc_stack, &i))) {
84
media_ctrl->stream = NULL;
85
media_ctrl->ck = NULL;
87
gf_list_del(odm->mc_stack);
89
if (odm->mo) odm->mo->odm = NULL;
91
if (odm->raw_frame_sema) gf_sema_del(odm->raw_frame_sema);
93
gf_list_del(odm->channels);
95
gf_odf_desc_del((GF_Descriptor *)odm->OD);
97
assert (!odm->net_service);
98
if (lock) gf_mx_v(odm->mx);
104
void gf_odm_lock(GF_ObjectManager *odm, u32 LockIt)
113
Bool gf_odm_lock_mo(GF_MediaObject *mo)
115
if (!mo || !mo->odm) return 0;
116
gf_odm_lock(mo->odm, 1);
117
/*the ODM may have been destroyed here !!*/
118
if (!mo->odm) return 0;
123
void gf_odm_disconnect(GF_ObjectManager *odm, Bool do_remove)
127
if (do_remove) odm->flags |= GF_ODM_DESTROYED;
130
/*disconnect sub-scene*/
131
if (odm->subscene) gf_scene_disconnect(odm->subscene, do_remove);
134
if (!do_remove) return;
138
/*unload the decoders before deleting the channels to prevent any access fault*/
140
if (odm->codec->type==GF_STREAM_INTERACT) {
142
// Remove all Registered InputSensor nodes -> shut down the InputSensor threads -> prevent illegal access on deleted pointers
143
GF_MediaObject *obj = odm->mo;
144
count = gf_list_count(obj->nodes);
145
for (i=0; i<count; i++) {
146
GF_Node *n = (GF_Node *)gf_list_get(obj->nodes, i);
147
switch (gf_node_get_tag(n)) {
148
#ifndef GPAC_DISABLE_VRML
149
case TAG_MPEG4_InputSensor:
150
((M_InputSensor*)n)->enabled = 0;
151
InputSensorModified(n);
159
gf_term_remove_codec(odm->term, odm->codec);
161
if (odm->ocr_codec) gf_term_remove_codec(odm->term, odm->ocr_codec);
162
#ifndef GPAC_MINIMAL_ODF
163
if (odm->oci_codec) gf_term_remove_codec(odm->term, odm->oci_codec);
166
/*then delete all the channels in this OD */
167
while (gf_list_count(odm->channels)) {
168
ch = (GF_Channel*)gf_list_get(odm->channels, 0);
170
if (ch->clock->mc && ch->clock->mc->stream && ch->clock->mc->stream->odm==odm) {
171
ch->clock->mc->stream = NULL;
172
ch->clock->mc = NULL;
175
ODM_DeleteChannel(odm, ch);
178
/*delete the decoders*/
180
gf_codec_del(odm->codec);
183
if (odm->ocr_codec) {
184
gf_codec_del(odm->ocr_codec);
185
odm->ocr_codec = NULL;
187
#ifndef GPAC_MINIMAL_ODF
188
if (odm->oci_codec) {
189
gf_codec_del(odm->oci_codec);
190
odm->oci_codec = NULL;
194
/*detach from network service */
195
if (odm->net_service) {
196
GF_ClientService *ns = odm->net_service;
197
if (ns->nb_odm_users) ns->nb_odm_users--;
198
//if (odm->flags & GF_ODM_SERVICE_ENTRY)
200
if (ns->owner == odm) {
203
/*try to assign a new root in case this is not scene shutdown*/
204
if (ns->nb_odm_users && odm->parentscene) {
205
GF_ObjectManager *new_root;
207
while ((new_root = (GF_ObjectManager *)gf_list_enum(odm->parentscene->resources, &i)) ) {
208
if (new_root == odm) continue;
209
if (new_root->net_service != ns) continue;
210
ns->owner = new_root;
216
odm->net_service = NULL;
217
if (!ns->nb_odm_users) gf_term_close_services(odm->term, ns);
222
/*delete from the parent scene.*/
223
if (odm->parentscene) {
225
evt.type = GF_EVENT_CONNECT;
226
evt.connect.is_connected = 0;
227
gf_term_forward_event(odm->term, &evt, 0, 1);
229
gf_scene_remove_object(odm->parentscene, odm, do_remove);
230
if (odm->subscene) gf_scene_del(odm->subscene);
235
/*this is the scene root OD (may be a remote OD ..) */
236
if (odm->term->root_scene) {
238
assert(odm->term->root_scene == odm->subscene);
239
gf_scene_del(odm->subscene);
240
/*reset main pointer*/
241
odm->term->root_scene = NULL;
243
evt.type = GF_EVENT_CONNECT;
244
evt.connect.is_connected = 0;
245
gf_term_send_event(odm->term, &evt);
252
/*setup service for OD (extract IOD and go)*/
253
void gf_odm_setup_entry_point(GF_ObjectManager *odm, const char *service_sub_url)
257
char *sub_url = (char *) service_sub_url;
261
// assert(odm->OD==NULL);
265
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Setting up root object for %s\n", odm->net_service->url));
267
if (odm->subscene) od_type = GF_MEDIA_OBJECT_SCENE;
269
od_type = odm->mo->type;
270
if (!sub_url && odm->mo->URLs.count && odm->mo->URLs.vals[0].url) {
271
sub_url = odm->mo->URLs.vals[0].url;
274
else od_type = GF_MEDIA_OBJECT_UNDEF;
276
/*for remote ODs, get expected OD type in case the service needs to generate the IOD on the fly*/
277
if (odm->parentscene && odm->OD && odm->OD->URLString) {
279
mo = gf_scene_find_object(odm->parentscene, odm->OD->objectDescriptorID, odm->OD->URLString);
280
if (mo) od_type = mo->type;
281
ext = strchr(odm->OD->URLString, '#');
282
if (ext) sub_url = ext;
285
desc = odm->net_service->ifce->GetServiceDescriptor(odm->net_service->ifce, od_type, sub_url);
289
/*if desc is NULL for a media, the media will be declared later by the service (gf_term_media_add)*/
290
if (od_type != GF_MEDIA_OBJECT_SCENE)
292
/*create empty service descriptor, this will automatically create a dynamic scene*/
293
desc = gf_odf_desc_new(GF_ODF_OD_TAG);
295
odm->flags |= GF_ODM_SERVICE_ENTRY;
297
if (!gf_list_count( ((GF_ObjectDescriptor*)desc)->ESDescriptors)) {
299
if (!odm->subscene) {
300
assert(odm->parentscene);
301
odm->subscene = gf_scene_new(odm->parentscene);
302
odm->subscene->root_od = odm;
309
GF_InitialObjectDescriptor *the_iod = (GF_InitialObjectDescriptor *)desc;
310
odm->OD = (GF_ObjectDescriptor*)gf_malloc(sizeof(GF_ObjectDescriptor));
311
memcpy(odm->OD, the_iod, sizeof(GF_ObjectDescriptor));
312
odm->OD->tag = GF_ODF_OD_TAG;
313
/*Check P&Ls of this IOD*/
314
odm->Audio_PL = the_iod->audio_profileAndLevel;
315
odm->Graphics_PL = the_iod->graphics_profileAndLevel;
316
odm->OD_PL = the_iod->OD_profileAndLevel;
317
odm->Scene_PL = the_iod->scene_profileAndLevel;
318
odm->Visual_PL = the_iod->visual_profileAndLevel;
319
odm->flags |= GF_ODM_HAS_PROFILES;
320
if (the_iod->inlineProfileFlag) odm->flags |= GF_ODM_INLINE_PROFILES;
321
gf_odf_desc_del((GF_Descriptor *) the_iod->IPMPToolList);
326
odm->Audio_PL = odm->Graphics_PL = odm->OD_PL = odm->Scene_PL = odm->Visual_PL = (u8) -1;
327
odm->OD = (GF_ObjectDescriptor *)desc;
330
gf_term_message(odm->term, odm->net_service->url, "MPEG4 Service Setup Failure", GF_ODF_INVALID_DESCRIPTOR);
334
gf_term_lock_net(term, 1);
335
gf_odm_setup_object(odm, odm->net_service);
336
gf_term_lock_net(term, 0);
338
/*it may happen that this object was inserted in a dynamic scene from a service through a URL redirect. In which case,
339
the scene regeneration might not have been completed since the redirection was not done yet - force a scene regenerate*/
340
if (odm->parentscene && odm->parentscene->is_dynamic_scene)
341
gf_scene_regenerate(odm->parentscene);
345
if (!odm->parentscene) {
347
evt.type = GF_EVENT_CONNECT;
348
evt.connect.is_connected = 0;
349
gf_term_send_event(odm->term, &evt);
356
static GF_ESD *od_get_esd(GF_ObjectDescriptor *OD, u16 ESID)
360
while ((esd = (GF_ESD *)gf_list_enum(OD->ESDescriptors, &i)) ) {
361
if (esd->ESID==ESID) return esd;
366
#ifdef GPAC_UNUSED_FUNC
367
static void ODM_SelectAlternateStream(GF_ObjectManager *odm, u32 lang_code, u8 stream_type)
375
while ( (esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
376
if (esd->decoderConfig->streamType != stream_type) continue;
378
if (!esd->langDesc) {
379
if (!def_id) def_id = esd->ESID;
382
if (esd->langDesc->langCode==lang_code) {
385
} else if (!def_id) {
390
/*remove all other media streams*/
392
while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
393
if (esd->decoderConfig->streamType != stream_type) continue;
395
/*get base stream ID for this stream*/
397
if (esd->dependsOnESID && (esd->dependsOnESID != es_id)) {
398
es_id = esd->dependsOnESID;
400
GF_ESD *base = od_get_esd(odm->OD, es_id);
402
/*forbidden except for BIFS->OD*/
403
if (base->decoderConfig->streamType != stream_type) break;
404
if (!base->dependsOnESID) break;
405
es_id = base->dependsOnESID;
408
/*not part of same object as base, remove*/
409
if (es_id != def_id) {
410
gf_list_del_item(odm->OD->ESDescriptors, esd);
411
gf_odf_desc_del((GF_Descriptor*) esd);
416
#endif /*GPAC_UNUSED_FUNC*/
419
/*Validate the streams in this OD, and check if we have to setup an inline scene*/
420
GF_Err ODM_ValidateOD(GF_ObjectManager *odm, Bool *hasInline)
424
GF_ESD *esd, *base_scene;
426
u32 lang, nb_od, nb_ocr, nb_scene, nb_mp7, nb_ipmp, nb_oci, nb_mpj, nb_other, prev_st;
428
nb_od = nb_ocr = nb_scene = nb_mp7 = nb_ipmp = nb_oci = nb_mpj = nb_other = 0;
433
/*step 1: validate OD*/
435
while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i))) {
436
assert(esd->decoderConfig);
437
switch (esd->decoderConfig->streamType) {
438
case GF_STREAM_OD: nb_od++; break;
439
case GF_STREAM_OCR: nb_ocr++; break;
440
case GF_STREAM_SCENE:
441
switch (esd->decoderConfig->objectTypeIndication) {
442
case GPAC_OTI_SCENE_AFX:
443
case GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE:
450
case GF_STREAM_MPEG7: nb_mp7++; break;
451
case GF_STREAM_IPMP: nb_ipmp++; break;
452
case GF_STREAM_OCI: nb_oci++; break;
453
case GF_STREAM_MPEGJ: nb_mpj++; break;
454
case GF_STREAM_PRIVATE_SCENE: nb_scene++; break;
455
/*all other streams shall not be mixed: text, video, audio, interaction, font*/
457
if (esd->decoderConfig->streamType!=prev_st) nb_other++;
458
prev_st = esd->decoderConfig->streamType;
462
/*cf spec on stream aggregation*/
463
if (nb_other>1) return GF_ODF_INVALID_DESCRIPTOR; /*no more than one base media type*/
464
if (nb_od && !nb_scene) return GF_ODF_INVALID_DESCRIPTOR; /*if OD we must have scene description*/
465
if (nb_other && nb_scene) return GF_ODF_INVALID_DESCRIPTOR; /*scene OR media*/
466
if (nb_ocr>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE OCR*/
467
if (nb_oci>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE OCI*/
468
if (nb_mp7>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE MPEG-7 - this is not in the spec, but since MPEG-7 = OCI++ this seems reasonable*/
469
if (nb_mpj>1) return GF_ODF_INVALID_DESCRIPTOR; /*only ONE MPEG-J - this is not in the spec but well...*/
471
/*the rest should be OK*/
473
/*select independant streams - check language and (TODO) bitrate & term caps*/
474
sOpt = gf_cfg_get_key(odm->term->user->config, "Systems", "Language3CC");
477
gf_cfg_set_key(odm->term->user->config, "Systems", "Language3CC", sOpt);
478
gf_cfg_set_key(odm->term->user->config, "Systems", "Language2CC", "en");
479
gf_cfg_set_key(odm->term->user->config, "Systems", "LanguageName", "English");
481
lang = (sOpt[0]<<16) | (sOpt[1]<<8) | sOpt[2];
483
if (gf_list_count(odm->OD->ESDescriptors)>1) {
484
ODM_SelectAlternateStream(odm, lang, GF_STREAM_SCENE);
485
ODM_SelectAlternateStream(odm, lang, GF_STREAM_OD);
486
ODM_SelectAlternateStream(odm, lang, GF_STREAM_VISUAL);
487
ODM_SelectAlternateStream(odm, lang, GF_STREAM_AUDIO);
488
ODM_SelectAlternateStream(odm, lang, GF_STREAM_IPMP);
489
ODM_SelectAlternateStream(odm, lang, GF_STREAM_INTERACT);
490
ODM_SelectAlternateStream(odm, lang, GF_STREAM_TEXT);
494
if (!nb_scene) return GF_OK;
496
/*check if inline or animation stream*/
500
while ( (esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
501
switch (esd->decoderConfig->streamType) {
502
case GF_STREAM_PRIVATE_SCENE:
503
case GF_STREAM_SCENE:
509
if (base_scene) break;
512
/*we have a scene stream without dependancies, this is an inline*/
513
if (!base_scene || !base_scene->dependsOnESID) return GF_OK;
515
/*if the stream the base scene depends on is in this OD, this is in inline*/
516
es_id = base_scene->dependsOnESID;
518
esd = od_get_esd(odm->OD, es_id);
519
/*the stream this stream depends on is not in this OD, this is some anim stream*/
524
es_id = esd->dependsOnESID;
525
/*should be forbidden (circular reference), we assume this describes inline (usually wrong BIFS->OD setup)*/
526
if (es_id==base_scene->ESID) break;
528
/*no dependency to external stream, this is an inline*/
534
/*connection of OD and setup of streams. The streams are not requested if the OD
535
is in an unexecuted state
536
the ODM is created either because of IOD / remoteOD, or by the OD codec. In the later
537
case, the GF_Scene pointer will be set by the OD codec.*/
539
void gf_odm_setup_object(GF_ObjectManager *odm, GF_ClientService *serv)
545
GF_MediaObject *syncRef;
547
if (!odm->net_service) {
548
odm->net_service = serv;
549
if (!odm->OD->URLString)
550
odm->net_service->nb_odm_users++;
552
/*if this is a remote OD, we need a new manager and a new service...*/
553
if (odm->OD->URLString) {
554
GF_ClientService *parent = odm->net_service;
555
char *url = odm->OD->URLString;
556
odm->OD->URLString = NULL;
557
/*store original OD ID */
558
if (!odm->current_time) odm->current_time = odm->OD->objectDescriptorID;
560
gf_odf_desc_del((GF_Descriptor *)odm->OD);
562
odm->net_service = NULL;
563
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Object redirection to %s (MO %08x)\n", url, odm->mo));
565
/*if object is a scene, create the inline before connecting the object.
566
This is needed in irder to register the nodes using the resource for event
567
propagation (stored at the inline level)
569
if (odm->mo && (odm->mo->type==GF_MEDIA_OBJECT_SCENE)) {
570
odm->subscene = gf_scene_new(odm->parentscene);
571
odm->subscene->root_od = odm;
573
gf_term_connect_object(odm->term, odm, url, parent ? parent->url : NULL);
578
if (odm->current_time) {
579
odm->OD->objectDescriptorID = odm->current_time;
580
odm->current_time = 0;
581
odm->flags |= GF_ODM_REMOTE_OD;
584
/*HACK - temp storage of sync ref*/
585
syncRef = (GF_MediaObject*)odm->ocr_codec;
586
odm->ocr_codec = NULL;
588
e = ODM_ValidateOD(odm, &hasInline);
590
gf_term_message(odm->term, odm->net_service->url, "MPEG-4 Service Error", e);
591
gf_odm_disconnect(odm, 1);
595
if (odm->mo && (odm->mo->type == GF_MEDIA_OBJECT_UPDATES)) {
599
/*if there is a BIFS stream in the OD, we need an GF_Scene (except if we already
600
have one, which means this is the first IOD)*/
601
if (hasInline && !odm->subscene) {
602
odm->subscene = gf_scene_new(odm->parentscene);
603
odm->subscene->root_od = odm;
606
numOK = odm->pending_channels = 0;
607
/*empty IOD, use a dynamic scene*/
608
if (!gf_list_count(odm->OD->ESDescriptors) && odm->subscene) {
609
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM%d] No streams in object - taking over scene graph generation\n",odm->OD->objectDescriptorID));
610
assert(odm->subscene->root_od==odm);
611
odm->subscene->is_dynamic_scene = 1;
613
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[Terminal] Setting up object streams\n"));
614
/*avoid channels PLAY request when confirming connection (sync network service)*/
615
odm->state = GF_ODM_STATE_IN_SETUP;
619
while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
620
e = gf_odm_setup_es(odm, esd, serv, syncRef);
621
/*notify error but still go on, all streams are not so usefull*/
625
gf_term_message(odm->term, odm->net_service->url, "Stream Setup Failure", e);
628
odm->state = GF_ODM_STATE_STOP;
632
/*setup mediaobject info except for top-level OD*/
633
if (odm->parentscene) {
636
gf_scene_setup_object(odm->parentscene, odm);
638
/*setup node decoder*/
639
if (odm->mo && odm->codec && odm->codec->decio && (odm->codec->decio->InterfaceType==GF_NODE_DECODER_INTERFACE) ) {
640
GF_NodeDecoder *ndec = (GF_NodeDecoder *) odm->codec->decio;
641
GF_Node *n = gf_list_get(odm->mo->nodes, 0);
642
if (n) ndec->AttachNode(ndec, n);
644
/*not clear in the spec how the streams attached to AFC are started - default to "right now"*/
645
gf_odm_start(odm, 0);
648
evt.type = GF_EVENT_CONNECT;
649
evt.connect.is_connected = 1;
650
gf_term_forward_event(odm->term, &evt, 0, 1);
652
/*othewise send a connect ack for top level*/
655
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Root object connected !\n", odm->net_service->url));
657
evt.type = GF_EVENT_CONNECT;
658
evt.connect.is_connected = 1;
659
gf_term_send_event(odm->term, &evt);
663
/*case 1: object is the root, always start*/
664
if (!odm->parentscene) {
665
assert(odm->subscene == odm->term->root_scene);
666
assert(odm->subscene->root_od==odm);
667
gf_odm_start(odm, 0);
669
/*case 2: object is a pure OCR object - connect*/
670
else if (odm->ocr_codec) {
671
gf_odm_start(odm, 0);
673
/*case 3: if the object is inserted from a broadcast, start it if not already done. This covers cases where the scene (BIFS, LASeR) and
674
the media (images) are both carrouseled and the carrousels are interleaved. If we wait for the scene to trigger a PLAY, we will likely
675
have to wait for an entire image carousel period to start filling the buffers, which is sub-optimal
676
we also force a prefetch for object declared outside the OD stream to make sure we don't loose any data before object declaration and play
677
as can be the case with MPEG2 TS (first video packet right after the PMT) - this should be refined*/
678
else if (!odm->state && ((odm->flags & GF_ODM_NO_TIME_CTRL) || (odm->flags & GF_ODM_NOT_IN_OD_STREAM)) && (odm->parentscene->selected_service_id == odm->OD->ServiceID)) {
679
GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] Inserted from broadcast - forcing play\n", odm->OD->objectDescriptorID));
680
gf_odm_start(odm, 2);
681
odm->flags |= GF_ODM_PREFETCH;
684
/*for objects inserted by user (subs & co), auto select*/
685
if (odm->parentscene && odm->parentscene->is_dynamic_scene
686
&& (odm->OD->objectDescriptorID==GF_MEDIA_EXTERNAL_ID)
687
&& (odm->flags & GF_ODM_REMOTE_OD)
691
gf_scene_select_object(odm->parentscene, odm);
694
if (odm->parentscene==odm->term->root_scene) {
695
evt.type = GF_EVENT_STREAMLIST;
696
gf_term_send_event(odm->term,&evt);
703
void ODM_CheckChannelService(GF_Channel *ch)
705
if (ch->service == ch->odm->net_service) return;
706
/*if the stream has created a service check if close is needed or not*/
707
if (ch->esd->URLString && !ch->service->nb_ch_users)
708
gf_term_close_services(ch->odm->term, ch->service);
711
/*setup channel, clock and query caps*/
713
GF_Err gf_odm_setup_es(GF_ObjectManager *odm, GF_ESD *esd, GF_ClientService *serv, GF_MediaObject *sync_ref)
715
GF_CodecCapability cap;
718
GF_List *ck_namespace;
722
Bool emulated_od = 0;
726
/*find the clock for this new channel*/
731
if (sync_ref && sync_ref->odm && sync_ref->odm->codec) {
732
ck = sync_ref->odm->codec->ck;
735
/*timeline override*/
736
if (odm->flags & GF_ODM_INHERIT_TIMELINE) {
737
if (odm->parentscene->root_od->subscene->scene_codec)
738
ck = odm->parentscene->root_od->subscene->scene_codec->ck;
740
ck = odm->parentscene->root_od->subscene->dyn_ck;
744
/*get clocks namespace (eg, parent scene)*/
745
scene = odm->subscene ? odm->subscene : odm->parentscene;
747
ck_namespace = odm->net_service->Clocks;
748
/*little trick for non-OD addressing: if object is a remote one, and service owner already has clocks,
749
override OCR. This will solve addressing like file.avi#audio and file.avi#video*/
750
if (!esd->OCRESID && (odm->flags & GF_ODM_REMOTE_OD) && (gf_list_count(ck_namespace)==1) ) {
751
ck = (GF_Clock*)gf_list_get(ck_namespace, 0);
752
esd->OCRESID = ck->clockID;
754
/*for dynamic scene, force all streams to be sync on main OD stream (one timeline, no need to reload ressources)*/
755
else if (odm->parentscene && odm->parentscene->is_dynamic_scene && !odm->subscene) {
756
GF_ObjectManager *parent_od = odm->parentscene->root_od;
757
if (parent_od->net_service && (gf_list_count(parent_od->net_service->Clocks)==1)) {
758
ck = (GF_Clock*)gf_list_get(parent_od->net_service->Clocks, 0);
759
esd->OCRESID = ck->clockID;
764
/*do we have an OCR specified*/
765
clockID = esd->OCRESID;
766
/*if OCR stream force self-synchro !!*/
767
if (esd->decoderConfig->streamType==GF_STREAM_OCR) clockID = esd->ESID;
769
/*if no clock ID but depandancy, force the clock to be the base layer for AV but not systems (animation streams, ..)*/
770
if ((esd->decoderConfig->streamType==GF_STREAM_VISUAL) || (esd->decoderConfig->streamType==GF_STREAM_AUDIO)) clockID = esd->dependsOnESID;
771
if (!clockID) clockID = esd->ESID;
774
/*override clock dependencies if specified*/
775
if (odm->term->flags & GF_TERM_SINGLE_CLOCK) {
776
if (scene->scene_codec) {
777
clockID = scene->scene_codec->ck->clockID;
778
} else if (scene->od_codec) {
779
clockID = scene->od_codec->ck->clockID;
781
ck_namespace = odm->term->root_scene->root_od->net_service->Clocks;
783
/*if the GF_Clock is the stream, check if we have embedded OCR in the stream...*/
784
if (clockID == esd->ESID) {
785
flag = (esd->slConfig && esd->slConfig->OCRLength);
788
if (!esd->slConfig) {
789
esd->slConfig = (GF_SLConfig *)gf_odf_desc_new(GF_ODF_SLC_TAG);
790
esd->slConfig->timestampResolution = 1000;
793
ck = gf_clock_attach(ck_namespace, scene, clockID, esd->ESID, flag);
794
if (!ck) return GF_OUT_OF_MEM;
795
esd->OCRESID = ck->clockID;
798
/*create a channel for this stream*/
800
if (!ch) return GF_OUT_OF_MEM;
804
GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[ODM] Creating codec for stream %d\n", ch->esd->ESID));
806
/*setup the decoder for this stream or find the existing one.*/
809
switch (esd->decoderConfig->streamType) {
811
//OD - MUST be in inline
812
if (!odm->subscene) {
813
e = GF_NON_COMPLIANT_BITSTREAM;
816
/*OD codec acts as main scene codec when used to generate scene graph*/
817
if (! odm->subscene->od_codec) {
818
odm->subscene->od_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
820
gf_term_add_codec(odm->term, odm->subscene->od_codec);
822
dec = odm->subscene->od_codec;
825
/*OD codec acts as main scene codec when used to generate scene graph*/
826
dec = odm->ocr_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
827
gf_term_add_codec(odm->term, odm->ocr_codec);
829
case GF_STREAM_SCENE:
831
if (!odm->subscene) {
833
odm->codec = gf_codec_new(odm, esd, odm->Scene_PL, &e);
834
gf_term_add_codec(odm->term, odm->codec);
840
if (! odm->subscene->scene_codec) {
841
odm->subscene->scene_codec = gf_codec_new(odm, esd, odm->Scene_PL, &e);
842
if (!e) gf_term_add_codec(odm->term, odm->subscene->scene_codec);
844
dec = odm->subscene->scene_codec;
847
#ifndef GPAC_MINIMAL_ODF
849
/*OCI - only one per OD */
850
if (odm->oci_codec) {
851
e = GF_NON_COMPLIANT_BITSTREAM;
853
odm->oci_codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
854
odm->oci_codec->odm = odm;
855
gf_term_add_codec(odm->term, odm->oci_codec);
860
case GF_STREAM_AUDIO:
861
case GF_STREAM_VISUAL:
862
/*we have a media or user-specific codec...*/
864
odm->codec = gf_codec_new(odm, esd, (esd->decoderConfig->streamType==GF_STREAM_VISUAL) ? odm->Visual_PL : odm->Audio_PL, &e);
865
if (!e) gf_term_add_codec(odm->term, odm->codec);
870
/*interaction stream*/
871
#ifndef GPAC_DISABLE_VRML
872
case GF_STREAM_INTERACT:
874
odm->codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
876
gf_isdec_configure(odm->codec->decio, odm->parentscene, esd->URLString ? 1 : 0);
877
gf_term_add_codec(odm->term, odm->codec);
879
gf_list_add(odm->term->input_streams, odm->codec);
883
if ((esd->ESID==esd->OCRESID) &&(esd->ESID>=65530)) {
889
case GF_STREAM_PRIVATE_SCENE:
891
assert(!odm->subscene->scene_codec);
892
odm->subscene->scene_codec = gf_codec_new(odm, esd, odm->Scene_PL, &e);
893
if (odm->subscene->scene_codec) {
894
gf_term_add_codec(odm->term, odm->subscene->scene_codec);
896
dec = odm->subscene->scene_codec;
898
/*this is a bit tricky: the scene decoder needs to ba called with the dummy streams of this
899
object, so we associate the main decoder to this object*/
900
odm->codec = dec = gf_codec_use_codec(odm->parentscene->scene_codec, odm);
901
gf_term_add_codec(odm->term, odm->codec);
907
odm->codec = gf_codec_new(odm, esd, odm->OD_PL, &e);
908
if (!e) gf_term_add_codec(odm->term, odm->codec);
915
/*if we have a decoder, set up the channel and co.*/
923
/*setup scene decoder*/
924
if (dec->decio && (dec->decio->InterfaceType==GF_SCENE_DECODER_INTERFACE) ) {
925
GF_SceneDecoder *sdec = (GF_SceneDecoder *) dec->decio;
926
scene = odm->subscene ? odm->subscene : odm->parentscene;
927
if (sdec->AttachScene) {
928
/*if a node asked for this media object, use the scene graph of the node (AnimationStream in PROTO)*/
929
if (odm->mo && odm->mo->node_ptr) {
930
GF_SceneGraph *sg = scene->graph;
931
/*FIXME - this MUST be cleaned up*/
932
scene->graph = gf_node_get_graph((GF_Node*)odm->mo->node_ptr);
933
sdec->AttachScene(sdec, scene, (scene->scene_codec==dec) ? 1: 0);
935
odm->mo->node_ptr = NULL;
937
sdec->AttachScene(sdec, scene, (scene->scene_codec==dec) ? 1: 0);
942
GF_CodecCapability cap;
943
cap.CapCode = GF_CODEC_RAW_MEDIA;
944
gf_codec_get_capability(dec, &cap);
945
if (cap.cap.valueInt) {
946
dec->flags |= GF_ESM_CODEC_IS_RAW_MEDIA;
947
dec->process = gf_codec_process_private_media;
951
ch->es_state = GF_ESM_ES_SETUP;
954
/*get media padding BEFORE channel setup, since we use it on channel connect ack*/
956
cap.CapCode = GF_CODEC_PADDING_BYTES;
957
gf_codec_get_capability(dec, &cap);
958
ch->media_padding_bytes = cap.cap.valueInt;
960
cap.CapCode = GF_CODEC_RESILIENT;
961
gf_codec_get_capability(dec, &cap);
962
ch->codec_resilient = cap.cap.valueInt;
969
/*one more channel to wait for*/
970
odm->pending_channels++;
972
/*service redirection*/
973
if (esd->URLString) {
975
/*here we have a pb with the MPEG4 model: streams are supposed to be attachable as soon as the OD
976
update is received, but this is not true with ESD URLs, where service setup may take some time (file
977
downloading, authentification, etc...). We therefore need to wait for the service connect response before
978
setting up the channel...*/
979
cs = (GF_ChannelSetup*)gf_malloc(sizeof(GF_ChannelSetup));
983
/*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/
984
if ((ch->esd->decoderConfig->streamType==GF_STREAM_OD) && strstr(ch->esd->URLString, "data:application/mpeg4-od-au;") )
985
dec->flags |= GF_ESM_CODEC_IS_STATIC_OD;
987
gf_term_lock_net(odm->term, 1);
988
gf_list_add(odm->term->channels_pending, cs);
989
e = gf_term_connect_remote_channel(odm->term, ch, esd->URLString);
991
s32 i = gf_list_find(odm->term->channels_pending, cs);
993
gf_list_rem(odm->term->channels_pending, (u32) i);
995
odm->pending_channels--;
996
ODM_CheckChannelService(ch);
1000
gf_term_lock_net(odm->term, 0);
1001
if (ch->service->owner) {
1002
gf_list_del_item(odm->term->channels_pending, cs);
1004
return gf_odm_post_es_setup(ch, dec, GF_OK);
1010
return gf_odm_post_es_setup(ch, dec, GF_OK);
1013
GF_Err gf_odm_post_es_setup(GF_Channel *ch, GF_Codec *dec, GF_Err had_err)
1017
GF_NetworkCommand com;
1021
ch->odm->pending_channels--;
1026
if (dec) gf_list_insert(ch->odm->channels, ch, 0);
1029
ch->es_state = GF_ESM_ES_WAIT_FOR_ACK;
1030
if (ch->esd->URLString) {
1031
strcpy(szURL, ch->esd->URLString);
1033
sprintf(szURL, "ES_ID=%u", ch->esd->ESID);
1036
/*connect before setup: this is needed in case the decoder cfg is wrong, we may need to get it from
1038
e = ch->service->ifce->ConnectChannel(ch->service->ifce, ch, szURL, ch->esd->decoderConfig->upstream);
1040
/*special case (not really specified in specs ...): if the stream is not found and is an Interaction
1041
one (ie, used by an InputSensor), consider this means the stream shall be generated by the IS device*/
1042
if ((e==GF_STREAM_NOT_FOUND) && (ch->esd->decoderConfig->streamType==GF_STREAM_INTERACT)) e = GF_OK;
1044
ch->es_state = GF_ESM_ES_CONNECTED;
1045
ch->odm->pending_channels--;
1049
if (dec) gf_list_rem(ch->odm->channels, 0);
1054
e = gf_codec_add_channel(dec, ch);
1056
switch (ch->esd->decoderConfig->streamType) {
1057
case GF_STREAM_VISUAL:
1058
gf_term_message(ch->odm->term, ch->service->url, "Video Setup failed", e);
1060
case GF_STREAM_AUDIO:
1061
gf_term_message(ch->odm->term, ch->service->url, "Audio Setup failed", e);
1064
gf_list_rem(ch->odm->channels, 0);
1066
ch->service->ifce->DisconnectChannel(ch->service->ifce, ch);
1067
if (ch->esd->URLString) {
1068
assert(ch->service->nb_ch_users);
1069
ch->service->nb_ch_users--;
1075
/*in case a channel is inserted in a running OD, open and play if not in queue*/
1076
if ( (ch->odm->state==GF_ODM_STATE_PLAY)
1077
/*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/
1078
// || (dec && (dec->flags & GF_ESM_CODEC_IS_STATIC_OD))
1081
gf_term_lock_media_queue(ch->odm->term, 1);
1082
gf_list_del_item(ch->odm->term->media_queue, ch->odm);
1083
gf_term_lock_media_queue(ch->odm->term, 1);
1086
gf_term_lock_net(ch->odm->term, 1);
1088
com.command_type = GF_NET_CHAN_PLAY;
1089
com.base.on_channel = ch;
1090
com.play.speed = FIX2FLT(ch->clock->speed);
1091
com.play.start_range = gf_clock_time(ch->clock);
1092
com.play.start_range /= 1000;
1093
com.play.end_range = -1.0;
1094
gf_term_service_command(ch->service, &com);
1095
if (dec && (dec->Status!=GF_ESM_CODEC_PLAY)) gf_term_start_codec(dec);
1096
gf_term_lock_net(ch->odm->term, 0);
1101
ODM_CheckChannelService(ch);
1106
/*confirmation of channel delete from net*/
1107
void ODM_DeleteChannel(GF_ObjectManager *odm, GF_Channel *ch)
1109
u32 i, count, ch_pos;
1115
assert( odm->channels );
1117
//find a clock with this stream ES_ID
1118
ck = gf_clock_find(odm->net_service->Clocks, ch->esd->ESID, 0);
1120
count = gf_list_count(odm->channels);
1123
for (i=0; i<count; i++) {
1124
ch2 = (GF_Channel*)gf_list_get(odm->channels, i);
1130
//note that when a stream is added, we need to update clocks info ...
1131
if (ck && ch->clock && (ch2->clock->clockID == ck->clockID)) gf_es_stop(ch2);
1134
if (ch_pos != count+1) gf_list_rem(odm->channels, ch_pos);
1136
/*remove from the codec*/
1138
if (!count && odm->codec)
1139
count = gf_codec_remove_channel(odm->codec, ch);
1140
if (!count && odm->ocr_codec)
1141
count = gf_codec_remove_channel(odm->ocr_codec, ch);
1142
#ifndef GPAC_MINIMAL_ODF
1143
if (!count && odm->oci_codec)
1144
count = gf_codec_remove_channel(odm->oci_codec, ch);
1146
if (!count && odm->subscene) {
1147
if (odm->subscene->scene_codec) count = gf_codec_remove_channel(odm->subscene->scene_codec, ch);
1148
if (!count) count = gf_codec_remove_channel(odm->subscene->od_codec, ch);
1151
ch->service->ifce->DisconnectChannel(ch->service->ifce, ch);
1152
if (ch->esd->URLString) {
1153
assert(ch->service->nb_ch_users);
1154
ch->service->nb_ch_users--;
1156
ODM_CheckChannelService(ch);
1164
void gf_odm_remove_es(GF_ObjectManager *odm, u16 ES_ID)
1169
while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) {
1170
if (esd->ESID==ES_ID) goto esd_found;
1176
gf_list_rem(odm->OD->ESDescriptors, i-1);
1180
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1181
if (ch->esd->ESID == ES_ID) break;
1185
if (ch) ODM_DeleteChannel(odm, ch);
1187
gf_odf_desc_del((GF_Descriptor *) esd);
1190
/*this is the tricky part: make sure the net is locked before doing anything since an async service
1191
reply could destroy the object we're queuing for play*/
1192
void gf_odm_start(GF_ObjectManager *odm, u32 media_queue_state)
1194
Bool skip_register = 1;
1195
gf_term_lock_media_queue(odm->term, 1);
1197
/*only if not open & ready (not waiting for ACK on channel setup)*/
1198
if (!odm->pending_channels && odm->OD) {
1199
/*object is not started - issue channel setup requests*/
1203
odm->state = GF_ODM_STATE_PLAY;
1205
/*look for a given segment name to play*/
1206
if (odm->subscene) {
1208
assert(odm->subscene->root_od==odm);
1210
url = (odm->mo && odm->mo->URLs.count) ? odm->mo->URLs.vals[0].url : odm->net_service->url;
1211
frag = strrchr(url, '#');
1213
GF_Segment *seg = gf_odm_find_segment(odm, frag+1);
1215
odm->media_start_time = (u64) ((s64) seg->startTime*1000);
1216
odm->media_stop_time = (u64) ((s64) (seg->startTime + seg->Duration)*1000);
1221
/*start all channels and postpone play - this assures that all channels of a multiplexed are setup
1222
before one starts playing*/
1223
while ( (ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1225
GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH%d: At OTB %d starting channel\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock)));
1229
/*object is already started - only reinsert in media queue if this function was called on an object already in the queue*/
1231
skip_register = media_queue_state ? 0 : 1;
1234
if (media_queue_state==2) {
1235
odm->action_type = GF_ODM_ACTION_PLAY;
1237
} else if (!skip_register && (gf_list_find(odm->term->media_queue, odm)<0)) {
1238
odm->action_type = GF_ODM_ACTION_PLAY;
1239
gf_list_add(odm->term->media_queue, odm);
1244
/*reset CB to stop state, otherwise updating a texture between gf_odm_start and gf_odm_play might trigger an end of stream*/
1245
if (odm->codec && odm->codec->CB) {
1246
gf_cm_set_status(odm->codec->CB, CB_STOP);
1247
odm->codec->CB->HasSeenEOS = 0;
1251
gf_term_lock_media_queue(odm->term, 0);
1254
void gf_odm_play(GF_ObjectManager *odm)
1261
GF_NetworkCommand com;
1262
#ifndef GPAC_DISABLE_VRML
1263
MediaControlStack *ctrl;
1265
GF_Clock *parent_ck = NULL;
1267
if (odm->codec && odm->codec->CB && !(odm->flags & GF_ODM_PREFETCH)) {
1269
gf_cm_set_status(odm->codec->CB, CB_STOP);
1270
odm->codec->CB->HasSeenEOS = 0;
1272
odm->flags &= ~GF_ODM_PREFETCH;
1275
if (odm->parentscene) {
1276
parent_ck = gf_odm_get_media_clock(odm->parentscene->root_od);
1277
if (!gf_odm_shares_clock(odm, parent_ck)) parent_ck = NULL;
1280
skip_od_st = (odm->subscene && odm->subscene->static_media_ressources) ? 1 : 0;
1281
range_end = odm->media_stop_time;
1282
// odm->media_stop_time = 0;
1284
nb_failure = gf_list_count(odm->channels);
1286
/*send play command*/
1287
com.command_type = GF_NET_CHAN_PLAY;
1289
while ( (ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1292
if (ch->ipmp_tool) {
1295
memset(&evt, 0, sizeof(evt));
1296
evt.event_type=GF_IPMP_TOOL_GRANT_ACCESS;
1298
e = ch->ipmp_tool->process(ch->ipmp_tool, &evt);
1300
gf_term_message(odm->term, NULL, "PLAY access is not granted on channel - please check your license", e);
1307
com.base.on_channel = ch;
1308
com.play.speed = 1.0;
1309
/*play from requested time (seeking or non-mpeg4 media control)*/
1310
if (odm->media_start_time && !ch->clock->clock_init) {
1311
ck_time = (Double) (s64) odm->media_start_time;
1314
/*play from current time*/
1316
ck_time = gf_clock_time(ch->clock);
1318
/*handle initial start - MPEG-4 is a bit annoying here, streams are not started through OD but through
1319
scene nodes. If the stream runs on the BIFS/OD clock, the clock is already started at this point and we're
1320
sure to get at least a one-frame delay in PLAY, so just remove it - note we're generous but this shouldn't hurt*/
1321
if (ck_time<=0.5) ck_time = 0;
1323
com.play.start_range = ck_time;
1326
com.play.end_range = (s64) range_end / 1000.0;
1328
if (!odm->subscene && gf_odm_shares_clock(odm->parentscene->root_od, ch->clock)
1329
&& (odm->parentscene->root_od->media_stop_time != odm->parentscene->root_od->duration)
1331
com.play.end_range = (s64) odm->parentscene->root_od->media_stop_time / 1000.0;
1333
com.play.end_range = -1;
1337
#ifndef GPAC_DISABLE_VRML
1338
/*if object shares parent scene clock, do not use media control*/
1339
ctrl = parent_ck ? NULL : gf_odm_get_mediacontrol(odm);
1340
/*override range and speed with MC*/
1342
MC_GetRange(ctrl, &com.play.start_range, &com.play.end_range);
1343
com.play.speed = FIX2FLT(ctrl->control->mediaSpeed);
1344
/*if the channel doesn't control the clock, jump to current time in the controled range, not just the begining*/
1345
if ((ch->esd->ESID!=ch->clock->clockID) && (ck_time>com.play.start_range) && (com.play.end_range>com.play.start_range) && (ck_time<com.play.end_range)) {
1346
com.play.start_range = ck_time;
1348
gf_clock_set_speed(ch->clock, ctrl->control->mediaSpeed);
1349
/*if requested seek time AND media control, adjust start range to current play time*/
1350
if (odm->media_start_time) {
1351
if ((com.play.start_range>=0) && (com.play.end_range>com.play.start_range)) {
1352
if (ctrl->control->loop) {
1353
Double active_dur = com.play.end_range - com.play.start_range;
1354
while (ck_time>active_dur) ck_time -= active_dur;
1357
//com.play.start_range = com.play.end_range;
1360
com.play.start_range += ck_time;
1365
/*full object playback*/
1366
if (com.play.end_range<=0) {
1367
odm->media_stop_time = odm->subscene ? 0 : odm->duration;
1369
/*segment playback - since our timing is in ms whereas segment ranges are double precision,
1370
make sure we have a LARGER range in ms, otherwise media sensors won't deactivate properly*/
1371
odm->media_stop_time = (u64) ceil(1000 * com.play.end_range);
1374
/*don't replay OD channel, only init clock if needed*/
1375
if (!ch->service || (skip_od_st && (ch->esd->decoderConfig->streamType==GF_STREAM_OD))) {
1376
Bool gf_es_owns_clock(GF_Channel *ch);
1378
if (gf_es_owns_clock(ch) )
1379
gf_clock_set_time(ch->clock, (u32) (com.play.start_range*1000));
1381
ch->IsClockInit = 1;
1384
gf_clock_buffer_off(ch->clock);
1387
gf_term_service_command(ch->service, &com);
1388
GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH%d: At OTB %d requesting PLAY from %g to %g (clock init %d)\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock), com.play.start_range, com.play.end_range, ch->clock->clock_init));
1391
// odm->media_start_time = 0;
1394
odm->state = GF_ODM_STATE_BLOCKED;
1398
gf_term_service_media_event(odm, GF_EVENT_MEDIA_DATA_REQUEST);
1401
/*start codecs last (otherwise we end up pulling data from channels not yet connected->pbs when seeking)*/
1403
gf_term_start_codec(odm->codec);
1404
} else if (odm->subscene) {
1405
if (odm->subscene->scene_codec) gf_term_start_codec(odm->subscene->scene_codec);
1406
if (!skip_od_st && odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec);
1408
if (odm->flags & GF_ODM_REGENERATE_SCENE) {
1409
odm->flags &= ~GF_ODM_REGENERATE_SCENE;
1410
gf_scene_regenerate(odm->subscene);
1413
if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec);
1414
#ifndef GPAC_MINIMAL_ODF
1415
if (odm->oci_codec) gf_term_start_codec(odm->oci_codec);
1419
Bool gf_odm_owns_clock(GF_ObjectManager *odm, GF_Clock *ck)
1422
GF_ObjectManager *od;
1425
while ((ch = gf_list_enum(odm->channels, &i))) {
1426
if (ch->esd->ESID==ck->clockID) return 1;
1429
while ((od = gf_list_enum(odm->subscene->resources, &j))) {
1431
while ((ch = gf_list_enum(od->channels, &i))) {
1432
if (ch->esd->ESID==ck->clockID) return 1;
1438
void gf_odm_stop(GF_ObjectManager *odm, Bool force_close)
1442
#ifndef GPAC_DISABLE_VRML
1443
MediaControlStack *ctrl;
1444
MediaSensorStack *media_sens;
1447
GF_NetworkCommand com;
1449
if (!odm->state) return;
1452
/*Handle broadcast environment, do not stop the object if no time control and instruction
1453
comes from the scene*/
1454
if (odm->no_time_ctrl && !force_close) {
1455
GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] - broadcast detected, ignoring Stop from scene\n", odm->OD->objectDescriptorID);
1461
gf_term_lock_media_queue(odm->term, 1);
1462
gf_list_del_item(odm->term->media_queue, odm);
1463
gf_term_lock_media_queue(odm->term, 0);
1465
/*little opt for image codecs: don't actually stop the OD*/
1466
if (!force_close && odm->codec && odm->codec->CB && !odm->codec->CB->no_allocation) {
1467
if (odm->codec->CB->Capacity==1) return;
1470
/*if raw media, stop all channels before sending stop command to network, to avoid new media frames to be set
1471
as pending and thereby locking the channel associated service*/
1472
if (odm->codec && odm->codec->flags & GF_ESM_CODEC_IS_RAW_MEDIA) {
1474
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1477
gf_term_stop_codec(odm->codec);
1478
/*and wait until frame has been consumed by the renderer
1479
we don't use semaphore wait as the raw channel may already be pending on the semaphore*/
1480
while (odm->codec->CB->UnitCount) {
1486
/*object was not unlocked, decoders were not started*/
1487
if (odm->state==GF_ODM_STATE_BLOCKED) {
1488
odm->current_time = 0;
1489
gf_sema_notify(odm->raw_frame_sema, 1);
1495
gf_term_stop_codec(odm->codec);
1496
} else if (odm->subscene) {
1498
GF_ObjectManager *sub_odm;
1499
if (odm->subscene->scene_codec) gf_term_stop_codec(odm->subscene->scene_codec);
1500
if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec);
1502
/*stops all resources of the subscene as well*/
1503
while ((sub_odm=(GF_ObjectManager *)gf_list_enum(odm->subscene->resources, &i))) {
1504
gf_odm_stop(sub_odm, force_close);
1507
if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec);
1508
#ifndef GPAC_MINIMAL_ODF
1509
if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec);
1512
gf_term_lock_net(odm->term, 1);
1514
/*send stop command*/
1515
com.command_type = GF_NET_CHAN_STOP;
1517
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1519
if (ch->ipmp_tool) {
1521
memset(&evt, 0, sizeof(evt));
1522
evt.event_type=GF_IPMP_TOOL_RELEASE_ACCESS;
1524
ch->ipmp_tool->process(ch->ipmp_tool, &evt);
1528
com.base.on_channel = ch;
1529
gf_term_service_command(ch->service, &com);
1530
GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] CH %d At OTB %d requesting STOP\n", odm->OD->objectDescriptorID, ch->esd->ESID, gf_clock_time(ch->clock)));
1533
gf_term_service_media_event(odm, GF_EVENT_MEDIA_STOP);
1537
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1538
/*stops clock if this is a scene stop*/
1539
if (!(odm->flags & GF_ODM_INHERIT_TIMELINE) && odm->subscene && gf_odm_owns_clock(odm, ch->clock) ) {
1540
gf_clock_stop(ch->clock);
1545
gf_term_lock_net(odm->term, 0);
1547
odm->state = GF_ODM_STATE_STOP;
1548
odm->current_time = 0;
1550
#ifndef GPAC_DISABLE_VRML
1551
/*reset media sensor(s)*/
1552
if (force_close!=2) {
1554
while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i))){
1555
MS_Stop(media_sens);
1558
/*reset media control state*/
1559
ctrl = gf_odm_get_mediacontrol(odm);
1560
if (ctrl) ctrl->current_seg = 0;
1565
void gf_odm_on_eos(GF_ObjectManager *odm, GF_Channel *on_channel)
1567
u32 i, count, nb_eos, nb_share_clock;
1568
#ifndef GPAC_DISABLE_VRML
1569
if (gf_odm_check_segment_switch(odm)) return;
1574
count = gf_list_count(odm->channels);
1575
for (i=0; i<count; i++) {
1576
GF_Channel *ch = gf_list_get(odm->channels, i);
1578
if (ch->clock != on_channel->clock) continue;
1581
if (ch->IsEndOfStream) nb_eos++;
1584
if (nb_eos==nb_share_clock) {
1585
on_channel->clock->has_seen_eos = 1;
1587
if (nb_eos != count) return;
1589
if (nb_eos != count) return;
1591
gf_term_service_media_event(odm, GF_EVENT_MEDIA_END_OF_DATA);
1593
if (odm->codec && (on_channel->esd->decoderConfig->streamType==odm->codec->type)) {
1594
gf_codec_set_status(odm->codec, GF_ESM_CODEC_EOS);
1597
if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OCR) {
1598
gf_codec_set_status(odm->ocr_codec, GF_ESM_CODEC_EOS);
1601
if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OCI) {
1602
#ifndef GPAC_MINIMAL_ODF
1603
gf_codec_set_status(odm->oci_codec, GF_ESM_CODEC_EOS);
1607
if (!odm->subscene) return;
1609
if (odm->subscene->scene_codec && (gf_list_find(odm->subscene->scene_codec->inChannels, on_channel)>=0) ) {
1610
gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_EOS);
1614
if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OD) {
1615
gf_codec_set_status(odm->subscene->od_codec, GF_ESM_CODEC_EOS);
1620
void gf_odm_set_duration(GF_ObjectManager *odm, GF_Channel *ch, u64 stream_duration)
1623
if (ch->esd->decoderConfig->streamType == odm->codec->type)
1624
if (odm->duration < stream_duration)
1625
odm->duration = stream_duration;
1626
} else if (odm->ocr_codec) {
1627
if (ch->esd->decoderConfig->streamType == odm->ocr_codec->type)
1628
if (odm->duration < stream_duration)
1629
odm->duration = stream_duration;
1630
} else if (odm->subscene && odm->subscene->scene_codec) {
1631
//if (gf_list_find(odm->subscene->scene_codec->inChannels, ch) >= 0) {
1632
if (odm->duration < stream_duration) odm->duration = stream_duration;
1636
/*update scene duration*/
1637
gf_scene_set_duration(odm->subscene ? odm->subscene : (odm->parentscene ? odm->parentscene : odm->term->root_scene));
1641
GF_Clock *gf_odm_get_media_clock(GF_ObjectManager *odm)
1643
if (odm->codec) return odm->codec->ck;
1644
if (odm->ocr_codec) return odm->ocr_codec->ck;
1645
if (odm->subscene && odm->subscene->scene_codec) return odm->subscene->scene_codec->ck;
1646
if (odm->subscene && odm->subscene->dyn_ck) return odm->subscene->dyn_ck;
1652
Bool gf_odm_shares_clock(GF_ObjectManager *odm, GF_Clock *ck)
1656
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
1657
if (ch->clock == ck) return 1;
1664
void gf_odm_pause(GF_ObjectManager *odm)
1667
GF_NetworkCommand com;
1668
#ifndef GPAC_DISABLE_VRML
1669
MediaSensorStack *media_sens;
1673
if (odm->flags & GF_ODM_NO_TIME_CTRL) return;
1676
/*stop codecs, and update status for media codecs*/
1678
gf_term_stop_codec(odm->codec);
1679
gf_codec_set_status(odm->codec, GF_ESM_CODEC_PAUSE);
1680
} else if (odm->subscene) {
1681
if (odm->subscene->scene_codec) {
1682
gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PAUSE);
1683
gf_term_stop_codec(odm->subscene->scene_codec);
1685
if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec);
1687
if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec);
1688
#ifndef GPAC_MINIMAL_ODF
1689
if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec);
1692
com.command_type = GF_NET_CHAN_PAUSE;
1694
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) {
1695
gf_clock_pause(ch->clock);
1696
com.base.on_channel = ch;
1697
gf_term_service_command(ch->service, &com);
1700
#ifndef GPAC_DISABLE_VRML
1701
/*mediaSensor shall generate isActive false when paused*/
1703
while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i)) ) {
1704
if (media_sens && media_sens->sensor->isActive) {
1705
media_sens->sensor->isActive = 0;
1706
gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive");
1713
void gf_odm_resume(GF_ObjectManager *odm)
1716
GF_NetworkCommand com;
1718
#ifndef GPAC_DISABLE_VRML
1719
MediaSensorStack *media_sens;
1722
if (odm->flags & GF_ODM_NO_TIME_CTRL) return;
1725
/*start codecs, and update status for media codecs*/
1727
gf_term_start_codec(odm->codec);
1728
gf_codec_set_status(odm->codec, GF_ESM_CODEC_PLAY);
1729
} else if (odm->subscene) {
1730
if (odm->subscene->scene_codec) {
1731
gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PLAY);
1732
gf_term_start_codec(odm->subscene->scene_codec);
1734
if (odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec);
1736
if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec);
1737
#ifndef GPAC_MINIMAL_ODF
1738
if (odm->oci_codec) gf_term_start_codec(odm->oci_codec);
1741
com.command_type = GF_NET_CHAN_RESUME;
1743
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ){
1744
gf_clock_resume(ch->clock);
1745
com.base.on_channel = ch;
1746
gf_term_service_command(ch->service, &com);
1749
#ifndef GPAC_DISABLE_VRML
1750
/*mediaSensor shall generate isActive TRUE when resumed*/
1752
while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i)) ){
1753
if (media_sens && !media_sens->sensor->isActive) {
1754
media_sens->sensor->isActive = 1;
1755
gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive");
1761
void gf_odm_set_speed(GF_ObjectManager *odm, Fixed speed)
1764
GF_NetworkCommand com;
1767
if (odm->flags & GF_ODM_NO_TIME_CTRL) return;
1769
com.command_type = GF_NET_CHAN_SET_SPEED;
1770
com.play.speed = FIX2FLT(speed);
1772
while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) {
1773
gf_clock_set_speed(ch->clock, speed);
1774
com.play.on_channel = ch;
1775
gf_term_service_command(ch->service, &com);
1779
GF_Segment *gf_odm_find_segment(GF_ObjectManager *odm, char *descName)
1783
while ( (desc = (GF_Segment *)gf_list_enum(odm->OD->OCIDescriptors, &i)) ){
1784
if (desc->tag != GF_ODF_SEGMENT_TAG) continue;
1785
if (!stricmp(desc->SegmentName, descName)) return desc;
1790
static void gf_odm_insert_segment(GF_ObjectManager *odm, GF_Segment *seg, GF_List *list)
1792
/*this reorders segments when inserting into list - I believe this is not compliant*/
1796
while ((desc = gf_list_enum(list, &i))) {
1797
if (desc == seg) return;
1798
if (seg->startTime + seg->Duration <= desc->startTime) {
1799
gf_list_insert(list, seg, i);
1804
gf_list_add(list, seg);
1807
/*add segment descriptor and sort them*/
1808
void gf_odm_init_segments(GF_ObjectManager *odm, GF_List *list, MFURL *url)
1811
char seg1[1024], seg2[1024], seg_url[4096];
1812
GF_Segment *first_seg, *last_seg, *seg;
1816
for (i=0; i<url->count; i++) {
1817
if (!url->vals[i].url) continue;
1818
str = strstr(url->vals[i].url, "#");
1821
strcpy(seg_url, str);
1822
/*segment closed range*/
1823
if ((sep = strstr(seg_url, "-")) ) {
1824
strcpy(seg2, sep+1);
1826
strcpy(seg1, seg_url);
1827
first_seg = gf_odm_find_segment(odm, seg1);
1828
if (!first_seg) continue;
1829
last_seg = gf_odm_find_segment(odm, seg2);
1831
/*segment open range*/
1832
else if ((sep = strstr(seg_url, "+")) ) {
1834
strcpy(seg1, seg_url);
1835
first_seg = gf_odm_find_segment(odm, seg_url);
1836
if (!first_seg) continue;
1841
first_seg = gf_odm_find_segment(odm, seg_url);
1842
if (!first_seg) continue;
1843
gf_odm_insert_segment(odm, first_seg, list);
1846
/*segment range process*/
1847
gf_odm_insert_segment(odm, first_seg, list);
1849
while ( (seg = (GF_Segment *)gf_list_enum(odm->OD->OCIDescriptors, &j)) ) {
1850
if (seg->tag != GF_ODF_SEGMENT_TAG) continue;
1851
if (seg==first_seg) continue;
1852
if (seg->startTime + seg->Duration <= first_seg->startTime) continue;
1853
/*this also includes last_seg insertion !!*/
1854
if (last_seg && (seg->startTime + seg->Duration > last_seg->startTime + last_seg->Duration) ) continue;
1855
gf_odm_insert_segment(odm, seg, list);
1860
void gf_odm_signal_eos(GF_ObjectManager *odm)
1862
if (odm->parentscene != odm->term->root_scene) return;
1863
if (gf_term_check_end_of_scene(odm->term, 0)) {
1865
evt.type = GF_EVENT_EOS;
1866
gf_term_send_event(odm->term, &evt);