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 / openjpeg2k 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 : #ifdef GPAC_HAS_JP2
29 :
30 : //we MUST set OPJ_STATIC before including openjpeg.h
31 : #if !defined(__GNUC__) && (defined(_WIN32_WCE) || defined (WIN32))
32 : # define OPJ_STATIC
33 : #endif
34 :
35 : #include <gpac/constants.h>
36 : #include <gpac/isomedia.h>
37 :
38 : #include <openjpeg.h>
39 :
40 : #ifdef OPJ_PROFILE_NONE
41 : #define OPENJP2 1
42 :
43 : # if !defined(__GNUC__) && (defined(_WIN32_WCE) || defined (WIN32))
44 : # if defined(_DEBUG)
45 : # pragma comment(lib, "libopenjp2d")
46 : # else
47 : # pragma comment(lib, "libopenjp2")
48 : # endif
49 : # endif
50 :
51 : #else
52 :
53 : #define OPENJP2 0
54 :
55 : # if !defined(__GNUC__) && (defined(_WIN32_WCE) || defined (WIN32))
56 : # if defined(_DEBUG)
57 : # pragma comment(lib, "LibOpenJPEGd")
58 : # else
59 : # pragma comment(lib, "LibOpenJPEG")
60 : # endif
61 : # endif
62 :
63 : #endif
64 :
65 : typedef struct
66 : {
67 : GF_FilterPid *ipid, *opid;
68 : u32 cfg_crc;
69 : /*no support for scalability with JPEG (progressive JPEG to test)*/
70 : u32 bpp, nb_comp, width, height, out_size, pixel_format, dsi_size;
71 : char *dsi;
72 : } GF_J2KCtx;
73 :
74 :
75 : static GF_Err j2kdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
76 : {
77 : const GF_PropertyValue *p;
78 : GF_J2KCtx *ctx = gf_filter_get_udta(filter);
79 :
80 : if (is_remove) {
81 : if (ctx->opid) {
82 : gf_filter_pid_remove(ctx->opid);
83 : ctx->opid = NULL;
84 : }
85 : ctx->ipid = NULL;
86 : return GF_OK;
87 : }
88 : if (! gf_filter_pid_check_caps(pid))
89 : return GF_NOT_SUPPORTED;
90 :
91 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
92 : if (p && p->value.data.ptr && p->value.data.size) {
93 : GF_BitStream *bs;
94 : u32 d4cc;
95 : Bool dsi_ok=GF_FALSE;
96 : u32 ex_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
97 : if (ctx->cfg_crc == ex_crc) {
98 : return GF_OK;
99 : }
100 : ctx->cfg_crc = ex_crc;
101 :
102 : //old gpac version used to store only the payload of ihdr in the dsi, but the new version exposes the entire jp2h (without box size and type) as dsi
103 : //so handle both on read
104 : d4cc = 0;
105 : if (p->value.data.size>8)
106 : d4cc = GF_4CC(p->value.data.ptr[4], p->value.data.ptr[5], p->value.data.ptr[6], p->value.data.ptr[7]);
107 :
108 : bs = gf_bs_new(p->value.data.ptr, p->value.data.size, GF_BITSTREAM_READ);
109 : if ((d4cc==GF_4CC('i','h','d','r')) || (d4cc==GF_4CC('c','o','l','r'))) {
110 : while (gf_bs_available(bs)) {
111 : u32 bsize = gf_bs_read_u32(bs);
112 : u32 btype = gf_bs_read_u32(bs);
113 : if (btype==GF_4CC('i','h','d','r')) {
114 : dsi_ok=GF_TRUE;
115 : break;
116 : }
117 : gf_bs_skip_bytes(bs, bsize-8);
118 : }
119 : } else {
120 : dsi_ok=GF_TRUE;
121 : }
122 : if (dsi_ok) {
123 : ctx->height = gf_bs_read_u32(bs);
124 : ctx->width = gf_bs_read_u32(bs);
125 : ctx->nb_comp = gf_bs_read_u16(bs);
126 : ctx->bpp = 1 + gf_bs_read_u8(bs);
127 : }
128 : gf_bs_del(bs);
129 :
130 : if (!dsi_ok) {
131 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[OpenJPEG] Broken decoder config in j2k stream, cannot decode\n"));
132 : return GF_NON_COMPLIANT_BITSTREAM;
133 : }
134 :
135 : ctx->out_size = ctx->width * ctx->height * ctx->nb_comp /* * ctx->bpp / 8 */;
136 :
137 : switch (ctx->nb_comp) {
138 : case 1:
139 : ctx->pixel_format = GF_PIXEL_GREYSCALE;
140 : break;
141 : case 2:
142 : ctx->pixel_format = GF_PIXEL_ALPHAGREY;
143 : break;
144 : case 3:
145 : ctx->pixel_format = GF_PIXEL_RGB;
146 : break;
147 : case 4:
148 : ctx->pixel_format = GF_PIXEL_RGBA;
149 : break;
150 : default:
151 : return GF_NOT_SUPPORTED;
152 : }
153 : } else {
154 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_WIDTH);
155 : if (p) ctx->width = p->value.uint;
156 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_HEIGHT);
157 : if (p) ctx->height = p->value.uint;
158 : ctx->nb_comp = 0;
159 : ctx->pixel_format = 0;
160 : }
161 :
162 : ctx->ipid = pid;
163 : if (!ctx->opid) {
164 : ctx->opid = gf_filter_pid_new(filter);
165 : gf_filter_pid_set_framing_mode(ctx->ipid, GF_TRUE);
166 : }
167 : //copy properties at init or reconfig
168 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
169 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
170 :
171 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(ctx->width) );
172 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(ctx->height) );
173 : if (ctx->pixel_format) {
174 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT( (ctx->pixel_format == GF_PIXEL_YUV) ? ctx->width : ctx->width * ctx->nb_comp) );
175 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(ctx->pixel_format) );
176 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_COLR_RANGE, &PROP_BOOL(GF_TRUE) );
177 : }
178 : return GF_OK;
179 : }
180 :
181 : /**
182 : sample error callback expecting a FILE* client object
183 : */
184 : void error_callback(const char *msg, void *client_data)
185 : {
186 : if (msg) {
187 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[OpenJPEG] Error %s", msg));
188 : } else {
189 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[OpenJPEG] coverage test\n"));
190 : }
191 : }
192 : /**
193 : sample warning callback expecting a FILE* client object
194 : */
195 : void warning_callback(const char *msg, void *client_data)
196 : {
197 : if (msg) {
198 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[OpenJPEG] Warning %s", msg));
199 : } else {
200 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[OpenJPEG] coverage test\n"));
201 : }
202 : }
203 : /**
204 : sample debug callback expecting no client object
205 : */
206 : void info_callback(const char *msg, void *client_data)
207 : {
208 : if (msg) {
209 : GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[OpenJPEG] Info %s", msg));
210 : } else {
211 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[OpenJPEG] coverage test\n"));
212 : }
213 : }
214 :
215 : /*
216 : * Divide an integer by a power of 2 and round upwards.
217 : *
218 : * a divided by 2^b
219 : */
220 : static int int_ceildivpow2(int a, int b) {
221 : return (a + (1 << b) - 1) >> b;
222 : }
223 :
224 : #if OPENJP2
225 : typedef struct
226 : {
227 : char *data;
228 : u32 len, pos;
229 : } OJP2Frame;
230 :
231 : static OPJ_SIZE_T j2kdec_stream_read(void *out_buffer, OPJ_SIZE_T nb_bytes, void *user_data)
232 : {
233 : OJP2Frame *frame = user_data;
234 : u32 remain;
235 : if (frame->pos == frame->len) return (OPJ_SIZE_T)-1;
236 : remain = frame->len - frame->pos;
237 : if (nb_bytes > remain) nb_bytes = remain;
238 : memcpy(out_buffer, frame->data + frame->pos, nb_bytes);
239 : frame->pos += (u32) nb_bytes;
240 : return nb_bytes;
241 : }
242 :
243 : static OPJ_OFF_T j2kdec_stream_skip(OPJ_OFF_T nb_bytes, void *user_data)
244 : {
245 : OJP2Frame *frame = user_data;
246 : if (!user_data) return 0;
247 :
248 : if (nb_bytes < 0) {
249 : if (frame->pos == 0) return (OPJ_SIZE_T)-1;
250 : if (nb_bytes + (s32) frame->pos < 0) {
251 : nb_bytes = -frame->pos;
252 : }
253 : } else {
254 : u32 remain;
255 : if (frame->pos == frame->len) {
256 : return (OPJ_SIZE_T)-1;
257 : }
258 : remain = frame->len - frame->pos;
259 : if (nb_bytes > remain) {
260 : nb_bytes = remain;
261 : }
262 : }
263 : frame->pos += (u32) nb_bytes;
264 : return nb_bytes;
265 : }
266 :
267 : static OPJ_BOOL j2kdec_stream_seek(OPJ_OFF_T nb_bytes, void *user_data)
268 : {
269 : OJP2Frame *frame = user_data;
270 : if (nb_bytes < 0 || nb_bytes > frame->pos) return OPJ_FALSE;
271 : frame->pos = (u32)nb_bytes;
272 : return OPJ_TRUE;
273 : }
274 : #endif
275 :
276 :
277 : static GF_Err j2kdec_process(GF_Filter *filter)
278 : {
279 : u32 i, w, wr, h, hr, wh, size, pf;
280 : u8 *data, *buffer;
281 : opj_dparameters_t parameters; /* decompression parameters */
282 : #if OPENJP2
283 : s32 res;
284 : opj_codec_t *codec = NULL;
285 : opj_stream_t * stream = NULL;
286 : OJP2Frame ojp2frame;
287 : #else
288 : opj_event_mgr_t event_mgr; /* event manager */
289 : opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
290 : opj_cio_t *cio = NULL;
291 : opj_codestream_info_t cinfo;
292 : #endif
293 : opj_image_t *image = NULL;
294 : u32 start_offset=0;
295 : GF_J2KCtx *ctx = gf_filter_get_udta(filter);
296 : GF_FilterPacket *pck, *pck_dst;
297 : Bool changed = GF_FALSE;
298 : pck = gf_filter_pid_get_packet(ctx->ipid);
299 : if (!pck) {
300 : if (gf_filter_pid_is_eos(ctx->ipid))
301 : gf_filter_pid_set_eos(ctx->opid);
302 : return GF_OK;
303 : }
304 : data = (char *) gf_filter_pck_get_data(pck, &size);
305 : if (!data) {
306 : gf_filter_pid_drop_packet(ctx->ipid);
307 : return GF_IO_ERR;
308 : }
309 :
310 : if (size>=8) {
311 : if ((data[4]=='j') && (data[5]=='p') && (data[6]=='2') && (data[7]=='c'))
312 : start_offset = 8;
313 : }
314 :
315 : /* set decoding parameters to default values */
316 : opj_set_default_decoder_parameters(¶meters);
317 :
318 : #if OPENJP2
319 : codec = opj_create_decompress(OPJ_CODEC_J2K);
320 : if (codec) res = 1;
321 : else res=0;
322 :
323 : if (res) res = opj_set_info_handler(codec, info_callback, NULL);
324 : if (res) res = opj_set_warning_handler(codec, warning_callback, NULL);
325 : if (res) res = opj_set_error_handler(codec, error_callback, NULL);
326 :
327 : if (res) res = opj_setup_decoder(codec, ¶meters);
328 :
329 : stream = opj_stream_default_create(OPJ_STREAM_READ);
330 : opj_stream_set_read_function(stream, j2kdec_stream_read);
331 : opj_stream_set_skip_function(stream, j2kdec_stream_skip);
332 : opj_stream_set_seek_function(stream, j2kdec_stream_seek);
333 : ojp2frame.data = data+start_offset;
334 : ojp2frame.len = size-start_offset;
335 : ojp2frame.pos = 0;
336 : opj_stream_set_user_data(stream, &ojp2frame, NULL);
337 : opj_stream_set_user_data_length(stream, ojp2frame.len);
338 :
339 : if (res) res = opj_read_header(stream, codec, &image);
340 : if (res) res = opj_set_decode_area(codec, image, 0, 0, image->x1, image->y1);
341 : if (res) {
342 : res = opj_decode(codec, stream, image);
343 : if (!res) {
344 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[OpenJPEG] Decoding failed\n"));
345 : opj_image_destroy(image);
346 : image = NULL;
347 : }
348 : }
349 :
350 : #else
351 :
352 : /* get a decoder handle for raw J2K frames*/
353 : dinfo = opj_create_decompress(CODEC_J2K);
354 :
355 : /* configure the event callbacks (not required) */
356 : memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
357 : event_mgr.error_handler = error_callback;
358 : event_mgr.warning_handler = warning_callback;
359 : event_mgr.info_handler = info_callback;
360 :
361 : /* catch events using our callbacks and give a local context */
362 : opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
363 :
364 : /* setup the decoder decoding parameters using the current image and user parameters */
365 : opj_setup_decoder(dinfo, ¶meters);
366 :
367 : cio = opj_cio_open((opj_common_ptr)dinfo, data+start_offset, size-start_offset);
368 : /* decode the stream and fill the image structure */
369 : image = opj_decode_with_info(dinfo, cio, &cinfo);
370 : #endif
371 :
372 : if (!image) {
373 : #if OPENJP2
374 : opj_stream_destroy(stream);
375 : opj_destroy_codec(codec);
376 : #else
377 : opj_destroy_decompress(dinfo);
378 : opj_cio_close(cio);
379 : #endif
380 : gf_filter_pid_drop_packet(ctx->ipid);
381 : return GF_IO_ERR;
382 : }
383 :
384 : #if OPENJP2
385 : ctx->nb_comp = image->numcomps;
386 : w = image->x1;
387 : h = image->y1;
388 : #else
389 : ctx->nb_comp = cinfo.numcomps;
390 : w = cinfo.image_w;
391 : h = cinfo.image_h;
392 : #endif
393 : ctx->bpp = ctx->nb_comp * 8;
394 : ctx->out_size = ctx->width * ctx->height * ctx->nb_comp /* * ctx->bpp / 8 */;
395 :
396 : switch (ctx->nb_comp) {
397 : case 1:
398 : pf = GF_PIXEL_GREYSCALE;
399 : break;
400 : case 2:
401 : pf = GF_PIXEL_ALPHAGREY;
402 : break;
403 : case 3:
404 : pf = GF_PIXEL_RGB;
405 : break;
406 : case 4:
407 : pf = GF_PIXEL_RGBA;
408 : break;
409 : default:
410 : gf_filter_pid_drop_packet(ctx->ipid);
411 : return GF_NOT_SUPPORTED;
412 : }
413 : if ((image->comps[0].w==2*image->comps[1].w)
414 : && (image->comps[1].w==image->comps[2].w)
415 : && (image->comps[0].h==2*image->comps[1].h)
416 : && (image->comps[1].h==image->comps[2].h)) {
417 : pf = GF_PIXEL_YUV;
418 : ctx->out_size = 3*ctx->width*ctx->height/2;
419 : changed = GF_TRUE;
420 : }
421 : if (ctx->pixel_format!=pf) {
422 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PIXFMT, &PROP_UINT(pf) );
423 : ctx->pixel_format = pf;
424 : changed = GF_TRUE;
425 : }
426 : if (ctx->width!=w) {
427 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_WIDTH, &PROP_UINT(w) );
428 : ctx->width = w;
429 : changed = GF_TRUE;
430 : }
431 : if (ctx->height!=h) {
432 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_HEIGHT, &PROP_UINT(h) );
433 : ctx->height = h;
434 : changed = GF_TRUE;
435 : }
436 : if (changed) {
437 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STRIDE, &PROP_UINT( (ctx->pixel_format == GF_PIXEL_YUV) ? ctx->width : ctx->width * ctx->nb_comp) );
438 : }
439 :
440 : #if OPENJP2
441 : opj_end_decompress(codec, stream);
442 : opj_stream_destroy(stream);
443 : stream = NULL;
444 : opj_destroy_codec(codec);
445 : codec = NULL;
446 : #else
447 : /* close the byte stream */
448 : opj_cio_close(cio);
449 : cio = NULL;
450 :
451 : /* gf_free( remaining structures */
452 : if(dinfo) {
453 : opj_destroy_decompress(dinfo);
454 : dinfo = NULL;
455 : }
456 : #endif
457 :
458 : pck_dst = gf_filter_pck_new_alloc(ctx->opid, ctx->out_size, &buffer);
459 : if (!pck_dst) return GF_OUT_OF_MEM;
460 :
461 : w = image->comps[0].w;
462 : wr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor);
463 : h = image->comps[0].h;
464 : hr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor);
465 : wh = wr*hr;
466 :
467 : if (ctx->nb_comp==1) {
468 : if ((w==wr) && (h==hr)) {
469 : for (i=0; i<wh; i++) {
470 : buffer[i] = image->comps[0].data[i];
471 : }
472 : } else {
473 : for (i=0; i<wh; i++) {
474 : buffer[i] = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
475 : }
476 : }
477 : }
478 : else if (ctx->nb_comp==3) {
479 :
480 : if ((image->comps[0].w==2*image->comps[1].w) && (image->comps[1].w==image->comps[2].w)
481 : && (image->comps[0].h==2*image->comps[1].h) && (image->comps[1].h==image->comps[2].h)) {
482 :
483 : if ((w==wr) && (h==hr)) {
484 : for (i=0; i<wh; i++) {
485 : *buffer = image->comps[0].data[i];
486 : buffer++;
487 : }
488 : // w = image->comps[1].w;
489 : wr = int_ceildivpow2(image->comps[1].w, image->comps[1].factor);
490 : // h = image->comps[1].h;
491 : hr = int_ceildivpow2(image->comps[1].h, image->comps[1].factor);
492 : wh = wr*hr;
493 : for (i=0; i<wh; i++) {
494 : *buffer = image->comps[1].data[i];
495 : buffer++;
496 : }
497 : for (i=0; i<wh; i++) {
498 : *buffer = image->comps[2].data[i];
499 : buffer++;
500 : }
501 : } else {
502 : for (i=0; i<wh; i++) {
503 : *buffer = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
504 : }
505 : w = image->comps[1].w;
506 : wr = int_ceildivpow2(image->comps[1].w, image->comps[1].factor);
507 : // h = image->comps[1].h;
508 : hr = int_ceildivpow2(image->comps[1].h, image->comps[1].factor);
509 : wh = wr*hr;
510 : for (i=0; i<wh; i++) {
511 : *buffer = image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
512 : }
513 : for (i=0; i<wh; i++) {
514 : *buffer = image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
515 : }
516 : }
517 :
518 :
519 : } else if ((image->comps[0].w==image->comps[1].w) && (image->comps[1].w==image->comps[2].w)
520 : && (image->comps[0].h==image->comps[1].h) && (image->comps[1].h==image->comps[2].h)) {
521 :
522 : if ((w==wr) && (h==hr)) {
523 : for (i=0; i<wh; i++) {
524 : u32 idx = 3*i;
525 : buffer[idx] = image->comps[0].data[i];
526 : buffer[idx+1] = image->comps[1].data[i];
527 : buffer[idx+2] = image->comps[2].data[i];
528 : }
529 : } else {
530 : for (i=0; i<wh; i++) {
531 : u32 idx = 3*i;
532 : buffer[idx] = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
533 : buffer[idx+1] = image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
534 : buffer[idx+2] = image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
535 : }
536 : }
537 : }
538 : }
539 : else if (ctx->nb_comp==4) {
540 : if ((image->comps[0].w==image->comps[1].w) && (image->comps[1].w==image->comps[2].w) && (image->comps[2].w==image->comps[3].w)
541 : && (image->comps[0].h==image->comps[1].h) && (image->comps[1].h==image->comps[2].h) && (image->comps[2].h==image->comps[3].h)) {
542 :
543 : if ((w==wr) && (h==hr)) {
544 : for (i=0; i<wh; i++) {
545 : u32 idx = 4*i;
546 : buffer[idx] = image->comps[0].data[i];
547 : buffer[idx+1] = image->comps[1].data[i];
548 : buffer[idx+2] = image->comps[2].data[i];
549 : buffer[idx+3] = image->comps[3].data[i];
550 : }
551 : } else {
552 : for (i=0; i<wh; i++) {
553 : u32 idx = 4*i;
554 : buffer[idx] = image->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
555 : buffer[idx+1] = image->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
556 : buffer[idx+2] = image->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
557 : buffer[idx+3] = image->comps[3].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
558 : }
559 : }
560 : }
561 : }
562 :
563 : opj_image_destroy(image);
564 : image = NULL;
565 :
566 : if (gf_filter_pck_get_seek_flag(pck)) {
567 : gf_filter_pck_discard(pck_dst);
568 : } else {
569 : gf_filter_pck_merge_properties(pck, pck_dst);
570 : gf_filter_pck_send(pck_dst);
571 : }
572 : gf_filter_pid_drop_packet(ctx->ipid);
573 : return GF_OK;
574 : }
575 :
576 : static GF_Err j2kdec_initialize(GF_Filter *filter)
577 : {
578 : #ifdef GPAC_ENABLE_COVERAGE
579 : if (gf_sys_is_cov_mode()) {
580 : error_callback(NULL, NULL);
581 : warning_callback(NULL, NULL);
582 : info_callback(NULL, NULL);
583 : #if OPENJP2
584 : j2kdec_stream_skip(0, NULL);
585 : #endif
586 : }
587 : #endif
588 : return GF_OK;
589 : }
590 :
591 : static const GF_FilterCapability J2KCaps[] =
592 : {
593 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
594 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_J2K),
595 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
596 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
597 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
598 : };
599 :
600 : GF_FilterRegister J2KRegister = {
601 : .name = "j2kdec",
602 : #ifdef OPENJPEG_VERSION
603 : .version = ""OPENJPEG_VERSION,
604 : #elif OPENJP2
605 : .version = "2.x",
606 : #else
607 : .version = "1.x",
608 : #endif
609 : GF_FS_SET_DESCRIPTION("OpenJPEG2000 decoder")
610 : GF_FS_SET_HELP("This filter decodes JPEG2000 streams through OpenJPEG2000 library.")
611 : .private_size = sizeof(GF_J2KCtx),
612 : .priority = 1,
613 : SETCAPS(J2KCaps),
614 : .initialize = j2kdec_initialize,
615 : .configure_pid = j2kdec_configure_pid,
616 : .process = j2kdec_process,
617 : };
618 :
619 : #endif
620 :
621 2877 : const GF_FilterRegister *j2kdec_register(GF_FilterSession *session)
622 : {
623 : #ifdef GPAC_HAS_JP2
624 : return &J2KRegister;
625 : #else
626 2877 : return NULL;
627 : #endif
628 : }
629 :
|