Mercurial > libavcodec.hg
changeset 1306:799839d1e2e1 libavcodec
golomb rice codes
use gradients instead of prediction errors as context model
store independant quantization tables for each point
merge contexts with opposit sign
author | michaelni |
---|---|
date | Fri, 13 Jun 2003 21:31:28 +0000 |
parents | abca3b39231d |
children | 26bed13dd48d |
files | avcodec.h ffv1.c golomb.h |
diffstat | 3 files changed, 496 insertions(+), 167 deletions(-) [+] |
line wrap: on
line diff
--- a/avcodec.h Fri Jun 13 09:36:13 2003 +0000 +++ b/avcodec.h Fri Jun 13 21:31:28 2003 +0000 @@ -15,8 +15,8 @@ #define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION "0.4.6" -#define LIBAVCODEC_BUILD 4668 -#define LIBAVCODEC_BUILD_STR "4668" +#define LIBAVCODEC_BUILD 4669 +#define LIBAVCODEC_BUILD_STR "4669" #define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR @@ -1127,6 +1127,22 @@ * - decoding: unused */ int global_quality; + +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 + /** + * coder type + * - encoding: set by user. + * - decoding: unused + */ + int coder_type; + + /** + * context model + * - encoding: set by user. + * - decoding: unused + */ + int context_model; } AVCodecContext;
--- a/ffv1.c Fri Jun 13 09:36:13 2003 +0000 +++ b/ffv1.c Fri Jun 13 21:31:28 2003 +0000 @@ -28,74 +28,145 @@ #include "avcodec.h" #include "dsputil.h" #include "cabac.h" +#include "golomb.h" #define MAX_PLANES 4 #define CONTEXT_SIZE 32 -#if 0 -#define DEFAULT_QDIFF_COUNT (9) - -static const uint8_t default_quant_table[512]={ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, - 4, - 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -}; -#else -#define DEFAULT_QDIFF_COUNT (16) - -static const uint8_t default_quant_table[256]={ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +static const int8_t quant3[256]={ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, +}; +static const int8_t quant5[256]={ + 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, -8, - 9,10,11,11,12,12,12,12,13,13,13,13,13,13,13,13, -14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - }; -#endif - -static const int to5[16]={ -0,0,0,0, -0,0,0,1, -2,3,4,4, -4,4,4,4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-1, +}; +static const int8_t quant7[256]={ + 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2, +-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1, +}; +static const int8_t quant9[256]={ + 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3,-3,-3,-3, +-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-1,-1, +}; +static const int8_t quant11[256]={ + 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-4,-4, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4, +-4,-4,-4,-4,-4,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-1, +}; +static const int8_t quant13[256]={ + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, +-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, +-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, +-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6, +-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-6,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5, +-4,-4,-4,-4,-4,-4,-4,-4,-4,-3,-3,-3,-3,-2,-2,-1, }; +static const uint8_t log2_run[32]={ + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, + 8, 9,10,11,12,13,14,15, +}; + +typedef struct VlcState{ + int16_t drift; + uint16_t error_sum; + int8_t bias; + uint8_t count; +} VlcState; + typedef struct PlaneContext{ - uint8_t quant_table[256]; - int qdiff_count; int context_count; uint8_t (*state)[CONTEXT_SIZE]; + VlcState *vlc_state; uint8_t interlace_bit_state[2]; } PlaneContext; typedef struct FFV1Context{ AVCodecContext *avctx; CABACContext c; + GetBitContext gb; + PutBitContext pb; int version; int width, height; int chroma_h_shift, chroma_v_shift; @@ -103,67 +174,37 @@ int picture_number; AVFrame picture; int plane_count; + int ac; ///< 1-> CABAC 0-> golomb rice PlaneContext plane[MAX_PLANES]; + int16_t quant_table[5][256]; DSPContext dsp; }FFV1Context; - //1.774215 -static inline int predict(FFV1Context *s, uint8_t *src, int stride, int x, int y){ - if(x && y){ -// const int RT= src[+1-stride]; - const int LT= src[-1-stride]; - const int T= src[ -stride]; - const int L = src[-1 ]; - uint8_t *cm = cropTbl + MAX_NEG_CROP; - const int gradient= cm[L + T - LT]; +static inline int predict(uint8_t *src, uint8_t *last){ + const int LT= last[-1]; + const int T= last[ 0]; + const int L = src[-1]; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + const int gradient= cm[L + T - LT]; -// return gradient; - return mid_pred(L, gradient, T); - }else{ - if(y){ - return src[ -stride]; - }else if(x){ - return src[-1 ]; - }else{ - return 128; - } - } + return mid_pred(L, gradient, T); } +static inline int get_context(FFV1Context *f, uint8_t *src, uint8_t *last, uint8_t *last2){ + const int LT= last[-1]; + const int T= last[ 0]; + const int RT= last[ 1]; + const int L = src[-1]; -#if 0 -static inline void put_symbol(CABACContext, uint8_t *state, int v){ - put_cabac_ueg(c, state, v, 32, 1, 4 , 32); -} - -static inline int get_symbol(CABACContext, uint8_t *state){ - return get_cabac_ueg(c, state, 32, 1, 4 , 32); + if(f->quant_table[3][127]){ + const int TT= last2[0]; + const int LL= src[-2]; + return f->quant_table[0][(L-LT) & 0xFF] + f->quant_table[1][(LT-T) & 0xFF] + f->quant_table[2][(T-RT) & 0xFF] + +f->quant_table[3][(LL-L) & 0xFF] + f->quant_table[4][(TT-T) & 0xFF]; + }else + return f->quant_table[0][(L-LT) & 0xFF] + f->quant_table[1][(LT-T) & 0xFF] + f->quant_table[2][(T-RT) & 0xFF]; } -#elif 0 -static inline void put_symbol(CABACContext *c, uint8_t *state, int v){ - if(v==0) - put_cabac(c, state+0, 1); - else{ - put_cabac(c, state+0, 0); - put_cabac(c, state+1, v<0); - if(v<0) state += 64; - put_cabac_ueg(c, state+2, ABS(v)-1, 32, 0, 4 , 32); - } -} - -static inline int get_symbol(CABACContext *c, uint8_t *state){ - if(get_cabac(c, state+0)) - return 0; - else{ - int sign= get_cabac(c, state+1); - if(sign) - return -1-get_cabac_ueg(c, state+66, 32, 0, 4 , 32); - else - return 1+get_cabac_ueg(c, state+2 , 32, 0, 4 , 32); - } -} -#else /** * put @@ -214,53 +255,184 @@ return -128; } } + +static inline void update_vlc_state(VlcState * const state, const int v){ + int drift= state->drift; + int count= state->count; + state->error_sum += ABS(v); + drift += v; + + if(count == 128){ //FIXME variable + 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; +} + +static inline void put_vlc_symbol(PutBitContext *pb, VlcState * const state, int v){ + int i, k, code; +//printf("final: %d ", v); + v = (int8_t)(v - state->bias); + + i= state->count; + k=0; + while(i < state->error_sum){ //FIXME optimize + k++; + i += i; + } +#if 0 // JPEG LS + if(k==0 && 2*state->drift <= - state->count) code= v ^ (-1); + else code= v; +#else + code= v ^ ((2*state->drift + state->count)>>31); #endif + + code = -2*code-1; + code^= (code>>31); +//printf("v:%d/%d bias:%d error:%d drift:%d count:%d k:%d\n", v, code, state->bias, state->error_sum, state->drift, state->count, k); + set_ur_golomb(pb, code, k, 8, 8); + + update_vlc_state(state, v); +} + +static inline int get_vlc_symbol(GetBitContext *gb, VlcState * const state){ + int k, i, v, ret; + + i= state->count; + k=0; + while(i < state->error_sum){ //FIXME optimize + k++; + i += i; + } + + v= get_ur_golomb(gb, k, 8, 8); +//printf("v:%d bias:%d error:%d drift:%d count:%d k:%d", v, state->bias, state->error_sum, state->drift, state->count, k); + + v++; + if(v&1) v= (v>>1); + else v= -(v>>1); + +#if 0 // JPEG LS + if(k==0 && 2*state->drift <= - state->count) v ^= (-1); +#else + v ^= ((2*state->drift + state->count)>>31); +#endif + + ret= (int8_t)(v + state->bias); + + update_vlc_state(state, v); +//printf("final: %d\n", ret); + return ret; +} + + static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride, int plane_index){ PlaneContext * const p= &s->plane[plane_index]; CABACContext * const c= &s->c; int x,y; - uint8_t pred_diff_buffer[4][w+6]; + uint8_t pred_diff_buffer[4][w+6]; //FIXME rema,e uint8_t *pred_diff[4]= {pred_diff_buffer[0]+3, pred_diff_buffer[1]+3, pred_diff_buffer[2]+3, pred_diff_buffer[3]+3}; -// uint8_t temp_buf[3*w], *temp= temp_buf + 3*w; + int run_index=0; memset(pred_diff_buffer, 0, sizeof(pred_diff_buffer)); for(y=0; y<h; y++){ uint8_t *temp= pred_diff[0]; //FIXME try a normal buffer + int run_count=0; + int run_mode=0; pred_diff[0]= pred_diff[1]; pred_diff[1]= pred_diff[2]; pred_diff[2]= pred_diff[3]; pred_diff[3]= temp; + + pred_diff[3][-1]= pred_diff[2][0 ]; + pred_diff[2][ w]= pred_diff[2][w-1]; for(x=0; x<w; x++){ uint8_t *temp_src= src + x + stride*y; - int diff, context, qdiff; - - if(p->context_count == 256) - context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0]; - else - context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0] - + 16*16*to5[pred_diff[3-1][x+1]] + 16*16*5*to5[pred_diff[3-0][x-2]] + 16*16*5*5*to5[pred_diff[3-2][x+0]]; + int diff, context; + + context= get_context(s, pred_diff[3]+x, pred_diff[2]+x, pred_diff[1]+x); + diff= temp_src[0] - predict(pred_diff[3]+x, pred_diff[2]+x); + + if(context < 0){ + context = -context; + diff= -diff; + } + + diff= (int8_t)diff; + + if(s->ac) + put_symbol(c, p->state[context], diff, 1); + else{ + if(context == 0) run_mode=1; + + if(run_mode){ - diff = (int8_t)(temp_src[0] - predict(s, temp_src, stride, x, y)); - - qdiff= p->quant_table[128+diff]; + if(diff){ + while(run_count >= 1<<log2_run[run_index]){ + run_count -= 1<<log2_run[run_index]; + run_index++; + put_bits(&s->pb, 1, 1); + } + + put_bits(&s->pb, 1 + log2_run[run_index], run_count); + if(run_index) run_index--; + run_count=0; + run_mode=0; + if(diff>0) diff--; + }else{ + run_count++; + } + } + +// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, (int)get_bit_count(&s->pb)); - put_symbol(c, p->state[context], diff, 1); + if(run_mode == 0) + put_vlc_symbol(&s->pb, &p->vlc_state[context], diff); + } - pred_diff[3][x]= qdiff; + pred_diff[3][x]= temp_src[0]; + } + if(run_mode){ + while(run_count >= 1<<log2_run[run_index]){ + run_count -= 1<<log2_run[run_index]; + run_index++; + put_bits(&s->pb, 1, 1); + } + + if(run_count) + put_bits(&s->pb, 1, 1); } } } -static void write_quant_table(CABACContext *c, uint8_t *quant_table){ +static void write_quant_table(CABACContext *c, int16_t *quant_table){ int last=0; int i; uint8_t state[CONTEXT_SIZE]={0}; - for(i=1; i<256 ; i++){ + for(i=1; i<128 ; i++){ if(quant_table[i] != quant_table[i-1]){ put_symbol(c, state, i-last-1, 0); last= i; @@ -275,18 +447,15 @@ CABACContext * const c= &f->c; put_symbol(c, state, f->version, 0); + put_symbol(c, state, f->avctx->coder_type, 0); put_symbol(c, state, 0, 0); //YUV cs type put_cabac(c, state, 1); //chroma planes put_symbol(c, state, f->chroma_h_shift, 0); put_symbol(c, state, f->chroma_v_shift, 0); put_cabac(c, state, 0); //no transparency plane - for(i=0; i<3; i++){ //FIXME chroma & trasparency decission - PlaneContext * const p= &f->plane[i]; - - put_symbol(c, state, av_log2(p->context_count), 0); - write_quant_table(c, p->quant_table); - } + for(i=0; i<5; i++) + write_quant_table(c, f->quant_table[i]); } static int common_init(AVCodecContext *avctx){ @@ -314,21 +483,37 @@ common_init(avctx); s->version=0; + s->ac= avctx->coder_type; s->plane_count=3; + for(i=0; i<256; i++){ + s->quant_table[0][i]= quant11[i]; + s->quant_table[1][i]= 11*quant11[i]; + if(avctx->context_model==0){ + s->quant_table[2][i]= 11*11*quant11[i]; + s->quant_table[3][i]= + s->quant_table[4][i]=0; + }else{ + s->quant_table[2][i]= 11*11*quant5 [i]; + s->quant_table[3][i]= 5*11*11*quant5 [i]; + s->quant_table[4][i]= 5*5*11*11*quant5 [i]; + } + } for(i=0; i<s->plane_count; i++){ PlaneContext * const p= &s->plane[i]; - memcpy(p->quant_table, default_quant_table, sizeof(uint8_t)*256); - p->qdiff_count= DEFAULT_QDIFF_COUNT; - -#if 1 - p->context_count= 256; - p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); -#else - p->context_count= 16*16*128 /*5*5*5*/; - p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); -#endif + + if(avctx->context_model==0){ + p->context_count= (11*11*11+1)/2; + }else{ + p->context_count= (11*11*5*5*5+1)/2; + } + + if(s->ac){ + if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); + }else{ + if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState)); + } } avctx->coded_frame= &s->picture; @@ -362,8 +547,15 @@ p->interlace_bit_state[1]= 0; for(j=0; j<p->context_count; j++){ - memset(p->state[j], 0, sizeof(uint8_t)*CONTEXT_SIZE); - p->state[j][7] = 2*62; + if(f->ac){ + memset(p->state[j], 0, sizeof(uint8_t)*CONTEXT_SIZE); + p->state[j][7] = 2*62; + }else{ + p->vlc_state[j].drift= 0; + p->vlc_state[j].error_sum= 4; //FFMAX((RANGE + 32)/64, 2); + p->vlc_state[j].bias= 0; + p->vlc_state[j].count= 1; + } } } } @@ -375,6 +567,7 @@ const int width= f->width; const int height= f->height; AVFrame * const p= &f->picture; + int used_count= 0; if(avctx->strict_std_compliance >= 0){ printf("this codec is under development, files encoded with it wont be decodeable with future versions!!!\n" @@ -398,6 +591,12 @@ p->key_frame= 0; } + if(!f->ac){ + used_count += put_cabac_terminate(c, 1); +//printf("pos=%d\n", used_count); + init_put_bits(&f->pb, buf + used_count, buf_size - used_count, NULL, NULL); + } + if(1){ const int chroma_width = -((-width )>>f->chroma_h_shift); const int chroma_height= -((-height)>>f->chroma_v_shift); @@ -411,7 +610,12 @@ f->picture_number++; - return put_cabac_terminate(c, 1); + if(f->ac){ + return put_cabac_terminate(c, 1); + }else{ + flush_put_bits(&f->pb); //nicer padding FIXME + return used_count + (get_bit_count(&f->pb)+7)/8; + } } static void common_end(FFV1Context *s){ @@ -439,67 +643,109 @@ int x,y; uint8_t pred_diff_buffer[4][w+6]; uint8_t *pred_diff[4]= {pred_diff_buffer[0]+3, pred_diff_buffer[1]+3, pred_diff_buffer[2]+3, pred_diff_buffer[3]+3}; -// uint8_t temp_buf[3*w], *temp= temp_buf + 3*w; + int run_index=0; memset(pred_diff_buffer, 0, sizeof(pred_diff_buffer)); for(y=0; y<h; y++){ uint8_t *temp= pred_diff[0]; //FIXME try a normal buffer + int run_count=0; + int run_mode=0; pred_diff[0]= pred_diff[1]; pred_diff[1]= pred_diff[2]; pred_diff[2]= pred_diff[3]; pred_diff[3]= temp; + pred_diff[3][-1]= pred_diff[2][0 ]; + pred_diff[2][ w]= pred_diff[2][w-1]; + for(x=0; x<w; x++){ uint8_t *temp_src= src + x + stride*y; - int diff, context, qdiff; + int diff, context, sign; - if(p->context_count == 256) - context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0]; - else - context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0] - + 16*16*to5[pred_diff[3-1][x+1]] + 16*16*5*to5[pred_diff[3-0][x-2]] + 16*16*5*5*to5[pred_diff[3-2][x+0]]; + context= get_context(s, pred_diff[3] + x, pred_diff[2] + x, pred_diff[1] + x); + if(context < 0){ + context= -context; + sign=1; + }else + sign=0; + - diff= get_symbol(c, p->state[context], 1); + if(s->ac) + diff= get_symbol(c, p->state[context], 1); + else{ + if(context == 0 && run_mode==0) run_mode=1; + + if(run_mode){ + 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; + }else + diff= get_vlc_symbol(&s->gb, &p->vlc_state[context]); + +// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, get_bits_count(&s->gb)); + } - temp_src[0] = predict(s, temp_src, stride, x, y) + diff; + if(sign) diff= (int8_t)(-diff); //FIXME remove cast + + pred_diff[3][x]= + temp_src[0] = predict(pred_diff[3] + x, pred_diff[2] + x) + diff; assert(diff>= -128 && diff <= 127); - - qdiff= p->quant_table[128+diff]; - - pred_diff[3][x]= qdiff; } } } -static int read_quant_table(CABACContext *c, uint8_t *quant_table){ +static int read_quant_table(CABACContext *c, int16_t *quant_table, int scale){ int v; int i=0; uint8_t state[CONTEXT_SIZE]={0}; - for(v=0; i<256 ; v++){ + for(v=0; i<128 ; v++){ int len= get_symbol(c, state, 0) + 1; - if(len + i > 256) return -1; + if(len + i > 128) return -1; while(len--){ - quant_table[i++] = v; + quant_table[i] = scale*v; + i++; //printf("%2d ",v); //if(i%16==0) printf("\n"); } } + + for(i=1; i<128; i++){ + quant_table[256-i]= -quant_table[i]; + } + quant_table[128]= -quant_table[127]; - return v; + return 2*v - 1; } static int read_header(FFV1Context *f){ uint8_t state[CONTEXT_SIZE]={0}; - int i; + int i, context_count; CABACContext * const c= &f->c; f->version= get_symbol(c, state, 0); + f->ac= f->avctx->coder_type= get_symbol(c, state, 0); get_symbol(c, state, 0); //YUV cs type get_cabac(c, state); //no chroma = false f->chroma_h_shift= get_symbol(c, state, 0); @@ -507,15 +753,22 @@ get_cabac(c, state); //transparency plane f->plane_count= 3; + context_count=1; + for(i=0; i<5; i++){ + context_count*= read_quant_table(c, f->quant_table[i], context_count); + } + context_count= (context_count+1)/2; + for(i=0; i<f->plane_count; i++){ PlaneContext * const p= &f->plane[i]; - p->context_count= 1<<get_symbol(c, state, 0); - p->qdiff_count= read_quant_table(c, p->quant_table); - if(p->qdiff_count < 0) return -1; - - if(!p->state) - p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); + p->context_count= context_count; + + if(f->ac){ + if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); + }else{ + if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState)); + } } return 0; @@ -523,7 +776,7 @@ static int decode_init(AVCodecContext *avctx) { - FFV1Context *s = avctx->priv_data; +// FFV1Context *s = avctx->priv_data; common_init(avctx); @@ -587,6 +840,12 @@ if(avctx->debug&FF_DEBUG_PICT_INFO) printf("keyframe:%d\n", p->key_frame); + if(!f->ac){ + bytes_read = get_cabac_terminate(c); + if(bytes_read ==0) printf("error at end of AC stream\n"); +//printf("pos=%d\n", bytes_read); + init_get_bits(&f->gb, buf + bytes_read, buf_size - bytes_read); + } if(1){ const int chroma_width = -((-width )>>f->chroma_h_shift); @@ -607,9 +866,13 @@ *data_size = sizeof(AVFrame); - bytes_read= get_cabac_terminate(c); - if(bytes_read ==0) printf("error at end of frame\n"); - + if(f->ac){ + bytes_read= get_cabac_terminate(c); + if(bytes_read ==0) printf("error at end of frame\n"); + }else{ + bytes_read+= (get_bits_count(&f->gb)+7)/8; + } + return bytes_read; }
--- a/golomb.h Fri Jun 13 09:36:13 2003 +0000 +++ b/golomb.h Fri Jun 13 21:31:28 2003 +0000 @@ -178,6 +178,37 @@ } } +/** + * read unsigned golomb rice code. + */ +static inline int get_ur_golomb(GetBitContext *gb, int k, int limit, int esc_len){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + log= av_log2(buf); +//printf("buf:%X log:%d\n", buf, log); + if(log > 31-limit){ + buf >>= log - k; + buf += (30-log)<<k; + LAST_SKIP_BITS(re, gb, 32 + k - log); + CLOSE_READER(re, gb); + + return buf; + }else if(log == 31-limit){ + buf >>= log - esc_len; + buf -= 1<<esc_len; + LAST_SKIP_BITS(re, gb, esc_len + limit + 1); + CLOSE_READER(re, gb); + + return buf + 1; + }else + return -1; +} + #ifdef TRACE static inline int get_ue(GetBitContext *s, char *file, char *func, int line){ @@ -279,3 +310,22 @@ #endif set_ue_golomb(pb, i); } + +/** + * write unsigned golomb rice code. + */ +static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, int esc_len){ + int e; + + assert(i>=0); + + e= i>>k; + if(e<limit){ + put_bits(pb, e + k + 1, (1<<k) + (i&((1<<k)-1))); + }else{ +// printf("set %08X, %d\n", (1<<esc_len) + i - 1, limit + esc_len + 1); + put_bits(pb, limit + esc_len + 1, (1<<esc_len) + i - 1); +// put_bits(pb, 1, limit + 1); +// put_bits(pb, i - 1, esc_len); + } +}