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