On Fri, Mar 15, 2013 at 03:35:14PM +0100, Nicolas Bertrand wrote:
> Based on 2007 GSOC project and code cleaning (Kamil Nowosad)
> 
> Diego Biurrun modifications :
>  - K&R formatting cosmetics
>  - Give all files a jpeg2000 prefix
>  - Use designated initializers
>  - Fix some doxygen comments
>  - Switch to jpeg2000 name prefix
>  - Wwarning fixes
>  - Remove broken and/or silly debug code
> 
> Nicolas Bertrand modifications :
>  - Modifications to handle JPEG2000 for digital cinema
>  -  Corrections on header markers: COD
>  - Addition of CPRL progression order
>  - Addition of tile-parts mgmt (TLM)
>  - Corrections on arithmetic decoder (T1)
>  - Corrections on inverse DWT and MCT
>  - Robustness corrections on tag tree init
>  - Replace of av_malloc by av_malloc_array
>  - Adittion of low res parameter
>  - Addition of jpeg2000 profiles
>  - Replace CODEC_ID by AV_CODEC_ID
>  - Convert to refcounted frames
> ---
>  Changelog                |    4 +
>  doc/general.texi         |    3 +-
>  libavcodec/Makefile      |    2 +
>  libavcodec/allcodecs.c   |    1 +
>  libavcodec/avcodec.h     |    6 +
>  libavcodec/jpeg2000.c    |  475 ++++++++++++++++++
>  libavcodec/jpeg2000.h    |  256 ++++++++++
>  libavcodec/jpeg2000dec.c | 1253 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/jpeg2000dwt.c |  250 +++++++++
>  libavcodec/jpeg2000dwt.h |   62 +++
>  libavcodec/mqc.c         |  111 ++++
>  libavcodec/mqc.h         |   61 +++
>  libavcodec/mqcdec.c      |   93 ++++
>  libavcodec/version.h     |    2 +-
>  libavformat/img2.c       |    1 +
>  15 files changed, 2577 insertions(+), 3 deletions(-)
>  create mode 100644 libavcodec/jpeg2000.c
>  create mode 100644 libavcodec/jpeg2000.h
>  create mode 100644 libavcodec/jpeg2000dec.c
>  create mode 100644 libavcodec/jpeg2000dwt.c
>  create mode 100644 libavcodec/jpeg2000dwt.h
>  create mode 100644 libavcodec/mqc.c
>  create mode 100644 libavcodec/mqc.h
>  create mode 100644 libavcodec/mqcdec.c
> 
> diff --git a/Changelog b/Changelog
> index 15c0873..d9438f0 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -7,9 +7,11 @@ version 10:
>  - reference-counting for AVFrame and AVPacket data
>  - avconv now fails when input options are used for output file
>    or vice versa
> +- JPEG 2000 decoder
>  
>  
>  version 9:
> +

unrequired change

>  - av_basename and av_dirname
>  - adobe and limelight publisher authentication in RTMP
>  - VDPAU hardware acceleration through normal hwaccel
> @@ -17,6 +19,7 @@ version 9:
>  
>  
>  version 9_beta3:
> +

ditto

>  - ashowinfo audio filter
>  - 24-bit FLAC encoding
>  - audio volume filter
> @@ -27,6 +30,7 @@ version 9_beta3:
>  
>  
>  version 9_beta2:
> +

ditto

>  - metadata (INFO tag) support in WAV muxer
>  - support for building DLLs using MSVC
>  - remove avserver daemon mode
> diff --git a/doc/general.texi b/doc/general.texi
> index 2345ef7..9991021 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -373,8 +373,7 @@ following image formats are supported:
>      @tab Digital Picture Exchange
>  @item JPEG         @tab X @tab X
>      @tab Progressive JPEG is not supported.
> -@item JPEG 2000    @tab E @tab E
> -    @tab decoding supported through external library libopenjpeg
> +@item JPEG 2000    @tab X @tab X

looks wrong for now - encoder is still libopenjpeg only, isn't it?

>  @item JPEG-LS      @tab X @tab X
>  @item LJPEG        @tab X @tab
>      @tab Lossless JPEG
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index addf5a5..68d84d0 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -206,6 +206,8 @@ OBJS-$(CONFIG_INDEO4_DECODER)          += indeo4.o 
> ivi_common.o ivi_dsp.o
>  OBJS-$(CONFIG_INDEO5_DECODER)          += indeo5.o ivi_common.o ivi_dsp.o
>  OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER)  += dpcm.o
>  OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
> +OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o      \
> +                                          jpeg2000dwt.o mqcdec.o mqc.o
>  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o \
>                                            mjpegdec.o mjpeg.o
>  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 8bfa603..45fea3a 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -160,6 +160,7 @@ void avcodec_register_all(void)
>      REGISTER_DECODER(INDEO4,            indeo4);
>      REGISTER_DECODER(INDEO5,            indeo5);
>      REGISTER_DECODER(INTERPLAY_VIDEO,   interplay_video);
> +    REGISTER_DECODER(JPEG2000,          jpeg2000);
>      REGISTER_ENCDEC (JPEGLS,            jpegls);
>      REGISTER_DECODER(JV,                jv);
>      REGISTER_DECODER(KGV1,              kgv1);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index f7d6553..31c7237 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2561,6 +2561,12 @@ typedef struct AVCodecContext {
>  #define FF_PROFILE_MPEG4_SIMPLE_STUDIO             14
>  #define FF_PROFILE_MPEG4_ADVANCED_SIMPLE           15
>  
> +#define FF_PROFILE_JPEG2000_CSTRM_RSTRCTN_0         0
> +#define FF_PROFILE_JPEG2000_CSTRM_RSTRCTN_1         1
> +#define FF_PROFILE_JPEG2000_CSTRM_NO_RSTRCTN        2

Are those official names or just written in Semithic way?
If the latter please use full word for "restriction(s) -
it's too long in any case.

> +#define FF_PROFILE_JPEG2000_DCINEMA_2K              3
> +#define FF_PROFILE_JPEG2000_DCINEMA_4K              4
> +
>      /**
>       * level
>       * - encoding: Set by user.
> diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
> new file mode 100644
> index 0000000..17aa82d
> --- /dev/null
> +++ b/libavcodec/jpeg2000.c
[...]
> +int ff_jpeg2000_init_component(Jpeg2000Component *comp,
> +                               Jpeg2000CodingStyle *codsty,
> +                               Jpeg2000QuantStyle *qntsty,
> +                               int cbps, int dx, int dy, AVCodecContext *ctx)
> +{
> +    uint8_t log2_band_prec_width,log2_band_prec_height;
> +    int reslevelno, bandno, gbandno = 0, ret, i, j; 
> +    uint32_t csize = 1;
> +
> +    if (ret = ff_jpeg2000_dwt_init(&comp->dwt, comp->coord, 
> codsty->nreslevels2decode - 1,
> +                                   codsty->transform))
> +        return ret;
> +    // component size comp->coord is uint16_t so ir cannot overflow
> +    csize = (comp->coord[0][1] - comp->coord[0][0]) *
> +            (comp->coord[1][1] - comp->coord[1][0]);
> +    
> +    comp->data = av_malloc_array(csize, sizeof(*comp->data));
> +    
> +    if (!comp->data)
> +        return AVERROR(ENOMEM);
> +    comp->reslevel = av_malloc_array(codsty->nreslevels, 
> sizeof(*comp->reslevel));
> +    if (!comp->reslevel)
> +        return AVERROR(ENOMEM);
> +    /* LOOP on resolution levels */
> +    for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
> +        int declvl = codsty->nreslevels - reslevelno;    // N_L -r see  
> ISO/IEC 15444-1:2002 B.5
> +        Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
> +
> +        /* compute borders for each resolution levels
> +         * Computation of trx_0, trx_1, try_0 and try_1 see  ISO/IEC 
> 15444-1:2002 eB.5 q.  B-14 */
> +        for (i = 0; i < 2; i++)
> +            for (j = 0; j < 2; j++)
> +                reslevel->coord[i][j] = 
> ff_jpeg2000_ceildivpow2(comp->coord_o[i][j],
> +                                                                declvl - 1);
> +        // update precincts size: 2^n value
> +        reslevel->log2_prec_width  = codsty->log2_prec_widths[reslevelno];
> +        reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno];
> +
> +        /* Number of bands for each resolution level */
> +        if (reslevelno == 0)
> +            reslevel->nbands = 1;
> +        else
> +            reslevel->nbands = 3;
> +
> +        /* Number of precincts wich span the tile for resolution level 
> reslevelno
> +         * see B.6 in ISO/IEC 15444-1:2002 eq. B-16
> +         * num_precincts_x = |- trx_1 / 2^log2_prec_width) -| - (trx_0 / 
> 2^log2_prec_width)
> +         * num_precincts_y = |- try_1 / 2^log2_prec_width) -| - (try_0 / 
> 2^log2_prec_width)
> +         * for jp2K
> +         * num_precincts_x = |- trx_1 / 2^log2_prec_width) -|
> +         * num_precincts_y = |- try_1 / 2^log2_prec_width) -|
> +         * */
> +        if (reslevel->coord[0][1] == reslevel->coord[0][0])
> +            reslevel->num_precincts_x = 0;
> +        else
> +            reslevel->num_precincts_x = 
> ff_jpeg2000_ceildivpow2(reslevel->coord[0][1], reslevel->log2_prec_width)
> +                                             - (reslevel->coord[0][0] >> 
> reslevel->log2_prec_width);
> +
> +        if (reslevel->coord[1][1] == reslevel->coord[1][0])
> +            reslevel->num_precincts_y = 0;
> +        else
> +            reslevel->num_precincts_y = 
> ff_jpeg2000_ceildivpow2(reslevel->coord[1][1], reslevel->log2_prec_height)
> +                                            - (reslevel->coord[1][0] >> 
> reslevel->log2_prec_height);
> +
> +        /* Memory allocation for each band
> +         * TODO: Verify allocation and free

ahem

> +         */
> +        reslevel->band = av_malloc_array(reslevel->nbands, 
> sizeof(*reslevel->band));
> +        if (!reslevel->band)
> +            return AVERROR(ENOMEM);
> +
> +        /* LOOP on bands */

USELESS comment

> +        for (bandno = 0; bandno < reslevel->nbands; bandno++, gbandno++) {
> +            Jpeg2000Band *band = reslevel->band + bandno;
> +            int cblkno, precno;
> +            int nb_precincts;
> +
> +            /* TODO ; implementation of quantization step not finished
> +             * see ISO/IEC 15444-1:2002 §E.1 and §A.6.4
> +             *
> +             */
> +            switch (qntsty->quantsty) {
> +            uint8_t gain;
> +#if 0
> +            case JPEG2000_QSTY_NONE:
> +                const static uint8_t lut_gain[2][4] = { { 0, 0, 0, 0 }, { 0, 
> 1, 1, 2 } };
> +                int numbps;
> +                /* TODO: to verify. No quantisation in this case*/
> +                numbps = cbps + lut_gain[codsty->transform][bandno + 
> reslevelno > 0];
> +                band->stepsize = (float)(SHL(2048 + qntsty->mant[gbandno],
> +                                     2 + numbps - qntsty->expn[gbandno]));
> +
> +                break;
> +#endif

either enable it and hope for the best or drop it
Or do something else but having such commented out code is not good.

> +            case JPEG2000_QSTY_SI:
> +                /*TODO: compute formula to implement */
> +                band->stepsize = (float) (1 << 13);
> +                break;
> +            case JPEG2000_QSTY_SE:
> +               /* Scalar expounded.

According to the Oxford dictionary it means
"scalar [value] presented and explained (a theory or idea) in detail".

Was that the intended meaning?

> +                * Formula:
> +                * delta_b = 2^(R_b - expn_b) * (1 + (mant_b/2^11))
> +                * R_b = R_I + log2 (gain_b )
> +                * see  ISO/IEC 15444-1:2002 §E.1.1 eqn. E-3 and E-4
> +                */
> +                /* TODO/WARN: value of log2 (gain_b ) not taken into account
> +                 * but it works (compared to  opj). Why?
> +                 * Further investigation needed.
> +                  */
> +                gain = cbps;
> +                band->stepsize  = pow(2.0, gain - qntsty->expn[gbandno]);
> +                band->stepsize *= (1.0 + (((float)qntsty->mant[gbandno]) / 
> 2048.0));
> +               break;
> +
> +            default:
> +                band->stepsize = 0;
> +                av_log(ctx, AV_LOG_ERROR, "Unknown quantization format\n");
> +                break;
> +            }
> +
> +             /* computation of tbx_0, tbx_1, tby_0, tby_1
> +              * see  ISO/IEC 15444-1:2002 B.5 eq. B-15  and tbl B.1
> +              * codeblock width and height is computed
> +              * for DCI JP2K  codeblock_width = codeblock_width = 32 = 2^5
> +              */
> +            if (reslevelno == 0) {
> +              /* for reslevelno = 0, only one band, x0_b = y0_b = 0 */

indentation here and above is weird

> +               for (i = 0; i < 2; i++)
> +                   for (j = 0; j < 2; j++)
> +                       band->coord[i][j] = 
> ff_jpeg2000_ceildivpow2(comp->coord_o[i][j],
> +                                                                    declvl - 
> 1);
> +
> +                log2_band_prec_width  = reslevel->log2_prec_width;
> +                log2_band_prec_height = reslevel->log2_prec_height;
> +                /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */
> +                band->log2_cblk_width  = FFMIN(codsty->log2_cblk_width, 
> reslevel->log2_prec_width);
> +                band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, 
> reslevel->log2_prec_height);
> +
> +            } else {
> +                /* 3 bands  x0_b = 1 y0_b = 0; x0_b = 0 y0_b = 1; x0_b = 
> y0_b = 1  */
> +                /* x0_b and y0_b are computed with ((bandno + 1 >> i) & 1) */
> +                for (i = 0; i < 2; i++)
> +                    for (j = 0; j < 2; j++)
> +                        /* Formula example for tbx_0 = ceildiv( (tcx_0 - 
> 2^(declvl-1)*x0_b) /  declvl) */
> +                        band->coord[i][j] = 
> ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - (((bandno + 1 >> i) & 1) << 
> declvl - 1),
> +                                                                    declvl);
> +               /* TODO: manage case of 3 band offsets here or in 
> coding/decoding function? */
> +
> +                /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */
> +                band->log2_cblk_width  = FFMIN(codsty->log2_cblk_width, 
> reslevel->log2_prec_width - 1);
> +                band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, 
> reslevel->log2_prec_height - 1);
> +
> +                log2_band_prec_width = reslevel->log2_prec_width - 1;
> +                log2_band_prec_height = reslevel->log2_prec_height - 1;
> +            }
> +
> +            /* Memory allocation of precincts
> +             * TODO: verify free of precincts malloc
> +             */
> +            band->prec = av_malloc_array(reslevel->num_precincts_x * 
> reslevel->num_precincts_y,
> +                                         sizeof(*band->prec));
> +            if (!band->prec)
> +                return AVERROR(ENOMEM);
> +
> +            /* LOOP on precincts */

useless comment again

> +            nb_precincts = reslevel->num_precincts_x * 
> reslevel->num_precincts_y;
> +
> +            for (precno = 0; precno < nb_precincts; precno++){
> +                Jpeg2000Prec *prec = band->prec + precno;
> +
> +                /* TODO: explain formula for JPEG200 DCINEMA */
> +                /* TODO: verify with previous count of codeblocks per band */
> +                /* Compute P_x0 */
> +                prec->coord[0][0] = (precno % reslevel->num_precincts_x) * 
> (1 << log2_band_prec_width);
> +
> +                // TODO: Not useful for DCinema jp2k: band->coord[0][0] 
> always 0
> +                prec->coord[0][0] = FFMAX(prec->coord[0][0], 
> band->coord[0][0]);
> +
> +                /* Compute P_y0 */
> +                prec->coord[1][0] = (precno / reslevel->num_precincts_x) * 
> (1 << log2_band_prec_height);
> +
> +                // TODO:Not useful for DCinema jp2k: band->coord[1][0] 
> always 0

well, we hope to have other uses for this decoder besides DCinema, so the
comment is useless

> +                prec->coord[1][0] = FFMAX(prec->coord[1][0], 
> band->coord[1][0]);
> +
> +                /* Compute P_x1 */
> +                prec->coord[0][1] = prec->coord[0][0] + (1 << 
> log2_band_prec_width);
> +                prec->coord[0][1] = FFMIN(prec->coord[0][1], 
> band->coord[0][1]);
> +
> +                /* Compute P_y1 */
> +                prec->coord[1][1] = prec->coord[1][0] + (1 << 
> log2_band_prec_height);
> +                prec->coord[1][1] = FFMIN(prec->coord[1][1], 
> band->coord[1][1]);
> +
> +                prec->nb_codeblocks_width  = 
> ff_jpeg2000_ceildivpow2(prec->coord[0][1] - prec->coord[0][0],
> +                                                                     
> band->log2_cblk_width);
> +                prec->nb_codeblocks_height = 
> ff_jpeg2000_ceildivpow2(prec->coord[1][1] - prec->coord[1][0],
> +                                                                     
> band->log2_cblk_height);
> +
> +                /* Tag trees initialization */
> +                prec->cblkincl = 
> ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width ,
> +                                                           
> prec->nb_codeblocks_height);
> +                if (!prec->cblkincl)
> +                    return AVERROR(ENOMEM);
> +                
> +                prec->zerobits = 
> ff_jpeg2000_tag_tree_init(prec->nb_codeblocks_width ,
> +                                                           
> prec->nb_codeblocks_height);
> +                if (!prec->zerobits)
> +                    return AVERROR(ENOMEM);
> +                
> +                /* Memory allocation of codeblocks
> +                 */
> +                prec->cblk = av_malloc_array(prec->nb_codeblocks_width * 
> prec->nb_codeblocks_height,
> +                                             sizeof(*prec->cblk));
> +                if (!prec->cblk)
> +                    return AVERROR(ENOMEM);
> +                for (cblkno = 0; cblkno < prec->nb_codeblocks_width * 
> prec->nb_codeblocks_height; cblkno++) {
> +                   Jpeg2000Cblk *cblk = prec->cblk + cblkno;
> +                   uint16_t Cx0, Cy0;
> +                   /*Compute coordinates of codeblocks */
> +
> +                   /* Compute Cx0*/
> +                   Cx0 = (prec->coord[0][0] >> band->log2_cblk_width) <<  
> band->log2_cblk_width;
> +                   Cx0 = Cx0 + ((cblkno % prec->nb_codeblocks_width) << 
> band->log2_cblk_width);
> +                   cblk->coord[0][0] = FFMAX(Cx0, prec->coord[0][0]);
> +
> +                   /* Compute Cy0*/
> +                   Cy0 = (prec->coord[1][0] >> band->log2_cblk_height) <<  
> band->log2_cblk_height;
> +                   Cy0 = Cy0 + ((cblkno / prec->nb_codeblocks_width) << 
> band->log2_cblk_height);
> +                   cblk->coord[1][0] = FFMAX(Cy0, prec->coord[1][0]);
> +
> +                   /* Compute Cx1 */
> +                   cblk->coord[0][1] = FFMIN(Cx0 + (1 << 
> band->log2_cblk_width), prec->coord[0][1]);
> +
> +                   /* Compute Cy1 */
> +                   cblk->coord[1][1] = FFMIN(Cy0 + (1 << 
> band->log2_cblk_height), prec->coord[1][1]);
> +                   cblk->zero      = 0;
> +                   cblk->lblock    = 3;
> +                   cblk->length    = 0;
> +                   cblk->lengthinc = 0;
> +                   cblk->npasses   = 0;
> +               }
> +            }
> +        }
> +    }
> +    return 0;
> +}
> +
> +void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle 
> *codsty)
> +{
> +    int reslevelno, bandno, precno;
> +    for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
> +        Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;
> +
> +        for (bandno = 0; bandno < reslevel->nbands; bandno++) {
> +            Jpeg2000Band *band = reslevel->band + bandno;
> +            for (precno = 0; precno < reslevel->num_precincts_x * 
> reslevel->num_precincts_y; precno++) {
> +                Jpeg2000Prec *prec = band->prec + precno;
> +                av_freep(&prec->zerobits);
> +                av_freep(&prec->cblkincl);
> +                av_freep(&prec->cblk);
> +            }
> +
> +            av_freep(&band->prec);
> +        }
> +        av_freep(&reslevel->band);
> +    }
> +
> +    ff_dwt_destroy(&comp->dwt);
> +    av_freep(&comp->reslevel);
> +    av_freep(&comp->data);
> +}
> diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
> new file mode 100644
> index 0000000..26379a6
> --- /dev/null
> +++ b/libavcodec/jpeg2000.h
> @@ -0,0 +1,256 @@
> +/*
> + * JPEG 2000 tables

misleading description

> + * Copyright (c) 2007 Kamil Nowosad
> + * Copyright (c) 2013 Nicolas Bertrand <[email protected]>
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#ifndef AVCODEC_JPEG2000_H
> +#define AVCODEC_JPEG2000_H
> +
> +/**
> + * @file
> + * JPEG 2000 structures and defines common
> + * to encoder and decoder
> + */
> +
[...]

> diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
> new file mode 100644
> index 0000000..4280e11
> --- /dev/null
> +++ b/libavcodec/jpeg2000dec.c
> @@ -0,0 +1,1253 @@
> +/*
> + * JPEG 2000 image decoder
> + * Copyright (c) 2007 Kamil Nowosad
> + * Copyright (c) 2013 Nicolas Bertrand <[email protected]>
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/**
> + * @file
> + * JPEG 2000 image decoder
> + */
> +
> +#include "libavutil/common.h"
> +#include "libavutil/opt.h"
> +#include "avcodec.h"
> +#include "bytestream.h"
> +#include "internal.h"
> +#include "jpeg2000.h"
> +
> +#define JP2_SIG_TYPE    0x6A502020
> +#define JP2_SIG_VALUE   0x0D0A870A
> +#define JP2_CODESTREAM  0x6A703263
> +
> +#define HAD_COC 0x01
> +#define HAD_QCC 0x02
> +
> +typedef struct Jpeg2000TilePart {
> +    uint16_t tp_idx;                    // Tile-part index
> +    uint8_t  tile_index;                // Tile index who refers the 
> tile-part
> +    uint32_t tp_len;                    // Length of tile-part
> +    const uint8_t  *tp_start_bstrm;    // Start address bit stream in 
> tile-part
> +    const uint8_t  *tp_end_bstrm;      // End address of the bit stream tile 
> part
> +} Jpeg2000TilePart;
> +
> +
> +/* RMK : for JPEG2000 DCINEMA 3 tile-parts in a tile
> + * one per component, so tile_part element have a size of 3
> + */
> +typedef struct Jpeg2000Tile {
> +    Jpeg2000Component   *comp;
> +    uint8_t             properties[4];
> +    Jpeg2000CodingStyle codsty[4];
> +    Jpeg2000QuantStyle  qntsty[4];
> +    Jpeg2000TilePart    tile_part[3];
> +} Jpeg2000Tile;
> +
> +
> +

nit: too many empty lines

> +typedef struct Jpeg2000DecoderContext {
> +    AVClass         *class;
> +    AVCodecContext  *avctx;
> +
> +    int             width, height;
> +    int             image_offset_x, image_offset_y;
> +    int             tile_offset_x, tile_offset_y;
> +    uint8_t         cbps[4];    // bits per sample in particular components
> +    uint8_t         sgnd[4];    // if a component is signed
> +    uint8_t         properties[4];
> +    int             cdx[4], cdy[4];
> +    int             precision;
> +    int             ncomponents;
> +    int             tile_width, tile_height;
> +    int             numXtiles, numYtiles;
> +    int             maxtilelen;
> +
> +    Jpeg2000CodingStyle codsty[4];
> +    Jpeg2000QuantStyle  qntsty[4];
> +
> +    const uint8_t   *buf_start;
> +    const uint8_t   *buf;
> +    const uint8_t   *buf_end;
> +    int             bit_index;
> +
> +    int16_t         curtileno;
> +    Jpeg2000Tile    *tile;
> +
> +    /*options parameters*/
> +    int16_t         lowres;
> +    int16_t         reduction_factor;
> +} Jpeg2000DecoderContext;
> +
> +/*
> + * get_bits functions for JPEG2000 packets bitsteam
> + * Is a get_bit function with a bit stuffing routine
> + * if the value of the byte is 0xFF, the next byte includes an extra zero bit
> + * stuffed into the MSB
> + * cf. ISO-15444-1:2002 / B.10.1 Bit-stuffing routine
> + */
> +static int get_bits(Jpeg2000DecoderContext *s, int n)
> +{
> +    int res = 0;
> +    if (s->buf_end - s->buf < ((n - s->bit_index) >> 8))
> +        return AVERROR(EINVAL);
> +    while (--n >= 0) {
> +        res <<= 1;
> +        if (s->bit_index == 0) {
> +            s->bit_index = 7 + (*s->buf != 0xff);
> +            s->buf++;
> +        }
> +        s->bit_index--;
> +        res |= (*s->buf >> s->bit_index) & 1;
> +    }
> +    return res;
> +}

I still think it would be better to do like in JPEG-1992 (unescape buffer and
use standard bitreader) but that's me. This one looks extremely ineffective.

> +
> +static void jpeg2000_flush(Jpeg2000DecoderContext *s)
> +{
> +    if (*s->buf == 0xff)
> +        s->buf++;
> +    s->bit_index = 8;
> +    s->buf++;
> +}
> +
> +/* decode the value stored in node */
> +static int tag_tree_decode(Jpeg2000DecoderContext *s, Jpeg2000TgtNode *node,
> +                           int threshold)
> +{
> +    Jpeg2000TgtNode *stack[30];
> +    int sp = -1, curval = 0;
> +
> +    while (node && !node->vis) {
> +        stack[++sp] = node;
> +        node = node->parent;
> +    }
> +
> +    if (node)
> +        curval = node->val;
> +    else
> +        curval = stack[sp]->val;
> +
> +    while (curval < threshold && sp >= 0) {
> +        if (curval < stack[sp]->val)
> +            curval = stack[sp]->val;
> +        while (curval < threshold) {
> +            int ret;
> +            if ((ret = get_bits(s, 1)) > 0) {
> +                stack[sp]->vis++;
> +                break;
> +            } else if (!ret)
> +                curval++;
> +            else
> +                return ret;
> +        }
> +        stack[sp]->val = curval;
> +        sp--;
> +    }
> +    return curval;
> +}
> +
> +/* marker segments */
> +/* get sizes and offsets of image, tiles; number of components */
> +static int get_siz(Jpeg2000DecoderContext *s)
> +{
> +    int i, ret;
> +
> +    if (s->buf_end - s->buf < 36)
> +        return AVERROR(EINVAL);
> +
> +    s->avctx->profile = bytestream_get_be16(&s->buf); // Rsiz
> +    s->width  = bytestream_get_be32(&s->buf);         // width
> +    s->height = bytestream_get_be32(&s->buf);         // height
> +    s->image_offset_x = bytestream_get_be32(&s->buf); // X0Siz
> +    s->image_offset_y = bytestream_get_be32(&s->buf); // Y0Siz
> +
> +    s->tile_width    = bytestream_get_be32(&s->buf);  // XTSiz
> +    s->tile_height   = bytestream_get_be32(&s->buf);  // YTSiz
> +    s->tile_offset_x = bytestream_get_be32(&s->buf);  // XT0Siz
> +    s->tile_offset_y = bytestream_get_be32(&s->buf);  // YT0Siz
> +    s->ncomponents   = bytestream_get_be16(&s->buf);  // CSiz
> +
> +    if (s->buf_end - s->buf < 2 * s->ncomponents)
> +        return AVERROR(EINVAL);
> +
> +    for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i
> +        uint8_t x = bytestream_get_byte(&s->buf);
> +        s->cbps[i]   = (x & 0x7f) + 1;
> +        s->precision = FFMAX(s->cbps[i], s->precision);
> +        s->sgnd[i]   = (x & 0x80) == 1;
> +        s->cdx[i]    = bytestream_get_byte(&s->buf);
> +        s->cdy[i]    = bytestream_get_byte(&s->buf);
> +    }
> +
> +    s->numXtiles = ff_jpeg2000_ceildiv(s->width  - s->tile_offset_x, 
> s->tile_width);
> +    s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, 
> s->tile_height);
> +
> +    s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(*s->tile));
> +    if (!s->tile)
> +        return AVERROR(ENOMEM);
> +
> +    for (i = 0; i < s->numXtiles * s->numYtiles; i++) {
> +        Jpeg2000Tile *tile = s->tile + i;
> +
> +        tile->comp = av_mallocz(s->ncomponents * sizeof(*tile->comp));
> +        if (!tile->comp)
> +            return AVERROR(ENOMEM);
> +    }
> +
> +    /* compute image size with reduction factor */
> +    s->avctx->width  = ff_jpeg2000_ceildivpow2(s->width  - s->image_offset_x,
> +                                               s->reduction_factor);
> +    s->avctx->height = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y,
> +                                               s->reduction_factor);
> +
> +    switch (s->ncomponents) {
> +    case 1:
> +        if (s->precision > 8)
> +            s->avctx->pix_fmt = PIX_FMT_GRAY16;
> +        else
> +            s->avctx->pix_fmt = PIX_FMT_GRAY8;
> +        break;
> +    case 3:
> +        if (s->precision > 8)
> +            s->avctx->pix_fmt = PIX_FMT_RGB48;
> +        else
> +            s->avctx->pix_fmt = PIX_FMT_RGB24;
> +        break;
> +    case 4:
> +        s->avctx->pix_fmt = PIX_FMT_BGRA;
> +        break;
> +    }
> +
> +    // FIXME NBD deBUG
> +    s->avctx->pix_fmt = AV_PIX_FMT_XYZ12LE;

can't you set that depending on profile and such?

> +
> +    return 0;
> +}
> +

[...]

> +static void cleanup(Jpeg2000DecoderContext *s)
> +{
> +    int tileno, compno;
> +    for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) {
> +        for (compno = 0; compno < s->ncomponents; compno++) {
> +            Jpeg2000Component *comp     = s->tile[tileno].comp   + compno;
> +            Jpeg2000CodingStyle *codsty = s->tile[tileno].codsty + compno;
> +
> +            ff_jpeg2000_cleanup(comp, codsty);
> +        }
> +        av_freep(&s->tile[tileno].comp);
> +    }
> +    av_freep(&s->tile);
> +}

nit: too generic function name, ask Diego for better suggestions

[...]
> +#define OFFSET(x) offsetof(Jpeg2000DecoderContext, x)
> +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
> +
> +static const AVOption options[] = {
> +    { "lowres",  "Lower the decoding resolution by a power of two", 
> OFFSET(lowres),  AV_OPT_TYPE_INT, { .i64 = 4 }, 0, INT_MAX, VD },

Why such default value? And why sky is the limit?
I'd expect it to have default 0 and maximum 32 (max number of DWT
decomposition levels - because it's the thing that makes lowres possible).

> +    { NULL },
> +};
> +
> +static const AVClass class = {
> +    .class_name = "jpeg2000",
> +    .item_name  = av_default_item_name,
> +    .option     = options,
> +    .version    = LIBAVUTIL_VERSION_INT,
> +};
> +
> +
> +AVCodec ff_jpeg2000_decoder = {
> +    .name           = "jpeg2000",
> +    .long_name      = NULL_IF_CONFIG_SMALL("JPEG 2000"),
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_JPEG2000,
> +    .priv_data_size = sizeof(Jpeg2000DecoderContext),
> +    .decode         = jpeg2000_decode_frame,
> +    .priv_class       = &class,
> +    .pix_fmts       = (enum PixelFormat[]) { PIX_FMT_XYZ12, PIX_FMT_GRAY8, 
> -1 }
> +};
[...]
> diff --git a/libavcodec/mqc.c b/libavcodec/mqc.c
> new file mode 100644
> index 0000000..2ac7f87
> --- /dev/null
> +++ b/libavcodec/mqc.c
> @@ -0,0 +1,111 @@
> +/*
> + * MQ-coder encoder and decoder common functions
> + * Copyright (c) 2007 Kamil Nowosad
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/**
> + * MQ-coder ecoder and decoder common functions

typo

> + * @file
> + * @author Kamil Nowosad
> + */
> +
> +#include <string.h>
> +#include <stdint.h>
> +
> +#include "mqc.h"
> +
> +typedef struct {
> +        uint16_t qe;
> +        uint8_t  nmps;
> +        uint8_t  nlps;
> +        uint8_t  sw;
> +} MqcCxState;

weird indentation

> +
> +const static MqcCxState cx_states[47] = {
> +    {0x5601,  1,  1, 1},
> +    {0x3401,  2,  6, 0},
> +    {0x1801,  3,  9, 0},
> +    {0x0AC1,  4, 12, 0},
> +    {0x0521,  5, 29, 0},
> +    {0x0221, 38, 33, 0},
> +    {0x5601,  7,  6, 1},
> +    {0x5401,  8, 14, 0},
> +    {0x4801,  9, 14, 0},
> +    {0x3801, 10, 14, 0},
> +    {0x3001, 11, 17, 0},
> +    {0x2401, 12, 18, 0},
> +    {0x1C01, 13, 20, 0},
> +    {0x1601, 29, 21, 0},
> +    {0x5601, 15, 14, 1},
> +    {0x5401, 16, 14, 0},
> +    {0x5101, 17, 15, 0},
> +    {0x4801, 18, 16, 0},
> +    {0x3801, 19, 17, 0},
> +    {0x3401, 20, 18, 0},
> +    {0x3001, 21, 19, 0},
> +    {0x2801, 22, 19, 0},
> +    {0x2401, 23, 20, 0},
> +    {0x2201, 24, 21, 0},
> +    {0x1C01, 25, 22, 0},
> +    {0x1801, 26, 23, 0},
> +    {0x1601, 27, 24, 0},
> +    {0x1401, 28, 25, 0},
> +    {0x1201, 29, 26, 0},
> +    {0x1101, 30, 27, 0},
> +    {0x0AC1, 31, 28, 0},
> +    {0x09C1, 32, 29, 0},
> +    {0x08A1, 33, 30, 0},
> +    {0x0521, 34, 31, 0},
> +    {0x0441, 35, 32, 0},
> +    {0x02A1, 36, 33, 0},
> +    {0x0221, 37, 34, 0},
> +    {0x0141, 38, 35, 0},
> +    {0x0111, 39, 36, 0},
> +    {0x0085, 40, 37, 0},
> +    {0x0049, 41, 38, 0},
> +    {0x0025, 42, 39, 0},
> +    {0x0015, 43, 40, 0},
> +    {0x0009, 44, 41, 0},
> +    {0x0005, 45, 42, 0},
> +    {0x0001, 45, 43, 0},
> +    {0x5601, 46, 46, 0}
> +};
> +
> +uint16_t ff_mqc_qe [2*47];
> +uint8_t ff_mqc_nlps[2*47];
> +uint8_t ff_mqc_nmps[2*47];
> +
> +void ff_mqc_init_contexts(MqcState *mqc)
> +{
> +    int i;
> +    memset(mqc->cx_states, 0, sizeof(mqc->cx_states));
> +    mqc->cx_states[MQC_CX_UNI] = 2 * 46;
> +    mqc->cx_states[MQC_CX_RL] = 2 * 3;
> +    mqc->cx_states[0] = 2 * 4;
> +
> +    for (i = 0; i < 47; i++){
> +        ff_mqc_qe[2*i  ] =
> +        ff_mqc_qe[2*i+1] = cx_states[i].qe;
> +
> +        ff_mqc_nlps[2*i  ] = 2*cx_states[i].nlps + cx_states[i].sw;
> +        ff_mqc_nlps[2*i+1] = 2*cx_states[i].nlps + 1 - cx_states[i].sw;
> +        ff_mqc_nmps[2*i  ] = 2*cx_states[i].nmps;
> +        ff_mqc_nmps[2*i+1] = 2*cx_states[i].nmps + 1;

this file lacks Diego's care

> +    }
> +}
> diff --git a/libavcodec/mqc.h b/libavcodec/mqc.h
> new file mode 100644
> index 0000000..206d35c
> --- /dev/null
> +++ b/libavcodec/mqc.h
> @@ -0,0 +1,61 @@
> +/*
> + * MQ-coder
> + * Copyright (c) 2007 Kamil Nowosad
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#ifndef AVCODEC_MQC_H
> +#define AVCODEC_MQC_H
> +
> +/**
> + * MQ-coder
> + * @file
> + * @author Kamil Nowosad
> + */
> +
> +#include "avcodec.h"
> +
> +#define MQC_CX_UNI 17
> +#define MQC_CX_RL  18
> +
> +extern uint16_t  ff_mqc_qe[2*47];
> +extern uint8_t ff_mqc_nlps[2*47];
> +extern uint8_t ff_mqc_nmps[2*47];
> +
> +typedef struct {
> +    uint8_t *bp, *bpstart;
> +    unsigned int a;
> +    unsigned int c;
> +    unsigned int ct;
> +    uint8_t cx_states[19];
> +} MqcState;
> +
> +/* decoder */
> +
> +/** initialize the decoder */
> +void ff_mqc_initdec(MqcState *mqc, uint8_t *bp);
> +
> +/** returns decoded bit with context cx */
> +int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate);
> +
> +/* common */
> +
> +/** initialize the contexts */
> +void ff_mqc_init_contexts(MqcState *mqc);
> +
> +#endif /* AVCODEC_MQC_H */
> diff --git a/libavcodec/mqcdec.c b/libavcodec/mqcdec.c
> new file mode 100644
> index 0000000..801e149
> --- /dev/null
> +++ b/libavcodec/mqcdec.c
> @@ -0,0 +1,93 @@
> +/*
> + * MQ-coder decoder
> + * Copyright (c) 2007 Kamil Nowosad
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/**
> + * MQ-coder decoder
> + * @file
> + * @author Kamil Nowosad
> + */
> +
> +#include "mqc.h"
> +
> +static void bytein(MqcState *mqc)
> +{
> +    if (*mqc->bp == 0xff){
> +        if (*(mqc->bp+1) > 0x8f)
> +            mqc->c++;
> +        else{
> +            mqc->bp++;
> +            mqc->c += 2 + 0xfe00 - (*mqc->bp << 9);
> +        }
> +    } else{
> +        mqc->bp++;
> +        mqc->c += 1 + 0xff00 - (*mqc->bp << 8);
> +    }
> +}

another case where pre-escaping buffer would help

> +
> +static int exchange(MqcState *mqc, uint8_t *cxstate, int lps)
> +{
> +    int d;
> +    if ((mqc->a < ff_mqc_qe[*cxstate]) ^ (!lps)){
> +        if (lps)
> +            mqc->a = ff_mqc_qe[*cxstate];
> +        d = *cxstate & 1;
> +        *cxstate = ff_mqc_nmps[*cxstate];
> +    } else{
> +        if (lps)
> +            mqc->a = ff_mqc_qe[*cxstate];
> +        d = 1 - (*cxstate & 1);
> +        *cxstate = ff_mqc_nlps[*cxstate];
> +    }
> +    // renormd:
> +    do{
> +        if (!(mqc->c & 0xff)){
> +            mqc->c -= 0x100;
> +            bytein(mqc);
> +        }
> +        mqc->a += mqc->a;
> +        mqc->c += mqc->c;
> +    } while (!(mqc->a & 0x8000));
> +    return d;
> +}
> +
> +void ff_mqc_initdec(MqcState *mqc, uint8_t *bp)
> +{
> +    ff_mqc_init_contexts(mqc);
> +    mqc->bp = bp;
> +    mqc->c = (*mqc->bp ^ 0xff) << 16;
> +    bytein(mqc);
> +    mqc->c = mqc->c << 7;
> +    mqc->a = 0x8000;
> +}
> +
> +int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate)
> +{
> +    mqc->a -= ff_mqc_qe[*cxstate];
> +    if ((mqc->c >> 16) < mqc->a){
> +        if (mqc->a & 0x8000)
> +            return *cxstate & 1;
> +        else
> +            return exchange(mqc, cxstate, 0);
> +    } else {
> +        mqc->c -= mqc->a << 16;
> +        return exchange(mqc, cxstate, 1);
> +    }
> +}
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 8b4fbce..394bf1a 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -27,7 +27,7 @@
>   */
>  
>  #define LIBAVCODEC_VERSION_MAJOR 55
> -#define LIBAVCODEC_VERSION_MINOR  0
> +#define LIBAVCODEC_VERSION_MINOR  1
>  #define LIBAVCODEC_VERSION_MICRO  0
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
> diff --git a/libavformat/img2.c b/libavformat/img2.c
> index 6ee8f81..23176d2 100644
> --- a/libavformat/img2.c
> +++ b/libavformat/img2.c
> @@ -62,6 +62,7 @@ static const IdStrMap img_tags[] = {
>      { AV_CODEC_ID_SUNRAST,    "sunras"   },
>      { AV_CODEC_ID_JPEG2000,   "jp2"      },
>      { AV_CODEC_ID_JPEG2000,   "jpc"      },
> +    { AV_CODEC_ID_JPEG2000,   "j2k"      },
>      { AV_CODEC_ID_DPX,        "dpx"      },
>      { AV_CODEC_ID_PICTOR,     "pic"      },
>      { AV_CODEC_ID_XBM,        "xbm"      },
> -- 

At least there are no major faults spotted...
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to