mirror of https://github.com/FFmpeg/FFmpeg.git
parent
4c509fe305
commit
83654c7b1b
15 changed files with 3570 additions and 2 deletions
@ -0,0 +1,390 @@ |
||||
/*
|
||||
* JPEG2000 encoder and decoder common functions |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* JPEG2000 image encoder and decoder common functions |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
|
||||
#include "avcodec.h" |
||||
#include "j2k.h" |
||||
|
||||
#define SHL(a, n) ((n)>=0 ? (a) << (n) : (a) >> -(n)) |
||||
|
||||
#if 0 |
||||
void ff_j2k_printv(int *tab, int l) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < l; i++) |
||||
printf("%.3d ", tab[i]); |
||||
printf("\n"); |
||||
} |
||||
|
||||
void ff_j2k_printu(uint8_t *tab, int l) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < l; i++) |
||||
printf("%.3hd ", tab[i]); |
||||
printf("\n"); |
||||
} |
||||
#endif |
||||
|
||||
/* tag tree routines */ |
||||
|
||||
/** allocate the memory for tag tree */ |
||||
|
||||
static int tag_tree_size(int w, int h) |
||||
{ |
||||
int res = 0; |
||||
while (w > 1 || h > 1){ |
||||
res += w * h; |
||||
w = (w+1) >> 1; |
||||
h = (h+1) >> 1; |
||||
} |
||||
return res + 1; |
||||
} |
||||
|
||||
J2kTgtNode *ff_j2k_tag_tree_init(int w, int h) |
||||
{ |
||||
int pw = w, ph = h; |
||||
J2kTgtNode *res, *t, *t2; |
||||
|
||||
t = res = av_mallocz(tag_tree_size(w, h)*sizeof(J2kTgtNode)); |
||||
|
||||
if (res == NULL) |
||||
return NULL; |
||||
|
||||
while (w > 1 || h > 1){ |
||||
int i, j; |
||||
pw = w; |
||||
ph = h; |
||||
|
||||
w = (w+1) >> 1; |
||||
h = (h+1) >> 1; |
||||
t2 = t + pw*ph; |
||||
|
||||
for (i = 0; i < ph; i++) |
||||
for (j = 0; j < pw; j++){ |
||||
t[i*pw + j].parent = &t2[(i>>1)*w + (j>>1)]; |
||||
} |
||||
t = t2; |
||||
} |
||||
t[0].parent = NULL; |
||||
return res; |
||||
} |
||||
|
||||
static void tag_tree_zero(J2kTgtNode *t, int w, int h) |
||||
{ |
||||
int i, siz = tag_tree_size(w, h); |
||||
|
||||
for (i = 0; i < siz; i++){ |
||||
t[i].val = 0; |
||||
t[i].vis = 0; |
||||
} |
||||
} |
||||
|
||||
uint8_t ff_j2k_nbctxno_lut[256][4]; |
||||
|
||||
static int getnbctxno(int flag, int bandno) |
||||
{ |
||||
int h, v, d; |
||||
|
||||
h = ((flag & J2K_T1_SIG_E) ? 1:0)+ |
||||
((flag & J2K_T1_SIG_W) ? 1:0); |
||||
v = ((flag & J2K_T1_SIG_N) ? 1:0)+ |
||||
((flag & J2K_T1_SIG_S) ? 1:0); |
||||
d = ((flag & J2K_T1_SIG_NE) ? 1:0)+ |
||||
((flag & J2K_T1_SIG_NW) ? 1:0)+ |
||||
((flag & J2K_T1_SIG_SE) ? 1:0)+ |
||||
((flag & J2K_T1_SIG_SW) ? 1:0); |
||||
if (bandno < 3){ |
||||
if (bandno == 1) |
||||
FFSWAP(int, h, v); |
||||
if (h == 2) return 8; |
||||
if (h == 1){ |
||||
if (v >= 1) return 7; |
||||
if (d >= 1) return 6; |
||||
return 5; |
||||
} |
||||
if (v == 2) return 4; |
||||
if (v == 1) return 3; |
||||
if (d >= 2) return 2; |
||||
if (d == 1) return 1; |
||||
return 0; |
||||
} else{ |
||||
if (d >= 3) return 8; |
||||
if (d == 2){ |
||||
if (h+v >= 1) return 7; |
||||
return 6; |
||||
} |
||||
if (d == 1){ |
||||
if (h+v >= 2) return 5; |
||||
if (h+v == 1) return 4; |
||||
return 3; |
||||
} |
||||
if (h+v >= 2) return 2; |
||||
if (h+v == 1) return 1; |
||||
return 0; |
||||
} |
||||
assert(0); |
||||
} |
||||
|
||||
uint8_t ff_j2k_sgnctxno_lut[16][16], ff_j2k_xorbit_lut[16][16]; |
||||
|
||||
static int getsgnctxno(int flag, uint8_t *xorbit) |
||||
{ |
||||
int vcontrib, hcontrib; |
||||
static const int contribtab[3][3] = {{0, -1, 1}, {-1, -1, 0}, {1, 0, 1}}; |
||||
static const int ctxlbltab[3][3] = {{13, 12, 11}, {10, 9, 10}, {11, 12, 13}}; |
||||
static const int xorbittab[3][3] = {{1, 1, 1,}, {1, 0, 0}, {0, 0, 0}}; |
||||
|
||||
hcontrib = contribtab[flag & J2K_T1_SIG_E ? flag & J2K_T1_SGN_E ? 1:2:0] |
||||
[flag & J2K_T1_SIG_W ? flag & J2K_T1_SGN_W ? 1:2:0]+1; |
||||
vcontrib = contribtab[flag & J2K_T1_SIG_S ? flag & J2K_T1_SGN_S ? 1:2:0] |
||||
[flag & J2K_T1_SIG_N ? flag & J2K_T1_SGN_N ? 1:2:0]+1; |
||||
*xorbit = xorbittab[hcontrib][vcontrib]; |
||||
return ctxlbltab[hcontrib][vcontrib]; |
||||
} |
||||
|
||||
void ff_j2k_init_tier1_luts() |
||||
{ |
||||
int i, j; |
||||
for (i = 0; i < 256; i++) |
||||
for (j = 0; j < 4; j++) |
||||
ff_j2k_nbctxno_lut[i][j] = getnbctxno(i, j); |
||||
for (i = 0; i < 16; i++) |
||||
for (j = 0; j < 16; j++) |
||||
ff_j2k_sgnctxno_lut[i][j] = getsgnctxno(i + (j << 8), &ff_j2k_xorbit_lut[i][j]); |
||||
} |
||||
|
||||
void ff_j2k_set_significant(J2kT1Context *t1, int x, int y, int negative) |
||||
{ |
||||
x++; y++; |
||||
t1->flags[y][x] |= J2K_T1_SIG; |
||||
if (negative){ |
||||
t1->flags[y][x+1] |= J2K_T1_SIG_W | J2K_T1_SGN_W; |
||||
t1->flags[y][x-1] |= J2K_T1_SIG_E | J2K_T1_SGN_E; |
||||
t1->flags[y+1][x] |= J2K_T1_SIG_N | J2K_T1_SGN_N; |
||||
t1->flags[y-1][x] |= J2K_T1_SIG_S | J2K_T1_SGN_S; |
||||
} else{ |
||||
t1->flags[y][x+1] |= J2K_T1_SIG_W; |
||||
t1->flags[y][x-1] |= J2K_T1_SIG_E; |
||||
t1->flags[y+1][x] |= J2K_T1_SIG_N; |
||||
t1->flags[y-1][x] |= J2K_T1_SIG_S; |
||||
} |
||||
t1->flags[y+1][x+1] |= J2K_T1_SIG_NW; |
||||
t1->flags[y+1][x-1] |= J2K_T1_SIG_NE; |
||||
t1->flags[y-1][x+1] |= J2K_T1_SIG_SW; |
||||
t1->flags[y-1][x-1] |= J2K_T1_SIG_SE; |
||||
} |
||||
|
||||
int ff_j2k_init_component(J2kComponent *comp, J2kCodingStyle *codsty, J2kQuantStyle *qntsty, int cbps, int dx, int dy) |
||||
{ |
||||
int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1; |
||||
|
||||
if (ret=ff_j2k_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels-1, codsty->transform)) |
||||
return ret; |
||||
for (i = 0; i < 2; i++) |
||||
csize *= comp->coord[i][1] - comp->coord[i][0]; |
||||
|
||||
comp->data = av_malloc(csize * sizeof(int)); |
||||
if (!comp->data) |
||||
return AVERROR(ENOMEM); |
||||
comp->reslevel = av_malloc(codsty->nreslevels * sizeof(J2kResLevel)); |
||||
|
||||
if (!comp->reslevel) |
||||
return AVERROR(ENOMEM); |
||||
for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ |
||||
int declvl = codsty->nreslevels - reslevelno; |
||||
J2kResLevel *reslevel = comp->reslevel + reslevelno; |
||||
|
||||
for (i = 0; i < 2; i++) |
||||
for (j = 0; j < 2; j++) |
||||
reslevel->coord[i][j] = |
||||
ff_j2k_ceildivpow2(comp->coord[i][j], declvl - 1); |
||||
|
||||
if (reslevelno == 0) |
||||
reslevel->nbands = 1; |
||||
else |
||||
reslevel->nbands = 3; |
||||
|
||||
if (reslevel->coord[0][1] == reslevel->coord[0][0]) |
||||
reslevel->num_precincts_x = 0; |
||||
else |
||||
reslevel->num_precincts_x = ff_j2k_ceildivpow2(reslevel->coord[0][1], codsty->log2_prec_width) |
||||
- (reslevel->coord[0][0] >> codsty->log2_prec_width); |
||||
|
||||
if (reslevel->coord[1][1] == reslevel->coord[1][0]) |
||||
reslevel->num_precincts_y = 0; |
||||
else |
||||
reslevel->num_precincts_y = ff_j2k_ceildivpow2(reslevel->coord[1][1], codsty->log2_prec_height) |
||||
- (reslevel->coord[1][0] >> codsty->log2_prec_height); |
||||
|
||||
reslevel->band = av_malloc(reslevel->nbands * sizeof(J2kBand)); |
||||
if (!reslevel->band) |
||||
return AVERROR(ENOMEM); |
||||
for (bandno = 0; bandno < reslevel->nbands; bandno++, gbandno++){ |
||||
J2kBand *band = reslevel->band + bandno; |
||||
int cblkno, precx, precy, precno; |
||||
int x0, y0, x1, y1; |
||||
int xi0, yi0, xi1, yi1; |
||||
int cblkperprecw, cblkperprech; |
||||
|
||||
if (qntsty->quantsty != J2K_QSTY_NONE){ |
||||
const static uint8_t lut_gain[2][4] = {{0, 0, 0, 0}, {0, 1, 1, 2}}; |
||||
int numbps; |
||||
|
||||
numbps = cbps + lut_gain[codsty->transform][bandno + reslevelno>0]; |
||||
band->stepsize = SHL(2048 + qntsty->mant[gbandno], 2 + numbps - qntsty->expn[gbandno]); |
||||
} else |
||||
band->stepsize = 1 << 13; |
||||
|
||||
if (reslevelno == 0){ // the same everywhere
|
||||
band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width-1); |
||||
band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height-1); |
||||
for (i = 0; i < 2; i++) |
||||
for (j = 0; j < 2; j++) |
||||
band->coord[i][j] = ff_j2k_ceildivpow2(comp->coord[i][j], declvl-1); |
||||
} else{ |
||||
band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width); |
||||
band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height); |
||||
|
||||
for (i = 0; i < 2; i++) |
||||
for (j = 0; j < 2; j++) |
||||
band->coord[i][j] = ff_j2k_ceildivpow2(comp->coord[i][j] - (((bandno+1>>i)&1) << declvl-1), declvl); |
||||
} |
||||
band->cblknx = ff_j2k_ceildiv(band->coord[0][1], band->codeblock_width) - band->coord[0][0] / band->codeblock_width; |
||||
band->cblkny = ff_j2k_ceildiv(band->coord[1][1], band->codeblock_height) - band->coord[1][0] / band->codeblock_height; |
||||
|
||||
for (j = 0; j < 2; j++) |
||||
band->coord[0][j] = ff_j2k_ceildiv(band->coord[0][j], dx); |
||||
for (j = 0; j < 2; j++) |
||||
band->coord[1][j] = ff_j2k_ceildiv(band->coord[1][j], dy); |
||||
|
||||
band->cblknx = ff_j2k_ceildiv(band->cblknx, dx); |
||||
band->cblkny = ff_j2k_ceildiv(band->cblkny, dy); |
||||
|
||||
band->cblk = av_malloc(band->cblknx * band->cblkny * sizeof(J2kCblk)); |
||||
if (!band->cblk) |
||||
return AVERROR(ENOMEM); |
||||
band->prec = av_malloc(reslevel->num_precincts_x * reslevel->num_precincts_y * sizeof(J2kPrec)); |
||||
if (!band->prec) |
||||
return AVERROR(ENOMEM); |
||||
|
||||
for (cblkno = 0; cblkno < band->cblknx * band->cblkny; cblkno++){ |
||||
J2kCblk *cblk = band->cblk + cblkno; |
||||
cblk->zero = 0; |
||||
cblk->lblock = 3; |
||||
cblk->length = 0; |
||||
cblk->lengthinc = 0; |
||||
cblk->npasses = 0; |
||||
} |
||||
|
||||
y0 = band->coord[1][0]; |
||||
y1 = ((band->coord[1][0] + (1<<codsty->log2_prec_height)) & ~((1<<codsty->log2_prec_height)-1)) - y0; |
||||
yi0 = 0; |
||||
yi1 = ff_j2k_ceildivpow2(y1 - y0, codsty->log2_cblk_height) << codsty->log2_cblk_height; |
||||
yi1 = FFMIN(yi1, band->cblkny); |
||||
cblkperprech = 1<<(codsty->log2_prec_height - codsty->log2_cblk_height); |
||||
for (precy = 0, precno = 0; precy < reslevel->num_precincts_y; precy++){ |
||||
for (precx = 0; precx < reslevel->num_precincts_x; precx++, precno++){ |
||||
band->prec[precno].yi0 = yi0; |
||||
band->prec[precno].yi1 = yi1; |
||||
} |
||||
yi1 += cblkperprech; |
||||
yi0 = yi1 - cblkperprech; |
||||
yi1 = FFMIN(yi1, band->cblkny); |
||||
} |
||||
x0 = band->coord[0][0]; |
||||
x1 = ((band->coord[0][0] + (1<<codsty->log2_prec_width)) & ~((1<<codsty->log2_prec_width)-1)) - x0; |
||||
xi0 = 0; |
||||
xi1 = ff_j2k_ceildivpow2(x1 - x0, codsty->log2_cblk_width) << codsty->log2_cblk_width; |
||||
xi1 = FFMIN(xi1, band->cblknx); |
||||
|
||||
cblkperprecw = 1<<(codsty->log2_prec_width - codsty->log2_cblk_width); |
||||
for (precx = 0, precno = 0; precx < reslevel->num_precincts_x; precx++){ |
||||
for (precy = 0; precy < reslevel->num_precincts_y; precy++, precno = 0){ |
||||
J2kPrec *prec = band->prec + precno; |
||||
prec->xi0 = xi0; |
||||
prec->xi1 = xi1; |
||||
prec->cblkincl = ff_j2k_tag_tree_init(prec->xi1 - prec->xi0, |
||||
prec->yi1 - prec->yi0); |
||||
prec->zerobits = ff_j2k_tag_tree_init(prec->xi1 - prec->xi0, |
||||
prec->yi1 - prec->yi0); |
||||
if (!prec->cblkincl || !prec->zerobits) |
||||
return AVERROR(ENOMEM); |
||||
|
||||
} |
||||
xi1 += cblkperprecw; |
||||
xi0 = xi1 - cblkperprecw; |
||||
xi1 = FFMIN(xi1, band->cblknx); |
||||
} |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
void ff_j2k_reinit(J2kComponent *comp, J2kCodingStyle *codsty) |
||||
{ |
||||
int reslevelno, bandno, cblkno, precno; |
||||
for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ |
||||
J2kResLevel *rlevel = comp->reslevel + reslevelno; |
||||
for (bandno = 0; bandno < rlevel->nbands; bandno++){ |
||||
J2kBand *band = rlevel->band + bandno; |
||||
for(precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++){ |
||||
J2kPrec *prec = band->prec + precno; |
||||
tag_tree_zero(prec->zerobits, prec->xi1 - prec->xi0, prec->yi1 - prec->yi0); |
||||
tag_tree_zero(prec->cblkincl, prec->xi1 - prec->xi0, prec->yi1 - prec->yi0); |
||||
} |
||||
for (cblkno = 0; cblkno < band->cblknx * band->cblkny; cblkno++){ |
||||
J2kCblk *cblk = band->cblk + cblkno; |
||||
cblk->length = 0; |
||||
cblk->lblock = 3; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ff_j2k_cleanup(J2kComponent *comp, J2kCodingStyle *codsty) |
||||
{ |
||||
int reslevelno, bandno, precno; |
||||
for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ |
||||
J2kResLevel *reslevel = comp->reslevel + reslevelno; |
||||
|
||||
for (bandno = 0; bandno < reslevel->nbands ; bandno++){ |
||||
J2kBand *band = reslevel->band + bandno; |
||||
for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ |
||||
J2kPrec *prec = band->prec + precno; |
||||
av_freep(&prec->zerobits); |
||||
av_freep(&prec->cblkincl); |
||||
} |
||||
av_freep(&band->cblk); |
||||
av_freep(&band->prec); |
||||
} |
||||
av_freep(&reslevel->band); |
||||
} |
||||
|
||||
ff_j2k_dwt_destroy(&comp->dwt); |
||||
av_freep(&comp->reslevel); |
||||
av_freep(&comp->data); |
||||
} |
@ -0,0 +1,234 @@ |
||||
/*
|
||||
* JPEG2000 tables |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
#ifndef AVCODEC_J2K_H |
||||
#define AVCODEC_J2K_H |
||||
|
||||
/**
|
||||
* JPEG2000 tables |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
#include "mqc.h" |
||||
#include "j2k_dwt.h" |
||||
|
||||
enum J2kMarkers{ |
||||
J2K_SOC = 0xff4f, ///< start of codestream
|
||||
J2K_SIZ = 0xff51, ///< image and tile size
|
||||
J2K_COD, ///< coding style default
|
||||
J2K_COC, ///< coding style component
|
||||
J2K_TLM = 0xff55, ///< packed packet headers, tile-part header
|
||||
J2K_PLM = 0xff57, ///< tile-part lengths
|
||||
J2K_PLT, ///< packet length, main header
|
||||
J2K_QCD = 0xff5c, ///< quantization default
|
||||
J2K_QCC, ///< quantization component
|
||||
J2K_RGN, ///< region of interest
|
||||
J2K_POC, ///< progression order change
|
||||
J2K_PPM, ///< packet length, tile-part header
|
||||
J2K_PPT, ///< packed packet headers, main header
|
||||
J2K_CRG = 0xff63, ///< component registration
|
||||
J2K_COM, ///< comment
|
||||
J2K_SOT = 0xff90, ///< start of tile-part
|
||||
J2K_SOP, ///< start of packet
|
||||
J2K_EPH, ///< end of packet header
|
||||
J2K_SOD, ///< start of data
|
||||
J2K_EOC = 0xffd9, ///< end of codestream
|
||||
}; |
||||
|
||||
enum J2kQuantsty{ ///< quantization style
|
||||
J2K_QSTY_NONE, ///< no quantization
|
||||
J2K_QSTY_SI, ///< scalar derived
|
||||
J2K_QSTY_SE ///< scalar expoounded
|
||||
}; |
||||
|
||||
#define J2K_MAX_CBLKW 64 |
||||
#define J2K_MAX_CBLKH 64 |
||||
|
||||
// T1 flags
|
||||
// flags determining significance of neighbour coefficients
|
||||
#define J2K_T1_SIG_N 0x0001 |
||||
#define J2K_T1_SIG_E 0x0002 |
||||
#define J2K_T1_SIG_W 0x0004 |
||||
#define J2K_T1_SIG_S 0x0008 |
||||
#define J2K_T1_SIG_NE 0x0010 |
||||
#define J2K_T1_SIG_NW 0x0020 |
||||
#define J2K_T1_SIG_SE 0x0040 |
||||
#define J2K_T1_SIG_SW 0x0080 |
||||
#define J2K_T1_SIG_NB (J2K_T1_SIG_N | J2K_T1_SIG_E | J2K_T1_SIG_S | J2K_T1_SIG_W \ |
||||
|J2K_T1_SIG_NE | J2K_T1_SIG_NW | J2K_T1_SIG_SE | J2K_T1_SIG_SW) |
||||
// flags determining sign bit of neighbour coefficients
|
||||
#define J2K_T1_SGN_N 0x0100 |
||||
#define J2K_T1_SGN_S 0x0200 |
||||
#define J2K_T1_SGN_W 0x0400 |
||||
#define J2K_T1_SGN_E 0x0800 |
||||
|
||||
#define J2K_T1_VIS 0x1000 |
||||
#define J2K_T1_SIG 0x2000 |
||||
#define J2K_T1_REF 0x4000 |
||||
|
||||
#define J2K_T1_SGN 0x8000 |
||||
|
||||
// Codeblock coding styles
|
||||
#define J2K_CBLK_BYPASS 0x01 // Selective arithmetic coding bypass
|
||||
#define J2K_CBLK_RESET 0x02 // Reset context probabilities
|
||||
#define J2K_CBLK_TERMALL 0x04 // Terminate after each coding pass
|
||||
#define J2K_CBLK_VSC 0x08 // Vertical stripe causal context formation
|
||||
#define J2K_CBLK_PREDTERM 0x10 // Predictable termination
|
||||
#define J2K_CBLK_SEGSYM 0x20 // Segmentation symbols present
|
||||
|
||||
// Coding styles
|
||||
#define J2K_CSTY_PREC 0x01 // Precincts defined in coding style
|
||||
#define J2K_CSTY_SOP 0x02 // SOP marker present
|
||||
#define J2K_CSTY_EPH 0x04 // EPH marker present
|
||||
|
||||
typedef struct { |
||||
int data[J2K_MAX_CBLKW][J2K_MAX_CBLKH]; |
||||
int flags[J2K_MAX_CBLKW+2][J2K_MAX_CBLKH+2]; |
||||
MqcState mqc; |
||||
} J2kT1Context; |
||||
|
||||
typedef struct J2kTgtNode { |
||||
uint8_t val; |
||||
uint8_t vis; |
||||
struct J2kTgtNode *parent; |
||||
} J2kTgtNode; |
||||
|
||||
typedef struct { |
||||
uint8_t nreslevels; ///< number of resolution levels
|
||||
uint8_t log2_cblk_width, |
||||
log2_cblk_height; ///< exponent of codeblock size
|
||||
uint8_t transform; ///< DWT type
|
||||
uint8_t csty; ///< coding style
|
||||
uint8_t log2_prec_width, |
||||
log2_prec_height; ///< precinct size
|
||||
uint8_t nlayers; ///< number of layers
|
||||
uint8_t mct; ///< multiple component transformation
|
||||
uint8_t cblk_style; ///< codeblock coding style
|
||||
} J2kCodingStyle; |
||||
|
||||
typedef struct { |
||||
uint8_t expn[32 * 3]; ///< quantization exponent
|
||||
uint16_t mant[32 * 3]; ///< quantization mantissa
|
||||
uint8_t quantsty; ///< quantization style
|
||||
uint8_t nguardbits; ///< number of guard bits
|
||||
} J2kQuantStyle; |
||||
|
||||
typedef struct { |
||||
uint16_t rate; |
||||
int64_t disto; |
||||
} J2kPass; |
||||
|
||||
typedef struct { |
||||
uint8_t npasses; |
||||
uint8_t ninclpasses; ///< number coding of passes included in codestream
|
||||
uint8_t nonzerobits; |
||||
uint16_t length; |
||||
uint16_t lengthinc; |
||||
uint8_t lblock; |
||||
uint8_t zero; |
||||
uint8_t data[8192]; |
||||
J2kPass passes[100]; |
||||
} J2kCblk; ///< code block
|
||||
|
||||
typedef struct { |
||||
uint16_t xi0, xi1, yi0, yi1; ///< codeblock indexes ([xi0, xi1))
|
||||
J2kTgtNode *zerobits; |
||||
J2kTgtNode *cblkincl; |
||||
} J2kPrec; ///< precinct
|
||||
|
||||
typedef struct { |
||||
uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}}
|
||||
uint16_t codeblock_width, codeblock_height; |
||||
uint16_t cblknx, cblkny; |
||||
uint32_t stepsize; ///< quantization stepsize (* 2^13)
|
||||
J2kPrec *prec; |
||||
J2kCblk *cblk; |
||||
} J2kBand; ///< subband
|
||||
|
||||
typedef struct { |
||||
uint8_t nbands; |
||||
uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}}
|
||||
uint16_t num_precincts_x, num_precincts_y; ///< number of precincts in x/y direction
|
||||
uint8_t log2_prec_width, log2_prec_height; ///< exponent of precinct size
|
||||
J2kBand *band; |
||||
} J2kResLevel; ///< resolution level
|
||||
|
||||
typedef struct { |
||||
J2kResLevel *reslevel; |
||||
DWTContext dwt; |
||||
int *data; |
||||
uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}}
|
||||
} J2kComponent; |
||||
|
||||
/* debug routines */ |
||||
#if 0 |
||||
#undef fprintf |
||||
#undef printf |
||||
void ff_j2k_printv(int *tab, int l); |
||||
void ff_j2k_printu(uint8_t *tab, int l); |
||||
#endif |
||||
|
||||
/* misc tools */ |
||||
static inline int ff_j2k_ceildivpow2(int a, int b) |
||||
{ |
||||
return (a + (1 << b) - 1)>> b; |
||||
} |
||||
|
||||
static inline int ff_j2k_ceildiv(int a, int b) |
||||
{ |
||||
return (a + b - 1) / b; |
||||
} |
||||
|
||||
/* tag tree routines */ |
||||
J2kTgtNode *ff_j2k_tag_tree_init(int w, int h); |
||||
|
||||
/* TIER-1 routines */ |
||||
void ff_j2k_init_tier1_luts(void); |
||||
|
||||
void ff_j2k_set_significant(J2kT1Context *t1, int x, int y, int negative); |
||||
|
||||
extern uint8_t ff_j2k_nbctxno_lut[256][4]; |
||||
|
||||
static inline int ff_j2k_getnbctxno(int flag, int bandno) |
||||
{ |
||||
return ff_j2k_nbctxno_lut[flag&255][bandno]; |
||||
} |
||||
|
||||
static inline int ff_j2k_getrefctxno(int flag) |
||||
{ |
||||
static const uint8_t refctxno_lut[2][2] = {{14, 15}, {16, 16}}; |
||||
return refctxno_lut[(flag>>14)&1][(flag & 255) != 0]; |
||||
} |
||||
|
||||
extern uint8_t ff_j2k_sgnctxno_lut[16][16], ff_j2k_xorbit_lut[16][16]; |
||||
|
||||
static inline int ff_j2k_getsgnctxno(int flag, int *xorbit) |
||||
{ |
||||
*xorbit = ff_j2k_xorbit_lut[flag&15][(flag>>8)&15]; |
||||
return ff_j2k_sgnctxno_lut[flag&15][(flag>>8)&15]; |
||||
} |
||||
|
||||
int ff_j2k_init_component(J2kComponent *comp, J2kCodingStyle *codsty, J2kQuantStyle *qntsty, int cbps, int dx, int dy); |
||||
void ff_j2k_reinit(J2kComponent *comp, J2kCodingStyle *codsty); |
||||
void ff_j2k_cleanup(J2kComponent *comp, J2kCodingStyle *codsty); |
||||
|
||||
#endif /* AVCODEC_J2K_H */ |
@ -0,0 +1,384 @@ |
||||
/*
|
||||
* Discrete wavelet transform |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* Discrete wavelet transform |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
#include "j2k_dwt.h" |
||||
|
||||
const static float scale97[] = {1.625786, 1.230174}; |
||||
|
||||
static inline void extend53(int *p, int i0, int i1) |
||||
{ |
||||
p[i0 - 1] = p[i0 + 1]; |
||||
p[i1 ] = p[i1 - 2]; |
||||
p[i0 - 2] = p[i0 + 2]; |
||||
p[i1 + 1] = p[i1 - 3]; |
||||
} |
||||
|
||||
static inline void extend97(float *p, int i0, int i1) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 1; i <= 4; i++){ |
||||
p[i0 - i] = p[i0 + i]; |
||||
p[i1 + i - 1] = p[i1 - i - 1]; |
||||
} |
||||
} |
||||
|
||||
static void sd_1d53(int *p, int i0, int i1) |
||||
{ |
||||
int i; |
||||
|
||||
if (i1 == i0 + 1) |
||||
return; |
||||
|
||||
extend53(p, i0, i1); |
||||
|
||||
for (i = (i0+1)/2 - 1; i < (i1+1)/2; i++) |
||||
p[2*i+1] -= (p[2*i] + p[2*i+2]) >> 1; |
||||
for (i = (i0+1)/2; i < (i1+1)/2; i++) |
||||
p[2*i] += (p[2*i-1] + p[2*i+1] + 2) >> 2; |
||||
} |
||||
|
||||
static void dwt_encode53(DWTContext *s, int *t) |
||||
{ |
||||
int lev, |
||||
w = s->linelen[s->ndeclevels-1][0]; |
||||
int *line = s->linebuf; |
||||
line += 3; |
||||
|
||||
for (lev = s->ndeclevels-1; lev >= 0; lev--){ |
||||
int lh = s->linelen[lev][0], |
||||
lv = s->linelen[lev][1], |
||||
mh = s->mod[lev][0], |
||||
mv = s->mod[lev][1], |
||||
lp; |
||||
int *l; |
||||
|
||||
// HOR_SD
|
||||
l = line + mh; |
||||
for (lp = 0; lp < lv; lp++){ |
||||
int i, j = 0; |
||||
|
||||
for (i = 0; i < lh; i++) |
||||
l[i] = t[w*lp + i]; |
||||
|
||||
sd_1d53(line, mh, mh + lh); |
||||
|
||||
// copy back and deinterleave
|
||||
for (i = mh; i < lh; i+=2, j++) |
||||
t[w*lp + j] = l[i]; |
||||
for (i = 1-mh; i < lh; i+=2, j++) |
||||
t[w*lp + j] = l[i]; |
||||
} |
||||
|
||||
// VER_SD
|
||||
l = line + mv; |
||||
for (lp = 0; lp < lh; lp++) { |
||||
int i, j = 0; |
||||
|
||||
for (i = 0; i < lv; i++) |
||||
l[i] = t[w*i + lp]; |
||||
|
||||
sd_1d53(line, mv, mv + lv); |
||||
|
||||
// copy back and deinterleave
|
||||
for (i = mv; i < lv; i+=2, j++) |
||||
t[w*j + lp] = l[i]; |
||||
for (i = 1-mv; i < lv; i+=2, j++) |
||||
t[w*j + lp] = l[i]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void sd_1d97(float *p, int i0, int i1) |
||||
{ |
||||
int i; |
||||
|
||||
if (i1 == i0 + 1) |
||||
return; |
||||
|
||||
extend97(p, i0, i1); |
||||
i0++; i1++; |
||||
|
||||
for (i = i0/2 - 2; i < i1/2 + 1; i++) |
||||
p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]); |
||||
for (i = i0/2 - 1; i < i1/2 + 1; i++) |
||||
p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]); |
||||
for (i = i0/2 - 1; i < i1/2; i++) |
||||
p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]); |
||||
for (i = i0/2; i < i1/2; i++) |
||||
p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]); |
||||
} |
||||
|
||||
static void dwt_encode97(DWTContext *s, int *t) |
||||
{ |
||||
int lev, |
||||
w = s->linelen[s->ndeclevels-1][0]; |
||||
float *line = s->linebuf; |
||||
line += 5; |
||||
|
||||
for (lev = s->ndeclevels-1; lev >= 0; lev--){ |
||||
int lh = s->linelen[lev][0], |
||||
lv = s->linelen[lev][1], |
||||
mh = s->mod[lev][0], |
||||
mv = s->mod[lev][1], |
||||
lp; |
||||
float *l; |
||||
|
||||
// HOR_SD
|
||||
l = line + mh; |
||||
for (lp = 0; lp < lv; lp++){ |
||||
int i, j = 0; |
||||
|
||||
for (i = 0; i < lh; i++) |
||||
l[i] = t[w*lp + i]; |
||||
|
||||
sd_1d97(line, mh, mh + lh); |
||||
|
||||
// copy back and deinterleave
|
||||
for (i = mh; i < lh; i+=2, j++) |
||||
t[w*lp + j] = scale97[mh] * l[i] / 2; |
||||
for (i = 1-mh; i < lh; i+=2, j++) |
||||
t[w*lp + j] = scale97[mh] * l[i] / 2; |
||||
} |
||||
|
||||
// VER_SD
|
||||
l = line + mv; |
||||
for (lp = 0; lp < lh; lp++) { |
||||
int i, j = 0; |
||||
|
||||
for (i = 0; i < lv; i++) |
||||
l[i] = t[w*i + lp]; |
||||
|
||||
sd_1d97(line, mv, mv + lv); |
||||
|
||||
// copy back and deinterleave
|
||||
for (i = mv; i < lv; i+=2, j++) |
||||
t[w*j + lp] = scale97[mv] * l[i] / 2; |
||||
for (i = 1-mv; i < lv; i+=2, j++) |
||||
t[w*j + lp] = scale97[mv] * l[i] / 2; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void sr_1d53(int *p, int i0, int i1) |
||||
{ |
||||
int i; |
||||
|
||||
if (i1 == i0 + 1) |
||||
return; |
||||
|
||||
extend53(p, i0, i1); |
||||
|
||||
for (i = i0/2; i < i1/2 + 1; i++) |
||||
p[2*i] -= (p[2*i-1] + p[2*i+1] + 2) >> 2; |
||||
for (i = i0/2; i < i1/2; i++) |
||||
p[2*i+1] += (p[2*i] + p[2*i+2]) >> 1; |
||||
} |
||||
|
||||
static void dwt_decode53(DWTContext *s, int *t) |
||||
{ |
||||
int lev, |
||||
w = s->linelen[s->ndeclevels-1][0]; |
||||
int *line = s->linebuf; |
||||
line += 3; |
||||
|
||||
for (lev = 0; lev < s->ndeclevels; lev++){ |
||||
int lh = s->linelen[lev][0], |
||||
lv = s->linelen[lev][1], |
||||
mh = s->mod[lev][0], |
||||
mv = s->mod[lev][1], |
||||
lp; |
||||
int *l; |
||||
|
||||
// HOR_SD
|
||||
l = line + mh; |
||||
for (lp = 0; lp < lv; lp++){ |
||||
int i, j = 0; |
||||
// copy with interleaving
|
||||
for (i = mh; i < lh; i+=2, j++) |
||||
l[i] = t[w*lp + j]; |
||||
for (i = 1-mh; i < lh; i+=2, j++) |
||||
l[i] = t[w*lp + j]; |
||||
|
||||
sr_1d53(line, mh, mh + lh); |
||||
|
||||
for (i = 0; i < lh; i++) |
||||
t[w*lp + i] = l[i]; |
||||
} |
||||
|
||||
// VER_SD
|
||||
l = line + mv; |
||||
for (lp = 0; lp < lh; lp++){ |
||||
int i, j = 0; |
||||
// copy with interleaving
|
||||
for (i = mv; i < lv; i+=2, j++) |
||||
l[i] = t[w*j + lp]; |
||||
for (i = 1-mv; i < lv; i+=2, j++) |
||||
l[i] = t[w*j + lp]; |
||||
|
||||
sr_1d53(line, mv, mv + lv); |
||||
|
||||
for (i = 0; i < lv; i++) |
||||
t[w*i + lp] = l[i]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void sr_1d97(float *p, int i0, int i1) |
||||
{ |
||||
int i; |
||||
|
||||
if (i1 == i0 + 1) |
||||
return; |
||||
|
||||
extend97(p, i0, i1); |
||||
|
||||
for (i = i0/2 - 1; i < i1/2 + 2; i++) |
||||
p[2*i] -= 0.443506 * (p[2*i-1] + p[2*i+1]); |
||||
for (i = i0/2 - 1; i < i1/2 + 1; i++) |
||||
p[2*i+1] -= 0.882911 * (p[2*i] + p[2*i+2]); |
||||
for (i = i0/2; i < i1/2 + 1; i++) |
||||
p[2*i] += 0.052980 * (p[2*i-1] + p[2*i+1]); |
||||
for (i = i0/2; i < i1/2; i++) |
||||
p[2*i+1] += 1.586134 * (p[2*i] + p[2*i+2]); |
||||
} |
||||
|
||||
static void dwt_decode97(DWTContext *s, int *t) |
||||
{ |
||||
int lev, |
||||
w = s->linelen[s->ndeclevels-1][0]; |
||||
float *line = s->linebuf; |
||||
line += 5; |
||||
|
||||
for (lev = 0; lev < s->ndeclevels; lev++){ |
||||
int lh = s->linelen[lev][0], |
||||
lv = s->linelen[lev][1], |
||||
mh = s->mod[lev][0], |
||||
mv = s->mod[lev][1], |
||||
lp; |
||||
float *l; |
||||
|
||||
// HOR_SD
|
||||
l = line + mh; |
||||
for (lp = 0; lp < lv; lp++){ |
||||
int i, j = 0; |
||||
// copy with interleaving
|
||||
for (i = mh; i < lh; i+=2, j++) |
||||
l[i] = scale97[1-mh] * t[w*lp + j]; |
||||
for (i = 1-mh; i < lh; i+=2, j++) |
||||
l[i] = scale97[1-mh] * t[w*lp + j]; |
||||
|
||||
sr_1d97(line, mh, mh + lh); |
||||
|
||||
for (i = 0; i < lh; i++) |
||||
t[w*lp + i] = l[i]; |
||||
} |
||||
|
||||
// VER_SD
|
||||
l = line + mv; |
||||
for (lp = 0; lp < lh; lp++){ |
||||
int i, j = 0; |
||||
// copy with interleaving
|
||||
for (i = mv; i < lv; i+=2, j++) |
||||
l[i] = scale97[1-mv] * t[w*j + lp]; |
||||
for (i = 1-mv; i < lv; i+=2, j++) |
||||
l[i] = scale97[1-mv] * t[w*j + lp]; |
||||
|
||||
sr_1d97(line, mv, mv + lv); |
||||
|
||||
for (i = 0; i < lv; i++) |
||||
t[w*i + lp] = l[i]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
int ff_j2k_dwt_init(DWTContext *s, uint16_t border[2][2], int decomp_levels, int type) |
||||
{ |
||||
int i, j, lev = decomp_levels, maxlen, |
||||
b[2][2]; |
||||
|
||||
s->ndeclevels = decomp_levels; |
||||
s->type = type; |
||||
|
||||
for (i = 0; i < 2; i++) |
||||
for(j = 0; j < 2; j++) |
||||
b[i][j] = border[i][j]; |
||||
|
||||
maxlen = FFMAX(b[0][1] - b[0][0], |
||||
b[1][1] - b[1][0]); |
||||
|
||||
while(--lev >= 0){ |
||||
for (i = 0; i < 2; i++){ |
||||
s->linelen[lev][i] = b[i][1] - b[i][0]; |
||||
s->mod[lev][i] = b[i][0] & 1; |
||||
for (j = 0; j < 2; j++) |
||||
b[i][j] = (b[i][j] + 1) >> 1; |
||||
} |
||||
} |
||||
if (type == FF_DWT97) |
||||
s->linebuf = av_malloc((maxlen + 12) * sizeof(float)); |
||||
else if (type == FF_DWT53) |
||||
s->linebuf = av_malloc((maxlen + 6) * sizeof(int)); |
||||
else |
||||
return -1; |
||||
|
||||
if (!s->linebuf) |
||||
return AVERROR(ENOMEM); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int ff_j2k_dwt_encode(DWTContext *s, int *t) |
||||
{ |
||||
switch(s->type){ |
||||
case FF_DWT97: |
||||
dwt_encode97(s, t); break; |
||||
case FF_DWT53: |
||||
dwt_encode53(s, t); break; |
||||
default: |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int ff_j2k_dwt_decode(DWTContext *s, int *t) |
||||
{ |
||||
switch(s->type){ |
||||
case FF_DWT97: |
||||
dwt_decode97(s, t); break; |
||||
case FF_DWT53: |
||||
dwt_decode53(s, t); break; |
||||
default: |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
void ff_j2k_dwt_destroy(DWTContext *s) |
||||
{ |
||||
av_freep(&s->linebuf); |
||||
} |
@ -0,0 +1,63 @@ |
||||
/*
|
||||
* Discrete wavelet transform |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
#ifndef AVCODEC_DWT_H |
||||
#define AVCODEC_DWT_H |
||||
|
||||
/**
|
||||
* Discrete wavelet transform |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
#include "avcodec.h" |
||||
|
||||
#define FF_DWT_MAX_DECLVLS 32 ///< max number of decomposition levels
|
||||
|
||||
enum DWTType{ |
||||
FF_DWT97, |
||||
FF_DWT53 |
||||
}; |
||||
|
||||
typedef struct { |
||||
///line lengths {horizontal, vertical} in consecutive decomposition levels
|
||||
uint16_t linelen[FF_DWT_MAX_DECLVLS][2]; |
||||
uint8_t mod[FF_DWT_MAX_DECLVLS][2]; ///< coordinates (x0, y0) of decomp. levels mod 2
|
||||
uint8_t ndeclevels; ///< number of decomposition levels
|
||||
uint8_t type; ///< 0 for 9/7; 1 for 5/3
|
||||
void *linebuf; ///< buffer used by transform (int or float)
|
||||
} DWTContext; |
||||
|
||||
/**
|
||||
* initialize DWT |
||||
* @param s DWT context |
||||
* @param border coordinates of transformed region {{x0, x1}, {y0, y1}} |
||||
* @param decomp_levels number of decomposition levels |
||||
* @param type 0 for DWT 9/7; 1 for DWT 5/3 |
||||
*/ |
||||
int ff_j2k_dwt_init(DWTContext *s, uint16_t border[2][2], int decomp_levels, int type); |
||||
|
||||
int ff_j2k_dwt_encode(DWTContext *s, int *t); |
||||
int ff_j2k_dwt_decode(DWTContext *s, int *t); |
||||
|
||||
void ff_j2k_dwt_destroy(DWTContext *s); |
||||
|
||||
#endif /* AVCODEC_DWT_H */ |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,108 @@ |
||||
/*
|
||||
* MQ-coder encoder and decoder common functions |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; 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 |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
#include "mqc.h" |
||||
|
||||
typedef struct { |
||||
uint16_t qe; |
||||
uint8_t nmps; |
||||
uint8_t nlps; |
||||
uint8_t sw; |
||||
} MqcCxState; |
||||
|
||||
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; |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
/*
|
||||
* MQ-coder |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; 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; |
||||
|
||||
/* encoder */ |
||||
|
||||
/** initialize the encoder */ |
||||
void ff_mqc_initenc(MqcState *mqc, uint8_t *bp); |
||||
|
||||
/** code bit d with context cx */ |
||||
void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d); |
||||
|
||||
/** number of encoded bytes */ |
||||
int ff_mqc_length(MqcState *mqc); |
||||
|
||||
/** flush the encoder [returns number of bytes encoded] */ |
||||
int ff_mqc_flush(MqcState *mqc); |
||||
|
||||
/* 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 */ |
@ -0,0 +1,93 @@ |
||||
/*
|
||||
* MQ-coder decoder |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; 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); |
||||
} |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
@ -0,0 +1,119 @@ |
||||
/*
|
||||
* MQ-coder encoder |
||||
* Copyright (c) 2007 Kamil Nowosad |
||||
* |
||||
* This file is part of FFmpeg. |
||||
* |
||||
* FFmpeg 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. |
||||
* |
||||
* FFmpeg 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 FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* MQ-coder encoder |
||||
* @file |
||||
* @author Kamil Nowosad |
||||
*/ |
||||
|
||||
#include "mqc.h" |
||||
|
||||
static void byteout(MqcState *mqc) |
||||
{ |
||||
retry: |
||||
if (*mqc->bp == 0xff){ |
||||
mqc->bp++; |
||||
*mqc->bp = mqc->c >> 20; |
||||
mqc->c &= 0xfffff; |
||||
mqc->ct = 7; |
||||
} else if ((mqc->c & 0x8000000)){ |
||||
(*mqc->bp)++; |
||||
mqc->c &= 0x7ffffff; |
||||
goto retry; |
||||
} else{ |
||||
mqc->bp++; |
||||
*mqc->bp = mqc->c >> 19; |
||||
mqc->c &= 0x7ffff; |
||||
mqc->ct = 8; |
||||
} |
||||
} |
||||
|
||||
static void renorme(MqcState *mqc) |
||||
{ |
||||
do{ |
||||
mqc->a += mqc->a; |
||||
mqc->c += mqc->c; |
||||
if (!--mqc->ct) |
||||
byteout(mqc); |
||||
} while (!(mqc->a & 0x8000)); |
||||
} |
||||
|
||||
static void setbits(MqcState *mqc) |
||||
{ |
||||
int tmp = mqc->c + mqc->a; |
||||
mqc->c |= 0xffff; |
||||
if (mqc->c >= tmp) |
||||
mqc->c -= 0x8000; |
||||
} |
||||
|
||||
void ff_mqc_initenc(MqcState *mqc, uint8_t *bp) |
||||
{ |
||||
ff_mqc_init_contexts(mqc); |
||||
mqc->a = 0x8000; |
||||
mqc->c = 0; |
||||
mqc->bp = bp-1; |
||||
mqc->bpstart = bp; |
||||
mqc->ct = 12 + (*mqc->bp == 0xff); |
||||
} |
||||
|
||||
void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d) |
||||
{ |
||||
int qe; |
||||
|
||||
qe = ff_mqc_qe[*cxstate]; |
||||
mqc->a -= qe; |
||||
if ((*cxstate & 1) == d){ |
||||
if (!(mqc->a & 0x8000)){ |
||||
if (mqc->a < qe) |
||||
mqc->a = qe; |
||||
else |
||||
mqc->c += qe; |
||||
*cxstate = ff_mqc_nmps[*cxstate]; |
||||
renorme(mqc); |
||||
} else |
||||
mqc->c += qe; |
||||
} else{ |
||||
if (mqc->a < qe) |
||||
mqc->c += qe; |
||||
else |
||||
mqc->a = qe; |
||||
*cxstate = ff_mqc_nlps[*cxstate]; |
||||
renorme(mqc); |
||||
} |
||||
} |
||||
|
||||
int ff_mqc_length(MqcState *mqc) |
||||
{ |
||||
return mqc->bp - mqc->bpstart; |
||||
} |
||||
|
||||
int ff_mqc_flush(MqcState *mqc) |
||||
{ |
||||
setbits(mqc); |
||||
mqc->c = mqc->c << mqc->ct; |
||||
byteout(mqc); |
||||
mqc->c = mqc->c << mqc->ct; |
||||
byteout(mqc); |
||||
if (*mqc->bp != 0xff) |
||||
mqc->bp++; |
||||
return mqc->bp - mqc->bpstart; |
||||
} |
Loading…
Reference in new issue