- }
-
- return 0;
-}
-
-static av_always_inline void decode_line(FFV1Context *s, int w,
- int16_t *sample[2],
- int plane_index, int bits)
-{
- PlaneContext * const p= &s->plane[plane_index];
- RangeCoder * const c= &s->c;
- int x;
- int run_count=0;
- int run_mode=0;
- int run_index= s->run_index;
-
- for(x=0; x<w; x++){
- int diff, context, sign;
-
- context= get_context(p, sample[1] + x, sample[0] + x, sample[1] + x);
- if(context < 0){
- context= -context;
- sign=1;
- }else
- sign=0;
-
- av_assert2(context < p->context_count);
-
- if(s->ac){
- diff= get_symbol_inline(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<<ff_log2_run[run_index];
- if(x + run_count <= w) run_index++;
- }else{
- if(ff_log2_run[run_index]) run_count = get_bits(&s->gb, ff_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], bits);
- if(diff>=0) diff++;
- }else
- diff=0;
- }else
- diff= get_vlc_symbol(&s->gb, &p->vlc_state[context], bits);
-
-// 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));
- }
-
- if(sign) diff= -diff;
-
- sample[1][x]= (predict(sample[1] + x, sample[0] + x) + diff) & ((1<<bits)-1);
- }
- s->run_index= run_index;
-}
-
-static void decode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride, int plane_index){
- int x, y;
- int16_t *sample[2];
- sample[0]=s->sample_buffer +3;
- sample[1]=s->sample_buffer+w+6+3;
-
- s->run_index=0;
-
- memset(s->sample_buffer, 0, 2*(w+6)*sizeof(*s->sample_buffer));
-
- for(y=0; y<h; y++){
- int16_t *temp = sample[0]; //FIXME try a normal buffer
-
- sample[0]= sample[1];
- sample[1]= temp;
-
- sample[1][-1]= sample[0][0 ];
- sample[0][ w]= sample[0][w-1];
-
-//{START_TIMER
- if(s->avctx->bits_per_raw_sample <= 8){
- decode_line(s, w, sample, plane_index, 8);
- for(x=0; x<w; x++){
- src[x + stride*y]= sample[1][x];
- }
- }else{
- decode_line(s, w, sample, plane_index, s->avctx->bits_per_raw_sample);
- for(x=0; x<w; x++){
- ((uint16_t*)(src + stride*y))[x]= sample[1][x] << (16 - s->avctx->bits_per_raw_sample);
- }
- }
-//STOP_TIMER("decode-line")}
- }
-}
-
-static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
- int x, y, p;
- int16_t *sample[3][2];
- for(x=0; x<3; x++){
- sample[x][0] = s->sample_buffer + x*2 *(w+6) + 3;
- sample[x][1] = s->sample_buffer + (x*2+1)*(w+6) + 3;
- }
-
- s->run_index=0;
-
- memset(s->sample_buffer, 0, 6*(w+6)*sizeof(*s->sample_buffer));
-
- for(y=0; y<h; y++){
- for(p=0; p<3; p++){
- int16_t *temp = sample[p][0]; //FIXME try a normal buffer
-
- sample[p][0]= sample[p][1];
- sample[p][1]= temp;
-
- sample[p][1][-1]= sample[p][0][0 ];
- sample[p][0][ w]= sample[p][0][w-1];
- decode_line(s, w, sample[p], FFMIN(p, 1), 9);
- }
- for(x=0; x<w; x++){
- int g= sample[0][1][x];
- int b= sample[1][1][x];
- int r= sample[2][1][x];
-
-// assert(g>=0 && b>=0 && r>=0);
-// assert(g<256 && b<512 && r<512);
-
- b -= 0x100;
- r -= 0x100;
- g -= (b + r)>>2;
- b += g;
- r += g;
-
- src[x + stride*y]= b + (g<<8) + (r<<16) + (0xFF<<24);
- }
- }
-}
-
-static int decode_slice(AVCodecContext *c, void *arg){
- FFV1Context *fs= *(void**)arg;
- FFV1Context *f= fs->avctx->priv_data;
- int width = fs->slice_width;
- int height= fs->slice_height;
- int x= fs->slice_x;
- int y= fs->slice_y;
- AVFrame * const p= &f->picture;
-
- av_assert1(width && height);
- if(f->colorspace==0){
- const int chroma_width = -((-width )>>f->chroma_h_shift);
- const int chroma_height= -((-height)>>f->chroma_v_shift);
- const int cx= x>>f->chroma_h_shift;
- const int cy= y>>f->chroma_v_shift;
- decode_plane(fs, p->data[0] + x + y*p->linesize[0], width, height, p->linesize[0], 0);
-
- decode_plane(fs, p->data[1] + cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1);
- decode_plane(fs, p->data[2] + cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[2], 1);
- }else{
- decode_rgb_frame(fs, (uint32_t*)p->data[0] + x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
- }
-
- emms_c();
-
- return 0;
-}
-
-static int read_quant_table(RangeCoder *c, int16_t *quant_table, int scale){
- int v;
- int i=0;
- uint8_t state[CONTEXT_SIZE];
-
- memset(state, 128, sizeof(state));
-
- for(v=0; i<128 ; v++){
- int len= get_symbol(c, state, 0) + 1;
-
- if(len + i > 128) return -1;
-
- while(len--){
- 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 2*v - 1;
-}
-
-static int read_quant_tables(RangeCoder *c, int16_t quant_table[MAX_CONTEXT_INPUTS][256]){
- int i;
- int context_count=1;
-
- for(i=0; i<5; i++){
- context_count*= read_quant_table(c, quant_table[i], context_count);
- if(context_count > 32768U){
- return -1;
- }
- }
- return (context_count+1)/2;
-}
-
-static int read_extra_header(FFV1Context *f){
- RangeCoder * const c= &f->c;
- uint8_t state[CONTEXT_SIZE];
- int i, j, k;
- uint8_t state2[32][CONTEXT_SIZE];
-
- memset(state2, 128, sizeof(state2));
- memset(state, 128, sizeof(state));
-
- ff_init_range_decoder(c, f->avctx->extradata, f->avctx->extradata_size);
- ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
-
- f->version= get_symbol(c, state, 0);
- f->ac= f->avctx->coder_type= get_symbol(c, state, 0);
- if(f->ac>1){
- for(i=1; i<256; i++){
- f->state_transition[i]= get_symbol(c, state, 1) + c->one_state[i];
- }
- }
- f->colorspace= get_symbol(c, state, 0); //YUV cs type
- f->avctx->bits_per_raw_sample= get_symbol(c, state, 0);
- get_rac(c, state); //no chroma = false
- f->chroma_h_shift= get_symbol(c, state, 0);
- f->chroma_v_shift= get_symbol(c, state, 0);
- get_rac(c, state); //transparency plane
- f->plane_count= 2;
- f->num_h_slices= 1 + get_symbol(c, state, 0);
- f->num_v_slices= 1 + get_symbol(c, state, 0);
- if(f->num_h_slices > (unsigned)f->width || f->num_v_slices > (unsigned)f->height){
- av_log(f->avctx, AV_LOG_ERROR, "too many slices\n");
- return -1;
- }
-
- f->quant_table_count= get_symbol(c, state, 0);
- if(f->quant_table_count > (unsigned)MAX_QUANT_TABLES)
- return -1;
- for(i=0; i<f->quant_table_count; i++){
- if((f->context_count[i]= read_quant_tables(c, f->quant_tables[i])) < 0){
- av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
- return -1;
- }
- }
-
- if(allocate_initial_states(f) < 0)
- return AVERROR(ENOMEM);
-
- for(i=0; i<f->quant_table_count; i++){
- if(get_rac(c, state)){
- for(j=0; j<f->context_count[i]; j++){
- for(k=0; k<CONTEXT_SIZE; k++){
- int pred= j ? f->initial_states[i][j-1][k] : 128;
- f->initial_states[i][j][k]= (pred+get_symbol(c, state2[k], 1))&0xFF;
- }
- }
- }
- }
-
- return 0;
-}
-
-static int read_header(FFV1Context *f){
- uint8_t state[CONTEXT_SIZE];
- int i, j, context_count;
- RangeCoder * const c= &f->slice_context[0]->c;
-
- memset(state, 128, sizeof(state));
-
- if(f->version < 2){
- f->version= get_symbol(c, state, 0);
- f->ac= f->avctx->coder_type= get_symbol(c, state, 0);
- if(f->ac>1){
- for(i=1; i<256; i++){
- f->state_transition[i]= get_symbol(c, state, 1) + c->one_state[i];
- }
- }
- f->colorspace= get_symbol(c, state, 0); //YUV cs type
- if(f->version>0)
- f->avctx->bits_per_raw_sample= get_symbol(c, state, 0);
- get_rac(c, state); //no chroma = false
- f->chroma_h_shift= get_symbol(c, state, 0);
- f->chroma_v_shift= get_symbol(c, state, 0);
- get_rac(c, state); //transparency plane
- f->plane_count= 2;
- }
-
- if(f->colorspace==0){
- if(f->avctx->bits_per_raw_sample<=8){
- switch(16*f->chroma_h_shift + f->chroma_v_shift){
- case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P; break;
- case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P; break;
- case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P; break;
- case 0x20: f->avctx->pix_fmt= PIX_FMT_YUV411P; break;
- case 0x22: f->avctx->pix_fmt= PIX_FMT_YUV410P; break;
- default:
- av_log(f->avctx, AV_LOG_ERROR, "format not supported\n");
- return -1;
- }
- }else{
- switch(16*f->chroma_h_shift + f->chroma_v_shift){
- case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P16; break;
- case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P16; break;
- case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P16; break;
- default:
- av_log(f->avctx, AV_LOG_ERROR, "format not supported\n");
- return -1;
- }
- }
- }else if(f->colorspace==1){
- if(f->chroma_h_shift || f->chroma_v_shift){
- av_log(f->avctx, AV_LOG_ERROR, "chroma subsampling not supported in this colorspace\n");
- return -1;
- }
- f->avctx->pix_fmt= PIX_FMT_RGB32;
- }else{
- av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
- return -1;
- }
-
-//printf("%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift,f->avctx->pix_fmt);
- if(f->version < 2){
- context_count= read_quant_tables(c, f->quant_table);
- if(context_count < 0){
- av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
- return -1;
- }
- }else{
- f->slice_count= get_symbol(c, state, 0);
- if(f->slice_count > (unsigned)MAX_SLICES)
- return -1;
- }
-
- for(j=0; j<f->slice_count; j++){
- FFV1Context *fs= f->slice_context[j];
- fs->ac= f->ac;
-
- if(f->version >= 2){
- fs->slice_x = get_symbol(c, state, 0) *f->width ;
- fs->slice_y = get_symbol(c, state, 0) *f->height;
- fs->slice_width =(get_symbol(c, state, 0)+1)*f->width + fs->slice_x;
- fs->slice_height=(get_symbol(c, state, 0)+1)*f->height + fs->slice_y;
-
- fs->slice_x /= f->num_h_slices;
- fs->slice_y /= f->num_v_slices;
- fs->slice_width = fs->slice_width /f->num_h_slices - fs->slice_x;
- fs->slice_height = fs->slice_height/f->num_v_slices - fs->slice_y;
- if((unsigned)fs->slice_width > f->width || (unsigned)fs->slice_height > f->height)
- return -1;
- if( (unsigned)fs->slice_x + (uint64_t)fs->slice_width > f->width
- || (unsigned)fs->slice_y + (uint64_t)fs->slice_height > f->height)
- return -1;
- }
-
- for(i=0; i<f->plane_count; i++){
- PlaneContext * const p= &fs->plane[i];
-
- if(f->version >= 2){
- int idx=get_symbol(c, state, 0);
- if(idx > (unsigned)f->quant_table_count){
- av_log(f->avctx, AV_LOG_ERROR, "quant_table_index out of range\n");
- return -1;
- }
- p->quant_table_index= idx;
- memcpy(p->quant_table, f->quant_tables[idx], sizeof(p->quant_table));
- context_count= f->context_count[idx];
- }else{
- memcpy(p->quant_table, f->quant_table, sizeof(p->quant_table));
- }
-
- if(p->context_count < context_count){
- av_freep(&p->state);
- av_freep(&p->vlc_state);
- }
- p->context_count= context_count;
- }
- }