j2k/jpeg2000: merge lowres code

This also fixes lowres use with ffplay

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
pull/23/head
Michael Niedermayer 12 years ago
parent 840ee5e1a1
commit 8cf57efdd7
  1. 8
      libavcodec/j2k.c
  2. 4
      libavcodec/j2k.h
  3. 57
      libavcodec/j2kdec.c
  4. 11
      libavcodec/j2kenc.c
  5. 11
      libavcodec/jpeg2000dec.c

@ -184,7 +184,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
uint8_t log2_band_prec_width, log2_band_prec_height; uint8_t log2_band_prec_width, log2_band_prec_height;
int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1; int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1;
if (ret=ff_jpeg2000_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels-1, codsty->transform == FF_DWT53 ? FF_DWT53 : FF_DWT97_INT)) if (ret=ff_jpeg2000_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels2decode-1, codsty->transform == FF_DWT53 ? FF_DWT53 : FF_DWT97_INT))
return ret; return ret;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
csize *= comp->coord[i][1] - comp->coord[i][0]; csize *= comp->coord[i][1] - comp->coord[i][0];
@ -206,7 +206,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
reslevel->coord[i][j] = reslevel->coord[i][j] =
ff_jpeg2000_ceildivpow2(comp->coord[i][j], declvl - 1); ff_jpeg2000_ceildivpow2(comp->coord_o[i][j], declvl - 1);
// update precincts size: 2^n value // update precincts size: 2^n value
reslevel->log2_prec_width = codsty->log2_prec_widths[reslevelno]; reslevel->log2_prec_width = codsty->log2_prec_widths[reslevelno];
reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno]; reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno];
@ -300,7 +300,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
band->coord[i][j] = band->coord[i][j] =
ff_jpeg2000_ceildivpow2(comp->coord[i][j] - comp->coord[i][0], ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0],
declvl - 1); declvl - 1);
log2_band_prec_width = reslevel->log2_prec_width; log2_band_prec_width = reslevel->log2_prec_width;
log2_band_prec_height = reslevel->log2_prec_height; log2_band_prec_height = reslevel->log2_prec_height;
@ -316,7 +316,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
/* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */ /* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */
band->coord[i][j] = band->coord[i][j] =
ff_jpeg2000_ceildivpow2(comp->coord[i][j] - comp->coord[i][0] - ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0] -
(((bandno + 1 >> i) & 1) << declvl - 1), (((bandno + 1 >> i) & 1) << declvl - 1),
declvl); declvl);
/* TODO: Manage case of 3 band offsets here or /* TODO: Manage case of 3 band offsets here or

@ -129,6 +129,7 @@ typedef struct Jpeg2000TgtNode {
typedef struct Jpeg2000CodingStyle { typedef struct Jpeg2000CodingStyle {
uint8_t nreslevels; // number of resolution levels uint8_t nreslevels; // number of resolution levels
uint8_t nreslevels2decode; // number of resolution levels to decode
uint8_t log2_cblk_width, uint8_t log2_cblk_width,
log2_cblk_height; // exponent of codeblock size log2_cblk_height; // exponent of codeblock size
uint8_t transform; // DWT type uint8_t transform; // DWT type
@ -194,7 +195,8 @@ typedef struct Jpeg2000Component {
Jpeg2000ResLevel *reslevel; Jpeg2000ResLevel *reslevel;
DWTContext dwt; DWTContext dwt;
int *data; int *data;
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- can be reduced with lowres option
uint16_t coord_o[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- original values from jpeg2000 headers
} Jpeg2000Component; } Jpeg2000Component;
/* misc tools */ /* misc tools */

@ -26,12 +26,13 @@
* @author Kamil Nowosad * @author Kamil Nowosad
*/ */
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "avcodec.h" #include "avcodec.h"
#include "bytestream.h" #include "bytestream.h"
#include "internal.h" #include "internal.h"
#include "thread.h" #include "thread.h"
#include "j2k.h" #include "j2k.h"
#include "libavutil/common.h"
#define JP2_SIG_TYPE 0x6A502020 #define JP2_SIG_TYPE 0x6A502020
#define JP2_SIG_VALUE 0x0D0A870A #define JP2_SIG_VALUE 0x0D0A870A
@ -74,6 +75,10 @@ typedef struct Jpeg2000DecoderContext {
int curtileno; int curtileno;
Jpeg2000Tile *tile; Jpeg2000Tile *tile;
/*options parameters*/
int lowres;
int reduction_factor;
} Jpeg2000DecoderContext; } Jpeg2000DecoderContext;
static int get_bits(Jpeg2000DecoderContext *s, int n) static int get_bits(Jpeg2000DecoderContext *s, int n)
@ -198,9 +203,11 @@ static int get_siz(Jpeg2000DecoderContext *s)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
s->avctx->width = s->width - s->image_offset_x; /* compute image size with reduction factor */
s->avctx->height = s->height - s->image_offset_y; 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) { switch(s->ncomponents) {
case 1: case 1:
if (s->precision > 8) { if (s->precision > 8) {
@ -244,6 +251,12 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
/* compute number of resolution levels to decode */
if (c->nreslevels < s->reduction_factor)
c->nreslevels2decode = 1;
else
c->nreslevels2decode = c->nreslevels - s->reduction_factor;
c->log2_cblk_width = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk width c->log2_cblk_width = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk width
c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height
@ -434,10 +447,15 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; Jpeg2000QuantStyle *qntsty = tile->qntsty + compno;
int ret; // global bandno int ret; // global bandno
comp->coord[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x); comp->coord_o[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x);
comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width + s->tile_offset_x, s->width); comp->coord_o[0][1] = FFMIN((tilex + 1) * s->tile_width + s->tile_offset_x, s->width);
comp->coord[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y); comp->coord_o[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y);
comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height + s->tile_offset_y, s->height); comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height);
comp->coord[0][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], s->reduction_factor);
comp->coord[0][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][1], s->reduction_factor);
comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor);
comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor);
if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno], s->avctx)) if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno], s->avctx))
return ret; return ret;
@ -785,7 +803,7 @@ static int decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
Jpeg2000CodingStyle *codsty = tile->codsty + compno; Jpeg2000CodingStyle *codsty = tile->codsty + compno;
/* Loop on resolution levels */ /* Loop on resolution levels */
for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) {
Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
/* Loop on bands */ /* Loop on bands */
for (bandno = 0; bandno < rlevel->nbands; bandno++) { for (bandno = 0; bandno < rlevel->nbands; bandno++) {
@ -1025,6 +1043,9 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
bytestream2_init(&s->g, avpkt->data, avpkt->size); bytestream2_init(&s->g, avpkt->data, avpkt->size);
s->curtileno = -1; s->curtileno = -1;
// reduction factor, i.e number of resolution levels to skip
s->reduction_factor = avctx->lowres;
if (bytestream2_get_bytes_left(&s->g) < 2) { if (bytestream2_get_bytes_left(&s->g) < 2) {
ret = AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto err_out; goto err_out;
@ -1072,6 +1093,15 @@ static void jpeg2000_init_static_data(AVCodec *codec)
ff_jpeg2000_init_tier1_luts(); ff_jpeg2000_init_tier1_luts();
} }
#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 = 0 }, 0, JPEG2000_MAX_RESLEVELS - 1, VD },
{ NULL },
};
static const AVProfile profiles[] = { static const AVProfile profiles[] = {
{ FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0, "JPEG 2000 codestream restriction 0" }, { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0, "JPEG 2000 codestream restriction 0" },
{ FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1, "JPEG 2000 codestream restriction 1" }, { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1, "JPEG 2000 codestream restriction 1" },
@ -1081,6 +1111,13 @@ static const AVProfile profiles[] = {
{ FF_PROFILE_UNKNOWN }, { FF_PROFILE_UNKNOWN },
}; };
static const AVClass class = {
.class_name = "j2k",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVCodec ff_j2k_decoder = { AVCodec ff_j2k_decoder = {
.name = "j2k", .name = "j2k",
.long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"),
@ -1090,5 +1127,7 @@ AVCodec ff_j2k_decoder = {
.priv_data_size = sizeof(Jpeg2000DecoderContext), .priv_data_size = sizeof(Jpeg2000DecoderContext),
.init_static_data = jpeg2000_init_static_data, .init_static_data = jpeg2000_init_static_data,
.decode = jpeg2000_decode_frame, .decode = jpeg2000_decode_frame,
.priv_class = &class,
.max_lowres = 5,
.profiles = NULL_IF_CONFIG_SMALL(profiles) .profiles = NULL_IF_CONFIG_SMALL(profiles)
}; };

@ -357,14 +357,14 @@ static int init_tiles(Jpeg2000EncoderContext *s)
Jpeg2000Component *comp = tile->comp + compno; Jpeg2000Component *comp = tile->comp + compno;
int ret, i, j; int ret, i, j;
comp->coord[0][0] = tilex * s->tile_width; comp->coord[0][0] = comp->coord_o[0][0] = tilex * s->tile_width;
comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width, s->width); comp->coord[0][1] = comp->coord_o[0][1] = FFMIN((tilex+1)*s->tile_width, s->width);
comp->coord[1][0] = tiley * s->tile_height; comp->coord[1][0] = comp->coord_o[1][0] = tiley * s->tile_height;
comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height, s->height); comp->coord[1][1] = comp->coord_o[1][1] = FFMIN((tiley+1)*s->tile_height, s->height);
if (compno > 0) if (compno > 0)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
comp->coord[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]); comp->coord[i][j] = comp->coord_o[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]);
if (ret = ff_j2k_init_component(comp, if (ret = ff_j2k_init_component(comp,
codsty, codsty,
@ -982,6 +982,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx)
// TODO: implement setting non-standard precinct size // TODO: implement setting non-standard precinct size
memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths )); memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths ));
memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights)); memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights));
codsty->nreslevels2decode=
codsty->nreslevels = 7; codsty->nreslevels = 7;
codsty->log2_cblk_width = 4; codsty->log2_cblk_width = 4;
codsty->log2_cblk_height = 4; codsty->log2_cblk_height = 4;

@ -543,12 +543,10 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
comp->coord_o[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y); comp->coord_o[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y);
comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height); comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height);
// FIXME: add a dcinema profile check ? comp->coord[0][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], s->reduction_factor);
// value is guaranteed by profile (orig=0, 1 tile) comp->coord[0][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][1], s->reduction_factor);
comp->coord[0][0] = 0; comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor);
comp->coord[0][1] = s->avctx->width; comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor);
comp->coord[1][0] = 0;
comp->coord[1][1] = s->avctx->height;
if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty, if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty,
s->cbps[compno], s->cdx[compno], s->cbps[compno], s->cdx[compno],
@ -1369,5 +1367,6 @@ AVCodec ff_jpeg2000_decoder = {
.pix_fmts = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12, .pix_fmts = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12,
AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8,
-1 }, -1 },
.max_lowres = 5,
.profiles = NULL_IF_CONFIG_SMALL(profiles) .profiles = NULL_IF_CONFIG_SMALL(profiles)
}; };

Loading…
Cancel
Save