mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
wmv1 slice_height != mb_height support
encoding of slice_height != mb_height 1bit shorter wmv1 headers if bit_rate<50 !? ROTFL M$ is even more stupid than i thought using dc of non intra blocks for dc prediction of wmv1 if bitrate < 129 && res < 320x240 Originally committed as revision 723 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
0a12d6fdfd
commit
de0f2f4cca
@ -392,6 +392,7 @@ typedef struct MpegEncContext {
|
||||
UINT8 *intra_h_scantable;
|
||||
/* [mb_intra][isChroma][level][run][last] */
|
||||
int ac_stats[2][2][MAX_LEVEL+1][MAX_RUN+1][2];
|
||||
int inter_intra_pred;
|
||||
|
||||
|
||||
/* decompression specific */
|
||||
|
@ -43,6 +43,8 @@ static int msmpeg4_decode_motion(MpegEncContext * s,
|
||||
int *mx_ptr, int *my_ptr);
|
||||
static void msmpeg4v2_encode_motion(MpegEncContext * s, int val);
|
||||
static void init_h263_dc_for_msmpeg4(void);
|
||||
static inline void msmpeg4_memsetw(short *tab, int val, int n);
|
||||
|
||||
|
||||
|
||||
extern UINT32 inverse[256];
|
||||
@ -345,14 +347,17 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
|
||||
s->mv_table_index = 1; /* only if P frame */
|
||||
s->use_skip_mb_code = 1; /* only if P frame */
|
||||
s->per_mb_rl_table = 0;
|
||||
s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=128 && s->pict_type==P_TYPE);
|
||||
|
||||
if (s->pict_type == I_TYPE) {
|
||||
s->no_rounding = 1;
|
||||
put_bits(&s->pb, 5, 0x17); /* indicate only one "slice" */
|
||||
s->slice_height= s->mb_height/1;
|
||||
put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height);
|
||||
|
||||
if(s->msmpeg4_version==4){
|
||||
msmpeg4_encode_ext_header(s);
|
||||
put_bits(&s->pb, 1, s->per_mb_rl_table);
|
||||
if(s->bit_rate>50)
|
||||
put_bits(&s->pb, 1, s->per_mb_rl_table);
|
||||
}
|
||||
|
||||
if(s->msmpeg4_version>2){
|
||||
@ -366,7 +371,7 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
|
||||
} else {
|
||||
put_bits(&s->pb, 1, s->use_skip_mb_code);
|
||||
|
||||
if(s->msmpeg4_version==4)
|
||||
if(s->msmpeg4_version==4 && s->bit_rate>50)
|
||||
put_bits(&s->pb, 1, s->per_mb_rl_table);
|
||||
|
||||
if(s->msmpeg4_version>2){
|
||||
@ -398,7 +403,7 @@ void msmpeg4_encode_ext_header(MpegEncContext * s)
|
||||
{
|
||||
put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
|
||||
|
||||
put_bits(&s->pb, 11, MIN(s->bit_rate, 2047));
|
||||
put_bits(&s->pb, 11, MIN(s->bit_rate, 2047));
|
||||
|
||||
if(s->msmpeg4_version<3)
|
||||
s->flipflop_rounding=0;
|
||||
@ -474,6 +479,38 @@ static void msmpeg4_encode_motion(MpegEncContext * s,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void handle_slices(MpegEncContext *s){
|
||||
if (s->mb_x == 0) {
|
||||
if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
|
||||
if(s->msmpeg4_version != 4){
|
||||
int wrap;
|
||||
/* reset DC pred (set previous line to 1024) */
|
||||
wrap = 2 * s->mb_width + 2;
|
||||
msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap],
|
||||
1024, 2 * s->mb_width);
|
||||
wrap = s->mb_width + 2;
|
||||
msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap],
|
||||
1024, s->mb_width);
|
||||
msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap],
|
||||
1024, s->mb_width);
|
||||
|
||||
/* reset AC pred (set previous line to 0) */
|
||||
wrap = s->mb_width * 2 + 2;
|
||||
msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
|
||||
0, 2 * s->mb_width*16);
|
||||
wrap = s->mb_width + 2;
|
||||
msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
|
||||
0, s->mb_width*16);
|
||||
msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
|
||||
0, s->mb_width*16);
|
||||
}
|
||||
s->first_slice_line = 1;
|
||||
} else {
|
||||
s->first_slice_line = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void msmpeg4_encode_mb(MpegEncContext * s,
|
||||
DCTELEM block[6][64],
|
||||
int motion_x, int motion_y)
|
||||
@ -482,6 +519,8 @@ void msmpeg4_encode_mb(MpegEncContext * s,
|
||||
int pred_x, pred_y;
|
||||
UINT8 *coded_block;
|
||||
|
||||
handle_slices(s);
|
||||
|
||||
if (!s->mb_intra) {
|
||||
/* compute cbp */
|
||||
set_stat(ST_INTER_MB);
|
||||
@ -610,6 +649,19 @@ static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n,
|
||||
return s->last_dc[i];
|
||||
}
|
||||
|
||||
static int get_dc(uint8_t *src, int stride, int scale)
|
||||
{
|
||||
int y;
|
||||
int sum=0;
|
||||
for(y=0; y<8; y++){
|
||||
int x;
|
||||
for(x=0; x<8; x++){
|
||||
sum+=src[x + y*stride];
|
||||
}
|
||||
}
|
||||
return (sum + (scale>>1))/scale;
|
||||
}
|
||||
|
||||
/* dir = 0: left, dir = 1: top prediction */
|
||||
static inline int msmpeg4_pred_dc(MpegEncContext * s, int n,
|
||||
UINT16 **dc_val_ptr, int *dir_ptr)
|
||||
@ -675,12 +727,69 @@ static inline int msmpeg4_pred_dc(MpegEncContext * s, int n,
|
||||
/* XXX: WARNING: they did not choose the same test as MPEG4. This
|
||||
is very important ! */
|
||||
if(s->msmpeg4_version>3){
|
||||
if (abs(a - b) < abs(b - c)) {
|
||||
pred = c;
|
||||
*dir_ptr = 1;
|
||||
} else {
|
||||
pred = a;
|
||||
*dir_ptr = 0;
|
||||
if(s->inter_intra_pred){
|
||||
uint8_t *dest;
|
||||
int wrap;
|
||||
|
||||
if(n==1){
|
||||
pred=a;
|
||||
*dir_ptr = 0;
|
||||
}else if(n==2){
|
||||
pred=c;
|
||||
*dir_ptr = 1;
|
||||
}else if(n==3){
|
||||
if (abs(a - b) < abs(b - c)) {
|
||||
pred = c;
|
||||
*dir_ptr = 1;
|
||||
} else {
|
||||
pred = a;
|
||||
*dir_ptr = 0;
|
||||
}
|
||||
}else{
|
||||
if(n<4){
|
||||
wrap= s->linesize;
|
||||
dest= s->current_picture[0] + (((n>>1) + 2*s->mb_y) * 8* wrap ) + ((n&1) + 2*s->mb_x) * 8;
|
||||
}else{
|
||||
wrap= s->linesize>>1;
|
||||
dest= s->current_picture[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8;
|
||||
}
|
||||
if(s->mb_x==0) a= (1024 + (scale>>1))/scale;
|
||||
else a= get_dc(dest-8, wrap, scale*8);
|
||||
if(s->mb_y==0) c= (1024 + (scale>>1))/scale;
|
||||
else c= get_dc(dest-8*wrap, wrap, scale*8);
|
||||
|
||||
if (s->h263_aic_dir==0) {
|
||||
pred= a;
|
||||
*dir_ptr = 0;
|
||||
}else if (s->h263_aic_dir==1) {
|
||||
if(n==0){
|
||||
pred= c;
|
||||
*dir_ptr = 1;
|
||||
}else{
|
||||
pred= a;
|
||||
*dir_ptr = 0;
|
||||
}
|
||||
}else if (s->h263_aic_dir==2) {
|
||||
if(n==0){
|
||||
pred= a;
|
||||
*dir_ptr = 0;
|
||||
}else{
|
||||
pred= c;
|
||||
*dir_ptr = 1;
|
||||
}
|
||||
} else {
|
||||
pred= c;
|
||||
*dir_ptr = 1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (abs(a - b) < abs(b - c)) {
|
||||
pred = c;
|
||||
*dir_ptr = 1;
|
||||
} else {
|
||||
pred = a;
|
||||
*dir_ptr = 0;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (abs(a - b) <= abs(b - c)) {
|
||||
@ -904,6 +1013,7 @@ static VLC v2_mb_type_vlc;
|
||||
static VLC v2_mv_vlc;
|
||||
static VLC v1_intra_cbpc_vlc;
|
||||
static VLC v1_inter_cbpc_vlc;
|
||||
static VLC inter_intra_vlc;
|
||||
|
||||
/* this table is practically identical to the one from h263 except that its inverted */
|
||||
static void init_h263_dc_for_msmpeg4(void)
|
||||
@ -1029,6 +1139,10 @@ int ff_msmpeg4_decode_init(MpegEncContext *s)
|
||||
init_vlc(&v1_inter_cbpc_vlc, 6, 25,
|
||||
inter_MCBPC_bits, 1, 1,
|
||||
inter_MCBPC_code, 1, 1);
|
||||
|
||||
init_vlc(&inter_intra_vlc, 3, 4,
|
||||
&table_inter_intra[0][1], 2, 1,
|
||||
&table_inter_intra[0][0], 2, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1075,7 +1189,13 @@ return -1;
|
||||
fprintf(stderr, "invalid picture type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
static int had_i=0;
|
||||
if(s->pict_type == I_TYPE) had_i=1;
|
||||
if(!had_i) return -1;
|
||||
}
|
||||
#endif
|
||||
s->qscale = get_bits(&s->gb, 5);
|
||||
|
||||
if (s->pict_type == I_TYPE) {
|
||||
@ -1089,8 +1209,10 @@ return -1;
|
||||
s->slice_height = code;
|
||||
}else{
|
||||
/* 0x17: one slice, 0x18: two slices, ... */
|
||||
if (code < 0x17)
|
||||
if (code < 0x17){
|
||||
fprintf(stderr, "error, slice code was %X\n", code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->slice_height = s->mb_height / (code - 0x16);
|
||||
}
|
||||
@ -1112,24 +1234,27 @@ return -1;
|
||||
case 4:
|
||||
msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8);
|
||||
|
||||
s->per_mb_rl_table= get_bits1(&s->gb);
|
||||
if(s->bit_rate > 50) s->per_mb_rl_table= get_bits1(&s->gb);
|
||||
else s->per_mb_rl_table= 0;
|
||||
|
||||
if(!s->per_mb_rl_table){
|
||||
s->rl_chroma_table_index = decode012(&s->gb);
|
||||
s->rl_table_index = decode012(&s->gb);
|
||||
}
|
||||
|
||||
s->dc_table_index = get_bits1(&s->gb);
|
||||
s->inter_intra_pred= 0;
|
||||
break;
|
||||
}
|
||||
s->no_rounding = 1;
|
||||
/* printf(" %d %d %d %d %d \n",
|
||||
/* printf("qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d \n",
|
||||
s->qscale,
|
||||
s->rl_chroma_table_index,
|
||||
s->rl_table_index,
|
||||
s->dc_table_index,
|
||||
s->per_mb_rl_table);*/
|
||||
s->per_mb_rl_table,
|
||||
s->slice_height);*/
|
||||
} else {
|
||||
|
||||
switch(s->msmpeg4_version){
|
||||
case 1:
|
||||
case 2:
|
||||
@ -1153,7 +1278,10 @@ return -1;
|
||||
break;
|
||||
case 4:
|
||||
s->use_skip_mb_code = get_bits1(&s->gb);
|
||||
s->per_mb_rl_table= get_bits1(&s->gb);
|
||||
|
||||
if(s->bit_rate > 50) s->per_mb_rl_table= get_bits1(&s->gb);
|
||||
else s->per_mb_rl_table= 0;
|
||||
|
||||
if(!s->per_mb_rl_table){
|
||||
s->rl_table_index = decode012(&s->gb);
|
||||
s->rl_chroma_table_index = s->rl_table_index;
|
||||
@ -1162,15 +1290,17 @@ return -1;
|
||||
s->dc_table_index = get_bits1(&s->gb);
|
||||
|
||||
s->mv_table_index = get_bits1(&s->gb);
|
||||
s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=128);
|
||||
break;
|
||||
}
|
||||
/* printf(" %d %d %d %d %d %d \n",
|
||||
/* printf("skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d \n",
|
||||
s->use_skip_mb_code,
|
||||
s->rl_table_index,
|
||||
s->rl_chroma_table_index,
|
||||
s->dc_table_index,
|
||||
s->mv_table_index,
|
||||
s->per_mb_rl_table);*/
|
||||
s->per_mb_rl_table,
|
||||
s->qscale);*/
|
||||
if(s->flipflop_rounding){
|
||||
s->no_rounding ^= 1;
|
||||
}else{
|
||||
@ -1387,34 +1517,7 @@ if(s->mb_x==0){
|
||||
}
|
||||
#endif
|
||||
/* special slice handling */
|
||||
if (s->mb_x == 0) {
|
||||
if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
|
||||
int wrap;
|
||||
/* reset DC pred (set previous line to 1024) */
|
||||
wrap = 2 * s->mb_width + 2;
|
||||
msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap],
|
||||
1024, 2 * s->mb_width);
|
||||
wrap = s->mb_width + 2;
|
||||
msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap],
|
||||
1024, s->mb_width);
|
||||
msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap],
|
||||
1024, s->mb_width);
|
||||
|
||||
/* reset AC pred (set previous line to 0) */
|
||||
wrap = s->mb_width * 2 + 2;
|
||||
msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
|
||||
0, 2 * s->mb_width*16);
|
||||
wrap = s->mb_width + 2;
|
||||
msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
|
||||
0, s->mb_width*16);
|
||||
msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
|
||||
0, s->mb_width*16);
|
||||
|
||||
s->first_slice_line = 1;
|
||||
} else {
|
||||
s->first_slice_line = 0;
|
||||
}
|
||||
}
|
||||
handle_slices(s);
|
||||
|
||||
if(s->msmpeg4_version<=2) return msmpeg4v12_decode_mb(s, block); //FIXME export function & call from outside perhaps
|
||||
|
||||
@ -1489,6 +1592,10 @@ printf("P ");
|
||||
#ifdef PRINT_MB
|
||||
printf("%c", s->ac_pred ? 'A' : 'I');
|
||||
#endif
|
||||
if(s->inter_intra_pred){
|
||||
s->h263_aic_dir= get_vlc(&s->gb, &inter_intra_vlc);
|
||||
// printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y);
|
||||
}
|
||||
if(s->per_mb_rl_table && cbp){
|
||||
s->rl_table_index = decode012(&s->gb);
|
||||
s->rl_chroma_table_index = s->rl_table_index;
|
||||
@ -1532,19 +1639,20 @@ static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
|
||||
#endif
|
||||
if (level < 0){
|
||||
fprintf(stderr, "dc overflow- block: %d qscale: %d//\n", n, s->qscale);
|
||||
return -1;
|
||||
if(s->inter_intra_pred) level=0;
|
||||
else return -1;
|
||||
}
|
||||
if (n < 4) {
|
||||
rl = &rl_table[s->rl_table_index];
|
||||
if(level > 256*s->y_dc_scale){
|
||||
fprintf(stderr, "dc overflow+ L qscale: %d//\n", s->qscale);
|
||||
return -1;
|
||||
if(!s->inter_intra_pred) return -1;
|
||||
}
|
||||
} else {
|
||||
rl = &rl_table[3 + s->rl_chroma_table_index];
|
||||
if(level > 256*s->c_dc_scale){
|
||||
fprintf(stderr, "dc overflow+ C qscale: %d//\n", s->qscale);
|
||||
return -1;
|
||||
if(!s->inter_intra_pred) return -1;
|
||||
}
|
||||
}
|
||||
block[0] = level;
|
||||
|
@ -1867,3 +1867,7 @@ static UINT8 *wmv1_scantable[WMV1_SCANTABLE_COUNT+1]={
|
||||
wmv1_scantable03,
|
||||
};
|
||||
|
||||
static UINT8 table_inter_intra[4][2]={
|
||||
{0,1},{2,2},{6,3},{7,3}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user