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); f->chroma_planes= get_rac(c, state); f->chroma_h_shift= get_symbol(c, state, 0); f->chroma_v_shift= get_symbol(c, state, 0); f->transparency= get_rac(c, state); f->plane_count= 2 + f->transparency; } if(f->colorspace==0){ if(!f->transparency && !f->chroma_planes){ if (f->avctx->bits_per_raw_sample<=8) f->avctx->pix_fmt= PIX_FMT_GRAY8; else f->avctx->pix_fmt= PIX_FMT_GRAY16; }else if(f->avctx->bits_per_raw_sample<=8 && !f->transparency){ switch(16*f->chroma_h_shift + f->chroma_v_shift){ case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P; break; case 0x01: f->avctx->pix_fmt= PIX_FMT_YUV440P; 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 if(f->avctx->bits_per_raw_sample<=8 && f->transparency){ switch(16*f->chroma_h_shift + f->chroma_v_shift){ case 0x00: f->avctx->pix_fmt= PIX_FMT_YUVA444P; break; case 0x11: f->avctx->pix_fmt= PIX_FMT_YUVA420P; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return -1; } }else if(f->avctx->bits_per_raw_sample==9) { f->packed_at_lsb=1; switch(16*f->chroma_h_shift + f->chroma_v_shift){ case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P9; break; case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P9; break; case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P9; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return -1; } }else if(f->avctx->bits_per_raw_sample==10) { f->packed_at_lsb=1; switch(16*f->chroma_h_shift + f->chroma_v_shift){ case 0x00: f->avctx->pix_fmt= PIX_FMT_YUV444P10; break; case 0x10: f->avctx->pix_fmt= PIX_FMT_YUV422P10; break; case 0x11: f->avctx->pix_fmt= PIX_FMT_YUV420P10; 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; } if(f->transparency) f->avctx->pix_fmt= PIX_FMT_RGB32; else f->avctx->pix_fmt= PIX_FMT_0RGB32; }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; fs->packed_at_lsb= f->packed_at_lsb; 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; } } return 0; }