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