Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / BIFS decoder filter
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 : #include <gpac/filters.h>
27 : #include <gpac/bifs.h>
28 : #include <gpac/constants.h>
29 : #include <gpac/compositor.h>
30 : #include <gpac/internal/compositor_dev.h>
31 :
32 : #ifndef GPAC_DISABLE_BIFS
33 :
34 :
35 : typedef struct
36 : {
37 : GF_BifsDecoder *bifs_dec;
38 : GF_ObjectManager *odm;
39 : GF_Scene *scene;
40 :
41 : Bool is_playing;
42 : GF_FilterPid *out_pid;
43 : } GF_BIFSDecCtx;
44 :
45 11 : static GF_Err bifs_dec_configure_bifs_dec(GF_BIFSDecCtx *ctx, GF_FilterPid *pid)
46 : {
47 : GF_Err e;
48 : u32 es_id=0;
49 : u32 codecid=0;
50 : const GF_PropertyValue *prop;
51 :
52 11 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
53 11 : if (prop) es_id = prop->value.uint;
54 :
55 11 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
56 11 : if (prop) codecid = prop->value.uint;
57 :
58 :
59 : //we must have a dsi
60 11 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
61 11 : if (!prop || !prop->value.data.ptr || !prop->value.data.size) {
62 : return GF_NON_COMPLIANT_BITSTREAM;
63 : }
64 :
65 11 : if (!ctx->bifs_dec) {
66 : /*if a node asked for this media object, use the scene graph of the node (AnimationStream in PROTO)*/
67 11 : if (ctx->odm->mo && ctx->odm->mo->node_ptr) {
68 0 : GF_SceneGraph *sg = gf_node_get_graph((GF_Node*)ctx->odm->mo->node_ptr);
69 0 : ctx->bifs_dec = gf_bifs_decoder_new(sg, GF_TRUE);
70 0 : ctx->odm->mo->node_ptr = NULL;
71 : } else {
72 11 : ctx->bifs_dec = gf_bifs_decoder_new(ctx->scene->graph, GF_FALSE);
73 : }
74 : }
75 :
76 :
77 11 : e = gf_bifs_decoder_configure_stream(ctx->bifs_dec, es_id, prop->value.data.ptr, prop->value.data.size, codecid);
78 11 : if (e) return e;
79 :
80 11 : return GF_OK;
81 : }
82 :
83 15 : GF_Err bifs_dec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
84 : {
85 : GF_FilterPid *out_pid;
86 15 : GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
87 : const GF_PropertyValue *prop;
88 :
89 : //we must have streamtype SCENE
90 15 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
91 15 : if (!prop || (prop->value.uint != GF_STREAM_SCENE)) {
92 : return GF_NOT_SUPPORTED;
93 : }
94 15 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
95 15 : if (!prop || ( (prop->value.uint != GF_CODECID_BIFS) && (prop->value.uint != GF_CODECID_BIFS_V2)) ) {
96 : return GF_NOT_SUPPORTED;
97 : }
98 : //we must have a dsi
99 15 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
100 15 : if (!prop || !prop->value.data.ptr || !prop->value.data.size) {
101 : return GF_NON_COMPLIANT_BITSTREAM;
102 : }
103 :
104 15 : if (is_remove) {
105 4 : out_pid = gf_filter_pid_get_udta(pid);
106 4 : if (ctx->out_pid==out_pid)
107 4 : ctx->out_pid = NULL;
108 4 : if (out_pid)
109 4 : gf_filter_pid_remove(out_pid);
110 : return GF_OK;
111 : }
112 : //this is a reconfigure
113 11 : if (gf_filter_pid_get_udta(pid)) {
114 0 : return bifs_dec_configure_bifs_dec(ctx, pid);
115 : }
116 :
117 : //check our namespace
118 11 : if (ctx->scene && ! gf_filter_pid_is_filter_in_parents(pid, ctx->scene->root_od->scene_ns->source_filter)) {
119 : return GF_REQUIRES_NEW_INSTANCE;
120 : }
121 :
122 :
123 : //declare a new output PID of type SCENE, codecid RAW
124 11 : out_pid = gf_filter_pid_new(filter);
125 :
126 : //copy properties at init or reconfig
127 11 : gf_filter_pid_copy_properties(out_pid, pid);
128 11 : gf_filter_pid_set_property(out_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
129 11 : gf_filter_pid_set_udta(pid, out_pid);
130 :
131 11 : if (!ctx->out_pid)
132 11 : ctx->out_pid = out_pid;
133 : return GF_OK;
134 : }
135 :
136 :
137 :
138 1425 : GF_Err bifs_dec_process(GF_Filter *filter)
139 : {
140 : GF_Err e;
141 : Double ts_offset;
142 : u64 now, cts;
143 : u32 obj_time;
144 : u32 i, count;
145 : const char *data;
146 : u32 size, ESID=0;
147 : const GF_PropertyValue *prop;
148 : GF_FilterPacket *pck;
149 1425 : GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
150 :
151 1425 : GF_Scene *scene = ctx->scene;
152 :
153 1425 : if (!scene) {
154 0 : if (ctx->is_playing) {
155 0 : if (ctx->out_pid && gf_bifs_decode_has_conditionnals(ctx->bifs_dec)) {
156 0 : gf_filter_pid_set_info(ctx->out_pid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
157 : }
158 0 : gf_filter_pid_set_eos(ctx->out_pid);
159 0 : return GF_EOS;
160 : }
161 : return GF_OK;
162 : }
163 1425 : if (!ctx->bifs_dec) return GF_OK;
164 :
165 1425 : count = gf_filter_get_ipid_count(filter);
166 2850 : for (i=0; i<count; i++) {
167 1425 : GF_FilterPid *pid = gf_filter_get_ipid(filter, i);
168 1425 : GF_FilterPid *opid = gf_filter_pid_get_udta(pid);
169 :
170 1425 : GF_ObjectManager *odm = gf_filter_pid_get_udta(opid);
171 1425 : if (!odm) continue;
172 : //object clock shall be valid
173 : assert(odm->ck);
174 :
175 1425 : pck = gf_filter_pid_get_packet(pid);
176 1425 : if (!pck) {
177 14 : Bool is_eos = gf_filter_pid_is_eos(pid);
178 14 : if (is_eos) {
179 11 : if (opid && gf_bifs_decode_has_conditionnals(ctx->bifs_dec)) {
180 3 : gf_filter_pid_set_info(opid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
181 : }
182 11 : gf_filter_pid_set_eos(opid);
183 : }
184 14 : continue;
185 : }
186 1411 : data = gf_filter_pck_get_data(pck, &size);
187 :
188 1411 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
189 1411 : if (prop) ESID = prop->value.uint;
190 :
191 1411 : cts = gf_filter_pck_get_cts( pck );
192 1411 : ts_offset = (Double) cts;
193 1411 : ts_offset /= gf_filter_pck_get_timescale(pck);
194 :
195 1411 : gf_odm_check_buffering(odm, pid);
196 :
197 :
198 : //we still process any frame before our clock time even when buffering
199 1411 : obj_time = gf_clock_time(odm->ck);
200 1411 : if (ts_offset * 1000 > obj_time) {
201 939 : gf_sc_sys_frame_pending(scene->compositor, ts_offset, obj_time, filter);
202 939 : continue;
203 : }
204 :
205 472 : now = gf_sys_clock_high_res();
206 472 : e = gf_bifs_decode_au(ctx->bifs_dec, ESID, data, size, ts_offset);
207 472 : now = gf_sys_clock_high_res() - now;
208 :
209 472 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[BIFS] ODM%d #CH%d at %d decoded AU TS %u in "LLU" us\n", odm->ID, ESID, obj_time, cts, now));
210 :
211 472 : gf_filter_pid_drop_packet(pid);
212 :
213 472 : if (e) return e;
214 472 : if (odm == ctx->odm)
215 472 : gf_scene_attach_to_compositor(scene);
216 : }
217 : return GF_OK;
218 : }
219 :
220 11 : static void bifs_dec_finalize(GF_Filter *filter)
221 : {
222 11 : GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
223 11 : if (ctx->bifs_dec) gf_bifs_decoder_del(ctx->bifs_dec);
224 11 : }
225 :
226 :
227 73 : static Bool bifs_dec_process_event(GF_Filter *filter, const GF_FilterEvent *com)
228 : {
229 : u32 count, i;
230 73 : GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
231 : //check for scene attach
232 73 : switch (com->base.type) {
233 : case GF_FEVT_ATTACH_SCENE:
234 : break;
235 12 : case GF_FEVT_PLAY:
236 12 : ctx->is_playing = GF_TRUE;
237 12 : return GF_FALSE;
238 : case GF_FEVT_RESET_SCENE:
239 : return GF_FALSE;
240 :
241 : default:
242 : return GF_FALSE;
243 : }
244 11 : if (!com->attach_scene.on_pid) return GF_TRUE;
245 :
246 11 : count = gf_filter_get_ipid_count(filter);
247 11 : for (i=0; i<count; i++) {
248 11 : GF_FilterPid *ipid = gf_filter_get_ipid(filter, i);
249 11 : GF_FilterPid *opid = gf_filter_pid_get_udta(ipid);
250 : //we found our pid, set it up
251 11 : if (opid == com->attach_scene.on_pid) {
252 11 : if (!ctx->odm) {
253 11 : ctx->odm = com->attach_scene.object_manager;
254 11 : ctx->scene = ctx->odm->subscene ? ctx->odm->subscene : ctx->odm->parentscene;
255 : }
256 11 : bifs_dec_configure_bifs_dec(ctx, ipid);
257 11 : gf_filter_pid_set_udta(opid, com->attach_scene.object_manager);
258 11 : return GF_TRUE;
259 : }
260 : }
261 :
262 : return GF_TRUE;
263 : }
264 :
265 : static const GF_FilterCapability BIFSDecCaps[] =
266 : {
267 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
268 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
269 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_BIFS),
270 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_BIFS_V2),
271 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
272 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
273 : };
274 :
275 : GF_FilterRegister BIFSDecRegister = {
276 : .name = "bifsdec",
277 : GF_FS_SET_DESCRIPTION("MPEG-4 BIFS decoder")
278 : GF_FS_SET_HELP("This filter decodes MPEG-4 BIFS frames directly into the scene graph of the compositor. It cannot be used to dump BIFS content.")
279 : .private_size = sizeof(GF_BIFSDecCtx),
280 : .flags = GF_FS_REG_MAIN_THREAD,
281 : .priority = 1,
282 : SETCAPS(BIFSDecCaps),
283 : .finalize = bifs_dec_finalize,
284 : .process = bifs_dec_process,
285 : .configure_pid = bifs_dec_configure_pid,
286 : .process_event = bifs_dec_process_event,
287 : };
288 :
289 : #endif /*GPAC_DISABLE_BIFS*/
290 :
291 2877 : const GF_FilterRegister *bifs_dec_register(GF_FilterSession *session)
292 : {
293 : #ifdef GPAC_DISABLE_BIFS
294 : return NULL;
295 : #else
296 2877 : return &BIFSDecRegister;
297 : #endif /*GPAC_DISABLE_BIFS*/
298 : }
299 :
300 :
301 :
|