Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2017
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 :
27 : #include <gpac/constants.h>
28 : #include <gpac/internal/compositor_dev.h>
29 :
30 : #ifndef GPAC_DISABLE_VRML
31 :
32 : /*render : setup media sensor and update timing in case of inline scenes*/
33 2536 : void RenderMediaSensor(GF_Node *node, void *rs, Bool is_destroy)
34 : {
35 : GF_TraverseState *tr_state = (GF_TraverseState *)rs;
36 : GF_Clock *ck;
37 : Bool do_update_clock = 1;
38 2536 : MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node);
39 :
40 2536 : if (is_destroy) {
41 : /*unlink from OD*/
42 16 : if (st->stream && st->stream->odm)
43 12 : gf_list_del_item(st->stream->odm->ms_stack, st);
44 :
45 16 : gf_list_del(st->seg);
46 16 : gf_free(st);
47 16 : return;
48 : }
49 : //we need to disable culling otherwise we may never be called back again ...
50 2520 : tr_state->disable_cull = 1;
51 :
52 2520 : if (!st->is_init) {
53 826 : if (!st->stream) {
54 107 : st->stream = gf_mo_register(node, &st->sensor->url, 0, 0);
55 107 : if (!st->stream) return;
56 : }
57 733 : if (!st->stream->odm) return;
58 :
59 14 : gf_list_add(st->stream->odm->ms_stack, st);
60 14 : gf_odm_init_segments(st->stream->odm, st->seg, &st->sensor->url);
61 14 : st->is_init = 1;
62 14 : st->active_seg = 0;
63 : }
64 : //st->stream may be NULL when destroying the ODM
65 1708 : if (!st->stream || !st->stream->odm) return;
66 :
67 : /*media sensor bound to natural media (audio, video) is updated when fetching the stream
68 : data for rendering.*/
69 :
70 : ck = NULL;
71 : /*check inline scenes - if the scene is set to restart DON'T MODIFY SENSOR: since we need a 2 render
72 : passes to restart inline, scene is considered as not running*/
73 1708 : if (st->stream->odm->subscene && !st->stream->odm->subscene->needs_restart) {
74 279 : if (! st->stream->odm->subscene->is_dynamic_scene) ck = st->stream->odm->subscene->root_od->ck;
75 : /*dynamic scene*/
76 124 : else ck = st->stream->odm->ck;
77 :
78 279 : if (st->stream->odm->subscene->is_dynamic_scene) do_update_clock = 0;
79 : }
80 : /*check anim or OCR streams*/
81 1429 : else if (st->stream->odm->type==GF_STREAM_SCENE) ck = st->stream->odm->ck;
82 : /*check OCR streams*/
83 1428 : else if (st->stream->odm->ck) ck = st->stream->odm->ck;
84 :
85 1688 : if (ck && ck->clock_init ) {
86 1655 : if (do_update_clock)
87 1541 : st->stream->odm->media_current_time = gf_clock_media_time(ck);
88 1655 : mediasensor_update_timing(st->stream->odm, GF_FALSE);
89 : }
90 : //if main addon is VoD , fire a timeshift update
91 53 : else if (st->stream->odm->subscene && st->stream->odm->subscene->sys_clock_at_main_activation) {
92 : GF_Event evt;
93 : memset(&evt, 0, sizeof(evt));
94 0 : evt.type = GF_EVENT_TIMESHIFT_UPDATE;
95 0 : gf_sc_send_event(st->stream->odm->parentscene->compositor, &evt);
96 : }
97 : }
98 :
99 16 : void InitMediaSensor(GF_Scene *scene, GF_Node *node)
100 : {
101 : MediaSensorStack *st;
102 16 : GF_SAFEALLOC(st, MediaSensorStack);
103 16 : if (!st) {
104 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Terminal] Failed to allocate media sensor stack\n"));
105 : return;
106 : }
107 :
108 16 : st->parent = scene;
109 16 : st->sensor = (M_MediaSensor *)node;
110 16 : st->seg = gf_list_new();
111 16 : gf_node_set_callback_function(node, RenderMediaSensor);
112 16 : gf_node_set_private(node, st);
113 :
114 : }
115 :
116 : /*only URL can be changed, so reset and get new URL*/
117 1 : void MS_Modified(GF_Node *node)
118 : {
119 1 : MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node);
120 1 : if (!st) return;
121 :
122 0 : while (gf_list_count(st->seg)) gf_list_rem(st->seg, 0);
123 :
124 1 : if (st->stream) {
125 : /*unlink from OD*/
126 0 : if (st->stream->odm && st->stream->odm->ms_stack)
127 0 : gf_list_del_item(st->stream->odm->ms_stack, st);
128 :
129 0 : gf_mo_unregister(node, st->stream);
130 0 : if (st->sensor->isActive) {
131 0 : st->sensor->isActive = 0;
132 0 : gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/);
133 : }
134 : }
135 1 : st->stream = NULL;
136 1 : st->is_init = 0;
137 1 : gf_sc_invalidate(st->parent->compositor, NULL);
138 : }
139 :
140 12439 : void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos)
141 : {
142 : GF_Segment *desc;
143 : u32 i, count, j, ms_count;
144 : Double time;
145 12439 : ms_count = gf_list_count(odm->ms_stack);
146 12439 : if (!ms_count) return;
147 :
148 3149 : time = odm->media_current_time / 1000.0;
149 : //dirty hack to get timing of frame when very late (openhevc debug)
150 3149 : if (odm->subscene && odm->ck && odm->ck->last_ts_rendered)
151 0 : time = odm->ck->last_ts_rendered / 1000.0;
152 :
153 3503 : for (j=0; j<ms_count; j++) {
154 3503 : MediaSensorStack *media_sens = (MediaSensorStack *)gf_list_get(odm->ms_stack, j);
155 3503 : if (!media_sens->is_init) continue;
156 3503 : count = gf_list_count(media_sens->seg);
157 :
158 : /*full object controled*/
159 3503 : if (!media_sens->active_seg && !count) {
160 : /*check for end of scene (MediaSensor on inline)*/
161 3503 : if (odm->subscene && odm->subscene->duration) {
162 262 : GF_Clock *ck = gf_odm_get_media_clock(odm);
163 262 : if (ck->has_seen_eos && (1000*time>=(Double) (s64)odm->subscene->duration)) {
164 0 : if (media_sens->sensor->isActive) {
165 : /*force notification of time (ntify the scene duration rather than the current clock*/
166 0 : media_sens->sensor->mediaCurrentTime = (Double) odm->subscene->duration;
167 0 : media_sens->sensor->mediaCurrentTime /= 1000;
168 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
169 0 : media_sens->sensor->isActive = 0;
170 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
171 :
172 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", odm->ID));
173 : }
174 0 : continue;
175 : }
176 : }
177 :
178 3503 : if (!is_eos && !media_sens->sensor->isActive) {
179 18 : media_sens->sensor->isActive = 1;
180 18 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
181 :
182 18 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
183 18 : if (odm->subscene) {
184 6 : media_sens->sensor->mediaDuration = (Double) (s64)odm->subscene->duration;
185 : } else {
186 12 : media_sens->sensor->mediaDuration = (Double) (s64)odm->duration;
187 : }
188 18 : if (media_sens->sensor->mediaDuration)
189 17 : media_sens->sensor->mediaDuration /= 1000;
190 : else
191 1 : media_sens->sensor->mediaDuration = -FIX_ONE;
192 :
193 18 : gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
194 : }
195 :
196 3503 : if (is_eos && media_sens->sensor->isActive) {
197 1 : if (media_sens->sensor->mediaDuration>=0) {
198 1 : media_sens->sensor->mediaCurrentTime = media_sens->sensor->mediaDuration;
199 : } else {
200 0 : media_sens->sensor->mediaCurrentTime = time;
201 : }
202 1 : gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
203 1 : media_sens->sensor->isActive = 0;
204 1 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
205 : } else {
206 3502 : if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) {
207 2029 : media_sens->sensor->mediaCurrentTime = time;
208 2029 : gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
209 : }
210 : }
211 3503 : continue;
212 : }
213 :
214 : /*locate segment*/
215 0 : for (i=media_sens->active_seg; i<count; i++) {
216 0 : desc = (GF_Segment*)gf_list_get(media_sens->seg, i);
217 : /*not controled*/
218 0 : if (desc->startTime > time) {
219 0 : if (media_sens->sensor->isActive) {
220 0 : media_sens->sensor->isActive = 0;
221 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
222 :
223 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g - segment %s\n", odm->ID, time, desc->SegmentName));
224 : }
225 0 : continue;
226 : }
227 0 : if (desc->startTime + desc->Duration < time) continue;
228 0 : if (desc->startTime + desc->Duration == time) {
229 0 : continue;
230 : }
231 : /*segment switch, force activation (isActive TRUE send at each seg)*/
232 0 : if (media_sens->active_seg != i) {
233 0 : media_sens->active_seg = i;
234 0 : media_sens->sensor->isActive = 0;
235 : }
236 :
237 0 : if (!media_sens->sensor->isActive) {
238 :
239 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Activating media sensor time %g - segment %s\n", odm->ID, time, desc->SegmentName));
240 :
241 0 : media_sens->sensor->isActive = 1;
242 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
243 : /*set info*/
244 0 : gf_sg_vrml_mf_reset(& media_sens->sensor->info, GF_SG_VRML_MFSTRING);
245 0 : gf_sg_vrml_mf_alloc(& media_sens->sensor->info, GF_SG_VRML_MFSTRING, 1);
246 0 : media_sens->sensor->info.vals[0] = desc->SegmentName ? gf_strdup(desc->SegmentName) : NULL;
247 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 5/*"info"*/);
248 : /*set duration*/
249 0 : media_sens->sensor->mediaDuration = desc->Duration;
250 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
251 : /*set seg start time*/
252 0 : media_sens->sensor->streamObjectStartTime = desc->startTime;
253 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 2/*"streamObjectStartTime"*/);
254 :
255 : }
256 :
257 : /*set media time - relative to segment start time*/
258 0 : time -= desc->startTime;
259 0 : if (media_sens->sensor->mediaCurrentTime != time) {
260 0 : media_sens->sensor->mediaCurrentTime = time;
261 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
262 : }
263 : break;
264 : }
265 0 : if (i==count) {
266 : /*we're after last segment, deactivate*/
267 0 : if (media_sens->sensor->isActive) {
268 0 : media_sens->sensor->isActive = 0;
269 0 : gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
270 0 : media_sens->active_seg = count;
271 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g: no more segments\n", odm->ID, time));
272 : }
273 : }
274 : }
275 : }
276 :
277 16 : void MS_Stop(MediaSensorStack *st)
278 : {
279 16 : if (st->sensor->isActive) {
280 14 : st->sensor->isActive = 0;
281 14 : gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/);
282 :
283 14 : GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", st->stream->odm->ID));
284 : }
285 16 : st->active_seg = 0;
286 16 : }
287 :
288 : #endif /*GPAC_DISABLE_VRML*/
|