📄 object_manager.c
字号:
setting up the channel...*/ cs = (GF_ChannelSetup*)malloc(sizeof(GF_ChannelSetup)); cs->ch = ch; cs->dec = dec; /*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/ if ((ch->esd->decoderConfig->streamType==GF_STREAM_OD) && strstr(ch->esd->URLString, "data:application/mpeg4-od-au;") ) dec->flags |= GF_ESM_CODEC_IS_STATIC_OD; gf_term_lock_net(odm->term, 1); gf_list_add(odm->term->channels_pending, cs); e = gf_term_connect_remote_channel(odm->term, ch, esd->URLString); if (e) { s32 i = gf_list_find(odm->term->channels_pending, cs); if (i>=0) { gf_list_rem(odm->term->channels_pending, (u32) i); free(cs); odm->pending_channels--; ODM_CheckChannelService(ch); gf_es_del(ch); } } gf_term_lock_net(odm->term, 0); if (ch->service->owner) { gf_list_del_item(odm->term->channels_pending, cs); free(cs); return gf_odm_post_es_setup(ch, dec, GF_OK); } return e; } /*regular setup*/ return gf_odm_post_es_setup(ch, dec, GF_OK);}GF_Err gf_odm_post_es_setup(GF_Channel *ch, GF_Codec *dec, GF_Err had_err){ char szURL[2048]; GF_Err e; GF_NetworkCommand com; e = had_err; if (e) { ch->odm->pending_channels--; goto err_exit; } /*insert channel*/ if (dec) gf_list_insert(ch->odm->channels, ch, 0); if (ch->service) { ch->es_state = GF_ESM_ES_WAIT_FOR_ACK; if (ch->esd->URLString) { strcpy(szURL, ch->esd->URLString); } else { sprintf(szURL, "ES_ID=%d", ch->esd->ESID); } /*connect before setup: this is needed in case the decoder cfg is wrong, we may need to get it from network config...*/ e = ch->service->ifce->ConnectChannel(ch->service->ifce, ch, szURL, ch->esd->decoderConfig->upstream); /*special case (not really specified in specs ...): if the stream is not found and is an Interaction one (ie, used by an InputSensor), consider this means the stream shall be generated by the IS device*/ if ((e==GF_STREAM_NOT_FOUND) && (ch->esd->decoderConfig->streamType==GF_STREAM_INTERACT)) e = GF_OK; } else { ch->es_state = GF_ESM_ES_CONNECTED; ch->odm->pending_channels--; } if (e) { if (dec) gf_list_rem(ch->odm->channels, 0); goto err_exit; } /*add to decoder*/ if (dec) { e = gf_codec_add_channel(dec, ch); if (e) { switch (ch->esd->decoderConfig->streamType) { case GF_STREAM_VISUAL: gf_term_message(ch->odm->term, ch->service->url, "Video Setup failed", e); break; case GF_STREAM_AUDIO: gf_term_message(ch->odm->term, ch->service->url, "Audio Setup failed", e); break; } gf_list_rem(ch->odm->channels, 0); /*disconnect*/ ch->service->ifce->DisconnectChannel(ch->service->ifce, ch); if (ch->esd->URLString) ch->service->nb_ch_users--; goto err_exit; } } /*in case a channel is inserted in a running OD, open and play if not in queue*/ if ( (ch->odm->state==GF_ODM_STATE_PLAY) /*HACK: special case when OD resources are statically described in the ESD itself (ISMA streaming)*/// || (dec && (dec->flags & GF_ESM_CODEC_IS_STATIC_OD)) ) { gf_term_lock_net(ch->odm->term, 1); gf_list_del_item(ch->odm->term->media_queue, ch->odm); gf_es_start(ch); com.command_type = GF_NET_CHAN_PLAY; com.base.on_channel = ch; com.play.speed = FIX2FLT(ch->clock->speed); com.play.start_range = gf_clock_time(ch->clock); com.play.start_range /= 1000; com.play.end_range = -1.0; gf_term_service_command(ch->service, &com); if (dec && (dec->Status!=GF_ESM_CODEC_PLAY)) gf_term_start_codec(dec); gf_term_lock_net(ch->odm->term, 0); } return GF_OK;err_exit: ODM_CheckChannelService(ch); gf_es_del(ch); return e;}/*confirmation of channel delete from net*/void ODM_DeleteChannel(GF_ObjectManager *odm, GF_Channel *ch){ u32 i, count, ch_pos; GF_Channel *ch2; GF_Clock *ck; if (!ch) return; //find a clock with this stream ES_ID ck = gf_clock_find(odm->net_service->Clocks, ch->esd->ESID, 0); count = gf_list_count(odm->channels); ch_pos = count+1; for (i=0; i<count; i++) { ch2 = (GF_Channel*)gf_list_get(odm->channels, i); if (ch2 == ch) { ch_pos = i; if (ck) continue; break; } //note that when a stream is added, we need to update clocks info ... if (ck && ch->clock && (ch2->clock->clockID == ck->clockID)) gf_es_stop(ch2); } /*remove channel*/ if (ch_pos != count+1) gf_list_rem(odm->channels, ch_pos); /*remove from the codec*/ count = 0; if (!count && odm->codec) count = gf_codec_remove_channel(odm->codec, ch); if (!count && odm->ocr_codec) count = gf_codec_remove_channel(odm->ocr_codec, ch); if (!count && odm->oci_codec) count = gf_codec_remove_channel(odm->oci_codec, ch); if (!count && odm->subscene) { if (odm->subscene->scene_codec) count = gf_codec_remove_channel(odm->subscene->scene_codec, ch); if (!count) count = gf_codec_remove_channel(odm->subscene->od_codec, ch); } assert(count); if (ch->service) { ch->service->ifce->DisconnectChannel(ch->service->ifce, ch); if (ch->esd->URLString) ch->service->nb_ch_users--; ODM_CheckChannelService(ch); } //and delete gf_es_del(ch);}GF_EXPORTvoid gf_odm_remove_es(GF_ObjectManager *odm, u16 ES_ID){ GF_ESD *esd; GF_Channel *ch; u32 i = 0; while ((esd = (GF_ESD *)gf_list_enum(odm->OD->ESDescriptors, &i)) ) { if (esd->ESID==ES_ID) goto esd_found; } return;esd_found: /*remove esd*/ gf_list_rem(odm->OD->ESDescriptors, i-1); /*locate channel*/ ch = NULL; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { if (ch->esd->ESID == ES_ID) break; ch = NULL; } /*destroy ESD*/ gf_odf_desc_del((GF_Descriptor *) esd); /*remove channel*/ if (ch) ODM_DeleteChannel(odm, ch);}/*this is the tricky part: make sure the net is locked before doing anything since an async service reply could destroy the object we're queuing for play*/void gf_odm_start(GF_ObjectManager *odm){ gf_term_lock_net(odm->term, 1); /*only if not open & ready (not waiting for ACK on channel setup)*/ if (!odm->state && !odm->pending_channels) { GF_Channel *ch; u32 i = 0; odm->state = GF_ODM_STATE_PLAY; /*look for a given segment name to play*/ if (odm->subscene) { char *url, *frag; assert(odm->subscene->root_od==odm); url = (odm->mo && odm->mo->URLs.count) ? odm->mo->URLs.vals[0].url : odm->net_service->url; frag = strrchr(url, '#'); if (frag) { GF_Segment *seg = gf_odm_find_segment(odm, frag+1); if (seg) { odm->media_start_time = (u64) ((s64) seg->startTime*1000); odm->media_stop_time = (u64) ((s64) (seg->startTime + seg->Duration)*1000); } } } /*start all channels and postpone play - this assures that all channels of a multiplexed are setup before one starts playing*/ while ( (ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { gf_es_start(ch); 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))); } if (gf_list_find(odm->term->media_queue, odm)<0) gf_list_add(odm->term->media_queue, odm); } gf_term_lock_net(odm->term, 0);}void gf_odm_play(GF_ObjectManager *odm){ GF_Channel *ch; u32 i; u32 nb_failure; u64 range_end; Bool skip_od_st; GF_NetworkCommand com; MediaControlStack *ctrl; GF_Clock *parent_ck = NULL; if (odm->parentscene) { parent_ck = gf_odm_get_media_clock(odm->parentscene->root_od); if (!gf_odm_shares_clock(odm, parent_ck)) parent_ck = NULL; } skip_od_st = (odm->subscene && odm->subscene->static_media_ressources) ? 1 : 0; range_end = odm->media_stop_time;// odm->media_stop_time = 0; nb_failure = gf_list_count(odm->channels); /*send play command*/ com.command_type = GF_NET_CHAN_PLAY; i=0; while ( (ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { Double ck_time; if (ch->ipmp_tool) { GF_IPMPEvent evt; GF_Err e; memset(&evt, 0, sizeof(evt)); evt.event_type=GF_IPMP_TOOL_GRANT_ACCESS; evt.channel = ch; e = ch->ipmp_tool->process(ch->ipmp_tool, &evt); if (e) { gf_term_message(odm->term, NULL, "PLAY access is not granted on channel - please check your license", e); gf_es_stop(ch); continue; } } nb_failure --; com.base.on_channel = ch; com.play.speed = 1.0; /*play from requested time (seeking or non-mpeg4 media control)*/ if (odm->media_start_time && !ch->clock->clock_init) { ck_time = (Double) (s64) odm->media_start_time; ck_time /= 1000; } /*play from current time*/ else { ck_time = gf_clock_time(ch->clock); ck_time /= 1000; /*handle initial start - MPEG-4 is a bit annoying here, streams are not started through OD but through scene nodes. If the stream runs on the BIFS/OD clock, the clock is already started at this point and we're sure to get at least a one-frame delay in PLAY, so just remove it - note we're generous but this shouldn't hurt*/ if (ck_time<=0.5) ck_time = 0; } com.play.start_range = ck_time; if (range_end) { com.play.end_range = (s64) range_end / 1000.0; } else { if (!odm->subscene && gf_odm_shares_clock(odm->parentscene->root_od, ch->clock) && (odm->parentscene->root_od->media_stop_time != odm->parentscene->root_od->duration) ) { com.play.end_range = (s64) odm->parentscene->root_od->media_stop_time / 1000.0; } else { com.play.end_range = -1; } } /*if object shares parent scene clock, do not use media control*/ ctrl = parent_ck ? NULL : ODM_GetMediaControl(odm); /*override range and speed with MC*/ if (ctrl) { MC_GetRange(ctrl, &com.play.start_range, &com.play.end_range); com.play.speed = FIX2FLT(ctrl->control->mediaSpeed); /*if the channel doesn't control the clock, jump to current time in the controled range, not just the begining*/ 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)) { com.play.start_range = ck_time; } gf_clock_set_speed(ch->clock, ctrl->control->mediaSpeed); /*if requested seek time AND media control, adjust start range to current play time*/ if (odm->media_start_time) { if ((com.play.start_range>=0) && (com.play.end_range>com.play.start_range)) { if (ctrl->control->loop) { Double active_dur = com.play.end_range - com.play.start_range; while (ck_time>active_dur) ck_time -= active_dur; } else { ck_time = 0; //com.play.start_range = com.play.end_range; } } com.play.start_range += ck_time; } } /*full object playback*/ if (com.play.end_range<=0) { odm->media_stop_time = odm->subscene ? 0 : odm->duration; } else { /*segment playback - since our timing is in ms whereas segment ranges are double precision, make sure we have a LARGER range in ms, otherwise media sensors won't deactivate properly*/ odm->media_stop_time = (u64) ceil(1000 * com.play.end_range); } /*don't replay OD channel, only init clock if needed*/ if (!ch->service || (skip_od_st && (ch->esd->decoderConfig->streamType==GF_STREAM_OD))) { Bool gf_es_owns_clock(GF_Channel *ch); if (gf_es_owns_clock(ch) ) gf_clock_set_time(ch->clock, (u32) (com.play.start_range*1000)); ch->IsClockInit = 1; if (ch->BufferOn) { ch->BufferOn = 0; gf_clock_buffer_off(ch->clock); } } else { gf_term_service_command(ch->service, &com); 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)); } }// odm->media_start_time = 0; if (nb_failure) { odm->state = GF_ODM_STATE_BLOCKED; return; } /*start codecs last (otherwise we end up pulling data from channels not yet connected->pbs when seeking)*/ if (odm->codec) { /*reset*/ if (odm->codec->CB) { gf_cm_set_status(odm->codec->CB, CB_STOP); odm->codec->CB->HasSeenEOS = 0; } gf_term_start_codec(odm->codec); } else if (odm->subscene) { if (odm->subscene->scene_codec) gf_term_start_codec(odm->subscene->scene_codec); if (!skip_od_st && odm->subscene->od_codec) gf_term_start_codec(odm->subscene->od_codec); } if (odm->ocr_codec) gf_term_start_codec(odm->ocr_codec); if (odm->oci_codec) gf_term_start_codec(odm->oci_codec);}void gf_odm_stop(GF_ObjectManager *odm, Bool force_close){ GF_Channel *ch; u32 i; MediaControlStack *ctrl; MediaSensorStack *media_sens; GF_NetworkCommand com; if (!odm->state) return;#if 0 /*Handle broadcast environment, do not stop the object if no time control and instruction comes from the scene*/ if (odm->no_time_ctrl && !force_close) { GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ODM%d] - broadcast detected, ignoring Stop from scene\n", odm->OD->objectDescriptorID); return; }#endif gf_term_lock_net(odm->term, 1); gf_list_del_item(odm->term->media_queue, odm); gf_term_lock_net(odm->term, 0); /*little opt for image codecs: don't actually stop the OD*/ if (!force_close && odm->codec && odm->codec->CB) { if (odm->codec->CB->Capacity==1) return; } /*object was not unlocked, decoders were not started*/ if (odm->state==GF_ODM_STATE_BLOCKED) { odm->current_time = 0; return; } /*stop codecs*/ if (odm->codec) { gf_term_stop_codec(odm->codec); } else if (odm->subscene) { u32 i=0; GF_ObjectManager *sub_odm; if (odm->subscene->scene_codec) gf_term_stop_codec(odm->subscene->scene_codec); if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec); /*stops all resources of the subscene as well*/ while ((sub_odm=(GF_ObjectManager *)gf_list_enum(odm->subscene->ODlist, &i))) { gf_odm_stop(sub_odm, force_close); } } if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec); if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec); gf_term_lock_net(odm->term, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -