static void animationstream_check_url(AnimationStreamStack *stack, M_AnimationStream *as) { if (!stack->stream) { gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL); gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL); stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0); gf_sc_invalidate(stack->compositor, NULL); /*if changed while playing trigger*/ if (as->isActive) { gf_mo_play(stack->stream, 0, -1, 0); gf_mo_set_speed(stack->stream, as->speed); } return; } /*check change*/ if (gf_mo_url_changed(stack->stream, &as->url)) { gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL); gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL); /*if changed while playing stop old source*/ if (as->isActive) { gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1); gf_mo_stop(stack->stream); } gf_mo_unregister((GF_Node *)as, stack->stream); stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0); /*if changed while playing play new source*/ if (as->isActive) { gf_mo_play(stack->stream, 0, -1, 0); gf_mo_set_speed(stack->stream, as->speed); } gf_sc_invalidate(stack->compositor, NULL); } }
GF_EXPORT GF_Err gf_sc_audio_open(GF_AudioInput *ai, MFURL *url, Double clipBegin, Double clipEnd, Bool lock_timeline) { u32 i; if (ai->is_open) return GF_BAD_PARAM; /*get media object*/ ai->stream = gf_mo_register(ai->owner, url, lock_timeline, 0); /*bad URL*/ if (!ai->stream) return GF_NOT_SUPPORTED; /*request play*/ gf_mo_play(ai->stream, clipBegin, clipEnd, 0); ai->stream_finished = 0; ai->is_open = 1; gf_mo_set_flag(ai->stream, GF_MO_IS_INIT, 0); if (ai->filter) gf_af_del(ai->filter); ai->filter = NULL; for (i=0; i<url->count; i++) { if (url->vals[i].url && !strnicmp(url->vals[i].url, "#filter=", 8)) { ai->filter = gf_af_new(ai->compositor, &ai->input_ifce, url->vals[i].url+8); if (ai->filter) break; } } return GF_OK; }
static void svg_traverse_updates(GF_Node *node, void *rs, Bool is_destroy) { /*video stack is just an extension of image stack, type-casting is OK*/ SVG_updates_stack *stack = (SVG_updates_stack*)gf_node_get_private(node); GF_TraverseState *tr_state = (GF_TraverseState *)rs; SVGAllAttributes all_atts; SVGPropertiesPointers backup_props; u32 backup_flags, dirty_flags; if (is_destroy) { if (stack->resource) { if (stack->is_open) { gf_mo_set_flag(stack->resource, GF_MO_DISPLAY_REMOVE, GF_TRUE); gf_mo_stop(stack->resource); } gf_mo_unregister(node, stack->resource); } gf_free(stack); return; } if (tr_state->traversing_mode!=TRAVERSE_SORT) return; /*flatten attributes and apply animations + inheritance*/ gf_svg_flatten_attributes((SVG_Element *)node, &all_atts); if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags)) return; dirty_flags = gf_node_dirty_get(node); if (dirty_flags) { stack->clipBegin = all_atts.clipBegin ? *all_atts.clipBegin : 0; stack->clipEnd = all_atts.clipEnd ? *all_atts.clipEnd : -1; if (dirty_flags & GF_SG_SVG_XLINK_HREF_DIRTY) { GF_MediaObject *new_res; MFURL url; Bool lock_timeline=GF_FALSE; url.vals = NULL; url.count = 0; if (all_atts.syncBehavior) lock_timeline = (*all_atts.syncBehavior == SMIL_SYNCBEHAVIOR_LOCKED) ? GF_TRUE : GF_FALSE; gf_term_get_mfurl_from_xlink(node, &url); new_res = gf_mo_register(node, &url, lock_timeline, GF_FALSE); gf_sg_mfurl_del(url); if (stack->resource!=new_res) { if (stack->resource) { gf_mo_stop(stack->resource); gf_mo_unregister(node, stack->resource); } stack->resource = new_res; if (stack->resource && stack->is_open) gf_mo_play(stack->resource, stack->clipBegin, stack->clipEnd, GF_FALSE); } } gf_node_dirty_clear(node, 0); } memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers)); tr_state->svg_flags = backup_flags; }
/*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); } }
void compositor_init_afx_node(GF_Compositor *compositor, GF_Node *node, MFURL *url) { GF_MediaObject *mo = gf_mo_register(node, url, 0, 0); if (!mo) { GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] AFX Decoder not found for node %s - node may not be completely/correctly rendered\n", gf_node_get_class_name(node))); } #ifndef GPAC_DISABLE_VRML if (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper) { compositor_init_bitwrapper(compositor, node); } #endif }
GF_EXPORT GF_Err gf_sc_texture_open(GF_TextureHandler *txh, MFURL *url, Bool lock_scene_timeline) { if (txh->is_open) return GF_BAD_PARAM; /*if existing texture in cache destroy it - we don't destroy it on stop to handle MovieTexture*/ if (txh->tx_io) gf_sc_texture_release(txh); /*get media object*/ txh->stream = gf_mo_register(txh->owner, url, lock_scene_timeline, 0); /*bad/Empty URL*/ if (!txh->stream) return GF_NOT_SUPPORTED; return GF_OK; }
/*render : setup media sensor and update timing in case of inline scenes*/ void RenderMediaSensor(GF_Node *node, void *rs, Bool is_destroy) { GF_Clock *ck; 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; } 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; /*since audio may be used alone through an inline scene, we need to refresh the graph*/ if (ck && !ck->has_seen_eos && st->stream->odm->state) gf_term_invalidate_compositor(st->stream->odm->term); } /*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) ) { st->stream->odm->current_time = gf_clock_time(ck); mediasensor_update_timing(st->stream->odm, 0); } }
static void TraverseInputSensor(GF_Node *node, void *rs, Bool is_destroy) { ISStack *st = (ISStack*)gf_node_get_private(node); M_InputSensor *is = (M_InputSensor *)node; if (is_destroy) { GF_Scene *scene; if (st->registered) IS_Unregister(node, st); scene = (GF_Scene*)gf_sg_get_private(gf_node_get_graph(node)); gf_term_unqueue_node_traverse(scene->root_od->term, node); gf_free(st); } else { /*get decoder object */ if (!st->mo) st->mo = gf_mo_register(node, &is->url, 0, 0); /*register with decoder*/ if (st->mo && !st->registered) IS_Register(node); } }
/*check only URL changes*/ void InputSensorModified(GF_Node *node) { GF_MediaObject *mo; ISStack *st = (ISStack *)gf_node_get_private(node); mo = gf_mo_register(node, &st->is->url, 0, 0); if ((mo!=st->mo) || !st->registered){ if (mo!=st->mo) { if (st->mo) IS_Unregister(node, st); st->mo = mo; } if (st->is->enabled) IS_Register(node); else return; } else if (!st->is->enabled) { IS_Unregister(node, st); return; } }
GF_EXPORT GF_Err gf_sc_texture_play_from_to(GF_TextureHandler *txh, MFURL *url, Double start_offset, Double end_offset, Bool can_loop, Bool lock_scene_timeline) { if (txh->is_open) return GF_BAD_PARAM; /*if existing texture in cache destroy it - we don't destroy it on stop to handle MovieTexture*/ if (txh->tx_io) gf_sc_texture_release(txh); /*get media object*/ txh->stream = gf_mo_register(txh->owner, url, lock_scene_timeline, 0); /*bad/Empty URL*/ if (!txh->stream) return GF_NOT_SUPPORTED; /*request play*/ gf_mo_play(txh->stream, start_offset, end_offset, can_loop); txh->last_frame_time = (u32) (-1); //gf_sc_invalidate(txh->compositor, NULL); txh->is_open = 1; return GF_OK; }
/*only URL can be changed, so reset and get new URL*/ void MS_Modified(GF_Node *node) { MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node); if (!st) return; while (gf_list_count(st->seg)) gf_list_rem(st->seg, 0); if (st->stream) { /*unlink from OD*/ if (st->stream->odm && st->stream->odm->ms_stack) gf_list_del_item(st->stream->odm->ms_stack, st); gf_mo_unregister(node, st->stream); if (st->sensor->isActive) { st->sensor->isActive = 0; gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/); } } st->stream = gf_mo_register(node, &st->sensor->url, 0, 0); st->is_init = 0; gf_term_invalidate_compositor(st->parent->root_od->term); }