/*render : setup media sensor and update timing in case of inline scenes*/ void RenderMediaSensor(GF_Node *node, void *rs, Bool is_destroy) { GF_TraverseState *tr_state = (GF_TraverseState *)rs; GF_Clock *ck; Bool do_update_clock = 1; MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node); if (is_destroy) { /*unlink from OD*/ if (st->stream && st->stream->odm) gf_list_del_item(st->stream->odm->ms_stack, st); gf_list_del(st->seg); gf_free(st); return; } //we need to disable culling otherwise we may never be called back again ... tr_state->disable_cull = 1; if (!st->stream) st->stream = gf_mo_register(node, &st->sensor->url, 0, 0); if (!st->stream || !st->stream->odm) return; if (!st->is_init) { gf_list_add(st->stream->odm->ms_stack, st); gf_odm_init_segments(st->stream->odm, st->seg, &st->sensor->url); st->is_init = 1; st->active_seg = 0; } /*media sensor bound to natural media (audio, video) is updated when fetching the stream data for rendering.*/ ck = NULL; /*check inline scenes - if the scene is set to restart DON'T MODIFY SENSOR: since we need a 2 render passes to restart inline, scene is considered as not running*/ if (st->stream->odm->subscene && !st->stream->odm->subscene->needs_restart) { if (st->stream->odm->subscene->scene_codec) ck = st->stream->odm->subscene->scene_codec->ck; /*dynamic scene*/ else ck = st->stream->odm->subscene->dyn_ck; if (st->stream->odm->subscene->is_dynamic_scene) do_update_clock = 0; } /*check anim streams*/ else if (st->stream->odm->codec && (st->stream->odm->codec->type==GF_STREAM_SCENE)) ck = st->stream->odm->codec->ck; /*check OCR streams*/ else if (st->stream->odm->ocr_codec) ck = st->stream->odm->ocr_codec->ck; if (ck && gf_clock_is_started(ck) ) { if (do_update_clock) st->stream->odm->media_current_time = gf_clock_media_time(ck); mediasensor_update_timing(st->stream->odm, 0); } //if main addon is VoD and selected and clock is paused, fire a timeshift update else if (st->stream->odm->subscene && st->stream->odm->subscene->sys_clock_at_main_activation) { GF_Event evt; memset(&evt, 0, sizeof(evt)); evt.type = GF_EVENT_TIMESHIFT_UPDATE; gf_term_send_event(st->stream->odm->term, &evt); } }
GF_EXPORT GF_Err gf_term_get_object_info(GF_Terminal *term, GF_ObjectManager *odm, GF_MediaInfo *info) { GF_ObjectManager *an_odm; GF_Channel *ch; GF_Codec *codec; memset(info, 0, sizeof(GF_MediaInfo)); if (!term || !odm || !info) return GF_BAD_PARAM; if (!gf_term_check_odm(term, odm)) return GF_BAD_PARAM; info->od = odm->OD; info->duration = (Double) (s64)odm->duration; info->duration /= 1000; codec = odm->codec; an_odm = odm; while (!codec) { if (!an_odm->lower_layer_odm) break; an_odm = an_odm->lower_layer_odm; codec = an_odm->codec; } if (codec) { /*since we don't remove ODs that failed setup, check for clock*/ if (codec->ck) { if (codec->CB) { info->current_time = odm->media_current_time ? odm->media_current_time : codec->last_unit_cts; info->ntp_diff = codec->CB->LastRenderedNTPDiff; } else { info->current_time = gf_clock_media_time(codec->ck); } } info->current_time /= 1000; info->nb_dropped = codec->nb_dropped; } else if (odm->subscene) { if (odm->subscene->scene_codec) { if (odm->subscene->scene_codec->ck) { info->current_time = gf_clock_media_time(odm->subscene->scene_codec->ck); info->current_time /= 1000; } info->duration = (Double) (s64)odm->subscene->duration; info->duration /= 1000; info->nb_dropped = odm->subscene->scene_codec->nb_dropped; codec = odm->subscene->scene_codec; } else if (odm->subscene->is_dynamic_scene) { if (odm->subscene->dyn_ck) { info->current_time = gf_clock_media_time(odm->subscene->dyn_ck); info->current_time /= 1000; } info->generated_scene = 1; } } if (info->duration && info->current_time>info->duration) info->current_time = info->duration; info->buffer = -2; info->db_unit_count = 0; /*Warning: is_open==2 means object setup, don't check then*/ if (odm->state==GF_ODM_STATE_IN_SETUP) { info->status = 3; } else if (odm->state==GF_ODM_STATE_BLOCKED) { info->status = 0; info->protection = 2; } else if (odm->state) { u32 i, buf; GF_Clock *ck; ck = gf_odm_get_media_clock(odm); /*no clock means setup failed*/ if (!ck) { info->status = 4; } else { info->status = gf_clock_is_started(ck) ? 1 : 2; info->clock_drift = ck->drift; info->buffer = -1; info->min_buffer = -1; info->max_buffer = 0; buf = 0; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) { info->db_unit_count += ch->AU_Count; if (!ch->is_pulling || ch->MaxBuffer) { if (ch->MaxBuffer) info->buffer = 0; buf += ch->BufferTime; if (ch->MaxBuffer> info->max_buffer) info->max_buffer = ch->MaxBuffer; if (ch->MinBuffer < info->min_buffer) info->min_buffer = ch->MinBuffer; } if (ch->is_protected) info->protection = ch->ipmp_tool ? 1 : 2; } if (buf) info->buffer = (s32) buf; } } info->has_profiles = (odm->flags & GF_ODM_HAS_PROFILES) ? 1 : 0; if (info->has_profiles) { info->inline_pl = (odm->flags & GF_ODM_INLINE_PROFILES) ? 1 : 0; info->OD_pl = odm->OD_PL; info->scene_pl = odm->Scene_PL; info->audio_pl = odm->Audio_PL; info->visual_pl = odm->Visual_PL; info->graphics_pl = odm->Graphics_PL; } if (odm->net_service) { info->service_handler = odm->net_service->ifce->module_name; info->service_url = odm->net_service->url; if (odm->net_service->owner == odm) info->owns_service = 1; } else if ((odm->subscene && odm->subscene->graph_attached) || (odm->codec)) { info->service_url = "No associated network Service"; } else { info->service_url = "Service not found or error"; } if (codec) { if (codec->decio && codec->decio->GetName) { info->codec_name = codec->decio->GetName(codec->decio); } else { info->codec_name = codec->decio->module_name; } info->od_type = codec->type; if (codec->CB) { info->cb_max_count = codec->CB->Capacity; info->cb_unit_count = codec->CB->UnitCount; if (codec->direct_vout) { info->direct_video_memory = 1; } } get_codec_stats(codec, info); } if (odm->subscene) { gf_sg_get_scene_size_info(odm->subscene->graph, &info->width, &info->height); } else if (odm->mo) { switch (info->od_type) { case GF_STREAM_VISUAL: gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, &info->par, &info->pixelFormat, NULL); break; case GF_STREAM_AUDIO: gf_mo_get_audio_info(odm->mo, &info->sample_rate, &info->bits_per_sample, &info->num_channels, NULL); info->clock_drift = 0; break; case GF_STREAM_TEXT: gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, NULL, NULL, NULL); break; } } ch = (GF_Channel*)gf_list_get(odm->channels, 0); if (ch && ch->esd->langDesc) info->lang = ch->esd->langDesc->langCode; if (odm->mo && odm->mo->URLs.count) info->media_url = odm->mo->URLs.vals[0].url; return GF_OK; }