Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "nodes_stacks.h"
27 :
28 : #include <gpac/nodes_mpeg4.h>
29 :
30 : #ifndef GPAC_DISABLE_VRML
31 :
32 : typedef struct
33 : {
34 : GF_Compositor *compositor;
35 : GF_TimeNode time_handle;
36 : Double start_time;
37 : GF_MediaObject *stream;
38 : MFURL current_url;
39 : } AnimationStreamStack;
40 :
41 1619 : static void animationstream_destroy(GF_Node *node, void *rs, Bool is_destroy)
42 : {
43 1619 : if (is_destroy) {
44 : M_AnimationStream *as = (M_AnimationStream *)node;
45 217 : AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);
46 :
47 217 : if (st->time_handle.is_registered) {
48 213 : gf_sc_unregister_time_node(st->compositor, &st->time_handle);
49 : }
50 217 : if (st->stream && as->isActive) {
51 5 : gf_mo_set_flag(st->stream, GF_MO_DISPLAY_REMOVE, 1);
52 5 : gf_mo_stop(&st->stream);
53 : }
54 217 : gf_sg_vrml_mf_reset(&st->current_url, GF_SG_VRML_MFURL);
55 217 : gf_free(st);
56 : }
57 1619 : }
58 :
59 :
60 195 : static void animationstream_check_url(AnimationStreamStack *stack, M_AnimationStream *as)
61 : {
62 195 : if (!stack->stream) {
63 186 : gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
64 186 : gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
65 186 : stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
66 186 : gf_sc_invalidate(stack->compositor, NULL);
67 :
68 : /*if changed while playing trigger*/
69 186 : if (as->isActive) {
70 0 : gf_mo_play(stack->stream, 0, -1, 0);
71 0 : gf_mo_set_speed(stack->stream, as->speed);
72 : }
73 : return;
74 : }
75 : /*check change*/
76 9 : if (gf_mo_url_changed(stack->stream, &as->url)) {
77 1 : gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
78 1 : gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
79 : /*if changed while playing stop old source*/
80 1 : if (as->isActive) {
81 0 : gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
82 0 : gf_mo_stop(&stack->stream);
83 : }
84 1 : gf_mo_unregister((GF_Node *)as, stack->stream);
85 :
86 1 : stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
87 : /*if changed while playing play new source*/
88 1 : if (as->isActive) {
89 0 : gf_mo_play(stack->stream, 0, -1, 0);
90 0 : gf_mo_set_speed(stack->stream, as->speed);
91 : }
92 1 : gf_sc_invalidate(stack->compositor, NULL);
93 : }
94 : }
95 :
96 : static Fixed animationstream_get_speed(AnimationStreamStack *stack, M_AnimationStream *as)
97 : {
98 4047 : return gf_mo_get_speed(stack->stream, as->speed);
99 : }
100 : static Bool animationstream_get_loop(AnimationStreamStack *stack, M_AnimationStream *as)
101 : {
102 4 : return gf_mo_get_loop(stack->stream, as->loop);
103 : }
104 :
105 187 : static void animationstream_activate(AnimationStreamStack *stack, M_AnimationStream *as)
106 : {
107 187 : animationstream_check_url(stack, as);
108 187 : as->isActive = 1;
109 187 : gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);
110 :
111 187 : gf_mo_play(stack->stream, 0, -1, 0);
112 187 : gf_mo_set_speed(stack->stream, as->speed);
113 187 : }
114 :
115 5 : static void animationstream_deactivate(AnimationStreamStack *stack, M_AnimationStream *as)
116 : {
117 5 : if (as->isActive) {
118 5 : as->isActive = 0;
119 5 : gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);
120 : }
121 5 : if (stack->stream) {
122 5 : if (gf_mo_url_changed(stack->stream, &as->url))
123 0 : gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
124 5 : gf_mo_stop(&stack->stream);
125 : }
126 5 : stack->time_handle.needs_unregister = 1;
127 5 : gf_sc_invalidate(stack->compositor, NULL);
128 5 : }
129 :
130 4351 : static void animationstream_update_time(GF_TimeNode *st)
131 : {
132 : Double time;
133 4351 : M_AnimationStream *as = (M_AnimationStream *)st->udta;
134 4351 : AnimationStreamStack *stack = (AnimationStreamStack *)gf_node_get_private(st->udta);
135 :
136 : /*not active, store start time and speed*/
137 4351 : if ( ! as->isActive) {
138 491 : stack->start_time = as->startTime;
139 : }
140 4351 : time = gf_node_get_scene_time(st->udta);
141 :
142 4351 : if ((time < stack->start_time) || (stack->start_time < 0)) return;
143 :
144 8094 : if (animationstream_get_speed(stack, as) && as->isActive) {
145 : //if stoptime is reached (>startTime) deactivate
146 3860 : if ((as->stopTime > stack->start_time) && (time >= as->stopTime) ) {
147 1 : animationstream_deactivate(stack, as);
148 1 : return;
149 : }
150 3859 : if (gf_mo_is_done(stack->stream)) {
151 8 : if (animationstream_get_loop(stack, as)) {
152 0 : gf_mo_restart(stack->stream);
153 4 : } else if (gf_mo_should_deactivate(stack->stream)) {
154 4 : animationstream_deactivate(stack, as);
155 : }
156 : }
157 : }
158 :
159 : /*we're (about to be) active: VRML:
160 : "A time-dependent node is inactive until its startTime is reached. When time now becomes greater than or
161 : equal to startTime, an isActive TRUE event is generated and the time-dependent node becomes active */
162 4046 : if (!as->isActive && !st->needs_unregister) animationstream_activate(stack, as);
163 : }
164 :
165 :
166 217 : void compositor_init_animationstream(GF_Compositor *compositor, GF_Node *node)
167 : {
168 : AnimationStreamStack *st;
169 217 : GF_SAFEALLOC(st, AnimationStreamStack);
170 217 : if (!st) {
171 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate AnimationStream stack\n"));
172 : return;
173 : }
174 217 : st->compositor = compositor;
175 217 : st->time_handle.UpdateTimeNode = animationstream_update_time;
176 217 : st->time_handle.udta = node;
177 :
178 217 : gf_node_set_private(node, st);
179 217 : gf_node_set_callback_function(node, animationstream_destroy);
180 :
181 217 : gf_sc_register_time_node(compositor, &st->time_handle);
182 : }
183 :
184 :
185 :
186 8 : void compositor_animationstream_modified(GF_Node *node)
187 : {
188 : M_AnimationStream *as = (M_AnimationStream *)node;
189 8 : AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);
190 8 : if (!st) return;
191 :
192 : /*update state if we're active*/
193 8 : if (as->isActive)
194 1 : animationstream_update_time(&st->time_handle);
195 :
196 : /*check URL change*/
197 8 : animationstream_check_url(st, as);
198 :
199 8 : if (!st->time_handle.is_registered && !st->time_handle.needs_unregister)
200 0 : gf_sc_register_time_node(st->compositor, &st->time_handle);
201 : else
202 8 : st->time_handle.needs_unregister = 0;
203 : }
204 :
205 : #endif /*GPAC_DISABLE_VRML*/
|