Coverage Report

Created: 2026-10-08 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}