/src/gpac/src/bifs/conditional.c
Line | Count | Source |
1 | | /* |
2 | | * GPAC - Multimedia Framework C SDK |
3 | | * |
4 | | * Authors: Jean Le Feuvre |
5 | | * Copyright (c) Telecom ParisTech 2000-2023 |
6 | | * All rights reserved |
7 | | * |
8 | | * This file is part of GPAC / BIFS codec 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 | | |
28 | | #include <gpac/internal/bifs_dev.h> |
29 | | |
30 | | |
31 | | #ifndef GPAC_DISABLE_BIFS |
32 | | |
33 | | /*private stack for conditional*/ |
34 | | typedef struct |
35 | | { |
36 | | /*BIFS decoder*/ |
37 | | GF_BifsDecoder *codec; |
38 | | /*BIFS config of original stream carrying the conditional*/ |
39 | | BIFSStreamInfo *info; |
40 | | } ConditionalStack; |
41 | | |
42 | | void Conditional_PreDestroy(GF_Node *n, void *eff, Bool is_destroy) |
43 | 0 | { |
44 | 0 | if (is_destroy) { |
45 | 0 | ConditionalStack *priv = (ConditionalStack*)gf_node_get_private(n); |
46 | 0 | if (priv) gf_free(priv); |
47 | 0 | } |
48 | 0 | } |
49 | | |
50 | | void Conditional_BufferReplaced(GF_BifsDecoder *codec, GF_Node *n) |
51 | 0 | { |
52 | 0 | ConditionalStack *priv = (ConditionalStack*)gf_node_get_private(n); |
53 | 0 | if (!priv || (gf_node_get_tag(n) != TAG_MPEG4_Conditional)) return; |
54 | 0 | priv->info = codec->info; |
55 | 0 | } |
56 | | |
57 | | static void Conditional_execute(M_Conditional *node) |
58 | 0 | { |
59 | 0 | char *buffer; |
60 | 0 | u32 len; |
61 | 0 | GF_BitStream *bs; |
62 | 0 | GF_BifsDecoder *codec; |
63 | 0 | GF_Proto *prevproto; |
64 | 0 | GF_SceneGraph *prev_graph; |
65 | 0 | ConditionalStack *priv = (ConditionalStack*)gf_node_get_private((GF_Node*)node); |
66 | 0 | if (!priv) return; |
67 | | |
68 | | /*set the codec working graph to the node one (to handle conditional in protos)*/ |
69 | 0 | prev_graph = priv->codec->current_graph; |
70 | 0 | priv->codec->current_graph = gf_node_get_graph((GF_Node*)node); |
71 | 0 | if (!priv->codec->current_graph) return; |
72 | | |
73 | 0 | priv->codec->info = priv->info; |
74 | 0 | prevproto = priv->codec->pCurrentProto; |
75 | 0 | priv->codec->pCurrentProto = NULL; |
76 | 0 | if (priv->codec->current_graph->pOwningProto) priv->codec->pCurrentProto = priv->codec->current_graph->pOwningProto->proto_interface; |
77 | | |
78 | | /*set isActive - to clarify in the specs*/ |
79 | 0 | node->isActive = 1; |
80 | 0 | gf_node_event_out((GF_Node *)node, 3/*"isActive"*/); |
81 | 0 | if (!node->buffer.bufferSize) return; |
82 | | |
83 | | /*we may replace ourselves*/ |
84 | 0 | buffer = (char*)node->buffer.buffer; |
85 | 0 | len = node->buffer.bufferSize; |
86 | 0 | node->buffer.buffer = NULL; |
87 | 0 | node->buffer.bufferSize = 0; |
88 | 0 | bs = gf_bs_new(buffer, len, GF_BITSTREAM_READ); |
89 | 0 | codec = priv->codec; |
90 | 0 | codec->cts_offset = gf_node_get_scene_time((GF_Node*)node); |
91 | | /*a conditional may destroy/replace itself - to prevent that, protect node by a register/unregister ...*/ |
92 | 0 | gf_node_register((GF_Node*)node, NULL); |
93 | | #ifdef GF_SELF_REPLACE_ENABLE |
94 | | /*and a conditional may destroy the entire scene!*/ |
95 | | cur_graph->graph_has_been_reset = 0; |
96 | | #endif |
97 | 0 | gf_bifs_dec_command(codec, bs); |
98 | 0 | gf_bs_del(bs); |
99 | | #ifdef GF_SELF_REPLACE_ENABLE |
100 | | if (cur_graph->graph_has_been_reset) { |
101 | | return; |
102 | | } |
103 | | #endif |
104 | 0 | if (node->buffer.buffer) { |
105 | 0 | gf_free(buffer); |
106 | 0 | } else { |
107 | 0 | node->buffer.buffer = (u8*)buffer; |
108 | 0 | node->buffer.bufferSize = len; |
109 | 0 | } |
110 | | //set isActive - to clarify in the specs |
111 | | // node->isActive = 0; |
112 | 0 | gf_node_unregister((GF_Node*)node, NULL); |
113 | 0 | codec->cts_offset = 0; |
114 | 0 | codec->pCurrentProto = prevproto; |
115 | 0 | codec->current_graph = prev_graph; |
116 | 0 | } |
117 | | |
118 | | void Conditional_OnActivate(GF_Node *n, GF_Route *route) |
119 | 0 | { |
120 | 0 | M_Conditional *node = (M_Conditional *)n; |
121 | 0 | if (! node->activate) return; |
122 | 0 | Conditional_execute(node); |
123 | 0 | } |
124 | | |
125 | | void Conditional_OnReverseActivate(GF_Node *n, GF_Route *route) |
126 | 0 | { |
127 | 0 | M_Conditional *node = (M_Conditional *)n; |
128 | 0 | if (node->reverseActivate) return; |
129 | 0 | Conditional_execute(node); |
130 | 0 | } |
131 | | |
132 | | void SetupConditional(GF_BifsDecoder *codec, GF_Node *node) |
133 | 0 | { |
134 | 0 | ConditionalStack *priv; |
135 | 0 | if (gf_node_get_tag(node) != TAG_MPEG4_Conditional) return; |
136 | 0 | priv = (ConditionalStack*)gf_malloc(sizeof(ConditionalStack)); |
137 | | |
138 | | /*needed when initializing extern protos*/ |
139 | 0 | if (!codec->info) codec->info = (BIFSStreamInfo*)gf_list_get(codec->streamInfo, 0); |
140 | 0 | if (!codec->info) return; |
141 | | |
142 | 0 | priv->info = codec->info; |
143 | 0 | priv->codec = codec; |
144 | 0 | codec->has_conditionnals = GF_TRUE; |
145 | 0 | gf_node_set_callback_function(node, Conditional_PreDestroy); |
146 | 0 | gf_node_set_private(node, priv); |
147 | 0 | ((M_Conditional *)node)->on_activate = Conditional_OnActivate; |
148 | 0 | ((M_Conditional *)node)->on_reverseActivate = Conditional_OnReverseActivate; |
149 | 0 | } |
150 | | |
151 | | #endif /*GPAC_DISABLE_BIFS*/ |
152 | | |
153 | | |
154 | | /*this is ugly but we have no choice, we need to clone the conditional stack because of externProto*/ |
155 | | void BIFS_SetupConditionalClone(GF_Node *node, GF_Node *orig) |
156 | 0 | { |
157 | 0 | #ifndef GPAC_DISABLE_BIFS |
158 | 0 | M_Conditional *ptr; |
159 | 0 | ConditionalStack *priv_orig, *priv; |
160 | 0 | priv_orig = (ConditionalStack*)gf_node_get_private(orig); |
161 | | /*looks we're not in BIFS*/ |
162 | 0 | if (!priv_orig) { |
163 | | #else |
164 | | { |
165 | | #endif |
166 | |
|
167 | 0 | #ifndef GPAC_DISABLE_VRML |
168 | 0 | u32 i; |
169 | 0 | GF_Command *ori_com; |
170 | 0 | M_Conditional *c_orig, *c_dest; |
171 | 0 | c_orig = (M_Conditional *)orig; |
172 | 0 | c_dest = (M_Conditional *)node; |
173 | 0 | gf_node_init(node); |
174 | | /*and clone all commands*/ |
175 | 0 | i=0; |
176 | 0 | while ((ori_com = (GF_Command*)gf_list_enum(c_orig->buffer.commandList, &i))) { |
177 | 0 | GF_Command *dest_com = gf_sg_vrml_command_clone(ori_com, gf_node_get_graph(node), GF_TRUE); |
178 | 0 | if (dest_com) gf_list_add(c_dest->buffer.commandList, dest_com); |
179 | 0 | } |
180 | 0 | #endif |
181 | 0 | return; |
182 | 0 | } |
183 | | |
184 | 0 | #ifndef GPAC_DISABLE_BIFS |
185 | 0 | priv = (ConditionalStack*)gf_malloc(sizeof(ConditionalStack)); |
186 | 0 | priv->codec = priv_orig->codec; |
187 | 0 | priv->info = priv_orig->info; |
188 | 0 | gf_node_set_callback_function(node, Conditional_PreDestroy); |
189 | 0 | gf_node_set_private(node, priv); |
190 | 0 | ptr = (M_Conditional *)node; |
191 | 0 | ptr->on_activate = Conditional_OnActivate; |
192 | 0 | ptr->on_reverseActivate = Conditional_OnReverseActivate; |
193 | 0 | #endif |
194 | |
|
195 | 0 | } |