mpeg4 interlaced dct encoding
Originally committed as revision 971 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
b560f4b656
commit
fcb48651f4
@ -5,8 +5,8 @@
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT 0x000406
|
||||
#define LIBAVCODEC_VERSION "0.4.6"
|
||||
#define LIBAVCODEC_BUILD 4626
|
||||
#define LIBAVCODEC_BUILD_STR "4626"
|
||||
#define LIBAVCODEC_BUILD 4627
|
||||
#define LIBAVCODEC_BUILD_STR "4627"
|
||||
|
||||
enum CodecID {
|
||||
CODEC_ID_NONE,
|
||||
@ -124,6 +124,7 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG,
|
||||
#define CODEC_FLAG_NOT_TRUNCATED 0x00010000 /* input bitstream is not truncated, except before a startcode
|
||||
allows the last part of a frame to be decoded earlier */
|
||||
#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 /* normalize adaptive quantization */
|
||||
#define CODEC_FLAG_INTERLACED_DCT 0x00040000 /* use interlaced dct */
|
||||
|
||||
/* codec capabilities */
|
||||
|
||||
|
@ -458,6 +458,13 @@ void mpeg4_encode_mb(MpegEncContext * s,
|
||||
put_bits(&s->pb, 1, 0);
|
||||
}else
|
||||
s->qscale -= s->dquant;
|
||||
|
||||
if(!s->progressive_sequence){
|
||||
if(cbp)
|
||||
put_bits(&s->pb, 1, s->interlaced_dct);
|
||||
if(mb_type) // not diect mode
|
||||
put_bits(&s->pb, 1, 0); // no interlaced ME yet
|
||||
}
|
||||
|
||||
if(interleaved_stats){
|
||||
bits= get_bit_count(&s->pb);
|
||||
@ -580,6 +587,12 @@ void mpeg4_encode_mb(MpegEncContext * s,
|
||||
put_bits(pb2, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
|
||||
if(s->dquant)
|
||||
put_bits(pb2, 2, dquant_code[s->dquant+2]);
|
||||
|
||||
if(!s->progressive_sequence){
|
||||
if(cbp)
|
||||
put_bits(pb2, 1, s->interlaced_dct);
|
||||
put_bits(pb2, 1, 0); // no interlaced ME yet
|
||||
}
|
||||
|
||||
if(interleaved_stats){
|
||||
bits= get_bit_count(&s->pb);
|
||||
@ -701,6 +714,10 @@ void mpeg4_encode_mb(MpegEncContext * s,
|
||||
if(s->dquant)
|
||||
put_bits(dc_pb, 2, dquant_code[s->dquant+2]);
|
||||
|
||||
if(!s->progressive_sequence){
|
||||
put_bits(dc_pb, 1, s->interlaced_dct);
|
||||
}
|
||||
|
||||
if(interleaved_stats){
|
||||
bits= get_bit_count(&s->pb);
|
||||
s->misc_bits+= bits - s->last_bits;
|
||||
@ -1511,7 +1528,7 @@ static void mpeg4_encode_vol_header(MpegEncContext * s)
|
||||
put_bits(&s->pb, 1, 1); /* marker bit */
|
||||
put_bits(&s->pb, 13, s->height); /* vol height */
|
||||
put_bits(&s->pb, 1, 1); /* marker bit */
|
||||
put_bits(&s->pb, 1, 0); /* interlace */
|
||||
put_bits(&s->pb, 1, s->progressive_sequence ? 0 : 1);
|
||||
put_bits(&s->pb, 1, 1); /* obmc disable */
|
||||
if (vo_ver_id == 1) {
|
||||
put_bits(&s->pb, 1, s->vol_sprite_usage=0); /* sprite enable */
|
||||
@ -1586,6 +1603,10 @@ void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
|
||||
put_bits(&s->pb, 1, s->no_rounding); /* rounding type */
|
||||
}
|
||||
put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */
|
||||
if(!s->progressive_sequence){
|
||||
put_bits(&s->pb, 1, s->top_field_first);
|
||||
put_bits(&s->pb, 1, s->alternate_scan);
|
||||
}
|
||||
//FIXME sprite stuff
|
||||
|
||||
put_bits(&s->pb, 5, s->qscale);
|
||||
@ -4215,7 +4236,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
|
||||
|
||||
check_marker(&s->gb, "before time_increment");
|
||||
time_increment= get_bits(&s->gb, s->time_increment_bits);
|
||||
//printf(" type:%d incr:%d increment:%d\n", s->pict_type, time_incr, time_increment);
|
||||
//printf(" type:%d modulo_time_base:%d increment:%d\n", s->pict_type, time_incr, time_increment);
|
||||
if(s->pict_type!=B_TYPE){
|
||||
s->last_time_base= s->time_base;
|
||||
s->time_base+= time_incr;
|
||||
|
@ -450,6 +450,8 @@ int MPV_encode_init(AVCodecContext *avctx)
|
||||
|| s->avctx->spatial_cplx_masking
|
||||
|| s->avctx->p_masking)
|
||||
&& !s->fixed_qscale;
|
||||
|
||||
s->progressive_sequence= !(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
|
||||
|
||||
switch(avctx->codec->id) {
|
||||
case CODEC_ID_MPEG1VIDEO:
|
||||
@ -1747,29 +1749,154 @@ static inline void clip_coeffs(MpegEncContext *s, DCTELEM *block, int last_index
|
||||
}
|
||||
}
|
||||
|
||||
static inline void requantize_coeffs(MpegEncContext *s, DCTELEM block[64], int oldq, int newq, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(s->mb_intra){
|
||||
//FIXME requantize, note (mpeg1/h263/h263p-aic dont need it,...)
|
||||
i=1;
|
||||
}else
|
||||
i=0;
|
||||
|
||||
for(;i<=s->block_last_index[n]; i++){
|
||||
const int j = zigzag_direct[i];
|
||||
int level = block[j];
|
||||
|
||||
block[j]= ROUNDED_DIV(level*oldq, newq);
|
||||
}
|
||||
|
||||
for(i=s->block_last_index[n]; i>=0; i--){
|
||||
const int j = zigzag_direct[i]; //FIXME other scantabs
|
||||
if(block[j]) break;
|
||||
}
|
||||
s->block_last_index[n]= i;
|
||||
}
|
||||
|
||||
static inline void auto_requantize_coeffs(MpegEncContext *s, DCTELEM block[6][64])
|
||||
{
|
||||
int i,n, newq;
|
||||
const int maxlevel= s->max_qcoeff;
|
||||
const int minlevel= s->min_qcoeff;
|
||||
int largest=0, smallest=0;
|
||||
|
||||
assert(s->adaptive_quant);
|
||||
|
||||
for(n=0; n<6; n++){
|
||||
if(s->mb_intra) i=1;
|
||||
else i=0;
|
||||
|
||||
for(;i<=s->block_last_index[n]; i++){
|
||||
const int j = zigzag_direct[i]; //FIXME other scantabs
|
||||
int level = block[n][j];
|
||||
if(largest < level) largest = level;
|
||||
if(smallest > level) smallest= level;
|
||||
}
|
||||
}
|
||||
|
||||
for(newq=s->qscale+1; newq<32; newq++){
|
||||
if( ROUNDED_DIV(smallest*s->qscale, newq) >= minlevel
|
||||
&& ROUNDED_DIV(largest *s->qscale, newq) <= maxlevel)
|
||||
break;
|
||||
}
|
||||
|
||||
if(s->out_format==FMT_H263){
|
||||
/* h263 like formats cannot change qscale by more than 2 easiely */
|
||||
if(s->avctx->qmin + 2 < newq)
|
||||
newq= s->avctx->qmin + 2;
|
||||
}
|
||||
|
||||
for(n=0; n<6; n++){
|
||||
requantize_coeffs(s, block[n], s->qscale, newq, n);
|
||||
clip_coeffs(s, block[n], s->block_last_index[n]);
|
||||
}
|
||||
|
||||
s->dquant+= newq - s->qscale;
|
||||
s->qscale= newq;
|
||||
}
|
||||
#if 0
|
||||
static int pix_vcmp16x8(UINT8 *s, int stride){ //FIXME move to dsputil & optimize
|
||||
int score=0;
|
||||
int x,y;
|
||||
|
||||
for(y=0; y<7; y++){
|
||||
for(x=0; x<16; x+=4){
|
||||
score+= ABS(s[x ] - s[x +stride]) + ABS(s[x+1] - s[x+1+stride])
|
||||
+ABS(s[x+2] - s[x+2+stride]) + ABS(s[x+3] - s[x+3+stride]);
|
||||
}
|
||||
s+= stride;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
static int pix_diff_vcmp16x8(UINT8 *s1, UINT8*s2, int stride){ //FIXME move to dsputil & optimize
|
||||
int score=0;
|
||||
int x,y;
|
||||
|
||||
for(y=0; y<7; y++){
|
||||
for(x=0; x<16; x++){
|
||||
score+= ABS(s1[x ] - s2[x ] - s1[x +stride] + s2[x +stride]);
|
||||
}
|
||||
s1+= stride;
|
||||
s2+= stride;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
#else
|
||||
#define SQ(a) ((a)*(a))
|
||||
|
||||
static int pix_vcmp16x8(UINT8 *s, int stride){ //FIXME move to dsputil & optimize
|
||||
int score=0;
|
||||
int x,y;
|
||||
|
||||
for(y=0; y<7; y++){
|
||||
for(x=0; x<16; x+=4){
|
||||
score+= SQ(s[x ] - s[x +stride]) + SQ(s[x+1] - s[x+1+stride])
|
||||
+SQ(s[x+2] - s[x+2+stride]) + SQ(s[x+3] - s[x+3+stride]);
|
||||
}
|
||||
s+= stride;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
static int pix_diff_vcmp16x8(UINT8 *s1, UINT8*s2, int stride){ //FIXME move to dsputil & optimize
|
||||
int score=0;
|
||||
int x,y;
|
||||
|
||||
for(y=0; y<7; y++){
|
||||
for(x=0; x<16; x++){
|
||||
score+= SQ(s1[x ] - s2[x ] - s1[x +stride] + s2[x +stride]);
|
||||
}
|
||||
s1+= stride;
|
||||
s2+= stride;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
#endif
|
||||
static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
|
||||
{
|
||||
const int mb_x= s->mb_x;
|
||||
const int mb_y= s->mb_y;
|
||||
int i;
|
||||
int skip_dct[6];
|
||||
#if 0
|
||||
if (s->interlaced_dct) {
|
||||
dct_linesize = s->linesize * 2;
|
||||
dct_offset = s->linesize;
|
||||
} else {
|
||||
dct_linesize = s->linesize;
|
||||
dct_offset = s->linesize * 8;
|
||||
}
|
||||
#endif
|
||||
int dct_offset = s->linesize*8; //default for progressive frames
|
||||
|
||||
for(i=0; i<6; i++) skip_dct[i]=0;
|
||||
|
||||
if(s->adaptive_quant){
|
||||
s->dquant= s->qscale_table[mb_x + mb_y*s->mb_width] - s->qscale;
|
||||
if(s->codec_id==CODEC_ID_MPEG4){
|
||||
|
||||
if(s->out_format==FMT_H263){
|
||||
if (s->dquant> 2) s->dquant= 2;
|
||||
else if(s->dquant<-2) s->dquant=-2;
|
||||
|
||||
}
|
||||
|
||||
if(s->codec_id==CODEC_ID_MPEG4){
|
||||
if(!s->mb_intra){
|
||||
assert(s->dquant==0 || s->mv_type!=MV_TYPE_8X8);
|
||||
|
||||
@ -1784,39 +1911,56 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
|
||||
|
||||
if (s->mb_intra) {
|
||||
UINT8 *ptr;
|
||||
int wrap;
|
||||
int wrap_y;
|
||||
int emu=0;
|
||||
|
||||
wrap = s->linesize;
|
||||
ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16;
|
||||
wrap_y = s->linesize;
|
||||
ptr = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
|
||||
|
||||
if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){
|
||||
emulated_edge_mc(s, ptr, wrap, 16, 16, mb_x*16, mb_y*16, s->width, s->height);
|
||||
emulated_edge_mc(s, ptr, wrap_y, 16, 16, mb_x*16, mb_y*16, s->width, s->height);
|
||||
ptr= s->edge_emu_buffer;
|
||||
emu=1;
|
||||
}
|
||||
get_pixels(s->block[0], ptr , wrap);
|
||||
get_pixels(s->block[1], ptr + 8, wrap);
|
||||
get_pixels(s->block[2], ptr + 8 * wrap , wrap);
|
||||
get_pixels(s->block[3], ptr + 8 * wrap + 8, wrap);
|
||||
|
||||
if(s->flags&CODEC_FLAG_INTERLACED_DCT){
|
||||
int progressive_score, interlaced_score;
|
||||
|
||||
progressive_score= pix_vcmp16x8(ptr, wrap_y ) + pix_vcmp16x8(ptr + wrap_y*8, wrap_y );
|
||||
interlaced_score = pix_vcmp16x8(ptr, wrap_y*2) + pix_vcmp16x8(ptr + wrap_y , wrap_y*2);
|
||||
|
||||
if(progressive_score > interlaced_score + 100){
|
||||
s->interlaced_dct=1;
|
||||
|
||||
dct_offset= wrap_y;
|
||||
wrap_y<<=1;
|
||||
}else
|
||||
s->interlaced_dct=0;
|
||||
}
|
||||
|
||||
get_pixels(s->block[0], ptr , wrap_y);
|
||||
get_pixels(s->block[1], ptr + 8, wrap_y);
|
||||
get_pixels(s->block[2], ptr + dct_offset , wrap_y);
|
||||
get_pixels(s->block[3], ptr + dct_offset + 8, wrap_y);
|
||||
|
||||
if(s->flags&CODEC_FLAG_GRAY){
|
||||
skip_dct[4]= 1;
|
||||
skip_dct[5]= 1;
|
||||
}else{
|
||||
wrap >>=1;
|
||||
ptr = s->new_picture[1] + (mb_y * 8 * wrap) + mb_x * 8;
|
||||
int wrap_c = s->uvlinesize;
|
||||
ptr = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
|
||||
if(emu){
|
||||
emulated_edge_mc(s, ptr, wrap, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
|
||||
emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
|
||||
ptr= s->edge_emu_buffer;
|
||||
}
|
||||
get_pixels(s->block[4], ptr, wrap);
|
||||
get_pixels(s->block[4], ptr, wrap_c);
|
||||
|
||||
ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8;
|
||||
ptr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
|
||||
if(emu){
|
||||
emulated_edge_mc(s, ptr, wrap, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
|
||||
emulated_edge_mc(s, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1);
|
||||
ptr= s->edge_emu_buffer;
|
||||
}
|
||||
get_pixels(s->block[5], ptr, wrap);
|
||||
get_pixels(s->block[5], ptr, wrap_c);
|
||||
}
|
||||
}else{
|
||||
op_pixels_func (*op_pix)[4];
|
||||
@ -1830,7 +1974,7 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
|
||||
dest_cb = s->current_picture[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
|
||||
dest_cr = s->current_picture[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
|
||||
wrap_y = s->linesize;
|
||||
wrap_c = wrap_y>>1;
|
||||
wrap_c = s->uvlinesize;
|
||||
ptr_y = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16;
|
||||
ptr_cb = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8;
|
||||
ptr_cr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8;
|
||||
@ -1857,10 +2001,28 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
|
||||
ptr_y= s->edge_emu_buffer;
|
||||
emu=1;
|
||||
}
|
||||
|
||||
if(s->flags&CODEC_FLAG_INTERLACED_DCT){
|
||||
int progressive_score, interlaced_score;
|
||||
|
||||
progressive_score= pix_diff_vcmp16x8(ptr_y , dest_y , wrap_y )
|
||||
+ pix_diff_vcmp16x8(ptr_y + wrap_y*8, dest_y + wrap_y*8, wrap_y );
|
||||
interlaced_score = pix_diff_vcmp16x8(ptr_y , dest_y , wrap_y*2)
|
||||
+ pix_diff_vcmp16x8(ptr_y + wrap_y , dest_y + wrap_y , wrap_y*2);
|
||||
|
||||
if(progressive_score > interlaced_score + 600){
|
||||
s->interlaced_dct=1;
|
||||
|
||||
dct_offset= wrap_y;
|
||||
wrap_y<<=1;
|
||||
}else
|
||||
s->interlaced_dct=0;
|
||||
}
|
||||
|
||||
diff_pixels(s->block[0], ptr_y , dest_y , wrap_y);
|
||||
diff_pixels(s->block[1], ptr_y + 8, dest_y + 8, wrap_y);
|
||||
diff_pixels(s->block[2], ptr_y + 8 * wrap_y , dest_y + 8 * wrap_y , wrap_y);
|
||||
diff_pixels(s->block[3], ptr_y + 8 * wrap_y + 8, dest_y + 8 * wrap_y + 8, wrap_y);
|
||||
diff_pixels(s->block[2], ptr_y + dct_offset , dest_y + dct_offset , wrap_y);
|
||||
diff_pixels(s->block[3], ptr_y + dct_offset + 8, dest_y + dct_offset + 8, wrap_y);
|
||||
|
||||
if(s->flags&CODEC_FLAG_GRAY){
|
||||
skip_dct[4]= 1;
|
||||
@ -1880,10 +2042,11 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
|
||||
|
||||
/* pre quantization */
|
||||
if(s->mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){
|
||||
//FIXME optimize
|
||||
if(pix_abs8x8(ptr_y , dest_y , wrap_y) < 20*s->qscale) skip_dct[0]= 1;
|
||||
if(pix_abs8x8(ptr_y + 8, dest_y + 8, wrap_y) < 20*s->qscale) skip_dct[1]= 1;
|
||||
if(pix_abs8x8(ptr_y + 8*wrap_y , dest_y + 8*wrap_y , wrap_y) < 20*s->qscale) skip_dct[2]= 1;
|
||||
if(pix_abs8x8(ptr_y + 8*wrap_y + 8, dest_y + 8*wrap_y + 8, wrap_y) < 20*s->qscale) skip_dct[3]= 1;
|
||||
if(pix_abs8x8(ptr_y +dct_offset , dest_y +dct_offset , wrap_y) < 20*s->qscale) skip_dct[2]= 1;
|
||||
if(pix_abs8x8(ptr_y +dct_offset+ 8, dest_y +dct_offset+ 8, wrap_y) < 20*s->qscale) skip_dct[3]= 1;
|
||||
if(pix_abs8x8(ptr_cb , dest_cb , wrap_y) < 20*s->qscale) skip_dct[4]= 1;
|
||||
if(pix_abs8x8(ptr_cr , dest_cr , wrap_y) < 20*s->qscale) skip_dct[5]= 1;
|
||||
#if 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user