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