int run_index;
int colorspace;
int_fast16_t *sample_buffer;
+ int gob_count;
int quant_table_count;
return p->quant_table[0][(L-LT) & 0xFF] + p->quant_table[1][(LT-T) & 0xFF] + p->quant_table[2][(T-RT) & 0xFF];
}
+static void find_best_state(uint8_t best_state[256][256], const uint8_t one_state[256]){
+ int i,j,k,m;
+ double l2tab[256];
+
+ for(i=1; i<256; i++)
+ l2tab[i]= log2(i/256.0);
+
+ for(i=0; i<256; i++){
+ double best_len[256];
+ double p= i/256.0;
+
+ for(j=0; j<256; j++)
+ best_len[j]= 1<<30;
+
+ for(j=FFMAX(i-10,1); j<FFMIN(i+11,256); j++){
+ double occ[256]={0};
+ double len=0;
+ occ[j]=1.0;
+ for(k=0; k<256; k++){
+ double newocc[256]={0};
+ for(m=0; m<256; m++){
+ if(occ[m]){
+ len -=occ[m]*( p *l2tab[ m]
+ + (1-p)*l2tab[256-m]);
+ }
+ }
+ if(len < best_len[k]){
+ best_len[k]= len;
+ best_state[i][k]= j;
+ }
+ for(m=0; m<256; m++){
+ if(occ[m]){
+ newocc[ one_state[ m]] += occ[m]* p ;
+ newocc[256-one_state[256-m]] += occ[m]*(1-p);
+ }
+ }
+ memcpy(occ, newocc, sizeof(occ));
+ }
+ }
+ }
+}
+
static av_always_inline av_flatten void put_symbol_inline(RangeCoder *c, uint8_t *state, int v, int is_signed, uint64_t rc_stat[256][2], uint64_t rc_stat2[32][2]){
int i;
int sye= f->avctx->height*(sy+1) / f->num_v_slices;
f->slice_context[i]= fs;
memcpy(fs, f, sizeof(*fs));
+ memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2));
fs->slice_width = sxe - sxs;
fs->slice_height= sye - sys;
static av_cold int encode_init(AVCodecContext *avctx)
{
FFV1Context *s = avctx->priv_data;
- int i, j;
+ int i, j, k, m;
common_init(avctx);
s->picture_number=0;
+ if(avctx->flags & (CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)){
+ for(i=0; i<s->quant_table_count; i++){
+ s->rc_stat2[i]= av_mallocz(s->context_count[i]*sizeof(*s->rc_stat2[i]));
+ if(!s->rc_stat2[i])
+ return AVERROR(ENOMEM);
+ }
+ }
if(avctx->stats_in){
char *p= avctx->stats_in;
+ uint8_t best_state[256][256];
+ int gob_count=0;
+ char *next;
+
+ av_assert0(s->version>=2);
for(;;){
for(j=0; j<256; j++){
for(i=0; i<2; i++){
- char *next;
s->rc_stat[j][i]= strtol(p, &next, 0);
if(next==p){
av_log(avctx, AV_LOG_ERROR, "2Pass file invalid at %d %d [%s]\n", j,i,p);
p=next;
}
}
+ for(i=0; i<s->quant_table_count; i++){
+ for(j=0; j<s->context_count[i]; j++){
+ for(k=0; k<32; k++){
+ for(m=0; m<2; m++){
+ s->rc_stat2[i][j][k][m]= strtol(p, &next, 0);
+ if(next==p){
+ av_log(avctx, AV_LOG_ERROR, "2Pass file invalid at %d %d %d %d [%s]\n", i,j,k,m,p);
+ return -1;
+ }
+ p=next;
+ }
+ }
+ }
+ }
+ gob_count= strtol(p, &next, 0);
+ if(next==p || gob_count <0){
+ av_log(avctx, AV_LOG_ERROR, "2Pass file invalid\n");
+ return -1;
+ }
+ p=next;
while(*p=='\n' || *p==' ') p++;
if(p[0]==0) break;
}
sort_stt(s, s->state_transition);
+
+ find_best_state(best_state, s->state_transition);
+
+ for(i=0; i<s->quant_table_count; i++){
+ for(j=0; j<s->context_count[i]; j++){
+ for(k=0; k<32; k++){
+ double p= 128;
+ if(s->rc_stat2[i][j][k][0]+s->rc_stat2[i][j][k][1]){
+ p=256.0*s->rc_stat2[i][j][k][1] / (s->rc_stat2[i][j][k][0]+s->rc_stat2[i][j][k][1]);
+ }
+ s->initial_states[i][j][k]= best_state[av_clip(round(p), 1, 255)][av_clip((s->rc_stat2[i][j][k][0]+s->rc_stat2[i][j][k][1])/gob_count, 0, 255)];
+ }
+ }
+ }
}
if(s->version>1){
if(init_slice_state(s) < 0)
return -1;
-#define STATS_OUT_SIZE 1024*30
+#define STATS_OUT_SIZE 1024*1024*6
if(avctx->flags & CODEC_FLAG_PASS1){
avctx->stats_out= av_mallocz(STATS_OUT_SIZE);
for(i=0; i<s->quant_table_count; i++){
if(avctx->gop_size==0 || f->picture_number % avctx->gop_size == 0){
put_rac(c, &keystate, 1);
p->key_frame= 1;
+ f->gob_count++;
write_header(f);
clear_state(f);
}else{
}
if((avctx->flags&CODEC_FLAG_PASS1) && (f->picture_number&31)==0){
- int j;
+ int j, k, m;
char *p= avctx->stats_out;
char *end= p + STATS_OUT_SIZE;
memset(f->rc_stat, 0, sizeof(f->rc_stat));
+ for(i=0; i<f->quant_table_count; i++)
+ memset(f->rc_stat2[i], 0, f->context_count[i]*sizeof(*f->rc_stat2[i]));
+
for(j=0; j<f->slice_count; j++){
FFV1Context *fs= f->slice_context[j];
for(i=0; i<256; i++){
f->rc_stat[i][0] += fs->rc_stat[i][0];
f->rc_stat[i][1] += fs->rc_stat[i][1];
}
+ for(i=0; i<f->quant_table_count; i++){
+ for(k=0; k<f->context_count[i]; k++){
+ for(m=0; m<32; m++){
+ f->rc_stat2[i][k][m][0] += fs->rc_stat2[i][k][m][0];
+ f->rc_stat2[i][k][m][1] += fs->rc_stat2[i][k][m][1];
+ }
+ }
+ }
}
for(j=0; j<256; j++){
p+= strlen(p);
}
snprintf(p, end-p, "\n");
+
+ for(i=0; i<f->quant_table_count; i++){
+ for(j=0; j<f->context_count[i]; j++){
+ for(m=0; m<32; m++){
+ snprintf(p, end-p, "%"PRIu64" %"PRIu64" ", f->rc_stat2[i][j][m][0], f->rc_stat2[i][j][m][1]);
+ p+= strlen(p);
+ }
+ }
+ }
+ snprintf(p, end-p, "%d\n", f->gob_count);
} else if(avctx->flags&CODEC_FLAG_PASS1)
avctx->stats_out[0] = '\0';
FFV1Context *sf= s->slice_context[i];
av_freep(&sf->rc_stat2[j]);
}
+ av_freep(&s->rc_stat2[j]);
+ }
+
+ for(i=0; i<s->slice_count; i++){
+ av_freep(&s->slice_context[i]);
}
return 0;