golomb rice codes

use gradients instead of prediction errors as context model
store independant quantization tables for each point
merge contexts with opposit sign

Originally committed as revision 1957 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer 2003-06-13 21:31:28 +00:00
parent 5dbafeb7ba
commit 11e659c203
3 changed files with 497 additions and 168 deletions

View File

@ -15,8 +15,8 @@ extern "C" {
#define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION_INT 0x000406
#define LIBAVCODEC_VERSION "0.4.6" #define LIBAVCODEC_VERSION "0.4.6"
#define LIBAVCODEC_BUILD 4668 #define LIBAVCODEC_BUILD 4669
#define LIBAVCODEC_BUILD_STR "4668" #define LIBAVCODEC_BUILD_STR "4669"
#define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR #define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR
@ -1127,6 +1127,22 @@ typedef struct AVCodecContext {
* - decoding: unused * - decoding: unused
*/ */
int global_quality; 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; } AVCodecContext;

View File

@ -28,74 +28,145 @@
#include "avcodec.h" #include "avcodec.h"
#include "dsputil.h" #include "dsputil.h"
#include "cabac.h" #include "cabac.h"
#include "golomb.h"
#define MAX_PLANES 4 #define MAX_PLANES 4
#define CONTEXT_SIZE 32 #define CONTEXT_SIZE 32
#if 0 static const int8_t quant3[256]={
#define DEFAULT_QDIFF_COUNT (9) 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,
static const uint8_t default_quant_table[512]={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
4, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0,
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 static const int8_t quant5[256]={
#define DEFAULT_QDIFF_COUNT (16) 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
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,
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,
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, 4, 4, 4, 4, 5, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
9,10,11,11,12,12,12,12,13,13,13,13,13,13,13,13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, -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,
#endif -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,
static const int to5[16]={ -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-1,
0,0,0,0,
0,0,0,1,
2,3,4,4,
4,4,4,4,
}; };
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{ typedef struct PlaneContext{
uint8_t quant_table[256];
int qdiff_count;
int context_count; int context_count;
uint8_t (*state)[CONTEXT_SIZE]; uint8_t (*state)[CONTEXT_SIZE];
VlcState *vlc_state;
uint8_t interlace_bit_state[2]; uint8_t interlace_bit_state[2];
} PlaneContext; } PlaneContext;
typedef struct FFV1Context{ typedef struct FFV1Context{
AVCodecContext *avctx; AVCodecContext *avctx;
CABACContext c; CABACContext c;
GetBitContext gb;
PutBitContext pb;
int version; int version;
int width, height; int width, height;
int chroma_h_shift, chroma_v_shift; int chroma_h_shift, chroma_v_shift;
@ -103,68 +174,38 @@ typedef struct FFV1Context{
int picture_number; int picture_number;
AVFrame picture; AVFrame picture;
int plane_count; int plane_count;
int ac; ///< 1-> CABAC 0-> golomb rice
PlaneContext plane[MAX_PLANES]; PlaneContext plane[MAX_PLANES];
int16_t quant_table[5][256];
DSPContext dsp; DSPContext dsp;
}FFV1Context; }FFV1Context;
//1.774215 static inline int predict(uint8_t *src, uint8_t *last){
static inline int predict(FFV1Context *s, uint8_t *src, int stride, int x, int y){ const int LT= last[-1];
if(x && y){ const int T= last[ 0];
// const int RT= src[+1-stride]; const int L = src[-1];
const int LT= src[-1-stride]; uint8_t *cm = cropTbl + MAX_NEG_CROP;
const int T= src[ -stride]; const int gradient= cm[L + T - LT];
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);
return mid_pred(L, gradient, T);
}else{
if(y){
return src[ -stride];
}else if(x){
return src[-1 ];
}else{
return 128;
}
}
} }
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 if(f->quant_table[3][127]){
static inline void put_symbol(CABACContext, uint8_t *state, int v){ const int TT= last2[0];
put_cabac_ueg(c, state, v, 32, 1, 4 , 32); 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];
} }
static inline int get_symbol(CABACContext, uint8_t *state){
return get_cabac_ueg(c, state, 32, 1, 4 , 32);
}
#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 * put
*/ */
@ -214,53 +255,184 @@ static inline int get_symbol(CABACContext *c, uint8_t *state, int is_signed){
return -128; 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 #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){ 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]; PlaneContext * const p= &s->plane[plane_index];
CABACContext * const c= &s->c; CABACContext * const c= &s->c;
int x,y; 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 *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)); memset(pred_diff_buffer, 0, sizeof(pred_diff_buffer));
for(y=0; y<h; y++){ for(y=0; y<h; y++){
uint8_t *temp= pred_diff[0]; //FIXME try a normal buffer 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[0]= pred_diff[1];
pred_diff[1]= pred_diff[2]; pred_diff[1]= pred_diff[2];
pred_diff[2]= pred_diff[3]; pred_diff[2]= pred_diff[3];
pred_diff[3]= temp; 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++){ for(x=0; x<w; x++){
uint8_t *temp_src= src + x + stride*y; uint8_t *temp_src= src + x + stride*y;
int diff, context, qdiff; int diff, context;
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]];
diff = (int8_t)(temp_src[0] - predict(s, temp_src, stride, x, y));
qdiff= p->quant_table[128+diff]; 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);
put_symbol(c, p->state[context], diff, 1); if(context < 0){
context = -context;
diff= -diff;
}
pred_diff[3][x]= qdiff; 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){
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));
if(run_mode == 0)
put_vlc_symbol(&s->pb, &p->vlc_state[context], diff);
}
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 last=0;
int i; int i;
uint8_t state[CONTEXT_SIZE]={0}; 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]){ if(quant_table[i] != quant_table[i-1]){
put_symbol(c, state, i-last-1, 0); put_symbol(c, state, i-last-1, 0);
last= i; last= i;
@ -275,18 +447,15 @@ static void write_header(FFV1Context *f){
CABACContext * const c= &f->c; CABACContext * const c= &f->c;
put_symbol(c, state, f->version, 0); 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_symbol(c, state, 0, 0); //YUV cs type
put_cabac(c, state, 1); //chroma planes put_cabac(c, state, 1); //chroma planes
put_symbol(c, state, f->chroma_h_shift, 0); put_symbol(c, state, f->chroma_h_shift, 0);
put_symbol(c, state, f->chroma_v_shift, 0); put_symbol(c, state, f->chroma_v_shift, 0);
put_cabac(c, state, 0); //no transparency plane put_cabac(c, state, 0); //no transparency plane
for(i=0; i<3; i++){ //FIXME chroma & trasparency decission for(i=0; i<5; i++)
PlaneContext * const p= &f->plane[i]; write_quant_table(c, f->quant_table[i]);
put_symbol(c, state, av_log2(p->context_count), 0);
write_quant_table(c, p->quant_table);
}
} }
static int common_init(AVCodecContext *avctx){ static int common_init(AVCodecContext *avctx){
@ -314,21 +483,37 @@ static int encode_init(AVCodecContext *avctx)
common_init(avctx); common_init(avctx);
s->version=0; s->version=0;
s->ac= avctx->coder_type;
s->plane_count=3; 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++){ for(i=0; i<s->plane_count; i++){
PlaneContext * const p= &s->plane[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(avctx->context_model==0){
p->context_count= (11*11*11+1)/2;
#if 1 }else{
p->context_count= 256; p->context_count= (11*11*5*5*5+1)/2;
p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); }
#else
p->context_count= 16*16*128 /*5*5*5*/; if(s->ac){
p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t));
#endif }else{
if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState));
}
} }
avctx->coded_frame= &s->picture; avctx->coded_frame= &s->picture;
@ -362,8 +547,15 @@ static void clear_state(FFV1Context *f){
p->interlace_bit_state[1]= 0; p->interlace_bit_state[1]= 0;
for(j=0; j<p->context_count; j++){ for(j=0; j<p->context_count; j++){
memset(p->state[j], 0, sizeof(uint8_t)*CONTEXT_SIZE); if(f->ac){
p->state[j][7] = 2*62; 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 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
const int width= f->width; const int width= f->width;
const int height= f->height; const int height= f->height;
AVFrame * const p= &f->picture; AVFrame * const p= &f->picture;
int used_count= 0;
if(avctx->strict_std_compliance >= 0){ if(avctx->strict_std_compliance >= 0){
printf("this codec is under development, files encoded with it wont be decodeable with future versions!!!\n" printf("this codec is under development, files encoded with it wont be decodeable with future versions!!!\n"
@ -398,6 +591,12 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
p->key_frame= 0; 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){ if(1){
const int chroma_width = -((-width )>>f->chroma_h_shift); const int chroma_width = -((-width )>>f->chroma_h_shift);
const int chroma_height= -((-height)>>f->chroma_v_shift); const int chroma_height= -((-height)>>f->chroma_v_shift);
@ -411,7 +610,12 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
f->picture_number++; 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){ static void common_end(FFV1Context *s){
@ -439,67 +643,109 @@ static void decode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride,
int x,y; int x,y;
uint8_t pred_diff_buffer[4][w+6]; 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 *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)); memset(pred_diff_buffer, 0, sizeof(pred_diff_buffer));
for(y=0; y<h; y++){ for(y=0; y<h; y++){
uint8_t *temp= pred_diff[0]; //FIXME try a normal buffer 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[0]= pred_diff[1];
pred_diff[1]= pred_diff[2]; pred_diff[1]= pred_diff[2];
pred_diff[2]= pred_diff[3]; pred_diff[2]= pred_diff[3];
pred_diff[3]= temp; 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++){ for(x=0; x<w; x++){
uint8_t *temp_src= src + x + stride*y; uint8_t *temp_src= src + x + stride*y;
int diff, context, qdiff; int diff, context, sign;
if(p->context_count == 256) context= get_context(s, pred_diff[3] + x, pred_diff[2] + x, pred_diff[1] + x);
context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0]; if(context < 0){
else context= -context;
context= pred_diff[3+0][x-1] + 16*pred_diff[3-1][x+0] sign=1;
+ 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]]; }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); 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 v;
int i=0; int i=0;
uint8_t state[CONTEXT_SIZE]={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; int len= get_symbol(c, state, 0) + 1;
if(len + i > 256) return -1; if(len + i > 128) return -1;
while(len--){ while(len--){
quant_table[i++] = v; quant_table[i] = scale*v;
i++;
//printf("%2d ",v); //printf("%2d ",v);
//if(i%16==0) printf("\n"); //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){ static int read_header(FFV1Context *f){
uint8_t state[CONTEXT_SIZE]={0}; uint8_t state[CONTEXT_SIZE]={0};
int i; int i, context_count;
CABACContext * const c= &f->c; CABACContext * const c= &f->c;
f->version= get_symbol(c, state, 0); 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_symbol(c, state, 0); //YUV cs type
get_cabac(c, state); //no chroma = false get_cabac(c, state); //no chroma = false
f->chroma_h_shift= get_symbol(c, state, 0); f->chroma_h_shift= get_symbol(c, state, 0);
@ -507,15 +753,22 @@ static int read_header(FFV1Context *f){
get_cabac(c, state); //transparency plane get_cabac(c, state); //transparency plane
f->plane_count= 3; 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++){ for(i=0; i<f->plane_count; i++){
PlaneContext * const p= &f->plane[i]; PlaneContext * const p= &f->plane[i];
p->context_count= 1<<get_symbol(c, state, 0); p->context_count= context_count;
p->qdiff_count= read_quant_table(c, p->quant_table);
if(p->qdiff_count < 0) return -1; if(f->ac){
if(!p->state) p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t));
if(!p->state) }else{
p->state= av_malloc(CONTEXT_SIZE*p->context_count*sizeof(uint8_t)); if(!p->vlc_state) p->vlc_state= av_malloc(p->context_count*sizeof(VlcState));
}
} }
return 0; return 0;
@ -523,7 +776,7 @@ static int read_header(FFV1Context *f){
static int decode_init(AVCodecContext *avctx) static int decode_init(AVCodecContext *avctx)
{ {
FFV1Context *s = avctx->priv_data; // FFV1Context *s = avctx->priv_data;
common_init(avctx); common_init(avctx);
@ -587,6 +840,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8
if(avctx->debug&FF_DEBUG_PICT_INFO) if(avctx->debug&FF_DEBUG_PICT_INFO)
printf("keyframe:%d\n", p->key_frame); 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){ if(1){
const int chroma_width = -((-width )>>f->chroma_h_shift); const int chroma_width = -((-width )>>f->chroma_h_shift);
@ -607,9 +866,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8
*data_size = sizeof(AVFrame); *data_size = sizeof(AVFrame);
bytes_read= get_cabac_terminate(c); if(f->ac){
if(bytes_read ==0) printf("error at end of frame\n"); 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; return bytes_read;
} }

View File

@ -178,6 +178,37 @@ static inline int svq3_get_se_golomb(GetBitContext *gb){
} }
} }
/**
* 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 #ifdef TRACE
static inline int get_ue(GetBitContext *s, char *file, char *func, int line){ static inline int get_ue(GetBitContext *s, char *file, char *func, int line){
@ -279,3 +310,22 @@ static inline void set_se_golomb(PutBitContext *pb, int i){
#endif #endif
set_ue_golomb(pb, i); 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);
}
}