Newer
Older
return AVERROR(ENOMEM);
}
}
if(avctx->stats_in){
char *p= avctx->stats_in;
uint8_t best_state[256][256];
int gob_count=0;
for(;;){
for(j=0; j<256; j++){
for(i=0; i<2; i++){
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);
return -1;
}
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){
s->num_h_slices=2;
s->num_v_slices=2;
write_extra_header(s);
}
if(init_slice_contexts(s) < 0)
return -1;
if(init_slice_state(s) < 0)
return -1;
#define STATS_OUT_SIZE 1024*1024*6
Michael Niedermayer
committed
if(avctx->flags & CODEC_FLAG_PASS1){
avctx->stats_out= av_mallocz(STATS_OUT_SIZE);
Michael Niedermayer
committed
for(i=0; i<s->quant_table_count; i++){
for(j=0; j<s->slice_count; j++){
FFV1Context *sf= s->slice_context[j];
av_assert0(!sf->rc_stat2[i]);
sf->rc_stat2[i]= av_mallocz(s->context_count[i]*sizeof(*sf->rc_stat2[i]));
if(!sf->rc_stat2[i])
return AVERROR(ENOMEM);
}
}
}
Michael Niedermayer
committed
return 0;
}
#endif /* CONFIG_FFV1_ENCODER */
Michael Niedermayer
committed
static void clear_state(FFV1Context *f){
Michael Niedermayer
committed
for(si=0; si<f->slice_count; si++){
FFV1Context *fs= f->slice_context[si];
for(i=0; i<f->plane_count; i++){
PlaneContext *p= &fs->plane[i];
Michael Niedermayer
committed
p->interlace_bit_state[0]= 128;
p->interlace_bit_state[1]= 128;
if(f->initial_states[p->quant_table_index]){
memcpy(p->state, f->initial_states[p->quant_table_index], CONTEXT_SIZE*p->context_count);
}else
memset(p->state, 128, CONTEXT_SIZE*p->context_count);
}else{
for(j=0; j<p->context_count; j++){
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;
Michael Niedermayer
committed
}
Michael Niedermayer
committed
}
}
#if CONFIG_FFV1_ENCODER
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
static int encode_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;
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;
encode_plane(fs, p->data[0] + x + y*p->linesize[0], width, height, p->linesize[0], 0);
encode_plane(fs, p->data[1] + cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1);
encode_plane(fs, p->data[2] + cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1);
}else{
encode_rgb_frame(fs, (uint32_t*)(p->data[0]) + x + y*(p->linesize[0]/4), width, height, p->linesize[0]/4);
}
emms_c();
return 0;
}
Michael Niedermayer
committed
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
FFV1Context *f = avctx->priv_data;
RangeCoder * const c= &f->slice_context[0]->c;
Michael Niedermayer
committed
AVFrame *pict = data;
AVFrame * const p= &f->picture;
ff_init_range_encoder(c, buf, buf_size);
ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
Michael Niedermayer
committed
*p = *pict;
p->pict_type= FF_I_TYPE;
Michael Niedermayer
committed
if(avctx->gop_size==0 || f->picture_number % avctx->gop_size == 0){
put_rac(c, &keystate, 1);
Michael Niedermayer
committed
p->key_frame= 1;
f->gob_count++;
Michael Niedermayer
committed
write_header(f);
clear_state(f);
}else{
put_rac(c, &keystate, 0);
Michael Niedermayer
committed
p->key_frame= 0;
}
used_count += ff_rac_terminate(c);
init_put_bits(&f->slice_context[0]->pb, buf + used_count, buf_size - used_count);
}else if (f->ac>1){
int i;
for(i=1; i<256; i++){
c->one_state[i]= f->state_transition[i];
c->zero_state[256-i]= 256-c->one_state[i];
}
for(i=1; i<f->slice_count; i++){
FFV1Context *fs= f->slice_context[i];
uint8_t *start= buf + (buf_size-used_count)*i/f->slice_count;
int len= buf_size/f->slice_count;
Michael Niedermayer
committed
if(fs->ac){
ff_init_range_encoder(&fs->c, start, len);
}else{
init_put_bits(&fs->pb, start, len);
}
Michael Niedermayer
committed
}
avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL, f->slice_count, sizeof(void*));
buf_p=buf;
for(i=0; i<f->slice_count; i++){
FFV1Context *fs= f->slice_context[i];
int bytes;
Michael Niedermayer
committed
if(fs->ac){
uint8_t state=128;
put_rac(&fs->c, &state, 0);
bytes= ff_rac_terminate(&fs->c);
}else{
flush_put_bits(&fs->pb); //nicer padding FIXME
bytes= used_count + (put_bits_count(&fs->pb)+7)/8;
used_count= 0;
}
if(i>0){
av_assert0(bytes < buf_size/f->slice_count);
memmove(buf_p, fs->ac ? fs->c.bytestream_start : fs->pb.buf, bytes);
av_assert0(bytes < (1<<24));
AV_WB24(buf_p+bytes, bytes);
bytes+=3;
}
buf_p += bytes;
if((avctx->flags&CODEC_FLAG_PASS1) && (f->picture_number&31)==0){
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++){
snprintf(p, end-p, "%"PRIu64" %"PRIu64" ", f->rc_stat[j][0], f->rc_stat[j][1]);
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';
f->picture_number++;
return buf_p-buf;
Michael Niedermayer
committed
}
#endif /* CONFIG_FFV1_ENCODER */
Michael Niedermayer
committed
static av_cold int common_end(AVCodecContext *avctx){
Michael Niedermayer
committed
if (avctx->codec->decode && s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
for(j=0; j<s->slice_count; j++){
FFV1Context *fs= s->slice_context[j];
for(i=0; i<s->plane_count; i++){
PlaneContext *p= &fs->plane[i];
Michael Niedermayer
committed
av_freep(&p->state);
av_freep(&p->vlc_state);
}
av_freep(&fs->sample_buffer);
}
av_freep(&avctx->stats_out);
Michael Niedermayer
committed
for(j=0; j<s->quant_table_count; j++){
av_freep(&s->initial_states[j]);
Michael Niedermayer
committed
for(i=0; i<s->slice_count; i++){
FFV1Context *sf= s->slice_context[i];
av_freep(&sf->rc_stat2[j]);
}
Michael Niedermayer
committed
}
for(i=0; i<s->slice_count; i++){
av_freep(&s->slice_context[i]);
}
Michael Niedermayer
committed
return 0;
}
static av_always_inline void decode_line(FFV1Context *s, int w, int_fast16_t *sample[2], int plane_index, int bits){
Michael Niedermayer
committed
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);
diff= get_symbol_inline(c, p->state[context], 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(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);
}
}
static void decode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride, int plane_index){
int x, y;
sample[0]=s->sample_buffer +3;
sample[1]=s->sample_buffer+w+6+3;
memset(s->sample_buffer, 0, 2*(w+6)*sizeof(*s->sample_buffer));
Michael Niedermayer
committed
for(y=0; y<h; y++){
int_fast16_t *temp= sample[0]; //FIXME try a normal buffer
Michael Niedermayer
committed
Michael Niedermayer
committed
sample[1][-1]= sample[0][0 ];
sample[0][ w]= sample[0][w-1];
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);
}
}
Michael Niedermayer
committed
static void decode_rgb_frame(FFV1Context *s, uint32_t *src, int w, int h, int stride){
int x, y, p;
int_fast16_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;
memset(s->sample_buffer, 0, 6*(w+6)*sizeof(*s->sample_buffer));
for(y=0; y<h; y++){
for(p=0; p<3; p++){
int_fast16_t *temp= sample[p][0]; //FIXME try a normal buffer
sample[p][0]= sample[p][1];
sample[p][1]= temp;
Michael Niedermayer
committed
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);
Michael Niedermayer
committed
}
}
}
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
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){
Michael Niedermayer
committed
int v;
int i=0;
uint8_t state[CONTEXT_SIZE];
memset(state, 128, sizeof(state));
Michael Niedermayer
committed
int len= get_symbol(c, state, 0) + 1;
Michael Niedermayer
committed
Michael Niedermayer
committed
while(len--){
Michael Niedermayer
committed
//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];
Michael Niedermayer
committed
}
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;
}
Michael Niedermayer
committed
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;
}
Michael Niedermayer
committed
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;
Michael Niedermayer
committed
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");
f->avctx->pix_fmt= PIX_FMT_RGB32;
av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
Michael Niedermayer
committed
return -1;
}
Michael Niedermayer
committed
//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;
Michael Niedermayer
committed
}
}else{
f->slice_count= get_symbol(c, state, 0);
if(f->slice_count > (unsigned)MAX_SLICES)
return -1;
Michael Niedermayer
committed
}
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;
}
Michael Niedermayer
committed
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;
Michael Niedermayer
committed
}
Michael Niedermayer
committed
return 0;
}
static av_cold int decode_init(AVCodecContext *avctx)
Michael Niedermayer
committed
{
FFV1Context *f = avctx->priv_data;
Michael Niedermayer
committed
common_init(avctx);
if(avctx->extradata && read_extra_header(f) < 0)
return -1;
if(init_slice_contexts(f) < 0)
return -1;
Michael Niedermayer
committed
return 0;
}
Thilo Borgmann
committed
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt){
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
Michael Niedermayer
committed
FFV1Context *f = avctx->priv_data;
RangeCoder * const c= &f->slice_context[0]->c;
Michael Niedermayer
committed
AVFrame * const p= &f->picture;
Michael Niedermayer
committed
AVFrame *picture = data;
/* release previously stored data */
if (p->data[0])
avctx->release_buffer(avctx, p);
ff_init_range_decoder(c, buf, buf_size);
ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
Laurent Aimar
committed
Michael Niedermayer
committed
p->pict_type= FF_I_TYPE; //FIXME I vs. P
if(get_rac(c, &keystate)){
Michael Niedermayer
committed
p->key_frame= 1;
if(read_header(f) < 0)
return -1;
if(init_slice_state(f) < 0)
return -1;
Michael Niedermayer
committed
clear_state(f);
}else{
p->key_frame= 0;
}
if(f->ac>1){
int i;
for(i=1; i<256; i++){
c->one_state[i]= f->state_transition[i];
c->zero_state[256-i]= 256-c->one_state[i];
}
}
Michael Niedermayer
committed
p->reference= 0;
if(avctx->get_buffer(avctx, p) < 0){
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
Michael Niedermayer
committed
return -1;
}
Michael Niedermayer
committed
if(avctx->debug&FF_DEBUG_PICT_INFO)
av_log(avctx, AV_LOG_ERROR, "keyframe:%d coder:%d\n", p->key_frame, f->ac);
bytes_read = c->bytestream - c->bytestream_start - 1;
if(bytes_read ==0) av_log(avctx, AV_LOG_ERROR, "error at end of AC stream\n"); //FIXME
init_get_bits(&f->slice_context[0]->gb, buf + bytes_read, buf_size - bytes_read);
buf_p= buf + buf_size;
for(i=f->slice_count-1; i>0; i--){
FFV1Context *fs= f->slice_context[i];
int v= AV_RB24(buf_p-3)+3;
if(buf_p - buf <= v){
av_log(avctx, AV_LOG_ERROR, "Slice pointer chain broken\n");
return -1;
}
buf_p -= v;
if(fs->ac){
ff_init_range_decoder(&fs->c, buf_p, v);
}else{
init_get_bits(&fs->gb, buf_p, v);
}
Michael Niedermayer
committed
}
avctx->execute(avctx, decode_slice, &f->slice_context[0], NULL, f->slice_count, sizeof(void*));
Michael Niedermayer
committed
f->picture_number++;
*picture= *p;
*data_size = sizeof(AVFrame);
Michael Niedermayer
committed
}
Diego Elio Pettenò
committed
AVCodec ff_ffv1_decoder = {
Michael Niedermayer
committed
"ffv1",
AVMEDIA_TYPE_VIDEO,
Michael Niedermayer
committed
CODEC_ID_FFV1,
sizeof(FFV1Context),
decode_init,
NULL,
Michael Niedermayer
committed
decode_frame,
Michael Niedermayer
committed
CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
.long_name= NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),
Michael Niedermayer
committed
};
#if CONFIG_FFV1_ENCODER
Diego Elio Pettenò
committed
AVCodec ff_ffv1_encoder = {
Michael Niedermayer
committed
"ffv1",
AVMEDIA_TYPE_VIDEO,
Michael Niedermayer
committed
CODEC_ID_FFV1,
sizeof(FFV1Context),
encode_init,
encode_frame,
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_RGB32, PIX_FMT_YUV420P16, PIX_FMT_YUV422P16, PIX_FMT_YUV444P16, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),
Michael Niedermayer
committed
};