Mercurial > libavcodec.hg
comparison ffv1.c @ 1336:c16ac5b7ac79 libavcodec
20% less memory needed for 8bit AC state (worst compression rate loss was 0.2%, all other files had <=0.1% loss)
author | michaelni |
---|---|
date | Wed, 02 Jul 2003 10:45:04 +0000 |
parents | 1cbc2380d172 |
children | c4e6ed5319e7 |
comparison
equal
deleted
inserted
replaced
1335:b4a72edb3a71 | 1336:c16ac5b7ac79 |
---|---|
207 } | 207 } |
208 | 208 |
209 /** | 209 /** |
210 * put | 210 * put |
211 */ | 211 */ |
212 static inline void put_symbol(CABACContext *c, uint8_t *state, int v, int is_signed){ | 212 static inline void put_symbol(CABACContext *c, uint8_t *state, int v, int is_signed, int max_exp){ |
213 int i; | 213 int i; |
214 | 214 |
215 if(v){ | 215 if(v){ |
216 const int a= ABS(v); | 216 const int a= ABS(v); |
217 const int e= av_log2(a); | 217 const int e= av_log2(a); |
218 | 218 |
219 put_cabac(c, state+0, 0); | 219 put_cabac(c, state+0, 0); |
220 put_cabac_u(c, state+1, e, 7, 6, 1); //1..7 | 220 |
221 if(e<7){ | 221 for(i=0; i<e; i++){ |
222 put_cabac(c, state+1+i, 1); //1..8 | |
223 } | |
224 | |
225 if(e<max_exp){ | |
226 put_cabac(c, state+1+i, 0); //1..8 | |
227 | |
222 for(i=e-1; i>=0; i--){ | 228 for(i=e-1; i>=0; i--){ |
223 static const int offset[7]= {15+0, 15+0, 15+1, 15+3, 15+6, 15+10, 15+11}; | 229 put_cabac(c, state+16+e+i, (a>>i)&1); //17..29 |
224 put_cabac(c, state+offset[e]+i, (a>>i)&1); //15..31 | |
225 } | 230 } |
226 if(is_signed) | 231 if(is_signed) |
227 put_cabac(c, state+8 + e, v < 0); //8..14 | 232 put_cabac(c, state+9 + e, v < 0); //9..16 |
228 } | 233 } |
229 }else{ | 234 }else{ |
230 put_cabac(c, state+0, 1); | 235 put_cabac(c, state+0, 1); |
231 } | 236 } |
232 } | 237 } |
233 | 238 |
234 static inline int get_symbol(CABACContext *c, uint8_t *state, int is_signed){ | 239 static inline int get_symbol(CABACContext *c, uint8_t *state, int is_signed, int max_exp){ |
235 int i; | |
236 | |
237 if(get_cabac(c, state+0)) | 240 if(get_cabac(c, state+0)) |
238 return 0; | 241 return 0; |
239 else{ | 242 else{ |
240 const int e= get_cabac_u(c, state+1, 7, 6, 1); //1..7 | 243 int i, e; |
241 | 244 |
242 if(e<7){ | 245 for(e=0; e<max_exp; e++){ |
243 int a= 1<<e; | 246 int a= 1<<e; |
244 | 247 |
245 for(i=e-1; i>=0; i--){ | 248 if(get_cabac(c, state + 1 + e)==0){ // 1..8 |
246 static const int offset[7]= {15+0, 15+0, 15+1, 15+3, 15+6, 15+10, 15+11}; | 249 for(i=e-1; i>=0; i--){ |
247 a += get_cabac(c, state+offset[e]+i)<<i; //14..31 | 250 a += get_cabac(c, state+16+e+i)<<i; //17..29 |
251 } | |
252 | |
253 if(is_signed && get_cabac(c, state+9 + e)) //9..16 | |
254 return -a; | |
255 else | |
256 return a; | |
248 } | 257 } |
249 | 258 } |
250 if(is_signed && get_cabac(c, state+8 + e)) //8..14 | 259 return -(1<<e); |
251 return -a; | |
252 else | |
253 return a; | |
254 }else | |
255 return -128; | |
256 } | 260 } |
257 } | 261 } |
258 | 262 |
259 static inline void update_vlc_state(VlcState * const state, const int v){ | 263 static inline void update_vlc_state(VlcState * const state, const int v){ |
260 int drift= state->drift; | 264 int drift= state->drift; |
380 diff= -diff; | 384 diff= -diff; |
381 } | 385 } |
382 | 386 |
383 diff= (int8_t)diff; | 387 diff= (int8_t)diff; |
384 | 388 |
385 if(s->ac) | 389 if(s->ac){ |
386 put_symbol(c, p->state[context], diff, 1); | 390 put_symbol(c, p->state[context], diff, 1, 7); |
387 else{ | 391 }else{ |
388 if(context == 0) run_mode=1; | 392 if(context == 0) run_mode=1; |
389 | 393 |
390 if(run_mode){ | 394 if(run_mode){ |
391 | 395 |
392 if(diff){ | 396 if(diff){ |
432 int i; | 436 int i; |
433 uint8_t state[CONTEXT_SIZE]={0}; | 437 uint8_t state[CONTEXT_SIZE]={0}; |
434 | 438 |
435 for(i=1; i<128 ; i++){ | 439 for(i=1; i<128 ; i++){ |
436 if(quant_table[i] != quant_table[i-1]){ | 440 if(quant_table[i] != quant_table[i-1]){ |
437 put_symbol(c, state, i-last-1, 0); | 441 put_symbol(c, state, i-last-1, 0, 7); |
438 last= i; | 442 last= i; |
439 } | 443 } |
440 } | 444 } |
441 put_symbol(c, state, i-last-1, 0); | 445 put_symbol(c, state, i-last-1, 0, 7); |
442 } | 446 } |
443 | 447 |
444 static void write_header(FFV1Context *f){ | 448 static void write_header(FFV1Context *f){ |
445 uint8_t state[CONTEXT_SIZE]={0}; | 449 uint8_t state[CONTEXT_SIZE]={0}; |
446 int i; | 450 int i; |
447 CABACContext * const c= &f->c; | 451 CABACContext * const c= &f->c; |
448 | 452 |
449 put_symbol(c, state, f->version, 0); | 453 put_symbol(c, state, f->version, 0, 7); |
450 put_symbol(c, state, f->avctx->coder_type, 0); | 454 put_symbol(c, state, f->avctx->coder_type, 0, 7); |
451 put_symbol(c, state, 0, 0); //YUV cs type | 455 put_symbol(c, state, 0, 0, 7); //YUV cs type |
452 put_cabac(c, state, 1); //chroma planes | 456 put_cabac(c, state, 1); //chroma planes |
453 put_symbol(c, state, f->chroma_h_shift, 0); | 457 put_symbol(c, state, f->chroma_h_shift, 0, 7); |
454 put_symbol(c, state, f->chroma_v_shift, 0); | 458 put_symbol(c, state, f->chroma_v_shift, 0, 7); |
455 put_cabac(c, state, 0); //no transparency plane | 459 put_cabac(c, state, 0); //no transparency plane |
456 | 460 |
457 for(i=0; i<5; i++) | 461 for(i=0; i<5; i++) |
458 write_quant_table(c, f->quant_table[i]); | 462 write_quant_table(c, f->quant_table[i]); |
459 } | 463 } |
671 }else | 675 }else |
672 sign=0; | 676 sign=0; |
673 | 677 |
674 | 678 |
675 if(s->ac) | 679 if(s->ac) |
676 diff= get_symbol(c, p->state[context], 1); | 680 diff= get_symbol(c, p->state[context], 1, 7); |
677 else{ | 681 else{ |
678 if(context == 0 && run_mode==0) run_mode=1; | 682 if(context == 0 && run_mode==0) run_mode=1; |
679 | 683 |
680 if(run_mode){ | 684 if(run_mode){ |
681 if(run_count==0 && run_mode==1){ | 685 if(run_count==0 && run_mode==1){ |
717 int v; | 721 int v; |
718 int i=0; | 722 int i=0; |
719 uint8_t state[CONTEXT_SIZE]={0}; | 723 uint8_t state[CONTEXT_SIZE]={0}; |
720 | 724 |
721 for(v=0; i<128 ; v++){ | 725 for(v=0; i<128 ; v++){ |
722 int len= get_symbol(c, state, 0) + 1; | 726 int len= get_symbol(c, state, 0, 7) + 1; |
723 | 727 |
724 if(len + i > 128) return -1; | 728 if(len + i > 128) return -1; |
725 | 729 |
726 while(len--){ | 730 while(len--){ |
727 quant_table[i] = scale*v; | 731 quant_table[i] = scale*v; |
742 static int read_header(FFV1Context *f){ | 746 static int read_header(FFV1Context *f){ |
743 uint8_t state[CONTEXT_SIZE]={0}; | 747 uint8_t state[CONTEXT_SIZE]={0}; |
744 int i, context_count; | 748 int i, context_count; |
745 CABACContext * const c= &f->c; | 749 CABACContext * const c= &f->c; |
746 | 750 |
747 f->version= get_symbol(c, state, 0); | 751 f->version= get_symbol(c, state, 0, 7); |
748 f->ac= f->avctx->coder_type= get_symbol(c, state, 0); | 752 f->ac= f->avctx->coder_type= get_symbol(c, state, 0, 7); |
749 get_symbol(c, state, 0); //YUV cs type | 753 get_symbol(c, state, 0, 7); //YUV cs type |
750 get_cabac(c, state); //no chroma = false | 754 get_cabac(c, state); //no chroma = false |
751 f->chroma_h_shift= get_symbol(c, state, 0); | 755 f->chroma_h_shift= get_symbol(c, state, 0, 7); |
752 f->chroma_v_shift= get_symbol(c, state, 0); | 756 f->chroma_v_shift= get_symbol(c, state, 0, 7); |
753 get_cabac(c, state); //transparency plane | 757 get_cabac(c, state); //transparency plane |
754 f->plane_count= 3; | 758 f->plane_count= 3; |
755 | 759 |
760 switch(16*f->chroma_h_shift + f->chroma_v_shift){ | |
761 case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P; break; | |
762 case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P; break; | |
763 case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P; break; | |
764 case 0x20: f->avctx->pix_fmt= PIX_FMT_YUV411P; break; | |
765 case 0x33: f->avctx->pix_fmt= PIX_FMT_YUV410P; break; | |
766 default: | |
767 fprintf(stderr, "format not supported\n"); | |
768 return -1; | |
769 } | |
770 //printf("%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift,f->avctx->pix_fmt); | |
771 | |
756 context_count=1; | 772 context_count=1; |
757 for(i=0; i<5; i++){ | 773 for(i=0; i<5; i++){ |
758 context_count*= read_quant_table(c, f->quant_table[i], context_count); | 774 context_count*= read_quant_table(c, f->quant_table[i], context_count); |
775 if(context_count < 0){ | |
776 printf("read_quant_table error\n"); | |
777 return -1; | |
778 } | |
759 } | 779 } |
760 context_count= (context_count+1)/2; | 780 context_count= (context_count+1)/2; |
761 | 781 |
762 for(i=0; i<f->plane_count; i++){ | 782 for(i=0; i<f->plane_count; i++){ |
763 PlaneContext * const p= &f->plane[i]; | 783 PlaneContext * const p= &f->plane[i]; |
821 return 0; | 841 return 0; |
822 | 842 |
823 ff_init_cabac_decoder(c, buf, buf_size); | 843 ff_init_cabac_decoder(c, buf, buf_size); |
824 ff_init_cabac_states(c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64); | 844 ff_init_cabac_states(c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64); |
825 | 845 |
826 p->reference= 0; | |
827 if(avctx->get_buffer(avctx, p) < 0){ | |
828 fprintf(stderr, "get_buffer() failed\n"); | |
829 return -1; | |
830 } | |
831 | |
832 p->pict_type= FF_I_TYPE; //FIXME I vs. P | 846 p->pict_type= FF_I_TYPE; //FIXME I vs. P |
833 if(get_cabac_bypass(c)){ | 847 if(get_cabac_bypass(c)){ |
834 p->key_frame= 1; | 848 p->key_frame= 1; |
835 read_header(f); | 849 read_header(f); |
836 clear_state(f); | 850 clear_state(f); |
837 }else{ | 851 }else{ |
838 p->key_frame= 0; | 852 p->key_frame= 0; |
839 } | 853 } |
854 | |
855 p->reference= 0; | |
856 if(avctx->get_buffer(avctx, p) < 0){ | |
857 fprintf(stderr, "get_buffer() failed\n"); | |
858 return -1; | |
859 } | |
860 | |
840 if(avctx->debug&FF_DEBUG_PICT_INFO) | 861 if(avctx->debug&FF_DEBUG_PICT_INFO) |
841 printf("keyframe:%d\n", p->key_frame); | 862 printf("keyframe:%d coder:%d\n", p->key_frame, f->ac); |
842 | 863 |
843 if(!f->ac){ | 864 if(!f->ac){ |
844 bytes_read = get_cabac_terminate(c); | 865 bytes_read = get_cabac_terminate(c); |
845 if(bytes_read ==0) printf("error at end of AC stream\n"); | 866 if(bytes_read ==0) printf("error at end of AC stream\n"); |
846 //printf("pos=%d\n", bytes_read); | 867 //printf("pos=%d\n", bytes_read); |