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