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