mirror of https://github.com/FFmpeg/FFmpeg.git
Originally committed as revision 4752 to svn://svn.ffmpeg.org/ffmpeg/trunkpull/126/head
parent
a42bed52ca
commit
5639729bed
4 changed files with 457 additions and 9 deletions
@ -0,0 +1,391 @@ |
||||
/*
|
||||
* JPEG-LS encoder and decoder |
||||
* Copyright (c) 2003 Michael Niedermayer |
||||
* |
||||
* This library 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 of the License, or (at your option) any later version. |
||||
* |
||||
* This library 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 this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/**
|
||||
* @file jpeg_ls.c |
||||
* JPEG-LS encoder and decoder. |
||||
*/ |
||||
|
||||
#undef printf |
||||
#undef fprintf |
||||
|
||||
static inline int quantize(MJpegDecodeContext *s, int v){ //FIXME optimize
|
||||
if(v==0) return 0; |
||||
if(v < 0){ |
||||
if (v >-s->t1) return -1; |
||||
else if(v >-s->t2) return -2; |
||||
else if(v >-s->t3) return -3; |
||||
else return -4; |
||||
}else{ |
||||
if (v < s->t1) return 1; |
||||
else if(v < s->t2) return 2; |
||||
else if(v < s->t3) return 3; |
||||
else return 4; |
||||
} |
||||
} |
||||
|
||||
static inline int predict8(uint8_t *src, uint8_t *last){ //FIXME perhaps its better to suppress these 2
|
||||
const int LT= last[-1]; |
||||
const int T= last[ 0]; |
||||
const int L = src[-1]; |
||||
|
||||
return mid_pred(L, L + T - LT, T); |
||||
} |
||||
|
||||
static inline int predict16(uint16_t *src, uint16_t *last){ |
||||
const int LT= last[-1]; |
||||
const int T= last[ 0]; |
||||
const int L = src[-1]; |
||||
|
||||
return mid_pred(L, L + T - LT, T); |
||||
} |
||||
|
||||
static int encode_picture_ls(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ |
||||
return 0; |
||||
} |
||||
|
||||
static int iso_clip(int v, int vmin, int vmax){ |
||||
if(v > vmax || v < vmin) return vmin; |
||||
else return v; |
||||
} |
||||
|
||||
static void reset_ls_coding_parameters(MJpegDecodeContext *s, int reset_all){ |
||||
const int basic_t1= 3; |
||||
const int basic_t2= 7; |
||||
const int basic_t3= 21; |
||||
int factor; |
||||
|
||||
if(s->maxval==0 || reset_all) s->maxval= (1<<s->bits) - 1; |
||||
|
||||
if(s->maxval >=128){ |
||||
factor= (FFMIN(s->maxval, 4096) + 128)>>8; |
||||
|
||||
if(s->t1==0 || reset_all) |
||||
s->t1= iso_clip(factor*(basic_t1-2) + 2 + 3*s->near, s->near+1, s->maxval); |
||||
if(s->t2==0 || reset_all) |
||||
s->t2= iso_clip(factor*(basic_t2-3) + 3 + 5*s->near, s->t1, s->maxval); |
||||
if(s->t3==0 || reset_all) |
||||
s->t3= iso_clip(factor*(basic_t3-4) + 4 + 7*s->near, s->t2, s->maxval); |
||||
}else{ |
||||
factor= 256 / (s->maxval + 1); |
||||
|
||||
if(s->t1==0 || reset_all) |
||||
s->t1= iso_clip(FFMAX(2, basic_t1/factor + 3*s->near), s->near+1, s->maxval); |
||||
if(s->t2==0 || reset_all) |
||||
s->t2= iso_clip(FFMAX(3, basic_t2/factor + 5*s->near), s->t1, s->maxval); |
||||
if(s->t3==0 || reset_all) |
||||
s->t3= iso_clip(FFMAX(4, basic_t3/factor + 6*s->near), s->t2, s->maxval); |
||||
} |
||||
|
||||
if(s->reset==0 || reset_all) s->reset= 64; |
||||
} |
||||
|
||||
static int decode_lse(MJpegDecodeContext *s) |
||||
{ |
||||
int len, id; |
||||
|
||||
/* XXX: verify len field validity */ |
||||
len = get_bits(&s->gb, 16); |
||||
id = get_bits(&s->gb, 8); |
||||
|
||||
switch(id){ |
||||
case 1: |
||||
s->maxval= get_bits(&s->gb, 16); |
||||
s->t1= get_bits(&s->gb, 16); |
||||
s->t2= get_bits(&s->gb, 16); |
||||
s->t3= get_bits(&s->gb, 16); |
||||
s->reset= get_bits(&s->gb, 16); |
||||
|
||||
reset_ls_coding_parameters(s, 0); |
||||
//FIXME quant table?
|
||||
break; |
||||
case 2: |
||||
case 3: |
||||
printf("palette not supported\n"); |
||||
return -1; |
||||
case 4: |
||||
printf("oversize image not supported\n"); |
||||
return -1; |
||||
default: |
||||
printf("invalid id %d\n", id); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
#if 0 |
||||
static inline void update_vlc_state(VlcState * const state, const int v, int half_count){ |
||||
int drift= state->drift; |
||||
int count= state->count; |
||||
state->error_sum += ABS(v); |
||||
drift += v; |
||||
|
||||
if(count == half_count){ |
||||
count >>= 1; |
||||
drift >>= 1; |
||||
state->error_sum >>= 1; |
||||
} |
||||
count++; |
||||
|
||||
if(drift <= -count){ |
||||
if(state->bias > -128) state->bias--; |
||||
|
||||
drift += count; |
||||
if(drift <= -count) |
||||
drift= -count + 1; |
||||
}else if(drift > 0){ |
||||
if(state->bias < 127) state->bias++; |
||||
|
||||
drift -= count; |
||||
if(drift > 0)
|
||||
drift= 0; |
||||
} |
||||
|
||||
state->drift= drift; |
||||
state->count= count; |
||||
} |
||||
|
||||
#define R(p, i) (is_uint8 ? (((uint8_t*)p)[i] : ((uint16_t*)p)[i]) |
||||
|
||||
static inline int ls_decode_line(MJpegDecodeContext *s, void *lastv, void *dstv, int last2, |
||||
int w, int point_transform, int is_uint8){ |
||||
int i, x, y; |
||||
|
||||
for(x=0; x < w; x++){ |
||||
int l, t, lt, rt; |
||||
|
||||
t= R(last, 0); |
||||
if(x){ |
||||
l = t; |
||||
lt= last2; |
||||
}else{ |
||||
l = R(dst, x-1); |
||||
lt= R(last, x-1); |
||||
} |
||||
|
||||
if(x<w-1) rt= R(last, x+1); |
||||
else rt= t; |
||||
|
||||
hr_gradient= rt - t; |
||||
hl_gradient= t - lt; |
||||
v_gradient= lt - l; |
||||
|
||||
context= quantize(s, v_gradient) + 9*(quantize(s, hl_gradient) + 9*quantize(s, hr_gradient)); |
||||
|
||||
if(context){ |
||||
int pred= mid_pred(l, l + t - lt, t); |
||||
|
||||
if(context < 0){ |
||||
context= -context; |
||||
sign= 1; |
||||
pred= clip(0, pred - state->bias, maxval); |
||||
}else{ |
||||
sign= 0; |
||||
pred= clip(0, pred + state->bias, maxval); |
||||
} |
||||
|
||||
i= state->count; |
||||
k=0; |
||||
while(i < state->error_sum){ //FIXME optimize
|
||||
k++; |
||||
i += i; |
||||
} |
||||
|
||||
v= get_ur_golomb_jpegls(gb, k, LIMIT-qbpp, qbpp); |
||||
#if 1 |
||||
v++; |
||||
if(v&1) v= (v>>1); |
||||
else v= -(v>>1); |
||||
|
||||
if(k==0 && 2*state->drift <= - state->count) v ^= (-1); |
||||
#else |
||||
v ^= (k==0 && 2*state->drift <= - state->count); |
||||
v++; |
||||
if(v&1) v= (v>>1); |
||||
else v= -(v>>1); |
||||
|
||||
#endif |
||||
update_vlc_state(state, v, half_count); |
||||
|
||||
if(sign) v= -v; |
||||
|
||||
if(is_uint8) ((uint8_t *)dst)[x]= (pred + v) & maxval; |
||||
else ((uint16_t*)dst)[x]= (pred + v) & maxval; |
||||
}else{ |
||||
int run_count; |
||||
|
||||
while(get_bits1(&s->gb)){ |
||||
run_count = 1<<log2_run[run_index]; |
||||
if(x + run_count > w) run_count= w - x; |
||||
else run_index++; |
||||
|
||||
for(; run_count; run_count--){ |
||||
if(is_uint8) ((uint8_t *)dst)[x++]= l; |
||||
else ((uint16_t*)dst)[x++]= l; |
||||
} |
||||
|
||||
if(x >= w) return 0;
|
||||
} |
||||
|
||||
run_count= get_bits(&s->gb, log2_run[run_index]); |
||||
|
||||
for(; run_count; run_count--){ |
||||
if(is_uint8) ((uint8_t *)dst)[x++]= l; |
||||
else ((uint16_t*)dst)[x++]= l; |
||||
} |
||||
|
||||
if(run_index) run_index--; |
||||
|
||||
if(x >= w) return 0; |
||||
|
||||
t= R(last, 0); |
||||
|
||||
RItype= (l==t); |
||||
if(l==t){ |
||||
state= 366; |
||||
temp= state->error_sum + (state->count>>1); |
||||
}else{ |
||||
state= 365; |
||||
temp= state->error_sum; |
||||
} |
||||
|
||||
pred= t; |
||||
sign= l > t; |
||||
|
||||
i= state->count; |
||||
k=0; |
||||
while(i < temp){ //FIXME optimize
|
||||
k++; |
||||
i += i; |
||||
} |
||||
|
||||
assert(Errval != 0); |
||||
map = (k==0 && 2*Nn < state->count) == (Errval>0);
|
||||
|
||||
|
||||
if(run_count==0 && run_mode==1){ |
||||
if(get_bits1(&s->gb)){ |
||||
run_count = 1<<log2_run[run_index]; |
||||
if(x + run_count <= w) run_index++; |
||||
}else{ |
||||
if(log2_run[run_index]) run_count = get_bits(&s->gb, log2_run[run_index]); |
||||
else run_count=0; |
||||
if(run_index) run_index--; |
||||
run_mode=2; |
||||
} |
||||
} |
||||
run_count--; |
||||
if(run_count < 0){ |
||||
run_mode=0; |
||||
run_count=0; |
||||
diff= get_vlc_symbol(&s->gb, &p->vlc_state[context]); |
||||
if(diff>=0) diff++; |
||||
}else |
||||
diff=0; |
||||
|
||||
} |
||||
} |
||||
|
||||
/* if (s->restart_interval && !s->restart_count)
|
||||
s->restart_count = s->restart_interval;*/ |
||||
|
||||
if(mb_x==0 || mb_y==0 || s->interlaced){ |
||||
for(i=0;i<nb_components;i++) { |
||||
uint8_t *ptr; |
||||
int n, h, v, x, y, c, j, linesize; |
||||
n = s->nb_blocks[i]; |
||||
c = s->comp_index[i]; |
||||
h = s->h_scount[i]; |
||||
v = s->v_scount[i]; |
||||
x = 0; |
||||
y = 0; |
||||
linesize= s->linesize[c]; |
||||
|
||||
for(j=0; j<n; j++) { |
||||
int pred; |
||||
|
||||
ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
|
||||
if(y==0 && mb_y==0){ |
||||
if(x==0 && mb_x==0){ |
||||
pred= 128 << point_transform; |
||||
}else{ |
||||
pred= ptr[-1]; |
||||
} |
||||
}else{ |
||||
if(x==0 && mb_x==0){ |
||||
pred= ptr[-linesize]; |
||||
}else{ |
||||
PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); |
||||
} |
||||
} |
||||
|
||||
if (s->interlaced && s->bottom_field) |
||||
ptr += linesize >> 1; |
||||
*ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); |
||||
|
||||
if (++x == h) { |
||||
x = 0; |
||||
y++; |
||||
} |
||||
} |
||||
} |
||||
}else{ |
||||
for(i=0;i<nb_components;i++) { |
||||
uint8_t *ptr; |
||||
int n, h, v, x, y, c, j, linesize; |
||||
n = s->nb_blocks[i]; |
||||
c = s->comp_index[i]; |
||||
h = s->h_scount[i]; |
||||
v = s->v_scount[i]; |
||||
x = 0; |
||||
y = 0; |
||||
linesize= s->linesize[c]; |
||||
|
||||
for(j=0; j<n; j++) { |
||||
int pred; |
||||
|
||||
ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
|
||||
PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); |
||||
*ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); |
||||
if (++x == h) { |
||||
x = 0; |
||||
y++; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (s->restart_interval && !--s->restart_count) { |
||||
align_get_bits(&s->gb); |
||||
skip_bits(&s->gb, 16); /* skip RSTn */ |
||||
} |
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
#ifdef CONFIG_ENCODERS |
||||
AVCodec jpegls_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
|
||||
"jpegls", |
||||
CODEC_TYPE_VIDEO, |
||||
CODEC_ID_JPEGLS, |
||||
sizeof(MpegEncContext), |
||||
MPV_encode_init, |
||||
encode_picture_ls, |
||||
MPV_encode_end, |
||||
}; |
||||
#endif |
Loading…
Reference in new issue