📄 object_manager.c
字号:
/*send stop command*/ com.command_type = GF_NET_CHAN_STOP; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { if (ch->ipmp_tool) { GF_IPMPEvent evt; memset(&evt, 0, sizeof(evt)); evt.event_type=GF_IPMP_TOOL_RELEASE_ACCESS; evt.channel = ch; ch->ipmp_tool->process(ch->ipmp_tool, &evt); } if (ch->service) { com.base.on_channel = ch; gf_term_service_command(ch->service, &com); 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))); } } /*stop channels*/ i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { /*stops clock if this is a scene stop*/ if (!(odm->flags & GF_ODM_INHERIT_TIMELINE) && odm->subscene) gf_clock_stop(ch->clock); gf_es_stop(ch); } gf_term_lock_net(odm->term, 0); odm->state = GF_ODM_STATE_STOP; odm->current_time = 0; /*reset media sensor(s)*/ if (force_close!=2) { i = 0; while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i))){ MS_Stop(media_sens); } } /*reset media control state*/ ctrl = ODM_GetMediaControl(odm); if (ctrl) ctrl->current_seg = 0;}void gf_odm_on_eos(GF_ObjectManager *odm, GF_Channel *on_channel){ if (gf_odm_check_segment_switch(odm)) return; if (odm->codec && (on_channel->esd->decoderConfig->streamType==odm->codec->type)) { gf_codec_set_status(odm->codec, GF_ESM_CODEC_EOS); return; } if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OCR) { gf_codec_set_status(odm->ocr_codec, GF_ESM_CODEC_EOS); return; } if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OCI) { gf_codec_set_status(odm->oci_codec, GF_ESM_CODEC_EOS); return; } if (!odm->subscene) return; if (odm->subscene->scene_codec && (gf_list_find(odm->subscene->scene_codec->inChannels, on_channel)>=0) ) { gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_EOS); return; } if (on_channel->esd->decoderConfig->streamType==GF_STREAM_OD) { gf_codec_set_status(odm->subscene->od_codec, GF_ESM_CODEC_EOS); return; }}void gf_odm_set_duration(GF_ObjectManager *odm, GF_Channel *ch, u64 stream_duration){ if (odm->codec) { if (ch->esd->decoderConfig->streamType == odm->codec->type) if (odm->duration < stream_duration) odm->duration = stream_duration; } else if (odm->ocr_codec) { if (ch->esd->decoderConfig->streamType == odm->ocr_codec->type) if (odm->duration < stream_duration) odm->duration = stream_duration; } else if (odm->subscene && odm->subscene->scene_codec) { //if (gf_list_find(odm->subscene->scene_codec->inChannels, ch) >= 0) { if (odm->duration < stream_duration) odm->duration = stream_duration; //} } /*update scene duration*/ gf_is_set_duration(odm->subscene ? odm->subscene : (odm->parentscene ? odm->parentscene : odm->term->root_scene));}GF_Clock *gf_odm_get_media_clock(GF_ObjectManager *odm){ if (odm->codec) return odm->codec->ck; if (odm->ocr_codec) return odm->ocr_codec->ck; if (odm->subscene && odm->subscene->scene_codec) return odm->subscene->scene_codec->ck; if (odm->subscene && odm->subscene->dyn_ck) return odm->subscene->dyn_ck; return NULL;}void ODM_SetMediaControl(GF_ObjectManager *odm, MediaControlStack *ctrl){ u32 i; GF_Channel *ch; /*keep track of it*/ if (ctrl && (gf_list_find(odm->mc_stack, ctrl) < 0)) gf_list_add(odm->mc_stack, ctrl); if (ctrl && !ctrl->control->enabled) return; if (odm->subscene && odm->subscene->is_dynamic_scene) { if (odm->subscene->dyn_ck) { /*deactivate current control*/ if (ctrl && odm->subscene->dyn_ck->mc) { odm->subscene->dyn_ck->mc->control->enabled = 0; gf_node_event_out_str((GF_Node *)odm->subscene->dyn_ck->mc->control, "enabled"); } odm->subscene->dyn_ck->mc = ctrl; } } else { /*for each clock in the controled OD*/ i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) { if (ch->clock->mc != ctrl) { /*deactivate current control*/ if (ctrl && ch->clock->mc) { ch->clock->mc->control->enabled = 0; gf_node_event_out_str((GF_Node *)ch->clock->mc->control, "enabled"); } /*and attach this control to the clock*/ ch->clock->mc = ctrl; } } } /*store active control on media*/ odm->media_ctrl = ODM_GetMediaControl(odm);}MediaControlStack *ODM_GetMediaControl(GF_ObjectManager *odm){ GF_Clock *ck; ck = gf_odm_get_media_clock(odm); if (!ck) return NULL; return ck->mc;}MediaControlStack *ODM_GetObjectMediaControl(GF_ObjectManager *odm){ MediaControlStack *ctrl; ctrl = ODM_GetMediaControl(odm); if (!ctrl) return NULL; /*inline scene control*/ if (odm->subscene && (ctrl->stream->odm == odm->subscene->root_od) ) return ctrl; if (ctrl->stream->OD_ID != odm->OD->objectDescriptorID) return NULL; return ctrl;}void ODM_RemoveMediaControl(GF_ObjectManager *odm, MediaControlStack *ctrl){ gf_list_del_item(odm->mc_stack, ctrl); /*removed. Note the spec doesn't say what to do in this case...*/ if (odm->media_ctrl == ctrl) ODM_SetMediaControl(odm, NULL);}Bool ODM_SwitchMediaControl(GF_ObjectManager *odm, MediaControlStack *ctrl){ u32 i; MediaControlStack *st2; if (!ctrl->control->enabled) return 0; /*for all media controls other than this one force enable to false*/ i=0; while ((st2 = (MediaControlStack *)gf_list_enum(odm->mc_stack, &i))) { if (st2 == ctrl) continue; if (st2->control->enabled) { st2->control->enabled = 0; gf_node_event_out_str((GF_Node *) st2->control, "enabled"); } st2->enabled = 0; } if (ctrl == odm->media_ctrl) return 0; ODM_SetMediaControl(odm, ctrl); return 1;}Bool gf_odm_shares_clock(GF_ObjectManager *odm, GF_Clock *ck){ u32 i = 0; GF_Channel *ch; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) { if (ch->clock == ck) return 1; } return 0;}void gf_odm_pause(GF_ObjectManager *odm){ u32 i; GF_NetworkCommand com; MediaSensorStack *media_sens; GF_Channel *ch; if (odm->flags & GF_ODM_NO_TIME_CTRL) return; /*stop codecs, and update status for media codecs*/ if (odm->codec) { gf_term_stop_codec(odm->codec); gf_codec_set_status(odm->codec, GF_ESM_CODEC_PAUSE); } else if (odm->subscene) { if (odm->subscene->scene_codec) { gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PAUSE); gf_term_stop_codec(odm->subscene->scene_codec); } if (odm->subscene->od_codec) gf_term_stop_codec(odm->subscene->od_codec); } if (odm->ocr_codec) gf_term_stop_codec(odm->ocr_codec); if (odm->oci_codec) gf_term_stop_codec(odm->oci_codec); com.command_type = GF_NET_CHAN_PAUSE; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) { gf_clock_pause(ch->clock); com.base.on_channel = ch; gf_term_service_command(ch->service, &com); } /*mediaSensor shall generate isActive false when paused*/ i=0; while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i)) ) { if (media_sens && media_sens->sensor->isActive) { media_sens->sensor->isActive = 0; gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive"); } }}void gf_odm_resume(GF_ObjectManager *odm){ u32 i; GF_NetworkCommand com; GF_Channel *ch; MediaSensorStack *media_sens; if (odm->flags & GF_ODM_NO_TIME_CTRL) return; /*start codecs, and update status for media codecs*/ if (odm->codec) { gf_term_start_codec(odm->codec); gf_codec_set_status(odm->codec, GF_ESM_CODEC_PLAY); } else if (odm->subscene) { if (odm->subscene->scene_codec) { gf_codec_set_status(odm->subscene->scene_codec, GF_ESM_CODEC_PLAY); gf_term_start_codec(odm->subscene->scene_codec); } if (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); com.command_type = GF_NET_CHAN_RESUME; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ){ gf_clock_resume(ch->clock); com.base.on_channel = ch; gf_term_service_command(ch->service, &com); } /*mediaSensor shall generate isActive TRUE when resumed*/ i=0; while ((media_sens = (MediaSensorStack *)gf_list_enum(odm->ms_stack, &i)) ){ if (media_sens && !media_sens->sensor->isActive) { media_sens->sensor->isActive = 1; gf_node_event_out_str((GF_Node *) media_sens->sensor, "isActive"); } }}void gf_odm_set_speed(GF_ObjectManager *odm, Fixed speed){ u32 i; GF_NetworkCommand com; GF_Channel *ch; if (odm->flags & GF_ODM_NO_TIME_CTRL) return; com.command_type = GF_NET_CHAN_SET_SPEED; com.play.speed = FIX2FLT(speed); i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i)) ) { gf_clock_set_speed(ch->clock, speed); com.play.on_channel = ch; gf_term_service_command(ch->service, &com); }}GF_Segment *gf_odm_find_segment(GF_ObjectManager *odm, char *descName){ GF_Segment *desc; u32 i = 0; while ( (desc = (GF_Segment *)gf_list_enum(odm->OD->OCIDescriptors, &i)) ){ if (desc->tag != GF_ODF_SEGMENT_TAG) continue; if (!stricmp(desc->SegmentName, descName)) return desc; } return NULL;}static void gf_odm_insert_segment(GF_ObjectManager *odm, GF_Segment *seg, GF_List *list){ /*this reorders segments when inserting into list - I believe this is not compliant*/#if 0 GF_Segment *desc; u32 i = 0; while ((desc = gf_list_enum(list, &i))) { if (desc == seg) return; if (seg->startTime + seg->Duration <= desc->startTime) { gf_list_insert(list, seg, i); return; } }#endif gf_list_add(list, seg);}/*add segment descriptor and sort them*/void gf_odm_init_segments(GF_ObjectManager *odm, GF_List *list, MFURL *url){ char *str, *sep; char seg1[1024], seg2[1024], seg_url[4096]; GF_Segment *first_seg, *last_seg, *seg; u32 i, j; /*browse all URLs*/ for (i=0; i<url->count; i++) { if (!url->vals[i].url) continue; str = strstr(url->vals[i].url, "#"); if (!str) continue; str++; strcpy(seg_url, str); /*segment closed range*/ if ((sep = strstr(seg_url, "-")) ) { strcpy(seg2, sep+1); sep[0] = 0; strcpy(seg1, seg_url); first_seg = gf_odm_find_segment(odm, seg1); if (!first_seg) continue; last_seg = gf_odm_find_segment(odm, seg2); } /*segment open range*/ else if ((sep = strstr(seg_url, "+")) ) { sep[0] = 0; strcpy(seg1, seg_url); first_seg = gf_odm_find_segment(odm, seg_url); if (!first_seg) continue; last_seg = NULL; } /*single segment*/ else { first_seg = gf_odm_find_segment(odm, seg_url); if (!first_seg) continue; gf_odm_insert_segment(odm, first_seg, list); continue; } /*segment range process*/ gf_odm_insert_segment(odm, first_seg, list); j=0; while ( (seg = (GF_Segment *)gf_list_enum(odm->OD->OCIDescriptors, &j)) ) { if (seg->tag != GF_ODF_SEGMENT_TAG) continue; if (seg==first_seg) continue; if (seg->startTime + seg->Duration <= first_seg->startTime) continue; /*this also includes last_seg insertion !!*/ if (last_seg && (seg->startTime + seg->Duration > last_seg->startTime + last_seg->Duration) ) continue; gf_odm_insert_segment(odm, seg, list); } }}Bool gf_odm_check_segment_switch(GF_ObjectManager *odm){ u32 count, i; GF_Segment *cur, *next; MediaControlStack *ctrl = ODM_GetMediaControl(odm); /*if no control or control not on this object ignore segment switch*/ if (!ctrl || (ctrl->stream->odm != odm)) return 0; count = gf_list_count(ctrl->seg); /*reached end of controled stream (no more segments)*/ if (ctrl->current_seg>=count) return 0; /*synth media, trigger if end of segment run-time*/ if (!odm->codec || ((odm->codec->type!=GF_STREAM_VISUAL) && (odm->codec->type!=GF_STREAM_AUDIO))) { GF_Clock *ck = gf_odm_get_media_clock(odm); u32 now = gf_clock_time(ck); u64 dur = odm->subscene ? odm->subscene->duration : odm->duration; cur = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg); if (odm->subscene && odm->subscene->needs_restart) return 0; if (cur) dur = (u32) ((cur->Duration+cur->startTime)*1000); if (now<=dur) return 0; } else { /*FIXME - for natural media with scalability, we should only process when all streams of the object are done*/ } /*get current segment and move to next one*/ cur = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg); ctrl->current_seg ++; /*resync in case we have been issuing a play range over several segments*/ for (i=ctrl->current_seg; i<count; i++) { next = (GF_Segment *)gf_list_get(ctrl->seg, i); if ( /*if next seg start is after cur seg start*/ (cur->startTime < next->startTime) /*if next seg start is before cur seg end*/ && (cur->startTime + cur->Duration > next->startTime) /*if next seg start is already passed*/ && (1000*next->startTime < odm->current_time) /*then next segment was taken into account when requesting play*/ ) { cur = next; ctrl->current_seg ++; } } /*if last segment in ctrl is done, end of stream*/ if (ctrl->current_seg >= count) return 0; next = (GF_Segment *)gf_list_get(ctrl->seg, ctrl->current_seg); /*if next seg start is not in current seg, media needs restart*/ if ((next->startTime < cur->startTime) || (cur->startTime + cur->Duration < next->startTime)) MC_Restart(odm); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -