LCOV - code coverage report
Current view: top level - filters - dec_j2k.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 2 100.0 %
Date: 2021-04-29 23:48:07 Functions: 1 1 100.0 %

          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(&parameters);
     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, &parameters);
     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, &parameters);
     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             : 

Generated by: LCOV version 1.13