Mercurial > libavcodec.hg
view jpeg_ls.c @ 3010:533c6386eca9 libavcodec
8x8 integer dct from x264 as cmp function (under CONFIG_GPL)
if this gives better quality then SATD then someone should port the x86 code too or maybe we could even just call it from libx264
the 4x4 one could be tried too ...
author | michael |
---|---|
date | Wed, 04 Jan 2006 16:31:23 +0000 |
parents | 583b6ac45c07 |
children | 0b546eab515d |
line wrap: on
line source
/* * 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