Coverage Report

Created: 2026-02-14 07:05

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) 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
}