/**
* @file h263.c
- * @brief h263/mpeg4 codec
- *
+ * h263/mpeg4 codec.
*/
//#define DEBUG
int n, int coded);
static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
- int n, int coded, int intra);
+ int n, int coded, int intra, int rvlc);
static int h263_pred_dc(MpegEncContext * s, int n, uint16_t **dc_val_ptr);
#ifdef CONFIG_ENCODERS
static void mpeg4_inv_pred_ac(MpegEncContext * s, DCTELEM *block, int n,
s->gob_number = 0;
put_bits(&s->pb, 22, 0x20); /* PSC */
- put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * FRAME_RATE_BASE) /
- s->frame_rate) & 0xff);
+ put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->frame_rate_base) /
+ s->avctx->frame_rate) & 0xff);
put_bits(&s->pb, 1, 1); /* marker */
put_bits(&s->pb, 1, 0); /* h263 id */
int time_div, time_mod;
if(s->pict_type==I_TYPE){ //we will encode a vol header
- s->time_increment_resolution= s->frame_rate/ff_gcd(s->frame_rate, FRAME_RATE_BASE);
- if(s->time_increment_resolution>=256*256) s->time_increment_resolution= 256*128;
-
+ int dummy;
+ av_reduce(&s->time_increment_resolution, &dummy, s->avctx->frame_rate, s->avctx->frame_rate_base, (1<<16)-1);
+
s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1;
}
if(s->current_picture.pts)
s->time= (s->current_picture.pts*s->time_increment_resolution + 500*1000)/(1000*1000);
else
- s->time= picture_number*(int64_t)FRAME_RATE_BASE*s->time_increment_resolution/s->frame_rate;
+ s->time= av_rescale(picture_number*(int64_t)s->avctx->frame_rate_base, s->time_increment_resolution, s->avctx->frame_rate);
time_div= s->time/s->time_increment_resolution;
time_mod= s->time%s->time_increment_resolution;
static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number)
{
int vo_ver_id;
- char buf[255];
if(s->max_b_frames || s->quarter_sample){
vo_ver_id= 5;
if(!(s->flags & CODEC_FLAG_BITEXACT)){
put_bits(&s->pb, 16, 0);
put_bits(&s->pb, 16, 0x1B2); /* user_data */
- sprintf(buf, "FFmpeg%sb%s", FFMPEG_VERSION, LIBAVCODEC_BUILD_STR);
- put_string(&s->pb, buf);
+ put_string(&s->pb, LIBAVCODEC_IDENT);
ff_mpeg4_stuffing(&s->pb);
}
}
&mvtab[0][0], 2, 1);
init_rl(&rl_inter);
init_rl(&rl_intra);
+ init_rl(&rvlc_rl_inter);
+ init_rl(&rvlc_rl_intra);
init_rl(&rl_intra_aic);
init_vlc_rl(&rl_inter);
init_vlc_rl(&rl_intra);
+ init_vlc_rl(&rvlc_rl_inter);
+ init_vlc_rl(&rvlc_rl_intra);
init_vlc_rl(&rl_intra_aic);
init_vlc(&dc_lum, DC_VLC_BITS, 10 /* 13 */,
&DCtab_lum[0][1], 2, 1,
if(dc_pred_dir) dir|=1;
}
s->pred_dir_table[xy]= dir;
-
- s->error_status_table[xy]= AC_ERROR;
}else{ /* P/S_TYPE */
int mx, my, pred_x, pred_y, bits;
int16_t * const mot_val= s->motion_val[s->block_index[0]];
if(s->mbintra_table[xy])
ff_clean_intra_table_entries(s);
-
- s->error_status_table[xy]= AC_ERROR;
continue;
}
cbpc = get_vlc2(&s->gb, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);
mot_val[0+stride]= mot_val[2+stride]= 0;
mot_val[1 ]= mot_val[3 ]=
mot_val[1+stride]= mot_val[3+stride]= 0;
- s->error_status_table[xy]= DC_ERROR|AC_ERROR;
}else{
if(s->mbintra_table[xy])
ff_clean_intra_table_entries(s);
mot_val[1] = my;
}
}
- s->error_status_table[xy]= AC_ERROR;
}
}
}
s->cbp_table[xy]&= 3; //remove dquant
s->cbp_table[xy]|= cbpy<<2;
s->pred_dir_table[xy]= dir | (ac_pred<<7);
- s->error_status_table[xy]&= ~DC_ERROR;
}else if(s->mb_type[xy]&MB_TYPE_SKIPED){
s->current_picture.qscale_table[xy]= s->qscale;
s->cbp_table[xy]= 0;
int ff_mpeg4_decode_partitions(MpegEncContext *s)
{
int mb_num;
+ const int part_a_error= s->pict_type==I_TYPE ? (DC_ERROR|MV_ERROR) : MV_ERROR;
+ const int part_a_end = s->pict_type==I_TYPE ? (DC_END |MV_END) : MV_END;
mb_num= mpeg4_decode_partition_a(s);
- if(mb_num<0)
+ if(mb_num<0){
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error);
return -1;
+ }
if(s->resync_mb_x + s->resync_mb_y*s->mb_width + mb_num > s->mb_num){
fprintf(stderr, "slice below monitor ...\n");
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error);
return -1;
}
if(get_bits(&s->gb, 19)!=DC_MARKER){
fprintf(stderr, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y);
return -1;
- }else
- s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END|DC_END;
+ }
}else{
if(get_bits(&s->gb, 17)!=MOTION_MARKER){
fprintf(stderr, "marker missing after first P partition at %d %d\n", s->mb_x, s->mb_y);
return -1;
- }else
- s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END;
+ }
}
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, part_a_end);
if( mpeg4_decode_partition_b(s, mb_num) < 0){
+ if(s->pict_type==P_TYPE)
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, DC_ERROR);
return -1;
+ }else{
+ if(s->pict_type==P_TYPE)
+ ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, DC_END);
}
-
- s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= DC_END;
return 0;
}
}
}else if(s->mb_intra){
s->ac_pred = s->pred_dir_table[xy]>>7;
-
- /* decode each block */
- for (i = 0; i < 6; i++) {
- if(mpeg4_decode_block(s, block[i], i, cbp&32, 1) < 0){
- fprintf(stderr, "texture corrupted at %d %d\n", s->mb_x, s->mb_y);
- return -1;
- }
- cbp+=cbp;
- }
}else if(!s->mb_intra){
// s->mcsel= 0; //FIXME do we need to init that
} else {
s->mv_type = MV_TYPE_16X16;
}
- /* decode each block */
- for (i = 0; i < 6; i++) {
- if(mpeg4_decode_block(s, block[i], i, cbp&32, 0) < 0){
- fprintf(stderr, "texture corrupted at %d %d (trying to continue with mc/dc only)\n", s->mb_x, s->mb_y);
- return -1;
- }
- cbp+=cbp;
- }
}
} else { /* I-Frame */
- int i;
s->mb_intra = 1;
s->ac_pred = s->pred_dir_table[xy]>>7;
-
+ }
+
+ if (!(mb_type&MB_TYPE_SKIPED)) {
+ int i;
/* decode each block */
for (i = 0; i < 6; i++) {
- if(mpeg4_decode_block(s, block[i], i, cbp&32, 1) < 0){
- fprintf(stderr, "texture corrupted at %d %d (trying to continue with dc only)\n", s->mb_x, s->mb_y);
+ if(mpeg4_decode_block(s, block[i], i, cbp&32, s->mb_intra, s->rvlc) < 0){
+ fprintf(stderr, "texture corrupted at %d %d %d\n", s->mb_x, s->mb_y, s->mb_intra);
return -1;
}
cbp+=cbp;
}
}
- s->error_status_table[xy]&= ~AC_ERROR;
-
/* per-MB end of slice check */
if(--s->mb_num_left <= 0){
int16_t *mot_val;
static int8_t quant_tab[4] = { -1, -2, 1, 2 };
- s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
-
if(s->mb_x==0) PRINT_MB_TYPE("\n");
if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) {
/* decode each block */
if (s->h263_pred) {
for (i = 0; i < 6; i++) {
- if (mpeg4_decode_block(s, block[i], i, cbp&32, 1) < 0)
+ if (mpeg4_decode_block(s, block[i], i, cbp&32, 1, 0) < 0)
return -1;
cbp+=cbp;
}
/* decode each block */
if (s->h263_pred) {
for (i = 0; i < 6; i++) {
- if (mpeg4_decode_block(s, block[i], i, cbp&32, 0) < 0)
+ if (mpeg4_decode_block(s, block[i], i, cbp&32, 0, 0) < 0)
return -1;
cbp+=cbp;
}
* @return <0 if an error occured
*/
static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
- int n, int coded, int intra)
+ int n, int coded, int intra, int rvlc)
{
int level, i, last, run;
int dc_pred_dir;
const uint8_t * scan_table;
int qmul, qadd;
+ //Note intra & rvlc should be optimized away if this is inlined
+
if(intra) {
/* DC coef */
if(s->partitioned_frame){
i = 0;
if (!coded)
goto not_coded;
- rl = &rl_intra;
- rl_vlc = rl_intra.rl_vlc[0];
+
+ if(rvlc){
+ rl = &rvlc_rl_intra;
+ rl_vlc = rvlc_rl_intra.rl_vlc[0];
+ }else{
+ rl = &rl_intra;
+ rl_vlc = rl_intra.rl_vlc[0];
+ }
if (s->ac_pred) {
if (dc_pred_dir == 0)
scan_table = s->intra_v_scantable.permutated; /* left */
s->block_last_index[n] = i;
return 0;
}
- rl = &rl_inter;
+ if(rvlc) rl = &rvlc_rl_inter;
+ else rl = &rl_inter;
scan_table = s->intra_scantable.permutated;
if(s->mpeg_quant){
qmul=1;
qadd=0;
- rl_vlc = rl_inter.rl_vlc[0];
+ if(rvlc){
+ rl_vlc = rvlc_rl_inter.rl_vlc[0];
+ }else{
+ rl_vlc = rl_inter.rl_vlc[0];
+ }
}else{
qmul = s->qscale << 1;
qadd = (s->qscale - 1) | 1;
- rl_vlc = rl_inter.rl_vlc[s->qscale];
+ if(rvlc){
+ rl_vlc = rvlc_rl_inter.rl_vlc[s->qscale];
+ }else{
+ rl_vlc = rl_inter.rl_vlc[s->qscale];
+ }
}
}
{
UPDATE_CACHE(re, &s->gb);
GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2);
if (level==0) {
+ /* escape */
+ if(rvlc){
+ if(SHOW_UBITS(re, &s->gb, 1)==0){
+ fprintf(stderr, "1. marker bit missing in rvlc esc\n");
+ return -1;
+ }; SKIP_CACHE(re, &s->gb, 1);
+
+ last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1);
+ run= SHOW_UBITS(re, &s->gb, 6); LAST_SKIP_CACHE(re, &s->gb, 6);
+ SKIP_COUNTER(re, &s->gb, 1+1+6);
+ UPDATE_CACHE(re, &s->gb);
+
+ if(SHOW_UBITS(re, &s->gb, 1)==0){
+ fprintf(stderr, "2. marker bit missing in rvlc esc\n");
+ return -1;
+ }; SKIP_CACHE(re, &s->gb, 1);
+
+ level= SHOW_UBITS(re, &s->gb, 11); SKIP_CACHE(re, &s->gb, 11);
+
+ if(SHOW_UBITS(re, &s->gb, 5)!=0x10){
+ fprintf(stderr, "reverse esc missing\n");
+ return -1;
+ }; SKIP_CACHE(re, &s->gb, 5);
+
+ level= level * qmul + qadd;
+ level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); LAST_SKIP_CACHE(re, &s->gb, 1);
+ SKIP_COUNTER(re, &s->gb, 1+11+5+1);
+
+ i+= run + 1;
+ if(last) i+=192;
+ }else{
int cache;
cache= GET_CACHE(re, &s->gb);
- /* escape */
if (cache&0x80000000) {
if (cache&0x40000000) {
/* third escape */
level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
LAST_SKIP_BITS(re, &s->gb, 1);
}
+ }
} else {
i+= run;
level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
s->data_partitioning= get_bits1(gb);
if(s->data_partitioning){
s->rvlc= get_bits1(gb);
- if(s->rvlc){
- printf("reversible vlc not supported\n");
- }
}
if(vo_ver_id != 1) {
int i;
int e;
int ver, build, ver2, ver3;
+ char last;
buf[0]= show_bits(gb, 8);
for(i=1; i<256; i++){
skip_bits(gb, 8);
}
buf[255]=0;
-
+
/* divx detection */
- e=sscanf(buf, "DivX%dBuild%d", &ver, &build);
- if(e!=2)
- e=sscanf(buf, "DivX%db%d", &ver, &build);
- if(e==2){
+ e=sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &last);
+ if(e<2)
+ e=sscanf(buf, "DivX%db%d%c", &ver, &build, &last);
+ if(e>=2){
s->divx_version= ver;
s->divx_build= build;
+ s->divx_packed= e==3 && last=='p';
if(s->picture_number==0){
- printf("This file was encoded with DivX%d Build%d\n", ver, build);
+ printf("This file was encoded with DivX%d Build%d", ver, build);
+ if(s->divx_packed)
+ printf("p\n");
+ else
+ printf("\n");
}
}
s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; //FIXME add short header support
s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
- if(s->divx_version==0 || s->divx_version < 500){
+ if(!(s->workaround_bugs&FF_BUG_EDGE)){
s->h_edge_pos= s->width;
s->v_edge_pos= s->height;
}