2007-07-03 12:55:56 +03:00
/*
* The simplest mpeg encoder ( well , it was the simplest ! )
* Copyright ( c ) 2000 , 2001 Fabrice Bellard .
* Copyright ( c ) 2002 - 2004 Michael Niedermayer < michaelni @ gmx . at >
*
2007-07-05 13:37:29 +03:00
* 4 MV & hq & B - frame encoding stuff by Michael Niedermayer < michaelni @ gmx . at >
*
2007-07-03 12:55:56 +03:00
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* FFmpeg is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
/**
* @ file mpegvideo_enc . c
* The simplest mpeg encoder ( well , it was the simplest ! ) .
*/
# include "avcodec.h"
# include "dsputil.h"
# include "mpegvideo.h"
# include "mpegvideo_common.h"
# include "mjpegenc.h"
# include "msmpeg4.h"
2007-07-10 23:23:08 +03:00
# include "h263.h"
2007-07-03 12:55:56 +03:00
# include "faandct.h"
# include <limits.h>
//#undef NDEBUG
//#include <assert.h>
static int encode_picture ( MpegEncContext * s , int picture_number ) ;
static int dct_quantize_refine ( MpegEncContext * s , DCTELEM * block , int16_t * weight , DCTELEM * orig , int n , int qscale ) ;
static int sse_mb ( MpegEncContext * s ) ;
/* enable all paranoid tests for rounding, overflows, etc... */
//#define PARANOID
//#define DEBUG
static const uint16_t aanscales [ 64 ] = {
/* precomputed values scaled up by 14 bits */
16384 , 22725 , 21407 , 19266 , 16384 , 12873 , 8867 , 4520 ,
22725 , 31521 , 29692 , 26722 , 22725 , 17855 , 12299 , 6270 ,
21407 , 29692 , 27969 , 25172 , 21407 , 16819 , 11585 , 5906 ,
19266 , 26722 , 25172 , 22654 , 19266 , 15137 , 10426 , 5315 ,
16384 , 22725 , 21407 , 19266 , 16384 , 12873 , 8867 , 4520 ,
12873 , 17855 , 16819 , 15137 , 12873 , 10114 , 6967 , 3552 ,
8867 , 12299 , 11585 , 10426 , 8867 , 6967 , 4799 , 2446 ,
4520 , 6270 , 5906 , 5315 , 4520 , 3552 , 2446 , 1247
} ;
2008-02-26 00:43:42 +02:00
static const uint16_t inv_aanscales [ 64 ] = {
4096 , 2953 , 3135 , 3483 , 4096 , 5213 , 7568 , 14846 ,
2953 , 2129 , 2260 , 2511 , 2953 , 3759 , 5457 , 10703 ,
3135 , 2260 , 2399 , 2666 , 3135 , 3990 , 5793 , 11363 ,
3483 , 2511 , 2666 , 2962 , 3483 , 4433 , 6436 , 12625 ,
4096 , 2953 , 3135 , 3483 , 4096 , 5213 , 7568 , 14846 ,
5213 , 3759 , 3990 , 4433 , 5213 , 6635 , 9633 , 18895 ,
7568 , 5457 , 5793 , 6436 , 7568 , 9633 , 13985 , 27432 ,
14846 , 10703 , 11363 , 12625 , 14846 , 18895 , 27432 , 53809 ,
} ;
2007-07-03 12:55:56 +03:00
static uint8_t default_mv_penalty [ MAX_FCODE + 1 ] [ MAX_MV * 2 + 1 ] ;
static uint8_t default_fcode_tab [ MAX_MV * 2 + 1 ] ;
2007-10-08 12:14:46 +03:00
void ff_convert_matrix ( DSPContext * dsp , int ( * qmat ) [ 64 ] , uint16_t ( * qmat16 ) [ 2 ] [ 64 ] ,
2007-07-03 12:55:56 +03:00
const uint16_t * quant_matrix , int bias , int qmin , int qmax , int intra )
{
int qscale ;
int shift = 0 ;
for ( qscale = qmin ; qscale < = qmax ; qscale + + ) {
int i ;
if ( dsp - > fdct = = ff_jpeg_fdct_islow
# ifdef FAAN_POSTSCALE
| | dsp - > fdct = = ff_faandct
# endif
) {
for ( i = 0 ; i < 64 ; i + + ) {
const int j = dsp - > idct_permutation [ i ] ;
/* 16 <= qscale * quant_matrix[i] <= 7905 */
/* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
/* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */
/* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */
qmat [ qscale ] [ i ] = ( int ) ( ( UINT64_C ( 1 ) < < QMAT_SHIFT ) /
( qscale * quant_matrix [ j ] ) ) ;
}
} else if ( dsp - > fdct = = fdct_ifast
# ifndef FAAN_POSTSCALE
| | dsp - > fdct = = ff_faandct
# endif
) {
for ( i = 0 ; i < 64 ; i + + ) {
const int j = dsp - > idct_permutation [ i ] ;
/* 16 <= qscale * quant_matrix[i] <= 7905 */
/* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
/* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */
/* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */
qmat [ qscale ] [ i ] = ( int ) ( ( UINT64_C ( 1 ) < < ( QMAT_SHIFT + 14 ) ) /
( aanscales [ i ] * qscale * quant_matrix [ j ] ) ) ;
}
} else {
for ( i = 0 ; i < 64 ; i + + ) {
const int j = dsp - > idct_permutation [ i ] ;
/* We can safely suppose that 16 <= quant_matrix[i] <= 255
So 16 < = qscale * quant_matrix [ i ] < = 7905
so ( 1 < < 19 ) / 16 > = ( 1 < < 19 ) / ( qscale * quant_matrix [ i ] ) > = ( 1 < < 19 ) / 7905
so 32768 > = ( 1 < < 19 ) / ( qscale * quant_matrix [ i ] ) > = 67
*/
qmat [ qscale ] [ i ] = ( int ) ( ( UINT64_C ( 1 ) < < QMAT_SHIFT ) / ( qscale * quant_matrix [ j ] ) ) ;
// qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]);
qmat16 [ qscale ] [ 0 ] [ i ] = ( 1 < < QMAT_SHIFT_MMX ) / ( qscale * quant_matrix [ j ] ) ;
if ( qmat16 [ qscale ] [ 0 ] [ i ] = = 0 | | qmat16 [ qscale ] [ 0 ] [ i ] = = 128 * 256 ) qmat16 [ qscale ] [ 0 ] [ i ] = 128 * 256 - 1 ;
qmat16 [ qscale ] [ 1 ] [ i ] = ROUNDED_DIV ( bias < < ( 16 - QUANT_BIAS_SHIFT ) , qmat16 [ qscale ] [ 0 ] [ i ] ) ;
}
}
for ( i = intra ; i < 64 ; i + + ) {
int64_t max = 8191 ;
if ( dsp - > fdct = = fdct_ifast
# ifndef FAAN_POSTSCALE
| | dsp - > fdct = = ff_faandct
# endif
) {
max = ( 8191LL * aanscales [ i ] ) > > 14 ;
}
while ( ( ( max * qmat [ qscale ] [ i ] ) > > shift ) > INT_MAX ) {
shift + + ;
}
}
}
if ( shift ) {
av_log ( NULL , AV_LOG_INFO , " Warning, QMAT_SHIFT is larger than %d, overflows possible \n " , QMAT_SHIFT - shift ) ;
}
}
static inline void update_qscale ( MpegEncContext * s ) {
s - > qscale = ( s - > lambda * 139 + FF_LAMBDA_SCALE * 64 ) > > ( FF_LAMBDA_SHIFT + 7 ) ;
s - > qscale = av_clip ( s - > qscale , s - > avctx - > qmin , s - > avctx - > qmax ) ;
s - > lambda2 = ( s - > lambda * s - > lambda + FF_LAMBDA_SCALE / 2 ) > > FF_LAMBDA_SHIFT ;
}
void ff_write_quant_matrix ( PutBitContext * pb , uint16_t * matrix ) {
int i ;
if ( matrix ) {
put_bits ( pb , 1 , 1 ) ;
for ( i = 0 ; i < 64 ; i + + ) {
put_bits ( pb , 8 , matrix [ ff_zigzag_direct [ i ] ] ) ;
}
} else
put_bits ( pb , 1 , 0 ) ;
}
static void copy_picture_attributes ( MpegEncContext * s , AVFrame * dst , AVFrame * src ) {
int i ;
dst - > pict_type = src - > pict_type ;
dst - > quality = src - > quality ;
dst - > coded_picture_number = src - > coded_picture_number ;
dst - > display_picture_number = src - > display_picture_number ;
// dst->reference = src->reference;
dst - > pts = src - > pts ;
dst - > interlaced_frame = src - > interlaced_frame ;
dst - > top_field_first = src - > top_field_first ;
if ( s - > avctx - > me_threshold ) {
if ( ! src - > motion_val [ 0 ] )
av_log ( s - > avctx , AV_LOG_ERROR , " AVFrame.motion_val not set! \n " ) ;
if ( ! src - > mb_type )
av_log ( s - > avctx , AV_LOG_ERROR , " AVFrame.mb_type not set! \n " ) ;
if ( ! src - > ref_index [ 0 ] )
av_log ( s - > avctx , AV_LOG_ERROR , " AVFrame.ref_index not set! \n " ) ;
if ( src - > motion_subsample_log2 ! = dst - > motion_subsample_log2 )
av_log ( s - > avctx , AV_LOG_ERROR , " AVFrame.motion_subsample_log2 doesn't match! (%d!=%d) \n " ,
src - > motion_subsample_log2 , dst - > motion_subsample_log2 ) ;
memcpy ( dst - > mb_type , src - > mb_type , s - > mb_stride * s - > mb_height * sizeof ( dst - > mb_type [ 0 ] ) ) ;
for ( i = 0 ; i < 2 ; i + + ) {
int stride = ( ( 16 * s - > mb_width ) > > src - > motion_subsample_log2 ) + 1 ;
int height = ( ( 16 * s - > mb_height ) > > src - > motion_subsample_log2 ) ;
if ( src - > motion_val [ i ] & & src - > motion_val [ i ] ! = dst - > motion_val [ i ] ) {
memcpy ( dst - > motion_val [ i ] , src - > motion_val [ i ] , 2 * stride * height * sizeof ( int16_t ) ) ;
}
if ( src - > ref_index [ i ] & & src - > ref_index [ i ] ! = dst - > ref_index [ i ] ) {
memcpy ( dst - > ref_index [ i ] , src - > ref_index [ i ] , s - > b8_stride * 2 * s - > mb_height * sizeof ( int8_t ) ) ;
}
}
}
}
static void update_duplicate_context_after_me ( MpegEncContext * dst , MpegEncContext * src ) {
# define COPY(a) dst->a= src->a
COPY ( pict_type ) ;
COPY ( current_picture ) ;
COPY ( f_code ) ;
COPY ( b_code ) ;
COPY ( qscale ) ;
COPY ( lambda ) ;
COPY ( lambda2 ) ;
COPY ( picture_in_gop_number ) ;
COPY ( gop_picture_number ) ;
COPY ( frame_pred_frame_dct ) ; //FIXME don't set in encode_header
COPY ( progressive_frame ) ; //FIXME don't set in encode_header
COPY ( partitioned_frame ) ; //FIXME don't set in encode_header
# undef COPY
}
/**
* sets the given MpegEncContext to defaults for encoding .
* the changed fields will not depend upon the prior state of the MpegEncContext .
*/
static void MPV_encode_defaults ( MpegEncContext * s ) {
int i ;
MPV_common_defaults ( s ) ;
for ( i = - 16 ; i < 16 ; i + + ) {
default_fcode_tab [ i + MAX_MV ] = 1 ;
}
s - > me . mv_penalty = default_mv_penalty ;
s - > fcode_tab = default_fcode_tab ;
}
/* init video encoder */
2008-03-21 05:11:20 +02:00
av_cold int MPV_encode_init ( AVCodecContext * avctx )
2007-07-03 12:55:56 +03:00
{
MpegEncContext * s = avctx - > priv_data ;
int i ;
int chroma_h_shift , chroma_v_shift ;
MPV_encode_defaults ( s ) ;
switch ( avctx - > codec_id ) {
case CODEC_ID_MPEG2VIDEO :
if ( avctx - > pix_fmt ! = PIX_FMT_YUV420P & & avctx - > pix_fmt ! = PIX_FMT_YUV422P ) {
av_log ( avctx , AV_LOG_ERROR , " only YUV420 and YUV422 are supported \n " ) ;
return - 1 ;
}
break ;
case CODEC_ID_LJPEG :
case CODEC_ID_MJPEG :
if ( avctx - > pix_fmt ! = PIX_FMT_YUVJ420P & & avctx - > pix_fmt ! = PIX_FMT_YUVJ422P & &
( ( avctx - > pix_fmt ! = PIX_FMT_YUV420P & & avctx - > pix_fmt ! = PIX_FMT_YUV422P ) | | avctx - > strict_std_compliance > FF_COMPLIANCE_INOFFICIAL ) ) {
av_log ( avctx , AV_LOG_ERROR , " colorspace not supported in jpeg \n " ) ;
return - 1 ;
}
break ;
default :
if ( avctx - > pix_fmt ! = PIX_FMT_YUV420P ) {
av_log ( avctx , AV_LOG_ERROR , " only YUV420 is supported \n " ) ;
return - 1 ;
}
}
switch ( avctx - > pix_fmt ) {
case PIX_FMT_YUVJ422P :
case PIX_FMT_YUV422P :
s - > chroma_format = CHROMA_422 ;
break ;
case PIX_FMT_YUVJ420P :
case PIX_FMT_YUV420P :
default :
s - > chroma_format = CHROMA_420 ;
break ;
}
s - > bit_rate = avctx - > bit_rate ;
s - > width = avctx - > width ;
s - > height = avctx - > height ;
if ( avctx - > gop_size > 600 & & avctx - > strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL ) {
av_log ( avctx , AV_LOG_ERROR , " Warning keyframe interval too large! reducing it ... \n " ) ;
avctx - > gop_size = 600 ;
}
s - > gop_size = avctx - > gop_size ;
s - > avctx = avctx ;
s - > flags = avctx - > flags ;
s - > flags2 = avctx - > flags2 ;
s - > max_b_frames = avctx - > max_b_frames ;
s - > codec_id = avctx - > codec - > id ;
s - > luma_elim_threshold = avctx - > luma_elim_threshold ;
s - > chroma_elim_threshold = avctx - > chroma_elim_threshold ;
s - > strict_std_compliance = avctx - > strict_std_compliance ;
s - > data_partitioning = avctx - > flags & CODEC_FLAG_PART ;
s - > quarter_sample = ( avctx - > flags & CODEC_FLAG_QPEL ) ! = 0 ;
s - > mpeg_quant = avctx - > mpeg_quant ;
s - > rtp_mode = ! ! avctx - > rtp_payload_size ;
s - > intra_dc_precision = avctx - > intra_dc_precision ;
s - > user_specified_pts = AV_NOPTS_VALUE ;
if ( s - > gop_size < = 1 ) {
s - > intra_only = 1 ;
s - > gop_size = 12 ;
} else {
s - > intra_only = 0 ;
}
s - > me_method = avctx - > me_method ;
/* Fixed QSCALE */
s - > fixed_qscale = ! ! ( avctx - > flags & CODEC_FLAG_QSCALE ) ;
s - > adaptive_quant = ( s - > avctx - > lumi_masking
| | s - > avctx - > dark_masking
| | s - > avctx - > temporal_cplx_masking
| | s - > avctx - > spatial_cplx_masking
| | s - > avctx - > p_masking
| | s - > avctx - > border_masking
| | ( s - > flags & CODEC_FLAG_QP_RD ) )
& & ! s - > fixed_qscale ;
s - > obmc = ! ! ( s - > flags & CODEC_FLAG_OBMC ) ;
s - > loop_filter = ! ! ( s - > flags & CODEC_FLAG_LOOP_FILTER ) ;
s - > alternate_scan = ! ! ( s - > flags & CODEC_FLAG_ALT_SCAN ) ;
s - > intra_vlc_format = ! ! ( s - > flags2 & CODEC_FLAG2_INTRA_VLC ) ;
s - > q_scale_type = ! ! ( s - > flags2 & CODEC_FLAG2_NON_LINEAR_QUANT ) ;
2008-06-09 03:43:07 +03:00
# if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
if ( s - > flags & CODEC_FLAG_TRELLIS_QUANT )
avctx - > trellis = 1 ;
# endif
2007-07-03 12:55:56 +03:00
if ( avctx - > rc_max_rate & & ! avctx - > rc_buffer_size ) {
av_log ( avctx , AV_LOG_ERROR , " a vbv buffer size is needed, for encoding with a maximum bitrate \n " ) ;
return - 1 ;
}
if ( avctx - > rc_min_rate & & avctx - > rc_max_rate ! = avctx - > rc_min_rate ) {
av_log ( avctx , AV_LOG_INFO , " Warning min_rate > 0 but min_rate != max_rate isn't recommended! \n " ) ;
}
if ( avctx - > rc_min_rate & & avctx - > rc_min_rate > avctx - > bit_rate ) {
av_log ( avctx , AV_LOG_ERROR , " bitrate below min bitrate \n " ) ;
return - 1 ;
}
if ( avctx - > rc_max_rate & & avctx - > rc_max_rate < avctx - > bit_rate ) {
av_log ( avctx , AV_LOG_INFO , " bitrate above max bitrate \n " ) ;
return - 1 ;
}
2007-07-29 22:21:56 +03:00
if ( avctx - > rc_max_rate & & avctx - > rc_max_rate = = avctx - > bit_rate & & avctx - > rc_max_rate ! = avctx - > rc_min_rate ) {
av_log ( avctx , AV_LOG_INFO , " impossible bitrate constraints, this will fail \n " ) ;
}
2007-07-03 12:55:56 +03:00
if ( avctx - > rc_buffer_size & & avctx - > bit_rate * av_q2d ( avctx - > time_base ) > avctx - > rc_buffer_size ) {
av_log ( avctx , AV_LOG_ERROR , " VBV buffer too small for bitrate \n " ) ;
return - 1 ;
}
if ( avctx - > bit_rate * av_q2d ( avctx - > time_base ) > avctx - > bit_rate_tolerance ) {
av_log ( avctx , AV_LOG_ERROR , " bitrate tolerance too small for bitrate \n " ) ;
return - 1 ;
}
if ( s - > avctx - > rc_max_rate & & s - > avctx - > rc_min_rate = = s - > avctx - > rc_max_rate
& & ( s - > codec_id = = CODEC_ID_MPEG1VIDEO | | s - > codec_id = = CODEC_ID_MPEG2VIDEO )
& & 90000LL * ( avctx - > rc_buffer_size - 1 ) > s - > avctx - > rc_max_rate * 0xFFFFLL ) {
av_log ( avctx , AV_LOG_INFO , " Warning vbv_delay will be set to 0xFFFF (=VBR) as the specified vbv buffer is too large for the given bitrate! \n " ) ;
}
if ( ( s - > flags & CODEC_FLAG_4MV ) & & s - > codec_id ! = CODEC_ID_MPEG4
& & s - > codec_id ! = CODEC_ID_H263 & & s - > codec_id ! = CODEC_ID_H263P & & s - > codec_id ! = CODEC_ID_FLV1 ) {
av_log ( avctx , AV_LOG_ERROR , " 4MV not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > obmc & & s - > avctx - > mb_decision ! = FF_MB_DECISION_SIMPLE ) {
av_log ( avctx , AV_LOG_ERROR , " OBMC is only supported with simple mb decision \n " ) ;
return - 1 ;
}
if ( s - > obmc & & s - > codec_id ! = CODEC_ID_H263 & & s - > codec_id ! = CODEC_ID_H263P ) {
av_log ( avctx , AV_LOG_ERROR , " OBMC is only supported with H263(+) \n " ) ;
return - 1 ;
}
if ( s - > quarter_sample & & s - > codec_id ! = CODEC_ID_MPEG4 ) {
av_log ( avctx , AV_LOG_ERROR , " qpel not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > data_partitioning & & s - > codec_id ! = CODEC_ID_MPEG4 ) {
av_log ( avctx , AV_LOG_ERROR , " data partitioning not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > max_b_frames & & s - > codec_id ! = CODEC_ID_MPEG4 & & s - > codec_id ! = CODEC_ID_MPEG1VIDEO & & s - > codec_id ! = CODEC_ID_MPEG2VIDEO ) {
av_log ( avctx , AV_LOG_ERROR , " b frames not supported by codec \n " ) ;
return - 1 ;
}
if ( ( s - > flags & ( CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME | CODEC_FLAG_ALT_SCAN ) )
& & s - > codec_id ! = CODEC_ID_MPEG4 & & s - > codec_id ! = CODEC_ID_MPEG2VIDEO ) {
av_log ( avctx , AV_LOG_ERROR , " interlacing not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > mpeg_quant & & s - > codec_id ! = CODEC_ID_MPEG4 ) { //FIXME mpeg2 uses that too
av_log ( avctx , AV_LOG_ERROR , " mpeg2 style quantization not supported by codec \n " ) ;
return - 1 ;
}
2008-06-09 03:43:07 +03:00
if ( ( s - > flags & CODEC_FLAG_CBP_RD ) & & ! avctx - > trellis ) {
2007-07-03 12:55:56 +03:00
av_log ( avctx , AV_LOG_ERROR , " CBP RD needs trellis quant \n " ) ;
return - 1 ;
}
if ( ( s - > flags & CODEC_FLAG_QP_RD ) & & s - > avctx - > mb_decision ! = FF_MB_DECISION_RD ) {
av_log ( avctx , AV_LOG_ERROR , " QP RD needs mbd=2 \n " ) ;
return - 1 ;
}
if ( s - > avctx - > scenechange_threshold < 1000000000 & & ( s - > flags & CODEC_FLAG_CLOSED_GOP ) ) {
2008-03-10 20:42:09 +02:00
av_log ( avctx , AV_LOG_ERROR , " closed gop with scene change detection are not supported yet, set threshold to 1000000000 \n " ) ;
2007-07-03 12:55:56 +03:00
return - 1 ;
}
if ( ( s - > flags2 & CODEC_FLAG2_INTRA_VLC ) & & s - > codec_id ! = CODEC_ID_MPEG2VIDEO ) {
av_log ( avctx , AV_LOG_ERROR , " intra vlc table not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > flags & CODEC_FLAG_LOW_DELAY ) {
2008-08-05 23:39:58 +03:00
if ( s - > codec_id ! = CODEC_ID_MPEG2VIDEO ) {
av_log ( avctx , AV_LOG_ERROR , " low delay forcing is only available for mpeg2 \n " ) ;
2007-07-03 12:55:56 +03:00
return - 1 ;
}
if ( s - > max_b_frames ! = 0 ) {
av_log ( avctx , AV_LOG_ERROR , " b frames cannot be used with low delay \n " ) ;
return - 1 ;
}
}
if ( s - > q_scale_type = = 1 ) {
if ( s - > codec_id ! = CODEC_ID_MPEG2VIDEO ) {
av_log ( avctx , AV_LOG_ERROR , " non linear quant is only available for mpeg2 \n " ) ;
return - 1 ;
}
if ( avctx - > qmax > 12 ) {
av_log ( avctx , AV_LOG_ERROR , " non linear quant only supports qmax <= 12 currently \n " ) ;
return - 1 ;
}
}
if ( s - > avctx - > thread_count > 1 & & s - > codec_id ! = CODEC_ID_MPEG4
& & s - > codec_id ! = CODEC_ID_MPEG1VIDEO & & s - > codec_id ! = CODEC_ID_MPEG2VIDEO
& & ( s - > codec_id ! = CODEC_ID_H263P | | ! ( s - > flags & CODEC_FLAG_H263P_SLICE_STRUCT ) ) ) {
av_log ( avctx , AV_LOG_ERROR , " multi threaded encoding not supported by codec \n " ) ;
return - 1 ;
}
if ( s - > avctx - > thread_count > 1 )
s - > rtp_mode = 1 ;
if ( ! avctx - > time_base . den | | ! avctx - > time_base . num ) {
av_log ( avctx , AV_LOG_ERROR , " framerate not set \n " ) ;
return - 1 ;
}
i = ( INT_MAX / 2 + 128 ) > > 8 ;
if ( avctx - > me_threshold > = i ) {
av_log ( avctx , AV_LOG_ERROR , " me_threshold too large, max is %d \n " , i - 1 ) ;
return - 1 ;
}
if ( avctx - > mb_threshold > = i ) {
av_log ( avctx , AV_LOG_ERROR , " mb_threshold too large, max is %d \n " , i - 1 ) ;
return - 1 ;
}
if ( avctx - > b_frame_strategy & & ( avctx - > flags & CODEC_FLAG_PASS2 ) ) {
av_log ( avctx , AV_LOG_INFO , " notice: b_frame_strategy only affects the first pass \n " ) ;
avctx - > b_frame_strategy = 0 ;
}
i = ff_gcd ( avctx - > time_base . den , avctx - > time_base . num ) ;
if ( i > 1 ) {
av_log ( avctx , AV_LOG_INFO , " removing common factors from framerate \n " ) ;
avctx - > time_base . den / = i ;
avctx - > time_base . num / = i ;
// return -1;
}
if ( s - > codec_id = = CODEC_ID_MJPEG ) {
s - > intra_quant_bias = 1 < < ( QUANT_BIAS_SHIFT - 1 ) ; //(a + x/2)/x
s - > inter_quant_bias = 0 ;
} else if ( s - > mpeg_quant | | s - > codec_id = = CODEC_ID_MPEG1VIDEO | | s - > codec_id = = CODEC_ID_MPEG2VIDEO ) {
s - > intra_quant_bias = 3 < < ( QUANT_BIAS_SHIFT - 3 ) ; //(a + x*3/8)/x
s - > inter_quant_bias = 0 ;
} else {
s - > intra_quant_bias = 0 ;
s - > inter_quant_bias = - ( 1 < < ( QUANT_BIAS_SHIFT - 2 ) ) ; //(a - x/4)/x
}
if ( avctx - > intra_quant_bias ! = FF_DEFAULT_QUANT_BIAS )
s - > intra_quant_bias = avctx - > intra_quant_bias ;
if ( avctx - > inter_quant_bias ! = FF_DEFAULT_QUANT_BIAS )
s - > inter_quant_bias = avctx - > inter_quant_bias ;
avcodec_get_chroma_sub_sample ( avctx - > pix_fmt , & chroma_h_shift , & chroma_v_shift ) ;
if ( avctx - > codec_id = = CODEC_ID_MPEG4 & & s - > avctx - > time_base . den > ( 1 < < 16 ) - 1 ) {
av_log ( avctx , AV_LOG_ERROR , " timebase not supported by mpeg 4 standard \n " ) ;
return - 1 ;
}
s - > time_increment_bits = av_log2 ( s - > avctx - > time_base . den - 1 ) + 1 ;
switch ( avctx - > codec - > id ) {
case CODEC_ID_MPEG1VIDEO :
s - > out_format = FMT_MPEG1 ;
s - > low_delay = ! ! ( s - > flags & CODEC_FLAG_LOW_DELAY ) ;
avctx - > delay = s - > low_delay ? 0 : ( s - > max_b_frames + 1 ) ;
break ;
case CODEC_ID_MPEG2VIDEO :
s - > out_format = FMT_MPEG1 ;
s - > low_delay = ! ! ( s - > flags & CODEC_FLAG_LOW_DELAY ) ;
avctx - > delay = s - > low_delay ? 0 : ( s - > max_b_frames + 1 ) ;
s - > rtp_mode = 1 ;
break ;
case CODEC_ID_LJPEG :
case CODEC_ID_MJPEG :
s - > out_format = FMT_MJPEG ;
s - > intra_only = 1 ; /* force intra only for jpeg */
s - > mjpeg_vsample [ 0 ] = 2 ;
s - > mjpeg_vsample [ 1 ] = 2 > > chroma_v_shift ;
s - > mjpeg_vsample [ 2 ] = 2 > > chroma_v_shift ;
s - > mjpeg_hsample [ 0 ] = 2 ;
s - > mjpeg_hsample [ 1 ] = 2 > > chroma_h_shift ;
s - > mjpeg_hsample [ 2 ] = 2 > > chroma_h_shift ;
if ( ! ( ENABLE_MJPEG_ENCODER | | ENABLE_LJPEG_ENCODER )
| | ff_mjpeg_encode_init ( s ) < 0 )
return - 1 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_H261 :
if ( ! ENABLE_H261_ENCODER ) return - 1 ;
if ( ff_h261_get_picture_format ( s - > width , s - > height ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " The specified picture size of %dx%d is not valid for the H.261 codec. \n Valid sizes are 176x144, 352x288 \n " , s - > width , s - > height ) ;
return - 1 ;
}
s - > out_format = FMT_H261 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_H263 :
2007-07-10 23:23:08 +03:00
if ( ! ENABLE_H263_ENCODER ) return - 1 ;
2007-07-03 12:55:56 +03:00
if ( h263_get_picture_format ( s - > width , s - > height ) = = 7 ) {
av_log ( avctx , AV_LOG_INFO , " The specified picture size of %dx%d is not valid for the H.263 codec. \n Valid sizes are 128x96, 176x144, 352x288, 704x576, and 1408x1152. Try H.263+. \n " , s - > width , s - > height ) ;
return - 1 ;
}
s - > out_format = FMT_H263 ;
s - > obmc = ( avctx - > flags & CODEC_FLAG_OBMC ) ? 1 : 0 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_H263P :
s - > out_format = FMT_H263 ;
s - > h263_plus = 1 ;
/* Fx */
s - > umvplus = ( avctx - > flags & CODEC_FLAG_H263P_UMV ) ? 1 : 0 ;
s - > h263_aic = ( avctx - > flags & CODEC_FLAG_AC_PRED ) ? 1 : 0 ;
s - > modified_quant = s - > h263_aic ;
s - > alt_inter_vlc = ( avctx - > flags & CODEC_FLAG_H263P_AIV ) ? 1 : 0 ;
s - > obmc = ( avctx - > flags & CODEC_FLAG_OBMC ) ? 1 : 0 ;
s - > loop_filter = ( avctx - > flags & CODEC_FLAG_LOOP_FILTER ) ? 1 : 0 ;
s - > unrestricted_mv = s - > obmc | | s - > loop_filter | | s - > umvplus ;
s - > h263_slice_structured = ( s - > flags & CODEC_FLAG_H263P_SLICE_STRUCT ) ? 1 : 0 ;
/* /Fx */
/* These are just to be sure */
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_FLV1 :
s - > out_format = FMT_H263 ;
s - > h263_flv = 2 ; /* format = 1; 11-bit codes */
s - > unrestricted_mv = 1 ;
s - > rtp_mode = 0 ; /* don't allow GOB */
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_RV10 :
s - > out_format = FMT_H263 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_RV20 :
s - > out_format = FMT_H263 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
s - > modified_quant = 1 ;
s - > h263_aic = 1 ;
s - > h263_plus = 1 ;
s - > loop_filter = 1 ;
s - > unrestricted_mv = s - > obmc | | s - > loop_filter | | s - > umvplus ;
break ;
case CODEC_ID_MPEG4 :
s - > out_format = FMT_H263 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > low_delay = s - > max_b_frames ? 0 : 1 ;
avctx - > delay = s - > low_delay ? 0 : ( s - > max_b_frames + 1 ) ;
break ;
case CODEC_ID_MSMPEG4V1 :
s - > out_format = FMT_H263 ;
s - > h263_msmpeg4 = 1 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > msmpeg4_version = 1 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_MSMPEG4V2 :
s - > out_format = FMT_H263 ;
s - > h263_msmpeg4 = 1 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > msmpeg4_version = 2 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_MSMPEG4V3 :
s - > out_format = FMT_H263 ;
s - > h263_msmpeg4 = 1 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > msmpeg4_version = 3 ;
s - > flipflop_rounding = 1 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_WMV1 :
s - > out_format = FMT_H263 ;
s - > h263_msmpeg4 = 1 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > msmpeg4_version = 4 ;
s - > flipflop_rounding = 1 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
case CODEC_ID_WMV2 :
s - > out_format = FMT_H263 ;
s - > h263_msmpeg4 = 1 ;
s - > h263_pred = 1 ;
s - > unrestricted_mv = 1 ;
s - > msmpeg4_version = 5 ;
s - > flipflop_rounding = 1 ;
avctx - > delay = 0 ;
s - > low_delay = 1 ;
break ;
default :
return - 1 ;
}
avctx - > has_b_frames = ! s - > low_delay ;
s - > encoding = 1 ;
/* init */
if ( MPV_common_init ( s ) < 0 )
return - 1 ;
2007-07-05 12:48:29 +03:00
if ( ! s - > dct_quantize )
s - > dct_quantize = dct_quantize_c ;
if ( ! s - > denoise_dct )
s - > denoise_dct = denoise_dct_c ;
s - > fast_dct_quantize = s - > dct_quantize ;
2008-06-09 03:43:07 +03:00
if ( avctx - > trellis )
2007-07-05 12:48:29 +03:00
s - > dct_quantize = dct_quantize_trellis_c ;
2007-07-10 23:23:08 +03:00
if ( ( ENABLE_H263P_ENCODER | | ENABLE_RV20_ENCODER ) & & s - > modified_quant )
2007-07-03 12:55:56 +03:00
s - > chroma_qscale_table = ff_h263_chroma_qscale_table ;
s - > progressive_frame =
s - > progressive_sequence = ! ( avctx - > flags & ( CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME | CODEC_FLAG_ALT_SCAN ) ) ;
s - > quant_precision = 5 ;
ff_set_cmp ( & s - > dsp , s - > dsp . ildct_cmp , s - > avctx - > ildct_cmp ) ;
ff_set_cmp ( & s - > dsp , s - > dsp . frame_skip_cmp , s - > avctx - > frame_skip_cmp ) ;
if ( ENABLE_H261_ENCODER & & s - > out_format = = FMT_H261 )
ff_h261_encode_init ( s ) ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_ANY_H263_ENCODER & & s - > out_format = = FMT_H263 )
2007-07-03 12:55:56 +03:00
h263_encode_init ( s ) ;
if ( ENABLE_MSMPEG4_ENCODER & & s - > msmpeg4_version )
ff_msmpeg4_encode_init ( s ) ;
2007-07-05 12:08:28 +03:00
if ( ( ENABLE_MPEG1VIDEO_ENCODER | | ENABLE_MPEG2VIDEO_ENCODER )
& & s - > out_format = = FMT_MPEG1 )
2007-07-03 12:55:56 +03:00
ff_mpeg1_encode_init ( s ) ;
/* init q matrix */
for ( i = 0 ; i < 64 ; i + + ) {
int j = s - > dsp . idct_permutation [ i ] ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & s - > codec_id = = CODEC_ID_MPEG4 & & s - > mpeg_quant ) {
2007-07-03 12:55:56 +03:00
s - > intra_matrix [ j ] = ff_mpeg4_default_intra_matrix [ i ] ;
s - > inter_matrix [ j ] = ff_mpeg4_default_non_intra_matrix [ i ] ;
} else if ( s - > out_format = = FMT_H263 | | s - > out_format = = FMT_H261 ) {
s - > intra_matrix [ j ] =
s - > inter_matrix [ j ] = ff_mpeg1_default_non_intra_matrix [ i ] ;
} else
{ /* mpeg1/2 */
s - > intra_matrix [ j ] = ff_mpeg1_default_intra_matrix [ i ] ;
s - > inter_matrix [ j ] = ff_mpeg1_default_non_intra_matrix [ i ] ;
}
if ( s - > avctx - > intra_matrix )
s - > intra_matrix [ j ] = s - > avctx - > intra_matrix [ i ] ;
if ( s - > avctx - > inter_matrix )
s - > inter_matrix [ j ] = s - > avctx - > inter_matrix [ i ] ;
}
/* precompute matrix */
/* for mjpeg, we do include qscale in the matrix */
if ( s - > out_format ! = FMT_MJPEG ) {
2007-10-08 12:14:46 +03:00
ff_convert_matrix ( & s - > dsp , s - > q_intra_matrix , s - > q_intra_matrix16 ,
2007-07-03 12:55:56 +03:00
s - > intra_matrix , s - > intra_quant_bias , avctx - > qmin , 31 , 1 ) ;
2007-10-08 12:14:46 +03:00
ff_convert_matrix ( & s - > dsp , s - > q_inter_matrix , s - > q_inter_matrix16 ,
2007-07-03 12:55:56 +03:00
s - > inter_matrix , s - > inter_quant_bias , avctx - > qmin , 31 , 0 ) ;
}
if ( ff_rate_control_init ( s ) < 0 )
return - 1 ;
return 0 ;
}
2008-03-21 05:11:20 +02:00
av_cold int MPV_encode_end ( AVCodecContext * avctx )
2007-07-03 12:55:56 +03:00
{
MpegEncContext * s = avctx - > priv_data ;
ff_rate_control_uninit ( s ) ;
MPV_common_end ( s ) ;
if ( ( ENABLE_MJPEG_ENCODER | | ENABLE_LJPEG_ENCODER ) & & s - > out_format = = FMT_MJPEG )
ff_mjpeg_encode_close ( s ) ;
av_freep ( & avctx - > extradata ) ;
return 0 ;
}
static int get_sae ( uint8_t * src , int ref , int stride ) {
int x , y ;
int acc = 0 ;
for ( y = 0 ; y < 16 ; y + + ) {
for ( x = 0 ; x < 16 ; x + + ) {
acc + = FFABS ( src [ x + y * stride ] - ref ) ;
}
}
return acc ;
}
static int get_intra_count ( MpegEncContext * s , uint8_t * src , uint8_t * ref , int stride ) {
int x , y , w , h ;
int acc = 0 ;
w = s - > width & ~ 15 ;
h = s - > height & ~ 15 ;
for ( y = 0 ; y < h ; y + = 16 ) {
for ( x = 0 ; x < w ; x + = 16 ) {
int offset = x + y * stride ;
int sad = s - > dsp . sad [ 0 ] ( NULL , src + offset , ref + offset , stride , 16 ) ;
int mean = ( s - > dsp . pix_sum ( src + offset , stride ) + 128 ) > > 8 ;
int sae = get_sae ( src + offset , mean , stride ) ;
acc + = sae + 500 < sad ;
}
}
return acc ;
}
static int load_input_picture ( MpegEncContext * s , AVFrame * pic_arg ) {
AVFrame * pic = NULL ;
int64_t pts ;
int i ;
const int encoding_delay = s - > max_b_frames ;
int direct = 1 ;
if ( pic_arg ) {
pts = pic_arg - > pts ;
pic_arg - > display_picture_number = s - > input_picture_number + + ;
if ( pts ! = AV_NOPTS_VALUE ) {
if ( s - > user_specified_pts ! = AV_NOPTS_VALUE ) {
int64_t time = pts ;
int64_t last = s - > user_specified_pts ;
if ( time < = last ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Error, Invalid timestamp=% " PRId64 " , last=% " PRId64 " \n " , pts , s - > user_specified_pts ) ;
return - 1 ;
}
}
s - > user_specified_pts = pts ;
} else {
if ( s - > user_specified_pts ! = AV_NOPTS_VALUE ) {
s - > user_specified_pts =
pts = s - > user_specified_pts + 1 ;
av_log ( s - > avctx , AV_LOG_INFO , " Warning: AVFrame.pts=? trying to guess (% " PRId64 " ) \n " , pts ) ;
} else {
pts = pic_arg - > display_picture_number ;
}
}
}
if ( pic_arg ) {
if ( encoding_delay & & ! ( s - > flags & CODEC_FLAG_INPUT_PRESERVED ) ) direct = 0 ;
if ( pic_arg - > linesize [ 0 ] ! = s - > linesize ) direct = 0 ;
if ( pic_arg - > linesize [ 1 ] ! = s - > uvlinesize ) direct = 0 ;
if ( pic_arg - > linesize [ 2 ] ! = s - > uvlinesize ) direct = 0 ;
// av_log(AV_LOG_DEBUG, "%d %d %d %d\n",pic_arg->linesize[0], pic_arg->linesize[1], s->linesize, s->uvlinesize);
if ( direct ) {
i = ff_find_unused_picture ( s , 1 ) ;
pic = ( AVFrame * ) & s - > picture [ i ] ;
pic - > reference = 3 ;
for ( i = 0 ; i < 4 ; i + + ) {
pic - > data [ i ] = pic_arg - > data [ i ] ;
pic - > linesize [ i ] = pic_arg - > linesize [ i ] ;
}
alloc_picture ( s , ( Picture * ) pic , 1 ) ;
} else {
i = ff_find_unused_picture ( s , 0 ) ;
pic = ( AVFrame * ) & s - > picture [ i ] ;
pic - > reference = 3 ;
alloc_picture ( s , ( Picture * ) pic , 0 ) ;
if ( pic - > data [ 0 ] + INPLACE_OFFSET = = pic_arg - > data [ 0 ]
& & pic - > data [ 1 ] + INPLACE_OFFSET = = pic_arg - > data [ 1 ]
& & pic - > data [ 2 ] + INPLACE_OFFSET = = pic_arg - > data [ 2 ] ) {
// empty
} else {
int h_chroma_shift , v_chroma_shift ;
avcodec_get_chroma_sub_sample ( s - > avctx - > pix_fmt , & h_chroma_shift , & v_chroma_shift ) ;
for ( i = 0 ; i < 3 ; i + + ) {
int src_stride = pic_arg - > linesize [ i ] ;
int dst_stride = i ? s - > uvlinesize : s - > linesize ;
int h_shift = i ? h_chroma_shift : 0 ;
int v_shift = i ? v_chroma_shift : 0 ;
int w = s - > width > > h_shift ;
int h = s - > height > > v_shift ;
uint8_t * src = pic_arg - > data [ i ] ;
uint8_t * dst = pic - > data [ i ] ;
if ( ! s - > avctx - > rc_buffer_size )
dst + = INPLACE_OFFSET ;
if ( src_stride = = dst_stride )
memcpy ( dst , src , src_stride * h ) ;
else {
while ( h - - ) {
memcpy ( dst , src , w ) ;
dst + = dst_stride ;
src + = src_stride ;
}
}
}
}
}
copy_picture_attributes ( s , pic , pic_arg ) ;
pic - > pts = pts ; //we set this here to avoid modifiying pic_arg
}
/* shift buffer entries */
for ( i = 1 ; i < MAX_PICTURE_COUNT /*s->encoding_delay+1*/ ; i + + )
s - > input_picture [ i - 1 ] = s - > input_picture [ i ] ;
s - > input_picture [ encoding_delay ] = ( Picture * ) pic ;
return 0 ;
}
static int skip_check ( MpegEncContext * s , Picture * p , Picture * ref ) {
int x , y , plane ;
int score = 0 ;
int64_t score64 = 0 ;
for ( plane = 0 ; plane < 3 ; plane + + ) {
const int stride = p - > linesize [ plane ] ;
const int bw = plane ? 1 : 2 ;
for ( y = 0 ; y < s - > mb_height * bw ; y + + ) {
for ( x = 0 ; x < s - > mb_width * bw ; x + + ) {
int off = p - > type = = FF_BUFFER_TYPE_SHARED ? 0 : 16 ;
int v = s - > dsp . frame_skip_cmp [ 1 ] ( s , p - > data [ plane ] + 8 * ( x + y * stride ) + off , ref - > data [ plane ] + 8 * ( x + y * stride ) , stride , 8 ) ;
switch ( s - > avctx - > frame_skip_exp ) {
case 0 : score = FFMAX ( score , v ) ; break ;
case 1 : score + = FFABS ( v ) ; break ;
case 2 : score + = v * v ; break ;
case 3 : score64 + = FFABS ( v * v * ( int64_t ) v ) ; break ;
case 4 : score64 + = v * v * ( int64_t ) ( v * v ) ; break ;
}
}
}
}
if ( score ) score64 = score ;
if ( score64 < s - > avctx - > frame_skip_threshold )
return 1 ;
if ( score64 < ( ( s - > avctx - > frame_skip_factor * ( int64_t ) s - > lambda ) > > 8 ) )
return 1 ;
return 0 ;
}
static int estimate_best_b_count ( MpegEncContext * s ) {
AVCodec * codec = avcodec_find_encoder ( s - > avctx - > codec_id ) ;
AVCodecContext * c = avcodec_alloc_context ( ) ;
AVFrame input [ FF_MAX_B_FRAMES + 2 ] ;
const int scale = s - > avctx - > brd_scale ;
int i , j , out_size , p_lambda , b_lambda , lambda2 ;
int outbuf_size = s - > width * s - > height ; //FIXME
uint8_t * outbuf = av_malloc ( outbuf_size ) ;
int64_t best_rd = INT64_MAX ;
int best_b_count = - 1 ;
assert ( scale > = 0 & & scale < = 3 ) ;
// emms_c();
2008-03-10 01:31:02 +02:00
p_lambda = s - > last_lambda_for [ FF_P_TYPE ] ; //s->next_picture_ptr->quality;
b_lambda = s - > last_lambda_for [ FF_B_TYPE ] ; //p_lambda *FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset;
2007-07-03 12:55:56 +03:00
if ( ! b_lambda ) b_lambda = p_lambda ; //FIXME we should do this somewhere else
lambda2 = ( b_lambda * b_lambda + ( 1 < < FF_LAMBDA_SHIFT ) / 2 ) > > FF_LAMBDA_SHIFT ;
c - > width = s - > width > > scale ;
c - > height = s - > height > > scale ;
c - > flags = CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR | CODEC_FLAG_INPUT_PRESERVED /*| CODEC_FLAG_EMU_EDGE*/ ;
c - > flags | = s - > avctx - > flags & CODEC_FLAG_QPEL ;
c - > mb_decision = s - > avctx - > mb_decision ;
c - > me_cmp = s - > avctx - > me_cmp ;
c - > mb_cmp = s - > avctx - > mb_cmp ;
c - > me_sub_cmp = s - > avctx - > me_sub_cmp ;
c - > pix_fmt = PIX_FMT_YUV420P ;
c - > time_base = s - > avctx - > time_base ;
c - > max_b_frames = s - > max_b_frames ;
if ( avcodec_open ( c , codec ) < 0 )
return - 1 ;
for ( i = 0 ; i < s - > max_b_frames + 2 ; i + + ) {
int ysize = c - > width * c - > height ;
int csize = ( c - > width / 2 ) * ( c - > height / 2 ) ;
Picture pre_input , * pre_input_ptr = i ? s - > input_picture [ i - 1 ] : s - > next_picture_ptr ;
avcodec_get_frame_defaults ( & input [ i ] ) ;
input [ i ] . data [ 0 ] = av_malloc ( ysize + 2 * csize ) ;
input [ i ] . data [ 1 ] = input [ i ] . data [ 0 ] + ysize ;
input [ i ] . data [ 2 ] = input [ i ] . data [ 1 ] + csize ;
input [ i ] . linesize [ 0 ] = c - > width ;
input [ i ] . linesize [ 1 ] =
input [ i ] . linesize [ 2 ] = c - > width / 2 ;
if ( pre_input_ptr & & ( ! i | | s - > input_picture [ i - 1 ] ) ) {
pre_input = * pre_input_ptr ;
if ( pre_input . type ! = FF_BUFFER_TYPE_SHARED & & i ) {
pre_input . data [ 0 ] + = INPLACE_OFFSET ;
pre_input . data [ 1 ] + = INPLACE_OFFSET ;
pre_input . data [ 2 ] + = INPLACE_OFFSET ;
}
s - > dsp . shrink [ scale ] ( input [ i ] . data [ 0 ] , input [ i ] . linesize [ 0 ] , pre_input . data [ 0 ] , pre_input . linesize [ 0 ] , c - > width , c - > height ) ;
s - > dsp . shrink [ scale ] ( input [ i ] . data [ 1 ] , input [ i ] . linesize [ 1 ] , pre_input . data [ 1 ] , pre_input . linesize [ 1 ] , c - > width > > 1 , c - > height > > 1 ) ;
s - > dsp . shrink [ scale ] ( input [ i ] . data [ 2 ] , input [ i ] . linesize [ 2 ] , pre_input . data [ 2 ] , pre_input . linesize [ 2 ] , c - > width > > 1 , c - > height > > 1 ) ;
}
}
for ( j = 0 ; j < s - > max_b_frames + 1 ; j + + ) {
int64_t rd = 0 ;
if ( ! s - > input_picture [ j ] )
break ;
c - > error [ 0 ] = c - > error [ 1 ] = c - > error [ 2 ] = 0 ;
2008-03-10 01:31:02 +02:00
input [ 0 ] . pict_type = FF_I_TYPE ;
2007-07-03 12:55:56 +03:00
input [ 0 ] . quality = 1 * FF_QP2LAMBDA ;
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , & input [ 0 ] ) ;
// rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT;
for ( i = 0 ; i < s - > max_b_frames + 1 ; i + + ) {
int is_p = i % ( j + 1 ) = = j | | i = = s - > max_b_frames ;
2008-03-10 01:31:02 +02:00
input [ i + 1 ] . pict_type = is_p ? FF_P_TYPE : FF_B_TYPE ;
2007-07-03 12:55:56 +03:00
input [ i + 1 ] . quality = is_p ? p_lambda : b_lambda ;
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , & input [ i + 1 ] ) ;
rd + = ( out_size * lambda2 ) > > ( FF_LAMBDA_SHIFT - 3 ) ;
}
/* get the delayed frames */
while ( out_size ) {
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , NULL ) ;
rd + = ( out_size * lambda2 ) > > ( FF_LAMBDA_SHIFT - 3 ) ;
}
rd + = c - > error [ 0 ] + c - > error [ 1 ] + c - > error [ 2 ] ;
if ( rd < best_rd ) {
best_rd = rd ;
best_b_count = j ;
}
}
av_freep ( & outbuf ) ;
avcodec_close ( c ) ;
av_freep ( & c ) ;
for ( i = 0 ; i < s - > max_b_frames + 2 ; i + + ) {
av_freep ( & input [ i ] . data [ 0 ] ) ;
}
return best_b_count ;
}
static void select_input_picture ( MpegEncContext * s ) {
int i ;
for ( i = 1 ; i < MAX_PICTURE_COUNT ; i + + )
s - > reordered_input_picture [ i - 1 ] = s - > reordered_input_picture [ i ] ;
s - > reordered_input_picture [ MAX_PICTURE_COUNT - 1 ] = NULL ;
/* set next picture type & ordering */
if ( s - > reordered_input_picture [ 0 ] = = NULL & & s - > input_picture [ 0 ] ) {
if ( /*s->picture_in_gop_number >= s->gop_size ||*/ s - > next_picture_ptr = = NULL | | s - > intra_only ) {
s - > reordered_input_picture [ 0 ] = s - > input_picture [ 0 ] ;
2008-03-10 01:31:02 +02:00
s - > reordered_input_picture [ 0 ] - > pict_type = FF_I_TYPE ;
2007-07-03 12:55:56 +03:00
s - > reordered_input_picture [ 0 ] - > coded_picture_number = s - > coded_picture_number + + ;
} else {
int b_frames ;
if ( s - > avctx - > frame_skip_threshold | | s - > avctx - > frame_skip_factor ) {
if ( s - > picture_in_gop_number < s - > gop_size & & skip_check ( s , s - > input_picture [ 0 ] , s - > next_picture_ptr ) ) {
//FIXME check that te gop check above is +-1 correct
//av_log(NULL, AV_LOG_DEBUG, "skip %p %"PRId64"\n", s->input_picture[0]->data[0], s->input_picture[0]->pts);
if ( s - > input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_SHARED ) {
for ( i = 0 ; i < 4 ; i + + )
s - > input_picture [ 0 ] - > data [ i ] = NULL ;
s - > input_picture [ 0 ] - > type = 0 ;
} else {
assert ( s - > input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_USER
| | s - > input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_INTERNAL ) ;
s - > avctx - > release_buffer ( s - > avctx , ( AVFrame * ) s - > input_picture [ 0 ] ) ;
}
emms_c ( ) ;
ff_vbv_update ( s , 0 ) ;
goto no_output_pic ;
}
}
if ( s - > flags & CODEC_FLAG_PASS2 ) {
for ( i = 0 ; i < s - > max_b_frames + 1 ; i + + ) {
int pict_num = s - > input_picture [ 0 ] - > display_picture_number + i ;
if ( pict_num > = s - > rc_context . num_entries )
break ;
if ( ! s - > input_picture [ i ] ) {
2008-03-10 01:31:02 +02:00
s - > rc_context . entry [ pict_num - 1 ] . new_pict_type = FF_P_TYPE ;
2007-07-03 12:55:56 +03:00
break ;
}
s - > input_picture [ i ] - > pict_type =
s - > rc_context . entry [ pict_num ] . new_pict_type ;
}
}
if ( s - > avctx - > b_frame_strategy = = 0 ) {
b_frames = s - > max_b_frames ;
while ( b_frames & & ! s - > input_picture [ b_frames ] ) b_frames - - ;
} else if ( s - > avctx - > b_frame_strategy = = 1 ) {
for ( i = 1 ; i < s - > max_b_frames + 1 ; i + + ) {
if ( s - > input_picture [ i ] & & s - > input_picture [ i ] - > b_frame_score = = 0 ) {
s - > input_picture [ i ] - > b_frame_score =
get_intra_count ( s , s - > input_picture [ i ] - > data [ 0 ] ,
s - > input_picture [ i - 1 ] - > data [ 0 ] , s - > linesize ) + 1 ;
}
}
for ( i = 0 ; i < s - > max_b_frames + 1 ; i + + ) {
if ( s - > input_picture [ i ] = = NULL | | s - > input_picture [ i ] - > b_frame_score - 1 > s - > mb_num / s - > avctx - > b_sensitivity ) break ;
}
b_frames = FFMAX ( 0 , i - 1 ) ;
/* reset scores */
for ( i = 0 ; i < b_frames + 1 ; i + + ) {
s - > input_picture [ i ] - > b_frame_score = 0 ;
}
} else if ( s - > avctx - > b_frame_strategy = = 2 ) {
b_frames = estimate_best_b_count ( s ) ;
} else {
av_log ( s - > avctx , AV_LOG_ERROR , " illegal b frame strategy \n " ) ;
b_frames = 0 ;
}
emms_c ( ) ;
//static int b_count=0;
//b_count+= b_frames;
//av_log(s->avctx, AV_LOG_DEBUG, "b_frames: %d\n", b_count);
for ( i = b_frames - 1 ; i > = 0 ; i - - ) {
int type = s - > input_picture [ i ] - > pict_type ;
2008-03-10 01:31:02 +02:00
if ( type & & type ! = FF_B_TYPE )
2007-07-03 12:55:56 +03:00
b_frames = i ;
}
2008-03-10 01:31:02 +02:00
if ( s - > input_picture [ b_frames ] - > pict_type = = FF_B_TYPE & & b_frames = = s - > max_b_frames ) {
2007-07-03 12:55:56 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " warning, too many b frames in a row \n " ) ;
}
if ( s - > picture_in_gop_number + b_frames > = s - > gop_size ) {
if ( ( s - > flags2 & CODEC_FLAG2_STRICT_GOP ) & & s - > gop_size > s - > picture_in_gop_number ) {
b_frames = s - > gop_size - s - > picture_in_gop_number - 1 ;
} else {
if ( s - > flags & CODEC_FLAG_CLOSED_GOP )
b_frames = 0 ;
2008-03-10 01:31:02 +02:00
s - > input_picture [ b_frames ] - > pict_type = FF_I_TYPE ;
2007-07-03 12:55:56 +03:00
}
}
if ( ( s - > flags & CODEC_FLAG_CLOSED_GOP )
& & b_frames
2008-03-10 01:31:02 +02:00
& & s - > input_picture [ b_frames ] - > pict_type = = FF_I_TYPE )
2007-07-03 12:55:56 +03:00
b_frames - - ;
s - > reordered_input_picture [ 0 ] = s - > input_picture [ b_frames ] ;
2008-03-10 01:31:02 +02:00
if ( s - > reordered_input_picture [ 0 ] - > pict_type ! = FF_I_TYPE )
s - > reordered_input_picture [ 0 ] - > pict_type = FF_P_TYPE ;
2007-07-03 12:55:56 +03:00
s - > reordered_input_picture [ 0 ] - > coded_picture_number = s - > coded_picture_number + + ;
for ( i = 0 ; i < b_frames ; i + + ) {
s - > reordered_input_picture [ i + 1 ] = s - > input_picture [ i ] ;
2008-03-10 01:31:02 +02:00
s - > reordered_input_picture [ i + 1 ] - > pict_type = FF_B_TYPE ;
2007-07-03 12:55:56 +03:00
s - > reordered_input_picture [ i + 1 ] - > coded_picture_number = s - > coded_picture_number + + ;
}
}
}
no_output_pic :
if ( s - > reordered_input_picture [ 0 ] ) {
2008-03-10 01:31:02 +02:00
s - > reordered_input_picture [ 0 ] - > reference = s - > reordered_input_picture [ 0 ] - > pict_type ! = FF_B_TYPE ? 3 : 0 ;
2007-07-03 12:55:56 +03:00
copy_picture ( & s - > new_picture , s - > reordered_input_picture [ 0 ] ) ;
if ( s - > reordered_input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_SHARED | | s - > avctx - > rc_buffer_size ) {
// input is a shared pix, so we can't modifiy it -> alloc a new one & ensure that the shared one is reuseable
int i = ff_find_unused_picture ( s , 0 ) ;
Picture * pic = & s - > picture [ i ] ;
pic - > reference = s - > reordered_input_picture [ 0 ] - > reference ;
alloc_picture ( s , pic , 0 ) ;
/* mark us unused / free shared pic */
if ( s - > reordered_input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_INTERNAL )
s - > avctx - > release_buffer ( s - > avctx , ( AVFrame * ) s - > reordered_input_picture [ 0 ] ) ;
for ( i = 0 ; i < 4 ; i + + )
s - > reordered_input_picture [ 0 ] - > data [ i ] = NULL ;
s - > reordered_input_picture [ 0 ] - > type = 0 ;
copy_picture_attributes ( s , ( AVFrame * ) pic , ( AVFrame * ) s - > reordered_input_picture [ 0 ] ) ;
s - > current_picture_ptr = pic ;
} else {
// input is not a shared pix -> reuse buffer for current_pix
assert ( s - > reordered_input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_USER
| | s - > reordered_input_picture [ 0 ] - > type = = FF_BUFFER_TYPE_INTERNAL ) ;
s - > current_picture_ptr = s - > reordered_input_picture [ 0 ] ;
for ( i = 0 ; i < 4 ; i + + ) {
s - > new_picture . data [ i ] + = INPLACE_OFFSET ;
}
}
copy_picture ( & s - > current_picture , s - > current_picture_ptr ) ;
s - > picture_number = s - > new_picture . display_picture_number ;
//printf("dpn:%d\n", s->picture_number);
} else {
memset ( & s - > new_picture , 0 , sizeof ( Picture ) ) ;
}
}
int MPV_encode_picture ( AVCodecContext * avctx ,
unsigned char * buf , int buf_size , void * data )
{
MpegEncContext * s = avctx - > priv_data ;
AVFrame * pic_arg = data ;
int i , stuffing_count ;
for ( i = 0 ; i < avctx - > thread_count ; i + + ) {
int start_y = s - > thread_context [ i ] - > start_mb_y ;
int end_y = s - > thread_context [ i ] - > end_mb_y ;
int h = s - > mb_height ;
uint8_t * start = buf + ( size_t ) ( ( ( int64_t ) buf_size ) * start_y / h ) ;
uint8_t * end = buf + ( size_t ) ( ( ( int64_t ) buf_size ) * end_y / h ) ;
init_put_bits ( & s - > thread_context [ i ] - > pb , start , end - start ) ;
}
s - > picture_in_gop_number + + ;
if ( load_input_picture ( s , pic_arg ) < 0 )
return - 1 ;
select_input_picture ( s ) ;
/* output? */
if ( s - > new_picture . data [ 0 ] ) {
s - > pict_type = s - > new_picture . pict_type ;
//emms_c();
//printf("qs:%f %f %d\n", s->new_picture.quality, s->current_picture.quality, s->qscale);
MPV_frame_start ( s , avctx ) ;
vbv_retry :
if ( encode_picture ( s , s - > picture_number ) < 0 )
return - 1 ;
avctx - > real_pict_num = s - > picture_number ;
avctx - > header_bits = s - > header_bits ;
avctx - > mv_bits = s - > mv_bits ;
avctx - > misc_bits = s - > misc_bits ;
avctx - > i_tex_bits = s - > i_tex_bits ;
avctx - > p_tex_bits = s - > p_tex_bits ;
avctx - > i_count = s - > i_count ;
avctx - > p_count = s - > mb_num - s - > i_count - s - > skip_count ; //FIXME f/b_count in avctx
avctx - > skip_count = s - > skip_count ;
MPV_frame_end ( s ) ;
if ( ENABLE_MJPEG_ENCODER & & s - > out_format = = FMT_MJPEG )
ff_mjpeg_encode_picture_trailer ( s ) ;
if ( avctx - > rc_buffer_size ) {
RateControlContext * rcc = & s - > rc_context ;
int max_size = rcc - > buffer_index / 3 ;
if ( put_bits_count ( & s - > pb ) > max_size & & s - > lambda < s - > avctx - > lmax ) {
s - > next_lambda = FFMAX ( s - > lambda + 1 , s - > lambda * ( s - > qscale + 1 ) / s - > qscale ) ;
if ( s - > adaptive_quant ) {
int i ;
for ( i = 0 ; i < s - > mb_height * s - > mb_stride ; i + + )
s - > lambda_table [ i ] = FFMAX ( s - > lambda_table [ i ] + 1 , s - > lambda_table [ i ] * ( s - > qscale + 1 ) / s - > qscale ) ;
}
s - > mb_skipped = 0 ; //done in MPV_frame_start()
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_P_TYPE ) { //done in encode_picture() so we must undo it
2007-07-03 12:55:56 +03:00
if ( s - > flipflop_rounding | | s - > codec_id = = CODEC_ID_H263P | | s - > codec_id = = CODEC_ID_MPEG4 )
s - > no_rounding ^ = 1 ;
}
2008-03-10 01:31:02 +02:00
if ( s - > pict_type ! = FF_B_TYPE ) {
2007-07-03 12:55:56 +03:00
s - > time_base = s - > last_time_base ;
s - > last_non_b_time = s - > time - s - > pp_time ;
}
// av_log(NULL, AV_LOG_ERROR, "R:%d ", s->next_lambda);
for ( i = 0 ; i < avctx - > thread_count ; i + + ) {
PutBitContext * pb = & s - > thread_context [ i ] - > pb ;
init_put_bits ( pb , pb - > buf , pb - > buf_end - pb - > buf ) ;
}
goto vbv_retry ;
}
assert ( s - > avctx - > rc_max_rate ) ;
}
if ( s - > flags & CODEC_FLAG_PASS1 )
ff_write_pass1_stats ( s ) ;
for ( i = 0 ; i < 4 ; i + + ) {
s - > current_picture_ptr - > error [ i ] = s - > current_picture . error [ i ] ;
avctx - > error [ i ] + = s - > current_picture_ptr - > error [ i ] ;
}
if ( s - > flags & CODEC_FLAG_PASS1 )
assert ( avctx - > header_bits + avctx - > mv_bits + avctx - > misc_bits + avctx - > i_tex_bits + avctx - > p_tex_bits = = put_bits_count ( & s - > pb ) ) ;
flush_put_bits ( & s - > pb ) ;
s - > frame_bits = put_bits_count ( & s - > pb ) ;
stuffing_count = ff_vbv_update ( s , s - > frame_bits ) ;
if ( stuffing_count ) {
if ( s - > pb . buf_end - s - > pb . buf - ( put_bits_count ( & s - > pb ) > > 3 ) < stuffing_count + 50 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " stuffing too large \n " ) ;
return - 1 ;
}
switch ( s - > codec_id ) {
case CODEC_ID_MPEG1VIDEO :
case CODEC_ID_MPEG2VIDEO :
while ( stuffing_count - - ) {
put_bits ( & s - > pb , 8 , 0 ) ;
}
break ;
case CODEC_ID_MPEG4 :
put_bits ( & s - > pb , 16 , 0 ) ;
put_bits ( & s - > pb , 16 , 0x1C3 ) ;
stuffing_count - = 4 ;
while ( stuffing_count - - ) {
put_bits ( & s - > pb , 8 , 0xFF ) ;
}
break ;
default :
av_log ( s - > avctx , AV_LOG_ERROR , " vbv buffer overflow \n " ) ;
}
flush_put_bits ( & s - > pb ) ;
s - > frame_bits = put_bits_count ( & s - > pb ) ;
}
/* update mpeg1/2 vbv_delay for CBR */
if ( s - > avctx - > rc_max_rate & & s - > avctx - > rc_min_rate = = s - > avctx - > rc_max_rate & & s - > out_format = = FMT_MPEG1
& & 90000LL * ( avctx - > rc_buffer_size - 1 ) < = s - > avctx - > rc_max_rate * 0xFFFFLL ) {
int vbv_delay ;
assert ( s - > repeat_first_field = = 0 ) ;
vbv_delay = lrintf ( 90000 * s - > rc_context . buffer_index / s - > avctx - > rc_max_rate ) ;
assert ( vbv_delay < 0xFFFF ) ;
s - > vbv_delay_ptr [ 0 ] & = 0xF8 ;
s - > vbv_delay_ptr [ 0 ] | = vbv_delay > > 13 ;
s - > vbv_delay_ptr [ 1 ] = vbv_delay > > 5 ;
s - > vbv_delay_ptr [ 2 ] & = 0x07 ;
s - > vbv_delay_ptr [ 2 ] | = vbv_delay < < 3 ;
}
s - > total_bits + = s - > frame_bits ;
avctx - > frame_bits = s - > frame_bits ;
} else {
assert ( ( pbBufPtr ( & s - > pb ) = = s - > pb . buf ) ) ;
s - > frame_bits = 0 ;
}
assert ( ( s - > frame_bits & 7 ) = = 0 ) ;
return s - > frame_bits / 8 ;
}
static inline void dct_single_coeff_elimination ( MpegEncContext * s , int n , int threshold )
{
static const char tab [ 64 ] =
{ 3 , 2 , 2 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
int score = 0 ;
int run = 0 ;
int i ;
DCTELEM * block = s - > block [ n ] ;
const int last_index = s - > block_last_index [ n ] ;
int skip_dc ;
if ( threshold < 0 ) {
skip_dc = 0 ;
threshold = - threshold ;
} else
skip_dc = 1 ;
2008-03-15 18:15:47 +02:00
/* Are all we could set to zero already zero? */
2007-07-03 12:55:56 +03:00
if ( last_index < = skip_dc - 1 ) return ;
for ( i = 0 ; i < = last_index ; i + + ) {
const int j = s - > intra_scantable . permutated [ i ] ;
const int level = FFABS ( block [ j ] ) ;
if ( level = = 1 ) {
if ( skip_dc & & i = = 0 ) continue ;
score + = tab [ run ] ;
run = 0 ;
} else if ( level > 1 ) {
return ;
} else {
run + + ;
}
}
if ( score > = threshold ) return ;
for ( i = skip_dc ; i < = last_index ; i + + ) {
const int j = s - > intra_scantable . permutated [ i ] ;
block [ j ] = 0 ;
}
if ( block [ 0 ] ) s - > block_last_index [ n ] = 0 ;
else s - > block_last_index [ n ] = - 1 ;
}
static inline void clip_coeffs ( MpegEncContext * s , DCTELEM * block , int last_index )
{
int i ;
const int maxlevel = s - > max_qcoeff ;
const int minlevel = s - > min_qcoeff ;
int overflow = 0 ;
if ( s - > mb_intra ) {
i = 1 ; //skip clipping of intra dc
} else
i = 0 ;
for ( ; i < = last_index ; i + + ) {
const int j = s - > intra_scantable . permutated [ i ] ;
int level = block [ j ] ;
if ( level > maxlevel ) {
level = maxlevel ;
overflow + + ;
} else if ( level < minlevel ) {
level = minlevel ;
overflow + + ;
}
block [ j ] = level ;
}
if ( overflow & & s - > avctx - > mb_decision = = FF_MB_DECISION_SIMPLE )
av_log ( s - > avctx , AV_LOG_INFO , " warning, clipping %d dct coefficients to %d..%d \n " , overflow , minlevel , maxlevel ) ;
}
2007-11-10 18:39:54 +02:00
static void get_visual_weight ( int16_t * weight , uint8_t * ptr , int stride ) {
2007-07-03 12:55:56 +03:00
int x , y ;
//FIXME optimize
for ( y = 0 ; y < 8 ; y + + ) {
for ( x = 0 ; x < 8 ; x + + ) {
int x2 , y2 ;
int sum = 0 ;
int sqr = 0 ;
int count = 0 ;
for ( y2 = FFMAX ( y - 1 , 0 ) ; y2 < FFMIN ( 8 , y + 2 ) ; y2 + + ) {
for ( x2 = FFMAX ( x - 1 , 0 ) ; x2 < FFMIN ( 8 , x + 2 ) ; x2 + + ) {
int v = ptr [ x2 + y2 * stride ] ;
sum + = v ;
sqr + = v * v ;
count + + ;
}
}
weight [ x + 8 * y ] = ( 36 * ff_sqrt ( count * sqr - sum * sum ) ) / count ;
}
}
}
static av_always_inline void encode_mb_internal ( MpegEncContext * s , int motion_x , int motion_y , int mb_block_height , int mb_block_count )
{
int16_t weight [ 8 ] [ 64 ] ;
DCTELEM orig [ 8 ] [ 64 ] ;
const int mb_x = s - > mb_x ;
const int mb_y = s - > mb_y ;
int i ;
int skip_dct [ 8 ] ;
int dct_offset = s - > linesize * 8 ; //default for progressive frames
uint8_t * ptr_y , * ptr_cb , * ptr_cr ;
int wrap_y , wrap_c ;
for ( i = 0 ; i < mb_block_count ; i + + ) skip_dct [ i ] = s - > skipdct ;
if ( s - > adaptive_quant ) {
const int last_qp = s - > qscale ;
const int mb_xy = mb_x + mb_y * s - > mb_stride ;
s - > lambda = s - > lambda_table [ mb_xy ] ;
update_qscale ( s ) ;
if ( ! ( s - > flags & CODEC_FLAG_QP_RD ) ) {
s - > qscale = s - > current_picture_ptr - > qscale_table [ mb_xy ] ;
s - > dquant = s - > qscale - last_qp ;
if ( s - > out_format = = FMT_H263 ) {
s - > dquant = av_clip ( s - > dquant , - 2 , 2 ) ;
if ( s - > codec_id = = CODEC_ID_MPEG4 ) {
if ( ! s - > mb_intra ) {
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_B_TYPE ) {
2007-07-03 12:55:56 +03:00
if ( s - > dquant & 1 | | s - > mv_dir & MV_DIRECT )
s - > dquant = 0 ;
}
if ( s - > mv_type = = MV_TYPE_8X8 )
s - > dquant = 0 ;
}
}
}
}
ff_set_qscale ( s , last_qp + s - > dquant ) ;
} else if ( s - > flags & CODEC_FLAG_QP_RD )
ff_set_qscale ( s , s - > qscale + s - > dquant ) ;
wrap_y = s - > linesize ;
wrap_c = s - > uvlinesize ;
ptr_y = s - > new_picture . data [ 0 ] + ( mb_y * 16 * wrap_y ) + mb_x * 16 ;
ptr_cb = s - > new_picture . data [ 1 ] + ( mb_y * mb_block_height * wrap_c ) + mb_x * 8 ;
ptr_cr = s - > new_picture . data [ 2 ] + ( mb_y * mb_block_height * wrap_c ) + mb_x * 8 ;
if ( mb_x * 16 + 16 > s - > width | | mb_y * 16 + 16 > s - > height ) {
uint8_t * ebuf = s - > edge_emu_buffer + 32 ;
ff_emulated_edge_mc ( ebuf , ptr_y , wrap_y , 16 , 16 , mb_x * 16 , mb_y * 16 , s - > width , s - > height ) ;
ptr_y = ebuf ;
ff_emulated_edge_mc ( ebuf + 18 * wrap_y , ptr_cb , wrap_c , 8 , mb_block_height , mb_x * 8 , mb_y * 8 , s - > width > > 1 , s - > height > > 1 ) ;
ptr_cb = ebuf + 18 * wrap_y ;
ff_emulated_edge_mc ( ebuf + 18 * wrap_y + 8 , ptr_cr , wrap_c , 8 , mb_block_height , mb_x * 8 , mb_y * 8 , s - > width > > 1 , s - > height > > 1 ) ;
ptr_cr = ebuf + 18 * wrap_y + 8 ;
}
if ( s - > mb_intra ) {
if ( s - > flags & CODEC_FLAG_INTERLACED_DCT ) {
int progressive_score , interlaced_score ;
s - > interlaced_dct = 0 ;
progressive_score = s - > dsp . ildct_cmp [ 4 ] ( s , ptr_y , NULL , wrap_y , 8 )
+ s - > dsp . ildct_cmp [ 4 ] ( s , ptr_y + wrap_y * 8 , NULL , wrap_y , 8 ) - 400 ;
if ( progressive_score > 0 ) {
interlaced_score = s - > dsp . ildct_cmp [ 4 ] ( s , ptr_y , NULL , wrap_y * 2 , 8 )
+ s - > dsp . ildct_cmp [ 4 ] ( s , ptr_y + wrap_y , NULL , wrap_y * 2 , 8 ) ;
if ( progressive_score > interlaced_score ) {
s - > interlaced_dct = 1 ;
dct_offset = wrap_y ;
wrap_y < < = 1 ;
if ( s - > chroma_format = = CHROMA_422 )
wrap_c < < = 1 ;
}
}
}
s - > dsp . get_pixels ( s - > block [ 0 ] , ptr_y , wrap_y ) ;
s - > dsp . get_pixels ( s - > block [ 1 ] , ptr_y + 8 , wrap_y ) ;
s - > dsp . get_pixels ( s - > block [ 2 ] , ptr_y + dct_offset , wrap_y ) ;
s - > dsp . get_pixels ( s - > block [ 3 ] , ptr_y + dct_offset + 8 , wrap_y ) ;
if ( s - > flags & CODEC_FLAG_GRAY ) {
skip_dct [ 4 ] = 1 ;
skip_dct [ 5 ] = 1 ;
} else {
s - > dsp . get_pixels ( s - > block [ 4 ] , ptr_cb , wrap_c ) ;
s - > dsp . get_pixels ( s - > block [ 5 ] , ptr_cr , wrap_c ) ;
if ( ! s - > chroma_y_shift ) { /* 422 */
s - > dsp . get_pixels ( s - > block [ 6 ] , ptr_cb + ( dct_offset > > 1 ) , wrap_c ) ;
s - > dsp . get_pixels ( s - > block [ 7 ] , ptr_cr + ( dct_offset > > 1 ) , wrap_c ) ;
}
}
} else {
op_pixels_func ( * op_pix ) [ 4 ] ;
qpel_mc_func ( * op_qpix ) [ 16 ] ;
uint8_t * dest_y , * dest_cb , * dest_cr ;
dest_y = s - > dest [ 0 ] ;
dest_cb = s - > dest [ 1 ] ;
dest_cr = s - > dest [ 2 ] ;
2008-03-10 01:31:02 +02:00
if ( ( ! s - > no_rounding ) | | s - > pict_type = = FF_B_TYPE ) {
2007-07-03 12:55:56 +03:00
op_pix = s - > dsp . put_pixels_tab ;
op_qpix = s - > dsp . put_qpel_pixels_tab ;
} else {
op_pix = s - > dsp . put_no_rnd_pixels_tab ;
op_qpix = s - > dsp . put_no_rnd_qpel_pixels_tab ;
}
if ( s - > mv_dir & MV_DIR_FORWARD ) {
MPV_motion ( s , dest_y , dest_cb , dest_cr , 0 , s - > last_picture . data , op_pix , op_qpix ) ;
op_pix = s - > dsp . avg_pixels_tab ;
op_qpix = s - > dsp . avg_qpel_pixels_tab ;
}
if ( s - > mv_dir & MV_DIR_BACKWARD ) {
MPV_motion ( s , dest_y , dest_cb , dest_cr , 1 , s - > next_picture . data , op_pix , op_qpix ) ;
}
if ( s - > flags & CODEC_FLAG_INTERLACED_DCT ) {
int progressive_score , interlaced_score ;
s - > interlaced_dct = 0 ;
progressive_score = s - > dsp . ildct_cmp [ 0 ] ( s , dest_y , ptr_y , wrap_y , 8 )
+ s - > dsp . ildct_cmp [ 0 ] ( s , dest_y + wrap_y * 8 , ptr_y + wrap_y * 8 , wrap_y , 8 ) - 400 ;
if ( s - > avctx - > ildct_cmp = = FF_CMP_VSSE ) progressive_score - = 400 ;
if ( progressive_score > 0 ) {
interlaced_score = s - > dsp . ildct_cmp [ 0 ] ( s , dest_y , ptr_y , wrap_y * 2 , 8 )
+ s - > dsp . ildct_cmp [ 0 ] ( s , dest_y + wrap_y , ptr_y + wrap_y , wrap_y * 2 , 8 ) ;
if ( progressive_score > interlaced_score ) {
s - > interlaced_dct = 1 ;
dct_offset = wrap_y ;
wrap_y < < = 1 ;
if ( s - > chroma_format = = CHROMA_422 )
wrap_c < < = 1 ;
}
}
}
s - > dsp . diff_pixels ( s - > block [ 0 ] , ptr_y , dest_y , wrap_y ) ;
s - > dsp . diff_pixels ( s - > block [ 1 ] , ptr_y + 8 , dest_y + 8 , wrap_y ) ;
s - > dsp . diff_pixels ( s - > block [ 2 ] , ptr_y + dct_offset , dest_y + dct_offset , wrap_y ) ;
s - > dsp . 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 ;
skip_dct [ 5 ] = 1 ;
} else {
s - > dsp . diff_pixels ( s - > block [ 4 ] , ptr_cb , dest_cb , wrap_c ) ;
s - > dsp . diff_pixels ( s - > block [ 5 ] , ptr_cr , dest_cr , wrap_c ) ;
if ( ! s - > chroma_y_shift ) { /* 422 */
s - > dsp . diff_pixels ( s - > block [ 6 ] , ptr_cb + ( dct_offset > > 1 ) , dest_cb + ( dct_offset > > 1 ) , wrap_c ) ;
s - > dsp . diff_pixels ( s - > block [ 7 ] , ptr_cr + ( dct_offset > > 1 ) , dest_cr + ( dct_offset > > 1 ) , wrap_c ) ;
}
}
/* pre quantization */
if ( s - > current_picture . mc_mb_var [ s - > mb_stride * mb_y + mb_x ] < 2 * s - > qscale * s - > qscale ) {
//FIXME optimize
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_y , dest_y , wrap_y , 8 ) < 20 * s - > qscale ) skip_dct [ 0 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_y + 8 , dest_y + 8 , wrap_y , 8 ) < 20 * s - > qscale ) skip_dct [ 1 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_y + dct_offset , dest_y + dct_offset , wrap_y , 8 ) < 20 * s - > qscale ) skip_dct [ 2 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_y + dct_offset + 8 , dest_y + dct_offset + 8 , wrap_y , 8 ) < 20 * s - > qscale ) skip_dct [ 3 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_cb , dest_cb , wrap_c , 8 ) < 20 * s - > qscale ) skip_dct [ 4 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_cr , dest_cr , wrap_c , 8 ) < 20 * s - > qscale ) skip_dct [ 5 ] = 1 ;
if ( ! s - > chroma_y_shift ) { /* 422 */
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_cb + ( dct_offset > > 1 ) , dest_cb + ( dct_offset > > 1 ) , wrap_c , 8 ) < 20 * s - > qscale ) skip_dct [ 6 ] = 1 ;
if ( s - > dsp . sad [ 1 ] ( NULL , ptr_cr + ( dct_offset > > 1 ) , dest_cr + ( dct_offset > > 1 ) , wrap_c , 8 ) < 20 * s - > qscale ) skip_dct [ 7 ] = 1 ;
}
}
}
if ( s - > avctx - > quantizer_noise_shaping ) {
2007-11-10 18:39:54 +02:00
if ( ! skip_dct [ 0 ] ) get_visual_weight ( weight [ 0 ] , ptr_y , wrap_y ) ;
if ( ! skip_dct [ 1 ] ) get_visual_weight ( weight [ 1 ] , ptr_y + 8 , wrap_y ) ;
if ( ! skip_dct [ 2 ] ) get_visual_weight ( weight [ 2 ] , ptr_y + dct_offset , wrap_y ) ;
if ( ! skip_dct [ 3 ] ) get_visual_weight ( weight [ 3 ] , ptr_y + dct_offset + 8 , wrap_y ) ;
if ( ! skip_dct [ 4 ] ) get_visual_weight ( weight [ 4 ] , ptr_cb , wrap_c ) ;
if ( ! skip_dct [ 5 ] ) get_visual_weight ( weight [ 5 ] , ptr_cr , wrap_c ) ;
2007-07-03 12:55:56 +03:00
if ( ! s - > chroma_y_shift ) { /* 422 */
2007-11-10 18:39:54 +02:00
if ( ! skip_dct [ 6 ] ) get_visual_weight ( weight [ 6 ] , ptr_cb + ( dct_offset > > 1 ) , wrap_c ) ;
if ( ! skip_dct [ 7 ] ) get_visual_weight ( weight [ 7 ] , ptr_cr + ( dct_offset > > 1 ) , wrap_c ) ;
2007-07-03 12:55:56 +03:00
}
memcpy ( orig [ 0 ] , s - > block [ 0 ] , sizeof ( DCTELEM ) * 64 * mb_block_count ) ;
}
/* DCT & quantize */
assert ( s - > out_format ! = FMT_MJPEG | | s - > qscale = = 8 ) ;
{
for ( i = 0 ; i < mb_block_count ; i + + ) {
if ( ! skip_dct [ i ] ) {
int overflow ;
s - > block_last_index [ i ] = s - > dct_quantize ( s , s - > block [ i ] , i , s - > qscale , & overflow ) ;
// FIXME we could decide to change to quantizer instead of clipping
// JS: I don't think that would be a good idea it could lower quality instead
// of improve it. Just INTRADC clipping deserves changes in quantizer
if ( overflow ) clip_coeffs ( s , s - > block [ i ] , s - > block_last_index [ i ] ) ;
} else
s - > block_last_index [ i ] = - 1 ;
}
if ( s - > avctx - > quantizer_noise_shaping ) {
for ( i = 0 ; i < mb_block_count ; i + + ) {
if ( ! skip_dct [ i ] ) {
s - > block_last_index [ i ] = dct_quantize_refine ( s , s - > block [ i ] , weight [ i ] , orig [ i ] , i , s - > qscale ) ;
}
}
}
if ( s - > luma_elim_threshold & & ! s - > mb_intra )
for ( i = 0 ; i < 4 ; i + + )
dct_single_coeff_elimination ( s , i , s - > luma_elim_threshold ) ;
if ( s - > chroma_elim_threshold & & ! s - > mb_intra )
for ( i = 4 ; i < mb_block_count ; i + + )
dct_single_coeff_elimination ( s , i , s - > chroma_elim_threshold ) ;
if ( s - > flags & CODEC_FLAG_CBP_RD ) {
for ( i = 0 ; i < mb_block_count ; i + + ) {
if ( s - > block_last_index [ i ] = = - 1 )
s - > coded_score [ i ] = INT_MAX / 256 ;
}
}
}
if ( ( s - > flags & CODEC_FLAG_GRAY ) & & s - > mb_intra ) {
s - > block_last_index [ 4 ] =
s - > block_last_index [ 5 ] = 0 ;
s - > block [ 4 ] [ 0 ] =
s - > block [ 5 ] [ 0 ] = ( 1024 + s - > c_dc_scale / 2 ) / s - > c_dc_scale ;
}
//non c quantize code returns incorrect block_last_index FIXME
if ( s - > alternate_scan & & s - > dct_quantize ! = dct_quantize_c ) {
for ( i = 0 ; i < mb_block_count ; i + + ) {
int j ;
if ( s - > block_last_index [ i ] > 0 ) {
for ( j = 63 ; j > 0 ; j - - ) {
if ( s - > block [ i ] [ s - > intra_scantable . permutated [ j ] ] ) break ;
}
s - > block_last_index [ i ] = j ;
}
}
}
/* huffman encode */
switch ( s - > codec_id ) { //FIXME funct ptr could be slightly faster
case CODEC_ID_MPEG1VIDEO :
case CODEC_ID_MPEG2VIDEO :
2007-07-05 12:08:28 +03:00
if ( ENABLE_MPEG1VIDEO_ENCODER | | ENABLE_MPEG2VIDEO_ENCODER )
2007-07-05 12:09:53 +03:00
mpeg1_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
2007-07-03 12:55:56 +03:00
case CODEC_ID_MPEG4 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER )
2007-07-10 23:27:50 +03:00
mpeg4_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
2007-07-03 12:55:56 +03:00
case CODEC_ID_MSMPEG4V2 :
case CODEC_ID_MSMPEG4V3 :
case CODEC_ID_WMV1 :
if ( ENABLE_MSMPEG4_ENCODER )
msmpeg4_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
case CODEC_ID_WMV2 :
if ( ENABLE_WMV2_ENCODER )
ff_wmv2_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
case CODEC_ID_H261 :
if ( ENABLE_H261_ENCODER )
ff_h261_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
case CODEC_ID_H263 :
case CODEC_ID_H263P :
case CODEC_ID_FLV1 :
case CODEC_ID_RV10 :
case CODEC_ID_RV20 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_H263_ENCODER | | ENABLE_H263P_ENCODER | |
ENABLE_FLV_ENCODER | | ENABLE_RV10_ENCODER | | ENABLE_RV20_ENCODER )
2007-07-10 23:27:50 +03:00
h263_encode_mb ( s , s - > block , motion_x , motion_y ) ;
break ;
2007-07-03 12:55:56 +03:00
case CODEC_ID_MJPEG :
if ( ENABLE_MJPEG_ENCODER )
ff_mjpeg_encode_mb ( s , s - > block ) ;
break ;
default :
assert ( 0 ) ;
}
}
static av_always_inline void encode_mb ( MpegEncContext * s , int motion_x , int motion_y )
{
if ( s - > chroma_format = = CHROMA_420 ) encode_mb_internal ( s , motion_x , motion_y , 8 , 6 ) ;
else encode_mb_internal ( s , motion_x , motion_y , 16 , 8 ) ;
}
static inline void copy_context_before_encode ( MpegEncContext * d , MpegEncContext * s , int type ) {
int i ;
memcpy ( d - > last_mv , s - > last_mv , 2 * 2 * 2 * sizeof ( int ) ) ; //FIXME is memcpy faster then a loop?
/* mpeg1 */
d - > mb_skip_run = s - > mb_skip_run ;
for ( i = 0 ; i < 3 ; i + + )
d - > last_dc [ i ] = s - > last_dc [ i ] ;
/* statistics */
d - > mv_bits = s - > mv_bits ;
d - > i_tex_bits = s - > i_tex_bits ;
d - > p_tex_bits = s - > p_tex_bits ;
d - > i_count = s - > i_count ;
d - > f_count = s - > f_count ;
d - > b_count = s - > b_count ;
d - > skip_count = s - > skip_count ;
d - > misc_bits = s - > misc_bits ;
d - > last_bits = 0 ;
d - > mb_skipped = 0 ;
d - > qscale = s - > qscale ;
d - > dquant = s - > dquant ;
2007-12-27 05:03:45 +02:00
d - > esc3_level_length = s - > esc3_level_length ;
2007-07-03 12:55:56 +03:00
}
static inline void copy_context_after_encode ( MpegEncContext * d , MpegEncContext * s , int type ) {
int i ;
memcpy ( d - > mv , s - > mv , 2 * 4 * 2 * sizeof ( int ) ) ;
memcpy ( d - > last_mv , s - > last_mv , 2 * 2 * 2 * sizeof ( int ) ) ; //FIXME is memcpy faster then a loop?
/* mpeg1 */
d - > mb_skip_run = s - > mb_skip_run ;
for ( i = 0 ; i < 3 ; i + + )
d - > last_dc [ i ] = s - > last_dc [ i ] ;
/* statistics */
d - > mv_bits = s - > mv_bits ;
d - > i_tex_bits = s - > i_tex_bits ;
d - > p_tex_bits = s - > p_tex_bits ;
d - > i_count = s - > i_count ;
d - > f_count = s - > f_count ;
d - > b_count = s - > b_count ;
d - > skip_count = s - > skip_count ;
d - > misc_bits = s - > misc_bits ;
d - > mb_intra = s - > mb_intra ;
d - > mb_skipped = s - > mb_skipped ;
d - > mv_type = s - > mv_type ;
d - > mv_dir = s - > mv_dir ;
d - > pb = s - > pb ;
if ( s - > data_partitioning ) {
d - > pb2 = s - > pb2 ;
d - > tex_pb = s - > tex_pb ;
}
d - > block = s - > block ;
for ( i = 0 ; i < 8 ; i + + )
d - > block_last_index [ i ] = s - > block_last_index [ i ] ;
d - > interlaced_dct = s - > interlaced_dct ;
d - > qscale = s - > qscale ;
2007-12-27 05:03:45 +02:00
d - > esc3_level_length = s - > esc3_level_length ;
2007-07-03 12:55:56 +03:00
}
static inline void encode_mb_hq ( MpegEncContext * s , MpegEncContext * backup , MpegEncContext * best , int type ,
PutBitContext pb [ 2 ] , PutBitContext pb2 [ 2 ] , PutBitContext tex_pb [ 2 ] ,
int * dmin , int * next_block , int motion_x , int motion_y )
{
int score ;
uint8_t * dest_backup [ 3 ] ;
copy_context_before_encode ( s , backup , type ) ;
s - > block = s - > blocks [ * next_block ] ;
s - > pb = pb [ * next_block ] ;
if ( s - > data_partitioning ) {
s - > pb2 = pb2 [ * next_block ] ;
s - > tex_pb = tex_pb [ * next_block ] ;
}
if ( * next_block ) {
memcpy ( dest_backup , s - > dest , sizeof ( s - > dest ) ) ;
s - > dest [ 0 ] = s - > rd_scratchpad ;
s - > dest [ 1 ] = s - > rd_scratchpad + 16 * s - > linesize ;
s - > dest [ 2 ] = s - > rd_scratchpad + 16 * s - > linesize + 8 ;
assert ( s - > linesize > = 32 ) ; //FIXME
}
encode_mb ( s , motion_x , motion_y ) ;
score = put_bits_count ( & s - > pb ) ;
if ( s - > data_partitioning ) {
score + = put_bits_count ( & s - > pb2 ) ;
score + = put_bits_count ( & s - > tex_pb ) ;
}
if ( s - > avctx - > mb_decision = = FF_MB_DECISION_RD ) {
MPV_decode_mb ( s , s - > block ) ;
score * = s - > lambda2 ;
score + = sse_mb ( s ) < < FF_LAMBDA_SHIFT ;
}
if ( * next_block ) {
memcpy ( s - > dest , dest_backup , sizeof ( s - > dest ) ) ;
}
if ( score < * dmin ) {
* dmin = score ;
* next_block ^ = 1 ;
copy_context_after_encode ( best , s , type ) ;
}
}
static int sse ( MpegEncContext * s , uint8_t * src1 , uint8_t * src2 , int w , int h , int stride ) {
uint32_t * sq = ff_squareTbl + 256 ;
int acc = 0 ;
int x , y ;
if ( w = = 16 & & h = = 16 )
return s - > dsp . sse [ 0 ] ( NULL , src1 , src2 , stride , 16 ) ;
else if ( w = = 8 & & h = = 8 )
return s - > dsp . sse [ 1 ] ( NULL , src1 , src2 , stride , 8 ) ;
for ( y = 0 ; y < h ; y + + ) {
for ( x = 0 ; x < w ; x + + ) {
acc + = sq [ src1 [ x + y * stride ] - src2 [ x + y * stride ] ] ;
}
}
assert ( acc > = 0 ) ;
return acc ;
}
static int sse_mb ( MpegEncContext * s ) {
int w = 16 ;
int h = 16 ;
if ( s - > mb_x * 16 + 16 > s - > width ) w = s - > width - s - > mb_x * 16 ;
if ( s - > mb_y * 16 + 16 > s - > height ) h = s - > height - s - > mb_y * 16 ;
if ( w = = 16 & & h = = 16 )
if ( s - > avctx - > mb_cmp = = FF_CMP_NSSE ) {
return s - > dsp . nsse [ 0 ] ( s , s - > new_picture . data [ 0 ] + s - > mb_x * 16 + s - > mb_y * s - > linesize * 16 , s - > dest [ 0 ] , s - > linesize , 16 )
+ s - > dsp . nsse [ 1 ] ( s , s - > new_picture . data [ 1 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 1 ] , s - > uvlinesize , 8 )
+ s - > dsp . nsse [ 1 ] ( s , s - > new_picture . data [ 2 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 2 ] , s - > uvlinesize , 8 ) ;
} else {
return s - > dsp . sse [ 0 ] ( NULL , s - > new_picture . data [ 0 ] + s - > mb_x * 16 + s - > mb_y * s - > linesize * 16 , s - > dest [ 0 ] , s - > linesize , 16 )
+ s - > dsp . sse [ 1 ] ( NULL , s - > new_picture . data [ 1 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 1 ] , s - > uvlinesize , 8 )
+ s - > dsp . sse [ 1 ] ( NULL , s - > new_picture . data [ 2 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 2 ] , s - > uvlinesize , 8 ) ;
}
else
return sse ( s , s - > new_picture . data [ 0 ] + s - > mb_x * 16 + s - > mb_y * s - > linesize * 16 , s - > dest [ 0 ] , w , h , s - > linesize )
+ sse ( s , s - > new_picture . data [ 1 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 1 ] , w > > 1 , h > > 1 , s - > uvlinesize )
+ sse ( s , s - > new_picture . data [ 2 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * 8 , s - > dest [ 2 ] , w > > 1 , h > > 1 , s - > uvlinesize ) ;
}
static int pre_estimate_motion_thread ( AVCodecContext * c , void * arg ) {
MpegEncContext * s = arg ;
s - > me . pre_pass = 1 ;
s - > me . dia_size = s - > avctx - > pre_dia_size ;
s - > first_slice_line = 1 ;
for ( s - > mb_y = s - > end_mb_y - 1 ; s - > mb_y > = s - > start_mb_y ; s - > mb_y - - ) {
for ( s - > mb_x = s - > mb_width - 1 ; s - > mb_x > = 0 ; s - > mb_x - - ) {
ff_pre_estimate_p_frame_motion ( s , s - > mb_x , s - > mb_y ) ;
}
s - > first_slice_line = 0 ;
}
s - > me . pre_pass = 0 ;
return 0 ;
}
static int estimate_motion_thread ( AVCodecContext * c , void * arg ) {
MpegEncContext * s = arg ;
ff_check_alignment ( ) ;
s - > me . dia_size = s - > avctx - > dia_size ;
s - > first_slice_line = 1 ;
for ( s - > mb_y = s - > start_mb_y ; s - > mb_y < s - > end_mb_y ; s - > mb_y + + ) {
s - > mb_x = 0 ; //for block init below
ff_init_block_index ( s ) ;
for ( s - > mb_x = 0 ; s - > mb_x < s - > mb_width ; s - > mb_x + + ) {
s - > block_index [ 0 ] + = 2 ;
s - > block_index [ 1 ] + = 2 ;
s - > block_index [ 2 ] + = 2 ;
s - > block_index [ 3 ] + = 2 ;
/* compute motion vector & mb_type and store in context */
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_B_TYPE )
2007-07-03 12:55:56 +03:00
ff_estimate_b_frame_motion ( s , s - > mb_x , s - > mb_y ) ;
else
ff_estimate_p_frame_motion ( s , s - > mb_x , s - > mb_y ) ;
}
s - > first_slice_line = 0 ;
}
return 0 ;
}
static int mb_var_thread ( AVCodecContext * c , void * arg ) {
MpegEncContext * s = arg ;
int mb_x , mb_y ;
ff_check_alignment ( ) ;
for ( mb_y = s - > start_mb_y ; mb_y < s - > end_mb_y ; mb_y + + ) {
for ( mb_x = 0 ; mb_x < s - > mb_width ; mb_x + + ) {
int xx = mb_x * 16 ;
int yy = mb_y * 16 ;
uint8_t * pix = s - > new_picture . data [ 0 ] + ( yy * s - > linesize ) + xx ;
int varc ;
int sum = s - > dsp . pix_sum ( pix , s - > linesize ) ;
varc = ( s - > dsp . pix_norm1 ( pix , s - > linesize ) - ( ( ( unsigned ) ( sum * sum ) ) > > 8 ) + 500 + 128 ) > > 8 ;
s - > current_picture . mb_var [ s - > mb_stride * mb_y + mb_x ] = varc ;
s - > current_picture . mb_mean [ s - > mb_stride * mb_y + mb_x ] = ( sum + 128 ) > > 8 ;
s - > me . mb_var_sum_temp + = varc ;
}
}
return 0 ;
}
static void write_slice_end ( MpegEncContext * s ) {
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & s - > codec_id = = CODEC_ID_MPEG4 ) {
2007-07-03 12:55:56 +03:00
if ( s - > partitioned_frame ) {
ff_mpeg4_merge_partitions ( s ) ;
}
ff_mpeg4_stuffing ( & s - > pb ) ;
} else if ( ENABLE_MJPEG_ENCODER & & s - > out_format = = FMT_MJPEG ) {
ff_mjpeg_encode_stuffing ( & s - > pb ) ;
}
align_put_bits ( & s - > pb ) ;
flush_put_bits ( & s - > pb ) ;
if ( ( s - > flags & CODEC_FLAG_PASS1 ) & & ! s - > partitioned_frame )
s - > misc_bits + = get_bits_diff ( s ) ;
}
static int encode_thread ( AVCodecContext * c , void * arg ) {
MpegEncContext * s = arg ;
int mb_x , mb_y , pdif = 0 ;
2008-08-08 05:56:44 +03:00
int chr_h = 16 > > s - > chroma_y_shift ;
2007-07-03 12:55:56 +03:00
int i , j ;
MpegEncContext best_s , backup_s ;
uint8_t bit_buf [ 2 ] [ MAX_MB_BYTES ] ;
uint8_t bit_buf2 [ 2 ] [ MAX_MB_BYTES ] ;
uint8_t bit_buf_tex [ 2 ] [ MAX_MB_BYTES ] ;
PutBitContext pb [ 2 ] , pb2 [ 2 ] , tex_pb [ 2 ] ;
//printf("%d->%d\n", s->resync_mb_y, s->end_mb_y);
ff_check_alignment ( ) ;
for ( i = 0 ; i < 2 ; i + + ) {
init_put_bits ( & pb [ i ] , bit_buf [ i ] , MAX_MB_BYTES ) ;
init_put_bits ( & pb2 [ i ] , bit_buf2 [ i ] , MAX_MB_BYTES ) ;
init_put_bits ( & tex_pb [ i ] , bit_buf_tex [ i ] , MAX_MB_BYTES ) ;
}
s - > last_bits = put_bits_count ( & s - > pb ) ;
s - > mv_bits = 0 ;
s - > misc_bits = 0 ;
s - > i_tex_bits = 0 ;
s - > p_tex_bits = 0 ;
s - > i_count = 0 ;
s - > f_count = 0 ;
s - > b_count = 0 ;
s - > skip_count = 0 ;
for ( i = 0 ; i < 3 ; i + + ) {
/* init last dc values */
/* note: quant matrix value (8) is implied here */
s - > last_dc [ i ] = 128 < < s - > intra_dc_precision ;
s - > current_picture . error [ i ] = 0 ;
}
s - > mb_skip_run = 0 ;
memset ( s - > last_mv , 0 , sizeof ( s - > last_mv ) ) ;
s - > last_mv_dir = 0 ;
switch ( s - > codec_id ) {
case CODEC_ID_H263 :
case CODEC_ID_H263P :
case CODEC_ID_FLV1 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_H263_ENCODER | | ENABLE_H263P_ENCODER | | ENABLE_FLV_ENCODER )
2007-07-10 23:27:50 +03:00
s - > gob_index = ff_h263_get_gob_height ( s ) ;
2007-07-03 12:55:56 +03:00
break ;
case CODEC_ID_MPEG4 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & s - > partitioned_frame )
2007-07-03 12:55:56 +03:00
ff_mpeg4_init_partitions ( s ) ;
break ;
}
s - > resync_mb_x = 0 ;
s - > resync_mb_y = 0 ;
s - > first_slice_line = 1 ;
s - > ptr_lastgob = s - > pb . buf ;
for ( mb_y = s - > start_mb_y ; mb_y < s - > end_mb_y ; mb_y + + ) {
// printf("row %d at %X\n", s->mb_y, (int)s);
s - > mb_x = 0 ;
s - > mb_y = mb_y ;
ff_set_qscale ( s , s - > qscale ) ;
ff_init_block_index ( s ) ;
for ( mb_x = 0 ; mb_x < s - > mb_width ; mb_x + + ) {
int xy = mb_y * s - > mb_stride + mb_x ; // removed const, H261 needs to adjust this
int mb_type = s - > mb_type [ xy ] ;
// int d;
int dmin = INT_MAX ;
int dir ;
if ( s - > pb . buf_end - s - > pb . buf - ( put_bits_count ( & s - > pb ) > > 3 ) < MAX_MB_BYTES ) {
av_log ( s - > avctx , AV_LOG_ERROR , " encoded frame too large \n " ) ;
return - 1 ;
}
if ( s - > data_partitioning ) {
if ( s - > pb2 . buf_end - s - > pb2 . buf - ( put_bits_count ( & s - > pb2 ) > > 3 ) < MAX_MB_BYTES
| | s - > tex_pb . buf_end - s - > tex_pb . buf - ( put_bits_count ( & s - > tex_pb ) > > 3 ) < MAX_MB_BYTES ) {
av_log ( s - > avctx , AV_LOG_ERROR , " encoded frame too large \n " ) ;
return - 1 ;
}
}
s - > mb_x = mb_x ;
s - > mb_y = mb_y ; // moved into loop, can get changed by H.261
ff_update_block_index ( s ) ;
if ( ENABLE_H261_ENCODER & & s - > codec_id = = CODEC_ID_H261 ) {
ff_h261_reorder_mb_index ( s ) ;
xy = s - > mb_y * s - > mb_stride + s - > mb_x ;
mb_type = s - > mb_type [ xy ] ;
}
/* write gob / video packet header */
if ( s - > rtp_mode ) {
int current_packet_size , is_gob_start ;
current_packet_size = ( ( put_bits_count ( & s - > pb ) + 7 ) > > 3 ) - ( s - > ptr_lastgob - s - > pb . buf ) ;
is_gob_start = s - > avctx - > rtp_payload_size & & current_packet_size > = s - > avctx - > rtp_payload_size & & mb_y + mb_x > 0 ;
if ( s - > start_mb_y = = mb_y & & mb_y > 0 & & mb_x = = 0 ) is_gob_start = 1 ;
switch ( s - > codec_id ) {
case CODEC_ID_H263 :
case CODEC_ID_H263P :
if ( ! s - > h263_slice_structured )
if ( s - > mb_x | | s - > mb_y % s - > gob_index ) is_gob_start = 0 ;
break ;
case CODEC_ID_MPEG2VIDEO :
if ( s - > mb_x = = 0 & & s - > mb_y ! = 0 ) is_gob_start = 1 ;
case CODEC_ID_MPEG1VIDEO :
if ( s - > mb_skip_run ) is_gob_start = 0 ;
break ;
}
if ( is_gob_start ) {
if ( s - > start_mb_y ! = mb_y | | mb_x ! = 0 ) {
write_slice_end ( s ) ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & s - > codec_id = = CODEC_ID_MPEG4 & & s - > partitioned_frame ) {
2007-07-03 12:55:56 +03:00
ff_mpeg4_init_partitions ( s ) ;
}
}
assert ( ( put_bits_count ( & s - > pb ) & 7 ) = = 0 ) ;
current_packet_size = pbBufPtr ( & s - > pb ) - s - > ptr_lastgob ;
if ( s - > avctx - > error_rate & & s - > resync_mb_x + s - > resync_mb_y > 0 ) {
int r = put_bits_count ( & s - > pb ) / 8 + s - > picture_number + 16 + s - > mb_x + s - > mb_y ;
int d = 100 / s - > avctx - > error_rate ;
if ( r % d = = 0 ) {
current_packet_size = 0 ;
# ifndef ALT_BITSTREAM_WRITER
s - > pb . buf_ptr = s - > ptr_lastgob ;
# endif
assert ( pbBufPtr ( & s - > pb ) = = s - > ptr_lastgob ) ;
}
}
if ( s - > avctx - > rtp_callback ) {
int number_mb = ( mb_y - s - > resync_mb_y ) * s - > mb_width + mb_x - s - > resync_mb_x ;
s - > avctx - > rtp_callback ( s - > avctx , s - > ptr_lastgob , current_packet_size , number_mb ) ;
}
switch ( s - > codec_id ) {
case CODEC_ID_MPEG4 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER ) {
2007-07-10 23:27:50 +03:00
ff_mpeg4_encode_video_packet_header ( s ) ;
ff_mpeg4_clean_buffers ( s ) ;
2007-07-10 23:23:08 +03:00
}
2007-07-03 12:55:56 +03:00
break ;
case CODEC_ID_MPEG1VIDEO :
case CODEC_ID_MPEG2VIDEO :
2007-07-05 12:08:28 +03:00
if ( ENABLE_MPEG1VIDEO_ENCODER | | ENABLE_MPEG2VIDEO_ENCODER ) {
2007-07-05 12:09:53 +03:00
ff_mpeg1_encode_slice_header ( s ) ;
ff_mpeg1_clean_buffers ( s ) ;
2007-07-05 12:08:28 +03:00
}
2007-07-03 12:55:56 +03:00
break ;
case CODEC_ID_H263 :
case CODEC_ID_H263P :
2007-07-10 23:23:08 +03:00
if ( ENABLE_H263_ENCODER | | ENABLE_H263P_ENCODER )
2007-07-10 23:27:50 +03:00
h263_encode_gob_header ( s , mb_y ) ;
2007-07-03 12:55:56 +03:00
break ;
}
if ( s - > flags & CODEC_FLAG_PASS1 ) {
int bits = put_bits_count ( & s - > pb ) ;
s - > misc_bits + = bits - s - > last_bits ;
s - > last_bits = bits ;
}
s - > ptr_lastgob + = current_packet_size ;
s - > first_slice_line = 1 ;
s - > resync_mb_x = mb_x ;
s - > resync_mb_y = mb_y ;
}
}
if ( ( s - > resync_mb_x = = s - > mb_x )
& & s - > resync_mb_y + 1 = = s - > mb_y ) {
s - > first_slice_line = 0 ;
}
s - > mb_skipped = 0 ;
s - > dquant = 0 ; //only for QP_RD
if ( mb_type & ( mb_type - 1 ) | | ( s - > flags & CODEC_FLAG_QP_RD ) ) { // more than 1 MB type possible or CODEC_FLAG_QP_RD
int next_block = 0 ;
int pb_bits_count , pb2_bits_count , tex_pb_bits_count ;
copy_context_before_encode ( & backup_s , s , - 1 ) ;
backup_s . pb = s - > pb ;
best_s . data_partitioning = s - > data_partitioning ;
best_s . partitioned_frame = s - > partitioned_frame ;
if ( s - > data_partitioning ) {
backup_s . pb2 = s - > pb2 ;
backup_s . tex_pb = s - > tex_pb ;
}
if ( mb_type & CANDIDATE_MB_TYPE_INTER ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 0 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > p_mv_table [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > p_mv_table [ xy ] [ 1 ] ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER , pb , pb2 , tex_pb ,
& dmin , & next_block , s - > mv [ 0 ] [ 0 ] [ 0 ] , s - > mv [ 0 ] [ 0 ] [ 1 ] ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_INTER_I ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 0 ] [ i ] = s - > p_field_select_table [ i ] [ xy ] ;
s - > mv [ 0 ] [ i ] [ 0 ] = s - > p_field_mv_table [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > p_field_mv_table [ i ] [ j ] [ xy ] [ 1 ] ;
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER_I , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_SKIPPED ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 0 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = 0 ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = 0 ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_SKIPPED , pb , pb2 , tex_pb ,
& dmin , & next_block , s - > mv [ 0 ] [ 0 ] [ 0 ] , s - > mv [ 0 ] [ 0 ] [ 1 ] ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_INTER4V ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_8X8 ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 4 ; i + + ) {
s - > mv [ 0 ] [ i ] [ 0 ] = s - > current_picture . motion_val [ 0 ] [ s - > block_index [ i ] ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > current_picture . motion_val [ 0 ] [ s - > block_index [ i ] ] [ 1 ] ;
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER4V , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_FORWARD ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 0 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > b_forw_mv_table [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > b_forw_mv_table [ xy ] [ 1 ] ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_FORWARD , pb , pb2 , tex_pb ,
& dmin , & next_block , s - > mv [ 0 ] [ 0 ] [ 0 ] , s - > mv [ 0 ] [ 0 ] [ 1 ] ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_BACKWARD ) {
s - > mv_dir = MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 0 ;
s - > mv [ 1 ] [ 0 ] [ 0 ] = s - > b_back_mv_table [ xy ] [ 0 ] ;
s - > mv [ 1 ] [ 0 ] [ 1 ] = s - > b_back_mv_table [ xy ] [ 1 ] ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BACKWARD , pb , pb2 , tex_pb ,
& dmin , & next_block , s - > mv [ 1 ] [ 0 ] [ 0 ] , s - > mv [ 1 ] [ 0 ] [ 1 ] ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_BIDIR ) {
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 0 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > b_bidir_forw_mv_table [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > b_bidir_forw_mv_table [ xy ] [ 1 ] ;
s - > mv [ 1 ] [ 0 ] [ 0 ] = s - > b_bidir_back_mv_table [ xy ] [ 0 ] ;
s - > mv [ 1 ] [ 0 ] [ 1 ] = s - > b_bidir_back_mv_table [ xy ] [ 1 ] ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BIDIR , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_FORWARD_I ) {
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 0 ] [ i ] = s - > b_field_select_table [ 0 ] [ i ] [ xy ] ;
s - > mv [ 0 ] [ i ] [ 0 ] = s - > b_field_mv_table [ 0 ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > b_field_mv_table [ 0 ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_FORWARD_I , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_BACKWARD_I ) {
s - > mv_dir = MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 1 ] [ i ] = s - > b_field_select_table [ 1 ] [ i ] [ xy ] ;
s - > mv [ 1 ] [ i ] [ 0 ] = s - > b_field_mv_table [ 1 ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 1 ] [ i ] [ 1 ] = s - > b_field_mv_table [ 1 ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BACKWARD_I , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_BIDIR_I ) {
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( dir = 0 ; dir < 2 ; dir + + ) {
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ dir ] [ i ] = s - > b_field_select_table [ dir ] [ i ] [ xy ] ;
s - > mv [ dir ] [ i ] [ 0 ] = s - > b_field_mv_table [ dir ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ dir ] [ i ] [ 1 ] = s - > b_field_mv_table [ dir ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BIDIR_I , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( mb_type & CANDIDATE_MB_TYPE_INTRA ) {
s - > mv_dir = 0 ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = 1 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = 0 ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = 0 ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTRA , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
if ( s - > h263_pred | | s - > h263_aic ) {
if ( best_s . mb_intra )
s - > mbintra_table [ mb_x + mb_y * s - > mb_stride ] = 1 ;
else
ff_clean_intra_table_entries ( s ) ; //old mode?
}
}
if ( ( s - > flags & CODEC_FLAG_QP_RD ) & & dmin < INT_MAX ) {
if ( best_s . mv_type = = MV_TYPE_16X16 ) { //FIXME move 4mv after QPRD
const int last_qp = backup_s . qscale ;
int qpi , qp , dc [ 6 ] ;
DCTELEM ac [ 6 ] [ 16 ] ;
const int mvdir = ( best_s . mv_dir & MV_DIR_BACKWARD ) ? 1 : 0 ;
static const int dquant_tab [ 4 ] = { - 1 , 1 , - 2 , 2 } ;
assert ( backup_s . dquant = = 0 ) ;
//FIXME intra
s - > mv_dir = best_s . mv_dir ;
s - > mv_type = MV_TYPE_16X16 ;
s - > mb_intra = best_s . mb_intra ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = best_s . mv [ 0 ] [ 0 ] [ 0 ] ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = best_s . mv [ 0 ] [ 0 ] [ 1 ] ;
s - > mv [ 1 ] [ 0 ] [ 0 ] = best_s . mv [ 1 ] [ 0 ] [ 0 ] ;
s - > mv [ 1 ] [ 0 ] [ 1 ] = best_s . mv [ 1 ] [ 0 ] [ 1 ] ;
2008-03-10 01:31:02 +02:00
qpi = s - > pict_type = = FF_B_TYPE ? 2 : 0 ;
2007-07-03 12:55:56 +03:00
for ( ; qpi < 4 ; qpi + + ) {
int dquant = dquant_tab [ qpi ] ;
qp = last_qp + dquant ;
if ( qp < s - > avctx - > qmin | | qp > s - > avctx - > qmax )
continue ;
backup_s . dquant = dquant ;
if ( s - > mb_intra & & s - > dc_val [ 0 ] ) {
for ( i = 0 ; i < 6 ; i + + ) {
dc [ i ] = s - > dc_val [ 0 ] [ s - > block_index [ i ] ] ;
memcpy ( ac [ i ] , s - > ac_val [ 0 ] [ s - > block_index [ i ] ] , sizeof ( DCTELEM ) * 16 ) ;
}
}
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER /* wrong but unused */ , pb , pb2 , tex_pb ,
& dmin , & next_block , s - > mv [ mvdir ] [ 0 ] [ 0 ] , s - > mv [ mvdir ] [ 0 ] [ 1 ] ) ;
if ( best_s . qscale ! = qp ) {
if ( s - > mb_intra & & s - > dc_val [ 0 ] ) {
for ( i = 0 ; i < 6 ; i + + ) {
s - > dc_val [ 0 ] [ s - > block_index [ i ] ] = dc [ i ] ;
memcpy ( s - > ac_val [ 0 ] [ s - > block_index [ i ] ] , ac [ i ] , sizeof ( DCTELEM ) * 16 ) ;
}
}
}
}
}
}
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & mb_type & CANDIDATE_MB_TYPE_DIRECT ) {
2007-07-03 12:55:56 +03:00
int mx = s - > b_direct_mv_table [ xy ] [ 0 ] ;
int my = s - > b_direct_mv_table [ xy ] [ 1 ] ;
backup_s . dquant = 0 ;
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s - > mb_intra = 0 ;
ff_mpeg4_set_direct_mv ( s , mx , my ) ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_DIRECT , pb , pb2 , tex_pb ,
& dmin , & next_block , mx , my ) ;
}
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & mb_type & CANDIDATE_MB_TYPE_DIRECT0 ) {
2007-07-03 12:55:56 +03:00
backup_s . dquant = 0 ;
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s - > mb_intra = 0 ;
ff_mpeg4_set_direct_mv ( s , 0 , 0 ) ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_DIRECT , pb , pb2 , tex_pb ,
& dmin , & next_block , 0 , 0 ) ;
}
if ( ! best_s . mb_intra & & s - > flags2 & CODEC_FLAG2_SKIP_RD ) {
int coded = 0 ;
for ( i = 0 ; i < 6 ; i + + )
coded | = s - > block_last_index [ i ] ;
if ( coded ) {
int mx , my ;
memcpy ( s - > mv , best_s . mv , sizeof ( s - > mv ) ) ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER & & best_s . mv_dir & MV_DIRECT ) {
2007-07-03 12:55:56 +03:00
mx = my = 0 ; //FIXME find the one we actually used
ff_mpeg4_set_direct_mv ( s , mx , my ) ;
} else if ( best_s . mv_dir & MV_DIR_BACKWARD ) {
mx = s - > mv [ 1 ] [ 0 ] [ 0 ] ;
my = s - > mv [ 1 ] [ 0 ] [ 1 ] ;
} else {
mx = s - > mv [ 0 ] [ 0 ] [ 0 ] ;
my = s - > mv [ 0 ] [ 0 ] [ 1 ] ;
}
s - > mv_dir = best_s . mv_dir ;
s - > mv_type = best_s . mv_type ;
s - > mb_intra = 0 ;
/* s->mv[0][0][0] = best_s.mv[0][0][0];
s - > mv [ 0 ] [ 0 ] [ 1 ] = best_s . mv [ 0 ] [ 0 ] [ 1 ] ;
s - > mv [ 1 ] [ 0 ] [ 0 ] = best_s . mv [ 1 ] [ 0 ] [ 0 ] ;
s - > mv [ 1 ] [ 0 ] [ 1 ] = best_s . mv [ 1 ] [ 0 ] [ 1 ] ; */
backup_s . dquant = 0 ;
s - > skipdct = 1 ;
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER /* wrong but unused */ , pb , pb2 , tex_pb ,
& dmin , & next_block , mx , my ) ;
s - > skipdct = 0 ;
}
}
s - > current_picture . qscale_table [ xy ] = best_s . qscale ;
copy_context_after_encode ( s , & best_s , - 1 ) ;
pb_bits_count = put_bits_count ( & s - > pb ) ;
flush_put_bits ( & s - > pb ) ;
ff_copy_bits ( & backup_s . pb , bit_buf [ next_block ^ 1 ] , pb_bits_count ) ;
s - > pb = backup_s . pb ;
if ( s - > data_partitioning ) {
pb2_bits_count = put_bits_count ( & s - > pb2 ) ;
flush_put_bits ( & s - > pb2 ) ;
ff_copy_bits ( & backup_s . pb2 , bit_buf2 [ next_block ^ 1 ] , pb2_bits_count ) ;
s - > pb2 = backup_s . pb2 ;
tex_pb_bits_count = put_bits_count ( & s - > tex_pb ) ;
flush_put_bits ( & s - > tex_pb ) ;
ff_copy_bits ( & backup_s . tex_pb , bit_buf_tex [ next_block ^ 1 ] , tex_pb_bits_count ) ;
s - > tex_pb = backup_s . tex_pb ;
}
s - > last_bits = put_bits_count ( & s - > pb ) ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_ANY_H263_ENCODER & &
2008-03-10 01:31:02 +02:00
s - > out_format = = FMT_H263 & & s - > pict_type ! = FF_B_TYPE )
2007-07-03 12:55:56 +03:00
ff_h263_update_motion_val ( s ) ;
if ( next_block = = 0 ) { //FIXME 16 vs linesize16
s - > dsp . put_pixels_tab [ 0 ] [ 0 ] ( s - > dest [ 0 ] , s - > rd_scratchpad , s - > linesize , 16 ) ;
s - > dsp . put_pixels_tab [ 1 ] [ 0 ] ( s - > dest [ 1 ] , s - > rd_scratchpad + 16 * s - > linesize , s - > uvlinesize , 8 ) ;
s - > dsp . put_pixels_tab [ 1 ] [ 0 ] ( s - > dest [ 2 ] , s - > rd_scratchpad + 16 * s - > linesize + 8 , s - > uvlinesize , 8 ) ;
}
if ( s - > avctx - > mb_decision = = FF_MB_DECISION_BITS )
MPV_decode_mb ( s , s - > block ) ;
} else {
int motion_x = 0 , motion_y = 0 ;
s - > mv_type = MV_TYPE_16X16 ;
// only one MB-Type possible
switch ( mb_type ) {
case CANDIDATE_MB_TYPE_INTRA :
s - > mv_dir = 0 ;
s - > mb_intra = 1 ;
motion_x = s - > mv [ 0 ] [ 0 ] [ 0 ] = 0 ;
motion_y = s - > mv [ 0 ] [ 0 ] [ 1 ] = 0 ;
break ;
case CANDIDATE_MB_TYPE_INTER :
s - > mv_dir = MV_DIR_FORWARD ;
s - > mb_intra = 0 ;
motion_x = s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > p_mv_table [ xy ] [ 0 ] ;
motion_y = s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > p_mv_table [ xy ] [ 1 ] ;
break ;
case CANDIDATE_MB_TYPE_INTER_I :
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 0 ] [ i ] = s - > p_field_select_table [ i ] [ xy ] ;
s - > mv [ 0 ] [ i ] [ 0 ] = s - > p_field_mv_table [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > p_field_mv_table [ i ] [ j ] [ xy ] [ 1 ] ;
}
break ;
case CANDIDATE_MB_TYPE_INTER4V :
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_8X8 ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 4 ; i + + ) {
s - > mv [ 0 ] [ i ] [ 0 ] = s - > current_picture . motion_val [ 0 ] [ s - > block_index [ i ] ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > current_picture . motion_val [ 0 ] [ s - > block_index [ i ] ] [ 1 ] ;
}
break ;
case CANDIDATE_MB_TYPE_DIRECT :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER ) {
2007-07-10 23:27:50 +03:00
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s - > mb_intra = 0 ;
motion_x = s - > b_direct_mv_table [ xy ] [ 0 ] ;
motion_y = s - > b_direct_mv_table [ xy ] [ 1 ] ;
ff_mpeg4_set_direct_mv ( s , motion_x , motion_y ) ;
2007-07-10 23:23:08 +03:00
}
2007-07-03 12:55:56 +03:00
break ;
case CANDIDATE_MB_TYPE_DIRECT0 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER ) {
2007-07-10 23:27:50 +03:00
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s - > mb_intra = 0 ;
ff_mpeg4_set_direct_mv ( s , 0 , 0 ) ;
2007-07-10 23:23:08 +03:00
}
2007-07-03 12:55:56 +03:00
break ;
case CANDIDATE_MB_TYPE_BIDIR :
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD ;
s - > mb_intra = 0 ;
s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > b_bidir_forw_mv_table [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > b_bidir_forw_mv_table [ xy ] [ 1 ] ;
s - > mv [ 1 ] [ 0 ] [ 0 ] = s - > b_bidir_back_mv_table [ xy ] [ 0 ] ;
s - > mv [ 1 ] [ 0 ] [ 1 ] = s - > b_bidir_back_mv_table [ xy ] [ 1 ] ;
break ;
case CANDIDATE_MB_TYPE_BACKWARD :
s - > mv_dir = MV_DIR_BACKWARD ;
s - > mb_intra = 0 ;
motion_x = s - > mv [ 1 ] [ 0 ] [ 0 ] = s - > b_back_mv_table [ xy ] [ 0 ] ;
motion_y = s - > mv [ 1 ] [ 0 ] [ 1 ] = s - > b_back_mv_table [ xy ] [ 1 ] ;
break ;
case CANDIDATE_MB_TYPE_FORWARD :
s - > mv_dir = MV_DIR_FORWARD ;
s - > mb_intra = 0 ;
motion_x = s - > mv [ 0 ] [ 0 ] [ 0 ] = s - > b_forw_mv_table [ xy ] [ 0 ] ;
motion_y = s - > mv [ 0 ] [ 0 ] [ 1 ] = s - > b_forw_mv_table [ xy ] [ 1 ] ;
// printf(" %d %d ", motion_x, motion_y);
break ;
case CANDIDATE_MB_TYPE_FORWARD_I :
s - > mv_dir = MV_DIR_FORWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 0 ] [ i ] = s - > b_field_select_table [ 0 ] [ i ] [ xy ] ;
s - > mv [ 0 ] [ i ] [ 0 ] = s - > b_field_mv_table [ 0 ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 0 ] [ i ] [ 1 ] = s - > b_field_mv_table [ 0 ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
break ;
case CANDIDATE_MB_TYPE_BACKWARD_I :
s - > mv_dir = MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ 1 ] [ i ] = s - > b_field_select_table [ 1 ] [ i ] [ xy ] ;
s - > mv [ 1 ] [ i ] [ 0 ] = s - > b_field_mv_table [ 1 ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ 1 ] [ i ] [ 1 ] = s - > b_field_mv_table [ 1 ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
break ;
case CANDIDATE_MB_TYPE_BIDIR_I :
s - > mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD ;
s - > mv_type = MV_TYPE_FIELD ;
s - > mb_intra = 0 ;
for ( dir = 0 ; dir < 2 ; dir + + ) {
for ( i = 0 ; i < 2 ; i + + ) {
j = s - > field_select [ dir ] [ i ] = s - > b_field_select_table [ dir ] [ i ] [ xy ] ;
s - > mv [ dir ] [ i ] [ 0 ] = s - > b_field_mv_table [ dir ] [ i ] [ j ] [ xy ] [ 0 ] ;
s - > mv [ dir ] [ i ] [ 1 ] = s - > b_field_mv_table [ dir ] [ i ] [ j ] [ xy ] [ 1 ] ;
}
}
break ;
default :
av_log ( s - > avctx , AV_LOG_ERROR , " illegal MB type \n " ) ;
}
encode_mb ( s , motion_x , motion_y ) ;
// RAL: Update last macroblock type
s - > last_mv_dir = s - > mv_dir ;
2007-07-10 23:23:08 +03:00
if ( ENABLE_ANY_H263_ENCODER & &
2008-03-10 01:31:02 +02:00
s - > out_format = = FMT_H263 & & s - > pict_type ! = FF_B_TYPE )
2007-07-03 12:55:56 +03:00
ff_h263_update_motion_val ( s ) ;
MPV_decode_mb ( s , s - > block ) ;
}
/* clean the MV table in IPS frames for direct mode in B frames */
if ( s - > mb_intra /* && I,P,S_TYPE */ ) {
s - > p_mv_table [ xy ] [ 0 ] = 0 ;
s - > p_mv_table [ xy ] [ 1 ] = 0 ;
}
if ( s - > flags & CODEC_FLAG_PSNR ) {
int w = 16 ;
int h = 16 ;
if ( s - > mb_x * 16 + 16 > s - > width ) w = s - > width - s - > mb_x * 16 ;
if ( s - > mb_y * 16 + 16 > s - > height ) h = s - > height - s - > mb_y * 16 ;
s - > current_picture . error [ 0 ] + = sse (
s , s - > new_picture . data [ 0 ] + s - > mb_x * 16 + s - > mb_y * s - > linesize * 16 ,
s - > dest [ 0 ] , w , h , s - > linesize ) ;
s - > current_picture . error [ 1 ] + = sse (
2008-08-08 05:56:44 +03:00
s , s - > new_picture . data [ 1 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * chr_h ,
s - > dest [ 1 ] , w > > 1 , h > > s - > chroma_y_shift , s - > uvlinesize ) ;
2007-07-03 12:55:56 +03:00
s - > current_picture . error [ 2 ] + = sse (
2008-08-08 05:56:44 +03:00
s , s - > new_picture . data [ 2 ] + s - > mb_x * 8 + s - > mb_y * s - > uvlinesize * chr_h ,
s - > dest [ 2 ] , w > > 1 , h > > s - > chroma_y_shift , s - > uvlinesize ) ;
2007-07-03 12:55:56 +03:00
}
if ( s - > loop_filter ) {
2007-07-10 23:23:08 +03:00
if ( ENABLE_ANY_H263_ENCODER & & s - > out_format = = FMT_H263 )
2007-07-03 12:55:56 +03:00
ff_h263_loop_filter ( s ) ;
}
//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_stride, put_bits_count(&s->pb));
}
}
//not beautiful here but we must write it before flushing so it has to be here
2008-03-10 01:31:02 +02:00
if ( ENABLE_MSMPEG4_ENCODER & & s - > msmpeg4_version & & s - > msmpeg4_version < 4 & & s - > pict_type = = FF_I_TYPE )
2007-07-03 12:55:56 +03:00
msmpeg4_encode_ext_header ( s ) ;
write_slice_end ( s ) ;
/* Send the last GOB if RTP */
if ( s - > avctx - > rtp_callback ) {
int number_mb = ( mb_y - s - > resync_mb_y ) * s - > mb_width - s - > resync_mb_x ;
pdif = pbBufPtr ( & s - > pb ) - s - > ptr_lastgob ;
/* Call the RTP callback to send the last GOB */
emms_c ( ) ;
s - > avctx - > rtp_callback ( s - > avctx , s - > ptr_lastgob , pdif , number_mb ) ;
}
return 0 ;
}
# define MERGE(field) dst->field += src->field; src->field=0
static void merge_context_after_me ( MpegEncContext * dst , MpegEncContext * src ) {
MERGE ( me . scene_change_score ) ;
MERGE ( me . mc_mb_var_sum_temp ) ;
MERGE ( me . mb_var_sum_temp ) ;
}
static void merge_context_after_encode ( MpegEncContext * dst , MpegEncContext * src ) {
int i ;
MERGE ( dct_count [ 0 ] ) ; //note, the other dct vars are not part of the context
MERGE ( dct_count [ 1 ] ) ;
MERGE ( mv_bits ) ;
MERGE ( i_tex_bits ) ;
MERGE ( p_tex_bits ) ;
MERGE ( i_count ) ;
MERGE ( f_count ) ;
MERGE ( b_count ) ;
MERGE ( skip_count ) ;
MERGE ( misc_bits ) ;
MERGE ( error_count ) ;
MERGE ( padding_bug_score ) ;
MERGE ( current_picture . error [ 0 ] ) ;
MERGE ( current_picture . error [ 1 ] ) ;
MERGE ( current_picture . error [ 2 ] ) ;
if ( dst - > avctx - > noise_reduction ) {
for ( i = 0 ; i < 64 ; i + + ) {
MERGE ( dct_error_sum [ 0 ] [ i ] ) ;
MERGE ( dct_error_sum [ 1 ] [ i ] ) ;
}
}
assert ( put_bits_count ( & src - > pb ) % 8 = = 0 ) ;
assert ( put_bits_count ( & dst - > pb ) % 8 = = 0 ) ;
ff_copy_bits ( & dst - > pb , src - > pb . buf , put_bits_count ( & src - > pb ) ) ;
flush_put_bits ( & dst - > pb ) ;
}
static int estimate_qp ( MpegEncContext * s , int dry_run ) {
if ( s - > next_lambda ) {
s - > current_picture_ptr - > quality =
s - > current_picture . quality = s - > next_lambda ;
if ( ! dry_run ) s - > next_lambda = 0 ;
} else if ( ! s - > fixed_qscale ) {
s - > current_picture_ptr - > quality =
s - > current_picture . quality = ff_rate_estimate_qscale ( s , dry_run ) ;
if ( s - > current_picture . quality < 0 )
return - 1 ;
}
if ( s - > adaptive_quant ) {
switch ( s - > codec_id ) {
case CODEC_ID_MPEG4 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_MPEG4_ENCODER )
2007-07-10 23:27:50 +03:00
ff_clean_mpeg4_qscales ( s ) ;
2007-07-03 12:55:56 +03:00
break ;
case CODEC_ID_H263 :
case CODEC_ID_H263P :
case CODEC_ID_FLV1 :
2007-07-10 23:23:08 +03:00
if ( ENABLE_H263_ENCODER | | ENABLE_H263P_ENCODER | | ENABLE_FLV_ENCODER )
2007-07-10 23:27:50 +03:00
ff_clean_h263_qscales ( s ) ;
2007-07-03 12:55:56 +03:00
break ;
}
s - > lambda = s - > lambda_table [ 0 ] ;
//FIXME broken
} else
s - > lambda = s - > current_picture . quality ;
//printf("%d %d\n", s->avctx->global_quality, s->current_picture.quality);
update_qscale ( s ) ;
return 0 ;
}
2007-07-10 17:37:33 +03:00
/* must be called before writing the header */
static void set_frame_distances ( MpegEncContext * s ) {
assert ( s - > current_picture_ptr - > pts ! = AV_NOPTS_VALUE ) ;
s - > time = s - > current_picture_ptr - > pts * s - > avctx - > time_base . num ;
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_B_TYPE ) {
2007-07-10 17:37:33 +03:00
s - > pb_time = s - > pp_time - ( s - > last_non_b_time - s - > time ) ;
assert ( s - > pb_time > 0 & & s - > pb_time < s - > pp_time ) ;
} else {
s - > pp_time = s - > time - s - > last_non_b_time ;
s - > last_non_b_time = s - > time ;
assert ( s - > picture_number = = 0 | | s - > pp_time > 0 ) ;
}
}
2007-07-03 12:55:56 +03:00
static int encode_picture ( MpegEncContext * s , int picture_number )
{
int i ;
int bits ;
s - > picture_number = picture_number ;
/* Reset the average MB variance */
s - > me . mb_var_sum_temp =
s - > me . mc_mb_var_sum_temp = 0 ;
/* we need to initialize some time vars before we can encode b-frames */
// RAL: Condition added for MPEG1VIDEO
if ( s - > codec_id = = CODEC_ID_MPEG1VIDEO | | s - > codec_id = = CODEC_ID_MPEG2VIDEO | | ( s - > h263_pred & & ! s - > h263_msmpeg4 ) )
2007-07-10 17:37:33 +03:00
set_frame_distances ( s ) ;
if ( ENABLE_MPEG4_ENCODER & & s - > codec_id = = CODEC_ID_MPEG4 )
ff_set_mpeg4_time ( s ) ;
2007-07-03 12:55:56 +03:00
s - > me . scene_change_score = 0 ;
2008-04-29 17:08:01 +03:00
// s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME rate distortion
2007-07-03 12:55:56 +03:00
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_I_TYPE ) {
2007-07-03 12:55:56 +03:00
if ( s - > msmpeg4_version > = 3 ) s - > no_rounding = 1 ;
else s - > no_rounding = 0 ;
2008-03-10 01:31:02 +02:00
} else if ( s - > pict_type ! = FF_B_TYPE ) {
2007-07-03 12:55:56 +03:00
if ( s - > flipflop_rounding | | s - > codec_id = = CODEC_ID_H263P | | s - > codec_id = = CODEC_ID_MPEG4 )
s - > no_rounding ^ = 1 ;
}
if ( s - > flags & CODEC_FLAG_PASS2 ) {
if ( estimate_qp ( s , 1 ) < 0 )
return - 1 ;
ff_get_2pass_fcode ( s ) ;
} else if ( ! ( s - > flags & CODEC_FLAG_QSCALE ) ) {
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_B_TYPE )
2007-07-03 12:55:56 +03:00
s - > lambda = s - > last_lambda_for [ s - > pict_type ] ;
else
s - > lambda = s - > last_lambda_for [ s - > last_non_b_pict_type ] ;
update_qscale ( s ) ;
}
s - > mb_intra = 0 ; //for the rate distortion & bit compare functions
for ( i = 1 ; i < s - > avctx - > thread_count ; i + + ) {
ff_update_duplicate_context ( s - > thread_context [ i ] , s ) ;
}
ff_init_me ( s ) ;
/* Estimate motion for every MB */
2008-03-10 01:31:02 +02:00
if ( s - > pict_type ! = FF_I_TYPE ) {
2007-07-03 12:55:56 +03:00
s - > lambda = ( s - > lambda * s - > avctx - > me_penalty_compensation + 128 ) > > 8 ;
s - > lambda2 = ( s - > lambda2 * ( int64_t ) s - > avctx - > me_penalty_compensation + 128 ) > > 8 ;
2008-03-10 01:31:02 +02:00
if ( s - > pict_type ! = FF_B_TYPE & & s - > avctx - > me_threshold = = 0 ) {
if ( ( s - > avctx - > pre_me & & s - > last_non_b_pict_type = = FF_I_TYPE ) | | s - > avctx - > pre_me = = 2 ) {
2007-07-03 12:55:56 +03:00
s - > avctx - > execute ( s - > avctx , pre_estimate_motion_thread , ( void * * ) & ( s - > thread_context [ 0 ] ) , NULL , s - > avctx - > thread_count ) ;
}
}
s - > avctx - > execute ( s - > avctx , estimate_motion_thread , ( void * * ) & ( s - > thread_context [ 0 ] ) , NULL , s - > avctx - > thread_count ) ;
2008-03-10 01:31:02 +02:00
} else /* if(s->pict_type == FF_I_TYPE) */ {
2007-07-03 12:55:56 +03:00
/* I-Frame */
for ( i = 0 ; i < s - > mb_stride * s - > mb_height ; i + + )
s - > mb_type [ i ] = CANDIDATE_MB_TYPE_INTRA ;
if ( ! s - > fixed_qscale ) {
/* finding spatial complexity for I-frame rate control */
s - > avctx - > execute ( s - > avctx , mb_var_thread , ( void * * ) & ( s - > thread_context [ 0 ] ) , NULL , s - > avctx - > thread_count ) ;
}
}
for ( i = 1 ; i < s - > avctx - > thread_count ; i + + ) {
merge_context_after_me ( s , s - > thread_context [ i ] ) ;
}
s - > current_picture . mc_mb_var_sum = s - > current_picture_ptr - > mc_mb_var_sum = s - > me . mc_mb_var_sum_temp ;
s - > current_picture . mb_var_sum = s - > current_picture_ptr - > mb_var_sum = s - > me . mb_var_sum_temp ;
emms_c ( ) ;
2008-03-10 01:31:02 +02:00
if ( s - > me . scene_change_score > s - > avctx - > scenechange_threshold & & s - > pict_type = = FF_P_TYPE ) {
s - > pict_type = FF_I_TYPE ;
2007-07-03 12:55:56 +03:00
for ( i = 0 ; i < s - > mb_stride * s - > mb_height ; i + + )
s - > mb_type [ i ] = CANDIDATE_MB_TYPE_INTRA ;
//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum);
}
if ( ! s - > umvplus ) {
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_P_TYPE | | s - > pict_type = = FF_S_TYPE ) {
2007-07-03 12:55:56 +03:00
s - > f_code = ff_get_best_fcode ( s , s - > p_mv_table , CANDIDATE_MB_TYPE_INTER ) ;
if ( s - > flags & CODEC_FLAG_INTERLACED_ME ) {
int a , b ;
a = ff_get_best_fcode ( s , s - > p_field_mv_table [ 0 ] [ 0 ] , CANDIDATE_MB_TYPE_INTER_I ) ; //FIXME field_select
b = ff_get_best_fcode ( s , s - > p_field_mv_table [ 1 ] [ 1 ] , CANDIDATE_MB_TYPE_INTER_I ) ;
2008-04-19 20:07:58 +03:00
s - > f_code = FFMAX3 ( s - > f_code , a , b ) ;
2007-07-03 12:55:56 +03:00
}
ff_fix_long_p_mvs ( s ) ;
ff_fix_long_mvs ( s , NULL , 0 , s - > p_mv_table , s - > f_code , CANDIDATE_MB_TYPE_INTER , 0 ) ;
if ( s - > flags & CODEC_FLAG_INTERLACED_ME ) {
int j ;
for ( i = 0 ; i < 2 ; i + + ) {
for ( j = 0 ; j < 2 ; j + + )
ff_fix_long_mvs ( s , s - > p_field_select_table [ i ] , j ,
s - > p_field_mv_table [ i ] [ j ] , s - > f_code , CANDIDATE_MB_TYPE_INTER_I , 0 ) ;
}
}
}
2008-03-10 01:31:02 +02:00
if ( s - > pict_type = = FF_B_TYPE ) {
2007-07-03 12:55:56 +03:00
int a , b ;
a = ff_get_best_fcode ( s , s - > b_forw_mv_table , CANDIDATE_MB_TYPE_FORWARD ) ;
b = ff_get_best_fcode ( s , s - > b_bidir_forw_mv_table , CANDIDATE_MB_TYPE_BIDIR ) ;
s - > f_code = FFMAX ( a , b ) ;
a = ff_get_best_fcode ( s , s - > b_back_mv_table , CANDIDATE_MB_TYPE_BACKWARD ) ;
b = ff_get_best_fcode ( s , s - > b_bidir_back_mv_table , CANDIDATE_MB_TYPE_BIDIR ) ;
s - > b_code = FFMAX ( a , b ) ;
ff_fix_long_mvs ( s , NULL , 0 , s - > b_forw_mv_table , s - > f_code , CANDIDATE_MB_TYPE_FORWARD , 1 ) ;
ff_fix_long_mvs ( s , NULL , 0 , s - > b_back_mv_table , s - > b_code , CANDIDATE_MB_TYPE_BACKWARD , 1 ) ;
ff_fix_long_mvs ( s , NULL , 0 , s - > b_bidir_forw_mv_table , s - > f_code , CANDIDATE_MB_TYPE_BIDIR , 1 ) ;
ff_fix_long_mvs ( s , NULL , 0 , s - > b_bidir_back_mv_table , s - > b_code , CANDIDATE_MB_TYPE_BIDIR , 1 ) ;
if ( s - > flags & CODEC_FLAG_INTERLACED_ME ) {
int dir , j ;
for ( dir = 0 ; dir < 2 ; dir + + ) {
for ( i = 0 ; i < 2 ; i + + ) {
for ( j = 0 ; j < 2 ; j + + ) {
int type = dir ? ( CANDIDATE_MB_TYPE_BACKWARD_I | CANDIDATE_MB_TYPE_BIDIR_I )
: ( CANDIDATE_MB_TYPE_FORWARD_I | CANDIDATE_MB_TYPE_BIDIR_I ) ;
ff_fix_long_mvs ( s , s - > b_field_select_table [ dir ] [ i ] , j ,
s - > b_field_mv_table [ dir ] [ i ] [ j ] , dir ? s - > b_code : s - > f_code , type , 1 ) ;
}
}
}
}
}
}
if ( estimate_qp ( s , 0 ) < 0 )
return - 1 ;
2008-03-10 01:31:02 +02:00
if ( s - > qscale < 3 & & s - > max_qcoeff < = 128 & & s - > pict_type = = FF_I_TYPE & & ! ( s - > flags & CODEC_FLAG_QSCALE ) )
2007-07-03 12:55:56 +03:00
s - > qscale = 3 ; //reduce clipping problems
if ( s - > out_format = = FMT_MJPEG ) {
/* for mjpeg, we do include qscale in the matrix */
s - > intra_matrix [ 0 ] = ff_mpeg1_default_intra_matrix [ 0 ] ;
for ( i = 1 ; i < 64 ; i + + ) {
int j = s - > dsp . idct_permutation [ i ] ;
s - > intra_matrix [ j ] = av_clip_uint8 ( ( ff_mpeg1_default_intra_matrix [ i ] * s - > qscale ) > > 3 ) ;
}
2007-10-08 12:14:46 +03:00
ff_convert_matrix ( & s - > dsp , s - > q_intra_matrix , s - > q_intra_matrix16 ,
2007-07-03 12:55:56 +03:00
s - > intra_matrix , s - > intra_quant_bias , 8 , 8 , 1 ) ;
s - > qscale = 8 ;
}
//FIXME var duplication
s - > current_picture_ptr - > key_frame =
2008-03-10 01:31:02 +02:00
s - > current_picture . key_frame = s - > pict_type = = FF_I_TYPE ; //FIXME pic_ptr
2007-07-03 12:55:56 +03:00
s - > current_picture_ptr - > pict_type =
s - > current_picture . pict_type = s - > pict_type ;
if ( s - > current_picture . key_frame )
s - > picture_in_gop_number = 0 ;
s - > last_bits = put_bits_count ( & s - > pb ) ;
switch ( s - > out_format ) {
case FMT_MJPEG :
if ( ENABLE_MJPEG_ENCODER )
ff_mjpeg_encode_picture_header ( s ) ;
break ;
case FMT_H261 :
if ( ENABLE_H261_ENCODER )
ff_h261_encode_picture_header ( s , picture_number ) ;
break ;
case FMT_H263 :
if ( ENABLE_WMV2_ENCODER & & s - > codec_id = = CODEC_ID_WMV2 )
ff_wmv2_encode_picture_header ( s , picture_number ) ;
else if ( ENABLE_MSMPEG4_ENCODER & & s - > h263_msmpeg4 )
msmpeg4_encode_picture_header ( s , picture_number ) ;
2007-07-10 23:23:08 +03:00
else if ( ENABLE_MPEG4_ENCODER & & s - > h263_pred )
2007-07-03 12:55:56 +03:00
mpeg4_encode_picture_header ( s , picture_number ) ;
else if ( ENABLE_RV10_ENCODER & & s - > codec_id = = CODEC_ID_RV10 )
rv10_encode_picture_header ( s , picture_number ) ;
else if ( ENABLE_RV20_ENCODER & & s - > codec_id = = CODEC_ID_RV20 )
rv20_encode_picture_header ( s , picture_number ) ;
2007-07-10 23:23:08 +03:00
else if ( ENABLE_FLV_ENCODER & & s - > codec_id = = CODEC_ID_FLV1 )
2007-07-03 12:55:56 +03:00
ff_flv_encode_picture_header ( s , picture_number ) ;
2007-07-10 23:23:08 +03:00
else if ( ENABLE_ANY_H263_ENCODER )
2007-07-03 12:55:56 +03:00
h263_encode_picture_header ( s , picture_number ) ;
break ;
case FMT_MPEG1 :
2007-07-05 12:08:28 +03:00
if ( ENABLE_MPEG1VIDEO_ENCODER | | ENABLE_MPEG2VIDEO_ENCODER )
2007-07-05 12:09:53 +03:00
mpeg1_encode_picture_header ( s , picture_number ) ;
2007-07-03 12:55:56 +03:00
break ;
case FMT_H264 :
break ;
default :
assert ( 0 ) ;
}
bits = put_bits_count ( & s - > pb ) ;
s - > header_bits = bits - s - > last_bits ;
for ( i = 1 ; i < s - > avctx - > thread_count ; i + + ) {
update_duplicate_context_after_me ( s - > thread_context [ i ] , s ) ;
}
s - > avctx - > execute ( s - > avctx , encode_thread , ( void * * ) & ( s - > thread_context [ 0 ] ) , NULL , s - > avctx - > thread_count ) ;
for ( i = 1 ; i < s - > avctx - > thread_count ; i + + ) {
merge_context_after_encode ( s , s - > thread_context [ i ] ) ;
}
emms_c ( ) ;
return 0 ;
}
void denoise_dct_c ( MpegEncContext * s , DCTELEM * block ) {
const int intra = s - > mb_intra ;
int i ;
s - > dct_count [ intra ] + + ;
for ( i = 0 ; i < 64 ; i + + ) {
int level = block [ i ] ;
if ( level ) {
if ( level > 0 ) {
s - > dct_error_sum [ intra ] [ i ] + = level ;
level - = s - > dct_offset [ intra ] [ i ] ;
if ( level < 0 ) level = 0 ;
} else {
s - > dct_error_sum [ intra ] [ i ] - = level ;
level + = s - > dct_offset [ intra ] [ i ] ;
if ( level > 0 ) level = 0 ;
}
block [ i ] = level ;
}
}
}
int dct_quantize_trellis_c ( MpegEncContext * s ,
DCTELEM * block , int n ,
int qscale , int * overflow ) {
const int * qmat ;
const uint8_t * scantable = s - > intra_scantable . scantable ;
const uint8_t * perm_scantable = s - > intra_scantable . permutated ;
int max = 0 ;
unsigned int threshold1 , threshold2 ;
int bias = 0 ;
int run_tab [ 65 ] ;
int level_tab [ 65 ] ;
int score_tab [ 65 ] ;
int survivor [ 65 ] ;
int survivor_count ;
int last_run = 0 ;
int last_level = 0 ;
int last_score = 0 ;
int last_i ;
int coeff [ 2 ] [ 64 ] ;
int coeff_count [ 64 ] ;
int qmul , qadd , start_i , last_non_zero , i , dc ;
const int esc_length = s - > ac_esc_length ;
uint8_t * length ;
uint8_t * last_length ;
const int lambda = s - > lambda2 > > ( FF_LAMBDA_SHIFT - 6 ) ;
s - > dsp . fdct ( block ) ;
if ( s - > dct_error_sum )
s - > denoise_dct ( s , block ) ;
qmul = qscale * 16 ;
qadd = ( ( qscale - 1 ) | 1 ) * 8 ;
if ( s - > mb_intra ) {
int q ;
if ( ! s - > h263_aic ) {
if ( n < 4 )
q = s - > y_dc_scale ;
else
q = s - > c_dc_scale ;
q = q < < 3 ;
} else {
/* For AIC we skip quant/dequant of INTRADC */
q = 1 < < 3 ;
qadd = 0 ;
}
/* note: block[0] is assumed to be positive */
block [ 0 ] = ( block [ 0 ] + ( q > > 1 ) ) / q ;
start_i = 1 ;
last_non_zero = 0 ;
qmat = s - > q_intra_matrix [ qscale ] ;
if ( s - > mpeg_quant | | s - > out_format = = FMT_MPEG1 )
bias = 1 < < ( QMAT_SHIFT - 1 ) ;
length = s - > intra_ac_vlc_length ;
last_length = s - > intra_ac_vlc_last_length ;
} else {
start_i = 0 ;
last_non_zero = - 1 ;
qmat = s - > q_inter_matrix [ qscale ] ;
length = s - > inter_ac_vlc_length ;
last_length = s - > inter_ac_vlc_last_length ;
}
last_i = start_i ;
threshold1 = ( 1 < < QMAT_SHIFT ) - bias - 1 ;
threshold2 = ( threshold1 < < 1 ) ;
for ( i = 63 ; i > = start_i ; i - - ) {
const int j = scantable [ i ] ;
int level = block [ j ] * qmat [ j ] ;
if ( ( ( unsigned ) ( level + threshold1 ) ) > threshold2 ) {
last_non_zero = i ;
break ;
}
}
for ( i = start_i ; i < = last_non_zero ; i + + ) {
const int j = scantable [ i ] ;
int level = block [ j ] * qmat [ j ] ;
// if( bias+level >= (1<<(QMAT_SHIFT - 3))
// || bias-level >= (1<<(QMAT_SHIFT - 3))){
if ( ( ( unsigned ) ( level + threshold1 ) ) > threshold2 ) {
if ( level > 0 ) {
level = ( bias + level ) > > QMAT_SHIFT ;
coeff [ 0 ] [ i ] = level ;
coeff [ 1 ] [ i ] = level - 1 ;
// coeff[2][k]= level-2;
} else {
level = ( bias - level ) > > QMAT_SHIFT ;
coeff [ 0 ] [ i ] = - level ;
coeff [ 1 ] [ i ] = - level + 1 ;
// coeff[2][k]= -level+2;
}
coeff_count [ i ] = FFMIN ( level , 2 ) ;
assert ( coeff_count [ i ] ) ;
max | = level ;
} else {
coeff [ 0 ] [ i ] = ( level > > 31 ) | 1 ;
coeff_count [ i ] = 1 ;
}
}
* overflow = s - > max_qcoeff < max ; //overflow might have happened
if ( last_non_zero < start_i ) {
memset ( block + start_i , 0 , ( 64 - start_i ) * sizeof ( DCTELEM ) ) ;
return last_non_zero ;
}
score_tab [ start_i ] = 0 ;
survivor [ 0 ] = start_i ;
survivor_count = 1 ;
for ( i = start_i ; i < = last_non_zero ; i + + ) {
2008-04-29 17:08:01 +03:00
int level_index , j , zero_distortion ;
2008-02-26 00:43:42 +02:00
int dct_coeff = FFABS ( block [ scantable [ i ] ] ) ;
2007-07-03 12:55:56 +03:00
int best_score = 256 * 256 * 256 * 120 ;
2008-02-26 00:43:42 +02:00
if ( s - > dsp . fdct = = fdct_ifast
# ifndef FAAN_POSTSCALE
| | s - > dsp . fdct = = ff_faandct
# endif
)
dct_coeff = ( dct_coeff * inv_aanscales [ scantable [ i ] ] ) > > 12 ;
2008-04-29 17:08:01 +03:00
zero_distortion = dct_coeff * dct_coeff ;
2008-02-26 00:43:42 +02:00
2007-07-03 12:55:56 +03:00
for ( level_index = 0 ; level_index < coeff_count [ i ] ; level_index + + ) {
2008-04-29 17:08:01 +03:00
int distortion ;
2007-07-03 12:55:56 +03:00
int level = coeff [ level_index ] [ i ] ;
const int alevel = FFABS ( level ) ;
int unquant_coeff ;
assert ( level ) ;
if ( s - > out_format = = FMT_H263 ) {
unquant_coeff = alevel * qmul + qadd ;
} else { //MPEG1
j = s - > dsp . idct_permutation [ scantable [ i ] ] ; //FIXME optimize
if ( s - > mb_intra ) {
unquant_coeff = ( int ) ( alevel * qscale * s - > intra_matrix [ j ] ) > > 3 ;
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
} else {
unquant_coeff = ( ( ( alevel < < 1 ) + 1 ) * qscale * ( ( int ) s - > inter_matrix [ j ] ) ) > > 4 ;
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
}
unquant_coeff < < = 3 ;
}
2008-04-29 17:08:01 +03:00
distortion = ( unquant_coeff - dct_coeff ) * ( unquant_coeff - dct_coeff ) - zero_distortion ;
2007-07-03 12:55:56 +03:00
level + = 64 ;
if ( ( level & ( ~ 127 ) ) = = 0 ) {
for ( j = survivor_count - 1 ; j > = 0 ; j - - ) {
int run = i - survivor [ j ] ;
2008-04-29 17:08:01 +03:00
int score = distortion + length [ UNI_AC_ENC_INDEX ( run , level ) ] * lambda ;
2007-07-03 12:55:56 +03:00
score + = score_tab [ i - run ] ;
if ( score < best_score ) {
best_score = score ;
run_tab [ i + 1 ] = run ;
level_tab [ i + 1 ] = level - 64 ;
}
}
if ( s - > out_format = = FMT_H263 ) {
for ( j = survivor_count - 1 ; j > = 0 ; j - - ) {
int run = i - survivor [ j ] ;
2008-04-29 17:08:01 +03:00
int score = distortion + last_length [ UNI_AC_ENC_INDEX ( run , level ) ] * lambda ;
2007-07-03 12:55:56 +03:00
score + = score_tab [ i - run ] ;
if ( score < last_score ) {
last_score = score ;
last_run = run ;
last_level = level - 64 ;
last_i = i + 1 ;
}
}
}
} else {
2008-04-29 17:08:01 +03:00
distortion + = esc_length * lambda ;
2007-07-03 12:55:56 +03:00
for ( j = survivor_count - 1 ; j > = 0 ; j - - ) {
int run = i - survivor [ j ] ;
2008-04-29 17:08:01 +03:00
int score = distortion + score_tab [ i - run ] ;
2007-07-03 12:55:56 +03:00
if ( score < best_score ) {
best_score = score ;
run_tab [ i + 1 ] = run ;
level_tab [ i + 1 ] = level - 64 ;
}
}
if ( s - > out_format = = FMT_H263 ) {
for ( j = survivor_count - 1 ; j > = 0 ; j - - ) {
int run = i - survivor [ j ] ;
2008-04-29 17:08:01 +03:00
int score = distortion + score_tab [ i - run ] ;
2007-07-03 12:55:56 +03:00
if ( score < last_score ) {
last_score = score ;
last_run = run ;
last_level = level - 64 ;
last_i = i + 1 ;
}
}
}
}
}
score_tab [ i + 1 ] = best_score ;
//Note: there is a vlc code in mpeg4 which is 1 bit shorter then another one with a shorter run and the same level
if ( last_non_zero < = 27 ) {
for ( ; survivor_count ; survivor_count - - ) {
if ( score_tab [ survivor [ survivor_count - 1 ] ] < = best_score )
break ;
}
} else {
for ( ; survivor_count ; survivor_count - - ) {
if ( score_tab [ survivor [ survivor_count - 1 ] ] < = best_score + lambda )
break ;
}
}
survivor [ survivor_count + + ] = i + 1 ;
}
if ( s - > out_format ! = FMT_H263 ) {
last_score = 256 * 256 * 256 * 120 ;
for ( i = survivor [ 0 ] ; i < = last_non_zero + 1 ; i + + ) {
int score = score_tab [ i ] ;
if ( i ) score + = lambda * 2 ; //FIXME exacter?
if ( score < last_score ) {
last_score = score ;
last_i = i ;
last_level = level_tab [ i ] ;
last_run = run_tab [ i ] ;
}
}
}
s - > coded_score [ n ] = last_score ;
dc = FFABS ( block [ 0 ] ) ;
last_non_zero = last_i - 1 ;
memset ( block + start_i , 0 , ( 64 - start_i ) * sizeof ( DCTELEM ) ) ;
if ( last_non_zero < start_i )
return last_non_zero ;
if ( last_non_zero = = 0 & & start_i = = 0 ) {
int best_level = 0 ;
int best_score = dc * dc ;
for ( i = 0 ; i < coeff_count [ 0 ] ; i + + ) {
int level = coeff [ i ] [ 0 ] ;
int alevel = FFABS ( level ) ;
int unquant_coeff , score , distortion ;
if ( s - > out_format = = FMT_H263 ) {
unquant_coeff = ( alevel * qmul + qadd ) > > 3 ;
} else { //MPEG1
unquant_coeff = ( ( ( alevel < < 1 ) + 1 ) * qscale * ( ( int ) s - > inter_matrix [ 0 ] ) ) > > 4 ;
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
}
unquant_coeff = ( unquant_coeff + 4 ) > > 3 ;
unquant_coeff < < = 3 + 3 ;
distortion = ( unquant_coeff - dc ) * ( unquant_coeff - dc ) ;
level + = 64 ;
if ( ( level & ( ~ 127 ) ) = = 0 ) score = distortion + last_length [ UNI_AC_ENC_INDEX ( 0 , level ) ] * lambda ;
else score = distortion + esc_length * lambda ;
if ( score < best_score ) {
best_score = score ;
best_level = level - 64 ;
}
}
block [ 0 ] = best_level ;
s - > coded_score [ n ] = best_score - dc * dc ;
if ( best_level = = 0 ) return - 1 ;
else return last_non_zero ;
}
i = last_i ;
assert ( last_level ) ;
block [ perm_scantable [ last_non_zero ] ] = last_level ;
i - = last_run + 1 ;
for ( ; i > start_i ; i - = run_tab [ i ] + 1 ) {
block [ perm_scantable [ i - 1 ] ] = level_tab [ i ] ;
}
return last_non_zero ;
}
//#define REFINE_STATS 1
static int16_t basis [ 64 ] [ 64 ] ;
static void build_basis ( uint8_t * perm ) {
int i , j , x , y ;
emms_c ( ) ;
for ( i = 0 ; i < 8 ; i + + ) {
for ( j = 0 ; j < 8 ; j + + ) {
for ( y = 0 ; y < 8 ; y + + ) {
for ( x = 0 ; x < 8 ; x + + ) {
double s = 0.25 * ( 1 < < BASIS_SHIFT ) ;
int index = 8 * i + j ;
int perm_index = perm [ index ] ;
if ( i = = 0 ) s * = sqrt ( 0.5 ) ;
if ( j = = 0 ) s * = sqrt ( 0.5 ) ;
basis [ perm_index ] [ 8 * x + y ] = lrintf ( s * cos ( ( M_PI / 8.0 ) * i * ( x + 0.5 ) ) * cos ( ( M_PI / 8.0 ) * j * ( y + 0.5 ) ) ) ;
}
}
}
}
}
static int dct_quantize_refine ( MpegEncContext * s , //FIXME breaks denoise?
DCTELEM * block , int16_t * weight , DCTELEM * orig ,
int n , int qscale ) {
int16_t rem [ 64 ] ;
DECLARE_ALIGNED_16 ( DCTELEM , d1 [ 64 ] ) ;
const int * qmat ;
const uint8_t * scantable = s - > intra_scantable . scantable ;
const uint8_t * perm_scantable = s - > intra_scantable . permutated ;
// unsigned int threshold1, threshold2;
// int bias=0;
int run_tab [ 65 ] ;
int prev_run = 0 ;
int prev_level = 0 ;
int qmul , qadd , start_i , last_non_zero , i , dc ;
uint8_t * length ;
uint8_t * last_length ;
int lambda ;
int rle_index , run , q = 1 , sum ; //q is only used when s->mb_intra is true
# ifdef REFINE_STATS
static int count = 0 ;
static int after_last = 0 ;
static int to_zero = 0 ;
static int from_zero = 0 ;
static int raise = 0 ;
static int lower = 0 ;
static int messed_sign = 0 ;
# endif
if ( basis [ 0 ] [ 0 ] = = 0 )
build_basis ( s - > dsp . idct_permutation ) ;
qmul = qscale * 2 ;
qadd = ( qscale - 1 ) | 1 ;
if ( s - > mb_intra ) {
if ( ! s - > h263_aic ) {
if ( n < 4 )
q = s - > y_dc_scale ;
else
q = s - > c_dc_scale ;
} else {
/* For AIC we skip quant/dequant of INTRADC */
q = 1 ;
qadd = 0 ;
}
q < < = RECON_SHIFT - 3 ;
/* note: block[0] is assumed to be positive */
dc = block [ 0 ] * q ;
// block[0] = (block[0] + (q >> 1)) / q;
start_i = 1 ;
qmat = s - > q_intra_matrix [ qscale ] ;
// if(s->mpeg_quant || s->out_format == FMT_MPEG1)
// bias= 1<<(QMAT_SHIFT-1);
length = s - > intra_ac_vlc_length ;
last_length = s - > intra_ac_vlc_last_length ;
} else {
dc = 0 ;
start_i = 0 ;
qmat = s - > q_inter_matrix [ qscale ] ;
length = s - > inter_ac_vlc_length ;
last_length = s - > inter_ac_vlc_last_length ;
}
last_non_zero = s - > block_last_index [ n ] ;
# ifdef REFINE_STATS
{ START_TIMER
# endif
dc + = ( 1 < < ( RECON_SHIFT - 1 ) ) ;
for ( i = 0 ; i < 64 ; i + + ) {
rem [ i ] = dc - ( orig [ i ] < < RECON_SHIFT ) ; //FIXME use orig dirrectly instead of copying to rem[]
}
# ifdef REFINE_STATS
STOP_TIMER ( " memset rem[] " ) }
# endif
sum = 0 ;
for ( i = 0 ; i < 64 ; i + + ) {
int one = 36 ;
int qns = 4 ;
int w ;
w = FFABS ( weight [ i ] ) + qns * one ;
w = 15 + ( 48 * qns * one + w / 2 ) / w ; // 16 .. 63
weight [ i ] = w ;
// w=weight[i] = (63*qns + (w/2)) / w;
assert ( w > 0 ) ;
assert ( w < ( 1 < < 6 ) ) ;
sum + = w * w ;
}
lambda = sum * ( uint64_t ) s - > lambda2 > > ( FF_LAMBDA_SHIFT - 6 + 6 + 6 + 6 ) ;
# ifdef REFINE_STATS
{ START_TIMER
# endif
run = 0 ;
rle_index = 0 ;
for ( i = start_i ; i < = last_non_zero ; i + + ) {
int j = perm_scantable [ i ] ;
const int level = block [ j ] ;
int coeff ;
if ( level ) {
if ( level < 0 ) coeff = qmul * level - qadd ;
else coeff = qmul * level + qadd ;
run_tab [ rle_index + + ] = run ;
run = 0 ;
s - > dsp . add_8x8basis ( rem , basis [ j ] , coeff ) ;
} else {
run + + ;
}
}
# ifdef REFINE_STATS
if ( last_non_zero > 0 ) {
STOP_TIMER ( " init rem[] " )
}
}
{ START_TIMER
# endif
for ( ; ; ) {
int best_score = s - > dsp . try_8x8basis ( rem , weight , basis [ 0 ] , 0 ) ;
int best_coeff = 0 ;
int best_change = 0 ;
int run2 , best_unquant_change = 0 , analyze_gradient ;
# ifdef REFINE_STATS
{ START_TIMER
# endif
analyze_gradient = last_non_zero > 2 | | s - > avctx - > quantizer_noise_shaping > = 3 ;
if ( analyze_gradient ) {
# ifdef REFINE_STATS
{ START_TIMER
# endif
for ( i = 0 ; i < 64 ; i + + ) {
int w = weight [ i ] ;
d1 [ i ] = ( rem [ i ] * w * w + ( 1 < < ( RECON_SHIFT + 12 - 1 ) ) ) > > ( RECON_SHIFT + 12 ) ;
}
# ifdef REFINE_STATS
STOP_TIMER ( " rem*w*w " ) }
{ START_TIMER
# endif
s - > dsp . fdct ( d1 ) ;
# ifdef REFINE_STATS
STOP_TIMER ( " dct " ) }
# endif
}
if ( start_i ) {
const int level = block [ 0 ] ;
int change , old_coeff ;
assert ( s - > mb_intra ) ;
old_coeff = q * level ;
for ( change = - 1 ; change < = 1 ; change + = 2 ) {
int new_level = level + change ;
int score , new_coeff ;
new_coeff = q * new_level ;
if ( new_coeff > = 2048 | | new_coeff < 0 )
continue ;
score = s - > dsp . try_8x8basis ( rem , weight , basis [ 0 ] , new_coeff - old_coeff ) ;
if ( score < best_score ) {
best_score = score ;
best_coeff = 0 ;
best_change = change ;
best_unquant_change = new_coeff - old_coeff ;
}
}
}
run = 0 ;
rle_index = 0 ;
run2 = run_tab [ rle_index + + ] ;
prev_level = 0 ;
prev_run = 0 ;
for ( i = start_i ; i < 64 ; i + + ) {
int j = perm_scantable [ i ] ;
const int level = block [ j ] ;
int change , old_coeff ;
if ( s - > avctx - > quantizer_noise_shaping < 3 & & i > last_non_zero + 1 )
break ;
if ( level ) {
if ( level < 0 ) old_coeff = qmul * level - qadd ;
else old_coeff = qmul * level + qadd ;
run2 = run_tab [ rle_index + + ] ; //FIXME ! maybe after last
} else {
old_coeff = 0 ;
run2 - - ;
assert ( run2 > = 0 | | i > = last_non_zero ) ;
}
for ( change = - 1 ; change < = 1 ; change + = 2 ) {
int new_level = level + change ;
int score , new_coeff , unquant_change ;
score = 0 ;
if ( s - > avctx - > quantizer_noise_shaping < 2 & & FFABS ( new_level ) > FFABS ( level ) )
continue ;
if ( new_level ) {
if ( new_level < 0 ) new_coeff = qmul * new_level - qadd ;
else new_coeff = qmul * new_level + qadd ;
if ( new_coeff > = 2048 | | new_coeff < = - 2048 )
continue ;
//FIXME check for overflow
if ( level ) {
if ( level < 63 & & level > - 63 ) {
if ( i < last_non_zero )
score + = length [ UNI_AC_ENC_INDEX ( run , new_level + 64 ) ]
- length [ UNI_AC_ENC_INDEX ( run , level + 64 ) ] ;
else
score + = last_length [ UNI_AC_ENC_INDEX ( run , new_level + 64 ) ]
- last_length [ UNI_AC_ENC_INDEX ( run , level + 64 ) ] ;
}
} else {
assert ( FFABS ( new_level ) = = 1 ) ;
if ( analyze_gradient ) {
int g = d1 [ scantable [ i ] ] ;
if ( g & & ( g ^ new_level ) > = 0 )
continue ;
}
if ( i < last_non_zero ) {
int next_i = i + run2 + 1 ;
int next_level = block [ perm_scantable [ next_i ] ] + 64 ;
if ( next_level & ( ~ 127 ) )
next_level = 0 ;
if ( next_i < last_non_zero )
score + = length [ UNI_AC_ENC_INDEX ( run , 65 ) ]
+ length [ UNI_AC_ENC_INDEX ( run2 , next_level ) ]
- length [ UNI_AC_ENC_INDEX ( run + run2 + 1 , next_level ) ] ;
else
score + = length [ UNI_AC_ENC_INDEX ( run , 65 ) ]
+ last_length [ UNI_AC_ENC_INDEX ( run2 , next_level ) ]
- last_length [ UNI_AC_ENC_INDEX ( run + run2 + 1 , next_level ) ] ;
} else {
score + = last_length [ UNI_AC_ENC_INDEX ( run , 65 ) ] ;
if ( prev_level ) {
score + = length [ UNI_AC_ENC_INDEX ( prev_run , prev_level ) ]
- last_length [ UNI_AC_ENC_INDEX ( prev_run , prev_level ) ] ;
}
}
}
} else {
new_coeff = 0 ;
assert ( FFABS ( level ) = = 1 ) ;
if ( i < last_non_zero ) {
int next_i = i + run2 + 1 ;
int next_level = block [ perm_scantable [ next_i ] ] + 64 ;
if ( next_level & ( ~ 127 ) )
next_level = 0 ;
if ( next_i < last_non_zero )
score + = length [ UNI_AC_ENC_INDEX ( run + run2 + 1 , next_level ) ]
- length [ UNI_AC_ENC_INDEX ( run2 , next_level ) ]
- length [ UNI_AC_ENC_INDEX ( run , 65 ) ] ;
else
score + = last_length [ UNI_AC_ENC_INDEX ( run + run2 + 1 , next_level ) ]
- last_length [ UNI_AC_ENC_INDEX ( run2 , next_level ) ]
- length [ UNI_AC_ENC_INDEX ( run , 65 ) ] ;
} else {
score + = - last_length [ UNI_AC_ENC_INDEX ( run , 65 ) ] ;
if ( prev_level ) {
score + = last_length [ UNI_AC_ENC_INDEX ( prev_run , prev_level ) ]
- length [ UNI_AC_ENC_INDEX ( prev_run , prev_level ) ] ;
}
}
}
score * = lambda ;
unquant_change = new_coeff - old_coeff ;
assert ( ( score < 100 * lambda & & score > - 100 * lambda ) | | lambda = = 0 ) ;
score + = s - > dsp . try_8x8basis ( rem , weight , basis [ j ] , unquant_change ) ;
if ( score < best_score ) {
best_score = score ;
best_coeff = i ;
best_change = change ;
best_unquant_change = unquant_change ;
}
}
if ( level ) {
prev_level = level + 64 ;
if ( prev_level & ( ~ 127 ) )
prev_level = 0 ;
prev_run = run ;
run = 0 ;
} else {
run + + ;
}
}
# ifdef REFINE_STATS
STOP_TIMER ( " iterative step " ) }
# endif
if ( best_change ) {
int j = perm_scantable [ best_coeff ] ;
block [ j ] + = best_change ;
if ( best_coeff > last_non_zero ) {
last_non_zero = best_coeff ;
assert ( block [ j ] ) ;
# ifdef REFINE_STATS
after_last + + ;
# endif
} else {
# ifdef REFINE_STATS
if ( block [ j ] ) {
if ( block [ j ] - best_change ) {
if ( FFABS ( block [ j ] ) > FFABS ( block [ j ] - best_change ) ) {
raise + + ;
} else {
lower + + ;
}
} else {
from_zero + + ;
}
} else {
to_zero + + ;
}
# endif
for ( ; last_non_zero > = start_i ; last_non_zero - - ) {
if ( block [ perm_scantable [ last_non_zero ] ] )
break ;
}
}
# ifdef REFINE_STATS
count + + ;
if ( 256 * 256 * 256 * 64 % count = = 0 ) {
printf ( " after_last:%d to_zero:%d from_zero:%d raise:%d lower:%d sign:%d xyp:%d/%d/%d \n " , after_last , to_zero , from_zero , raise , lower , messed_sign , s - > mb_x , s - > mb_y , s - > picture_number ) ;
}
# endif
run = 0 ;
rle_index = 0 ;
for ( i = start_i ; i < = last_non_zero ; i + + ) {
int j = perm_scantable [ i ] ;
const int level = block [ j ] ;
if ( level ) {
run_tab [ rle_index + + ] = run ;
run = 0 ;
} else {
run + + ;
}
}
s - > dsp . add_8x8basis ( rem , basis [ j ] , best_unquant_change ) ;
} else {
break ;
}
}
# ifdef REFINE_STATS
if ( last_non_zero > 0 ) {
STOP_TIMER ( " iterative search " )
}
}
# endif
return last_non_zero ;
}
int dct_quantize_c ( MpegEncContext * s ,
DCTELEM * block , int n ,
int qscale , int * overflow )
{
int i , j , level , last_non_zero , q , start_i ;
const int * qmat ;
const uint8_t * scantable = s - > intra_scantable . scantable ;
int bias ;
int max = 0 ;
unsigned int threshold1 , threshold2 ;
s - > dsp . fdct ( block ) ;
if ( s - > dct_error_sum )
s - > denoise_dct ( s , block ) ;
if ( s - > mb_intra ) {
if ( ! s - > h263_aic ) {
if ( n < 4 )
q = s - > y_dc_scale ;
else
q = s - > c_dc_scale ;
q = q < < 3 ;
} else
/* For AIC we skip quant/dequant of INTRADC */
q = 1 < < 3 ;
/* note: block[0] is assumed to be positive */
block [ 0 ] = ( block [ 0 ] + ( q > > 1 ) ) / q ;
start_i = 1 ;
last_non_zero = 0 ;
qmat = s - > q_intra_matrix [ qscale ] ;
bias = s - > intra_quant_bias < < ( QMAT_SHIFT - QUANT_BIAS_SHIFT ) ;
} else {
start_i = 0 ;
last_non_zero = - 1 ;
qmat = s - > q_inter_matrix [ qscale ] ;
bias = s - > inter_quant_bias < < ( QMAT_SHIFT - QUANT_BIAS_SHIFT ) ;
}
threshold1 = ( 1 < < QMAT_SHIFT ) - bias - 1 ;
threshold2 = ( threshold1 < < 1 ) ;
for ( i = 63 ; i > = start_i ; i - - ) {
j = scantable [ i ] ;
level = block [ j ] * qmat [ j ] ;
if ( ( ( unsigned ) ( level + threshold1 ) ) > threshold2 ) {
last_non_zero = i ;
break ;
} else {
block [ j ] = 0 ;
}
}
for ( i = start_i ; i < = last_non_zero ; i + + ) {
j = scantable [ i ] ;
level = block [ j ] * qmat [ j ] ;
// if( bias+level >= (1<<QMAT_SHIFT)
// || bias-level >= (1<<QMAT_SHIFT)){
if ( ( ( unsigned ) ( level + threshold1 ) ) > threshold2 ) {
if ( level > 0 ) {
level = ( bias + level ) > > QMAT_SHIFT ;
block [ j ] = level ;
} else {
level = ( bias - level ) > > QMAT_SHIFT ;
block [ j ] = - level ;
}
max | = level ;
} else {
block [ j ] = 0 ;
}
}
* overflow = s - > max_qcoeff < max ; //overflow might have happened
/* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */
if ( s - > dsp . idct_permutation_type ! = FF_NO_IDCT_PERM )
ff_block_permute ( block , s - > dsp . idct_permutation , scantable , last_non_zero ) ;
return last_non_zero ;
}
AVCodec h263_encoder = {
" h263 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_H263 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " H.263 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec h263p_encoder = {
" h263p " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_H263P ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " H.263+ / H.263 version 2 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec flv_encoder = {
" flv " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_FLV1 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " Flash Video " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec rv10_encoder = {
" rv10 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_RV10 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " RealVideo 1.0 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec rv20_encoder = {
" rv20 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_RV20 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " RealVideo 2.0 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec mpeg4_encoder = {
" mpeg4 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MPEG4 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2007-07-03 12:55:56 +03:00
. capabilities = CODEC_CAP_DELAY ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " MPEG-4 part 2 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec msmpeg4v1_encoder = {
" msmpeg4v1 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MSMPEG4V1 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " MPEG-4 part 2 Microsoft variant version 1 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec msmpeg4v2_encoder = {
" msmpeg4v2 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MSMPEG4V2 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " MPEG-4 part 2 Microsoft variant version 2 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec msmpeg4v3_encoder = {
" msmpeg4 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MSMPEG4V3 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " MPEG-4 part 2 Microsoft variant version 3 " ) ,
2007-07-03 12:55:56 +03:00
} ;
AVCodec wmv1_encoder = {
" wmv1 " ,
CODEC_TYPE_VIDEO ,
CODEC_ID_WMV1 ,
sizeof ( MpegEncContext ) ,
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2008-05-12 01:28:43 +03:00
. pix_fmts = ( enum PixelFormat [ ] ) { PIX_FMT_YUV420P , PIX_FMT_NONE } ,
2008-06-13 00:50:13 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " Windows Media Video 7 " ) ,
2007-07-03 12:55:56 +03:00
} ;