Commit 8f8402e4 authored by Michael Niedermayer's avatar Michael Niedermayer

dc scale simplification/optimization

Originally committed as revision 695 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent f0063c1a
...@@ -50,7 +50,6 @@ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr); ...@@ -50,7 +50,6 @@ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded); int n, int coded);
static int h263_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr); static int h263_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr);
static inline int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr);
static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n,
int dir); int dir);
static void mpeg4_decode_sprite_trajectory(MpegEncContext * s); static void mpeg4_decode_sprite_trajectory(MpegEncContext * s);
...@@ -176,6 +175,14 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -176,6 +175,14 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
} }
put_bits(&s->pb, 1, 0); /* no PEI */ put_bits(&s->pb, 1, 0); /* no PEI */
if(s->h263_aic){
s->y_dc_scale_table=
s->c_dc_scale_table= h263_aic_dc_scale_table;
}else{
s->y_dc_scale_table=
s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
}
} }
int h263_encode_gob_header(MpegEncContext * s, int mb_line) int h263_encode_gob_header(MpegEncContext * s, int mb_line)
...@@ -496,7 +503,7 @@ void mpeg4_encode_mb(MpegEncContext * s, ...@@ -496,7 +503,7 @@ void mpeg4_encode_mb(MpegEncContext * s,
const int level= block[i][0]; const int level= block[i][0];
UINT16 *dc_ptr; UINT16 *dc_ptr;
dc_diff[i]= level - mpeg4_pred_dc(s, i, &dc_ptr, &dir[i]); dc_diff[i]= level - ff_mpeg4_pred_dc(s, i, &dc_ptr, &dir[i]);
if (i < 4) { if (i < 4) {
*dc_ptr = level * s->y_dc_scale; *dc_ptr = level * s->y_dc_scale;
} else { } else {
...@@ -1098,9 +1105,12 @@ void h263_encode_init(MpegEncContext *s) ...@@ -1098,9 +1105,12 @@ void h263_encode_init(MpegEncContext *s)
s->min_qcoeff= -128; s->min_qcoeff= -128;
s->max_qcoeff= 127; s->max_qcoeff= 127;
break; break;
//Note for mpeg4 & h263 the dc-scale table will be set per frame as needed later
default: //nothing needed default table allready set in mpegvideo.c default: //nothing needed default table allready set in mpegvideo.c
s->min_qcoeff= -128; s->min_qcoeff= -128;
s->max_qcoeff= 127; s->max_qcoeff= 127;
s->y_dc_scale_table=
s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
} }
/* h263 type bias */ /* h263 type bias */
...@@ -1326,44 +1336,18 @@ void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -1326,44 +1336,18 @@ void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
if (s->pict_type == B_TYPE) if (s->pict_type == B_TYPE)
put_bits(&s->pb, 3, s->b_code); /* fcode_back */ put_bits(&s->pb, 3, s->b_code); /* fcode_back */
// printf("****frame %d\n", picture_number); // printf("****frame %d\n", picture_number);
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;
} }
void h263_dc_scale(MpegEncContext * s) static void h263_dc_scale(MpegEncContext * s)
{ {
#if 1 s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
const static UINT8 y_tab[32]={ s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8,10,12,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,36,38,40,42,44,46
};
const static UINT8 c_tab[32]={
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,21,22,23,24,25
};
s->y_dc_scale = y_tab[s->qscale];
s->c_dc_scale = c_tab[s->qscale];
#else
int quant;
quant = s->qscale;
/* luminance */
if (quant < 5)
s->y_dc_scale = 8;
else if (quant > 4 && quant < 9)
s->y_dc_scale = (2 * quant);
else if (quant > 8 && quant < 25)
s->y_dc_scale = (quant + 8);
else
s->y_dc_scale = (2 * quant - 16);
/* chrominance */
if (quant < 5)
s->c_dc_scale = 8;
else if (quant > 4 && quant < 25)
s->c_dc_scale = ((quant + 13) / 2);
else
s->c_dc_scale = (quant - 6);
#endif
} }
static inline int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr) inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr)
{ {
int a, b, c, wrap, pred, scale; int a, b, c, wrap, pred, scale;
UINT16 *dc_val; UINT16 *dc_val;
...@@ -2653,10 +2637,6 @@ intra: ...@@ -2653,10 +2637,6 @@ intra:
if (s->ac_pred && s->h263_aic) if (s->ac_pred && s->h263_aic)
s->h263_aic_dir = get_bits1(&s->gb); s->h263_aic_dir = get_bits1(&s->gb);
} }
if (s->h263_aic) {
s->y_dc_scale = 2 * s->qscale;
s->c_dc_scale = 2 * s->qscale;
}
cbpy = get_vlc(&s->gb, &cbpy_vlc); cbpy = get_vlc(&s->gb, &cbpy_vlc);
if(cbpy<0) return -1; if(cbpy<0) return -1;
cbp = (cbpc & 3) | (cbpy << 2); cbp = (cbpc & 3) | (cbpy << 2);
...@@ -2867,7 +2847,7 @@ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) ...@@ -2867,7 +2847,7 @@ static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
} }
} }
pred = mpeg4_pred_dc(s, n, &dc_val, dir_ptr); pred = ff_mpeg4_pred_dc(s, n, &dc_val, dir_ptr);
level += pred; level += pred;
if (level < 0) if (level < 0)
level = 0; level = 0;
...@@ -2956,8 +2936,8 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, ...@@ -2956,8 +2936,8 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
#if 1 #if 1
{ {
const int abs_level= ABS(level); const int abs_level= ABS(level);
int run1;
if(abs_level<=MAX_LEVEL && run<=MAX_RUN && s->error_resilience>=0){ if(abs_level<=MAX_LEVEL && run<=MAX_RUN && s->error_resilience>=0){
const int run1= run - rl->max_run[last][abs_level] - 1;
if(abs_level <= rl->max_level[last][run]){ if(abs_level <= rl->max_level[last][run]){
fprintf(stderr, "illegal 3. esc, vlc encoding possible\n"); fprintf(stderr, "illegal 3. esc, vlc encoding possible\n");
return DECODING_AC_LOST; return DECODING_AC_LOST;
...@@ -2966,7 +2946,6 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, ...@@ -2966,7 +2946,6 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n"); fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n");
return DECODING_AC_LOST; return DECODING_AC_LOST;
} }
run1 = run - rl->max_run[last][abs_level] - 1;
if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){ if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){
fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n"); fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n");
return DECODING_AC_LOST; return DECODING_AC_LOST;
...@@ -3185,6 +3164,15 @@ int h263_decode_picture_header(MpegEncContext *s) ...@@ -3185,6 +3164,15 @@ int h263_decode_picture_header(MpegEncContext *s)
skip_bits(&s->gb, 8); skip_bits(&s->gb, 8);
} }
s->f_code = 1; s->f_code = 1;
if(s->h263_aic){
s->y_dc_scale_table=
s->c_dc_scale_table= h263_aic_dc_scale_table;
}else{
s->y_dc_scale_table=
s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
}
return 0; return 0;
} }
...@@ -3626,7 +3614,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s) ...@@ -3626,7 +3614,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
}else{ }else{
printf("hmm, i havnt seen that version of divx yet, lets assume they fixed these bugs ...\n" printf("hmm, i havnt seen that version of divx yet, lets assume they fixed these bugs ...\n"
"using mpeg4 decoder, if it fails contact the developers (of ffmpeg)\n"); "using mpeg4 decoder, if it fails contact the developers (of ffmpeg)\n");
#endif #endif
} }
} }
} }
...@@ -3760,6 +3748,9 @@ int mpeg4_decode_picture_header(MpegEncContext * s) ...@@ -3760,6 +3748,9 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
s->picture_number++; // better than pic number==0 allways ;) s->picture_number++; // better than pic number==0 allways ;)
//printf("done\n"); //printf("done\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;
return 0; return 0;
} }
......
...@@ -202,3 +202,9 @@ static const UINT16 h263_format[8][2] = { ...@@ -202,3 +202,9 @@ static const UINT16 h263_format[8][2] = {
{ 704, 576 }, { 704, 576 },
{ 1408, 1152 }, { 1408, 1152 },
}; };
static UINT8 h263_aic_dc_scale_table[32]={
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 2, 4, 6, 8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
};
...@@ -76,6 +76,11 @@ static int h263_decode_init(AVCodecContext *avctx) ...@@ -76,6 +76,11 @@ static int h263_decode_init(AVCodecContext *avctx)
s->h263_pred = 1; s->h263_pred = 1;
s->msmpeg4_version=4; s->msmpeg4_version=4;
break; break;
case CODEC_ID_WMV2:
s->h263_msmpeg4 = 1;
s->h263_pred = 1;
s->msmpeg4_version=5;
break;
case CODEC_ID_H263I: case CODEC_ID_H263I:
s->h263_intel = 1; s->h263_intel = 1;
break; break;
...@@ -91,7 +96,7 @@ static int h263_decode_init(AVCodecContext *avctx) ...@@ -91,7 +96,7 @@ static int h263_decode_init(AVCodecContext *avctx)
return -1; return -1;
if (s->h263_msmpeg4) if (s->h263_msmpeg4)
msmpeg4_decode_init_vlc(s); ff_msmpeg4_decode_init(s);
else else
h263_decode_init_vlc(s); h263_decode_init_vlc(s);
...@@ -169,8 +174,10 @@ uint64_t time= rdtsc(); ...@@ -169,8 +174,10 @@ uint64_t time= rdtsc();
if(ret==FRAME_SKIPED) return 0; if(ret==FRAME_SKIPED) return 0;
/* skip if the header was thrashed */ /* skip if the header was thrashed */
if (ret < 0) if (ret < 0){
fprintf(stderr, "header damaged\n");
return -1; return -1;
}
/* skip b frames if we dont have reference frames */ /* skip b frames if we dont have reference frames */
if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return 0; if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return 0;
/* skip b frames if we are in a hurry */ /* skip b frames if we are in a hurry */
...@@ -216,6 +223,9 @@ uint64_t time= rdtsc(); ...@@ -216,6 +223,9 @@ uint64_t time= rdtsc();
s->last_dc[2]= 128; s->last_dc[2]= 128;
} }
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1; s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1); s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1);
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1; s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1;
...@@ -245,6 +255,9 @@ uint64_t time= rdtsc(); ...@@ -245,6 +255,9 @@ uint64_t time= rdtsc();
} }
} }
s->qscale= s->next_resync_qscale; s->qscale= s->next_resync_qscale;
s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
s->gb= s->next_resync_gb; s->gb= s->next_resync_gb;
s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it
s->resync_mb_y= s->mb_y; s->resync_mb_y= s->mb_y;
...@@ -265,18 +278,6 @@ uint64_t time= rdtsc(); ...@@ -265,18 +278,6 @@ uint64_t time= rdtsc();
//fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x); //fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x);
/* DCT & quantize */ /* DCT & quantize */
if (s->h263_pred && !(s->msmpeg4_version==1 || s->msmpeg4_version==2)) {
/* old ffmpeg encoded msmpeg4v3 workaround */
if(s->workaround_bugs==1 && s->msmpeg4_version==3)
ff_old_msmpeg4_dc_scale(s);
else
h263_dc_scale(s);
} else {
/* default quantization values */
s->y_dc_scale = 8;
s->c_dc_scale = 8;
}
if(s->decoding_error!=DECODING_DESYNC){ if(s->decoding_error!=DECODING_DESYNC){
int last_error= s->decoding_error; int last_error= s->decoding_error;
clear_blocks(s->block[0]); clear_blocks(s->block[0]);
...@@ -521,6 +522,18 @@ AVCodec wmv1_decoder = { ...@@ -521,6 +522,18 @@ AVCodec wmv1_decoder = {
CODEC_CAP_DRAW_HORIZ_BAND, CODEC_CAP_DRAW_HORIZ_BAND,
}; };
AVCodec wmv2_decoder = {
"wmv2",
CODEC_TYPE_VIDEO,
CODEC_ID_WMV2,
sizeof(MpegEncContext),
h263_decode_init,
NULL,
h263_decode_end,
h263_decode_frame,
CODEC_CAP_DRAW_HORIZ_BAND,
};
AVCodec h263i_decoder = { AVCodec h263i_decoder = {
"h263i", "h263i",
CODEC_TYPE_VIDEO, CODEC_TYPE_VIDEO,
......
...@@ -184,41 +184,14 @@ static void mpeg1_skip_picture(MpegEncContext *s, int pict_num) ...@@ -184,41 +184,14 @@ static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
put_bits(&s->pb, 1, 1); put_bits(&s->pb, 1, 1);
} }
void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) static void common_init(MpegEncContext *s)
{ {
static int done=0; s->y_dc_scale_table=
s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
if (!done) { }
int i;
done = 1;
init_rl(&rl_mpeg1);
for(i=0; i<64; i++)
{
mpeg1_max_level[0][i]= rl_mpeg1.max_level[0][i];
mpeg1_index_run[0][i]= rl_mpeg1.index_run[0][i];
}
/* build unified dc encoding tables */
for(i=-255; i<256; i++)
{
int adiff, index;
int bits, code;
int diff=i;
adiff = ABS(diff);
if(diff<0) diff--;
index = vlc_dc_table[adiff];
bits= vlc_dc_lum_bits[index] + index; void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
code= (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1)); {
mpeg1_lum_dc_uni[i+255]= bits + (code<<8);
bits= vlc_dc_chroma_bits[index] + index;
code= (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1));
mpeg1_chr_dc_uni[i+255]= bits + (code<<8);
}
}
mpeg1_encode_sequence_header(s); mpeg1_encode_sequence_header(s);
/* mpeg1 picture header */ /* mpeg1 picture header */
...@@ -354,14 +327,46 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val) ...@@ -354,14 +327,46 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val)
} }
} }
void mpeg1_encode_init(MpegEncContext *s) void ff_mpeg1_encode_init(MpegEncContext *s)
{ {
static int done=0; static int done=0;
common_init(s);
if(!done){ if(!done){
int f_code; int f_code;
int mv; int mv;
int i;
done=1; done=1;
init_rl(&rl_mpeg1);
for(i=0; i<64; i++)
{
mpeg1_max_level[0][i]= rl_mpeg1.max_level[0][i];
mpeg1_index_run[0][i]= rl_mpeg1.index_run[0][i];
}
/* build unified dc encoding tables */
for(i=-255; i<256; i++)
{
int adiff, index;
int bits, code;
int diff=i;
adiff = ABS(diff);
if(diff<0) diff--;
index = vlc_dc_table[adiff];
bits= vlc_dc_lum_bits[index] + index;
code= (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1));
mpeg1_lum_dc_uni[i+255]= bits + (code<<8);
bits= vlc_dc_chroma_bits[index] + index;
code= (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1));
mpeg1_chr_dc_uni[i+255]= bits + (code<<8);
}
for(f_code=1; f_code<=MAX_FCODE; f_code++){ for(f_code=1; f_code<=MAX_FCODE; f_code++){
for(mv=-MAX_MV; mv<=MAX_MV; mv++){ for(mv=-MAX_MV; mv<=MAX_MV; mv++){
int len; int len;
...@@ -403,7 +408,7 @@ void mpeg1_encode_init(MpegEncContext *s) ...@@ -403,7 +408,7 @@ void mpeg1_encode_init(MpegEncContext *s)
s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x
s->inter_quant_bias= 0; s->inter_quant_bias= 0;
} }
static inline void encode_dc(MpegEncContext *s, int diff, int component) static inline void encode_dc(MpegEncContext *s, int diff, int component)
{ {
if (component == 0) { if (component == 0) {
...@@ -1183,6 +1188,8 @@ typedef struct Mpeg1Context { ...@@ -1183,6 +1188,8 @@ typedef struct Mpeg1Context {
static int mpeg_decode_init(AVCodecContext *avctx) static int mpeg_decode_init(AVCodecContext *avctx)
{ {
Mpeg1Context *s = avctx->priv_data; Mpeg1Context *s = avctx->priv_data;
common_init(&s->mpeg_enc_ctx);
s->header_state = 0xff; s->header_state = 0xff;
s->mpeg_enc_ctx_allocated = 0; s->mpeg_enc_ctx_allocated = 0;
......
...@@ -402,3 +402,13 @@ static const UINT8 non_linear_qscale[32] = { ...@@ -402,3 +402,13 @@ static const UINT8 non_linear_qscale[32] = {
24,28,32,36,40,44,48,52, 24,28,32,36,40,44,48,52,
56,64,72,80,88,96,104,112, 56,64,72,80,88,96,104,112,
}; };
UINT8 ff_mpeg1_dc_scale_table[128]={ // MN: mpeg2 really can have such large qscales?
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
};
...@@ -153,3 +153,13 @@ INT16 ff_mpeg4_default_non_intra_matrix[64] = { ...@@ -153,3 +153,13 @@ INT16 ff_mpeg4_default_non_intra_matrix[64] = {
23, 24, 25, 27, 28, 30, 31, 33, 23, 24, 25, 27, 28, 30, 31, 33,
}; };
UINT8 ff_mpeg4_y_dc_scale_table[32]={
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8,10,12,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,36,38,40,42,44,46
};
UINT8 ff_mpeg4_c_dc_scale_table[32]={
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,21,22,23,24,25
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment