2001-07-22 14:18:56 +00:00
/*
* The simplest mpeg encoder (well, it was the simplest!)
2002-05-25 22:45:33 +00:00
* Copyright (c) 2000,2001 Fabrice Bellard.
2004-01-10 16:04:55 +00:00
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
2001-07-22 14:18:56 +00:00
*
2002-05-25 22:45:33 +00:00
* This library 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 of the License, or (at your option) any later version.
2001-07-22 14:18:56 +00:00
*
2002-05-25 22:45:33 +00:00
* This library is distributed in the hope that it will be useful,
2001-07-22 14:18:56 +00:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2002-05-25 22:45:33 +00:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2001-07-22 14:18:56 +00:00
*
2002-05-25 22:45:33 +00:00
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
2006-01-12 22:43:26 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2002-03-28 04:25:35 +00:00
*
2002-04-17 16:30:31 +00:00
* 4MV & hq & b-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
2001-07-22 14:18:56 +00:00
*/
2005-12-17 18:14:38 +00:00
2003-03-06 11:32:04 +00:00
/**
* @file mpegvideo.c
* The simplest mpeg encoder (well, it was the simplest!).
2005-12-17 18:14:38 +00:00
*/
2001-07-22 14:18:56 +00:00
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
2003-10-22 18:26:38 +00:00
#include "faandct.h"
2004-05-18 17:09:46 +00:00
#include <limits.h>
2001-07-22 14:18:56 +00:00
2001-08-02 08:29:38 +00:00
#ifdef USE_FASTMEMCPY
2006-08-18 13:38:24 +00:00
#include "libvo/fastmemcpy.h"
2001-08-02 08:29:38 +00:00
#endif
2003-08-25 22:54:53 +00:00
//#undef NDEBUG
//#include <assert.h>
2002-09-29 22:44:22 +00:00
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2006-09-26 14:04:36 +00:00
static int encode_picture ( MpegEncContext * s , int picture_number );
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg1_intra_c ( MpegEncContext * s ,
2001-07-30 23:26:26 +00:00
DCTELEM * block , int n , int qscale );
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg1_inter_c ( MpegEncContext * s ,
2002-04-17 16:30:31 +00:00
DCTELEM * block , int n , int qscale );
2003-12-14 02:57:00 +00:00
static void dct_unquantize_mpeg2_intra_c ( MpegEncContext * s ,
DCTELEM * block , int n , int qscale );
2006-04-28 17:03:52 +00:00
static void dct_unquantize_mpeg2_intra_bitexact ( MpegEncContext * s ,
DCTELEM * block , int n , int qscale );
2003-12-14 02:57:00 +00:00
static void dct_unquantize_mpeg2_inter_c ( MpegEncContext * s ,
DCTELEM * block , int n , int qscale );
2005-12-17 18:14:38 +00:00
static void dct_unquantize_h263_intra_c ( MpegEncContext * s ,
2003-12-14 02:57:00 +00:00
DCTELEM * block , int n , int qscale );
2005-12-17 18:14:38 +00:00
static void dct_unquantize_h263_inter_c ( MpegEncContext * s ,
2001-07-30 23:26:26 +00:00
DCTELEM * block , int n , int qscale );
2003-02-11 16:35:48 +00:00
static void draw_edges_c ( uint8_t * buf , int wrap , int width , int height , int w );
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2002-04-27 12:30:26 +00:00
static int dct_quantize_c ( MpegEncContext * s , DCTELEM * block , int n , int qscale , int * overflow );
2002-12-31 17:23:56 +00:00
static int dct_quantize_trellis_c ( MpegEncContext * s , DCTELEM * block , int n , int qscale , int * overflow );
2004-02-02 03:52:58 +00:00
static int dct_quantize_refine ( MpegEncContext * s , DCTELEM * block , int16_t * weight , DCTELEM * orig , int n , int qscale );
2003-07-29 02:09:12 +00:00
static int sse_mb ( MpegEncContext * s );
2004-01-02 22:29:08 +00:00
static void denoise_dct_c ( MpegEncContext * s , DCTELEM * block );
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2002-01-15 04:07:29 +00:00
2003-07-26 01:28:49 +00:00
#ifdef HAVE_XVMC
extern int XVMC_field_start ( MpegEncContext * s , AVCodecContext * avctx );
extern void XVMC_field_end ( MpegEncContext * s );
2003-10-27 23:22:43 +00:00
extern void XVMC_decode_mb ( MpegEncContext * s );
2003-07-26 01:28:49 +00:00
#endif
2003-02-11 16:35:48 +00:00
void ( * draw_edges )( uint8_t * buf , int wrap , int width , int height , int w ) = draw_edges_c ;
2002-01-15 04:07:29 +00:00
2001-07-22 14:18:56 +00:00
/* enable all paranoid tests for rounding, overflows, etc... */
//#define PARANOID
//#define DEBUG
2002-04-14 22:17:40 +00:00
2001-07-22 14:18:56 +00:00
/* for jpeg fast DCT */
#define CONST_BITS 14
2002-11-11 09:40:17 +00:00
static const uint16_t aanscales [ 64 ] = {
2001-07-22 14:18:56 +00:00
/* 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 ,
2002-12-27 23:51:46 +00:00
8867 , 12299 , 11585 , 10426 , 8867 , 6967 , 4799 , 2446 ,
4520 , 6270 , 5906 , 5315 , 4520 , 3552 , 2446 , 1247
2001-07-22 14:18:56 +00:00
};
2002-11-11 09:40:17 +00:00
static const uint8_t h263_chroma_roundtab [ 16 ] = {
2003-01-19 17:55:13 +00:00
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2001-07-22 14:18:56 +00:00
0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 ,
};
2003-12-01 15:23:14 +00:00
static const uint8_t ff_default_chroma_qscale_table [ 32 ] = {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31
};
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2003-03-31 11:13:14 +00:00
static uint8_t ( * default_mv_penalty )[ MAX_MV * 2 + 1 ] = NULL ;
2003-02-11 16:35:48 +00:00
static uint8_t default_fcode_tab [ MAX_MV * 2 + 1 ];
2002-03-22 02:21:17 +00:00
2003-01-12 00:48:29 +00:00
enum PixelFormat ff_yuv420p_list [ 2 ] = { PIX_FMT_YUV420P , - 1 };
2003-10-27 14:37:30 +00:00
static void convert_matrix ( DSPContext * dsp , int ( * qmat )[ 64 ], uint16_t ( * qmat16 )[ 2 ][ 64 ],
2004-12-11 18:33:18 +00:00
const uint16_t * quant_matrix , int bias , int qmin , int qmax , int intra )
2001-07-22 14:18:56 +00:00
{
2002-04-27 12:30:26 +00:00
int qscale ;
2004-12-11 18:33:18 +00:00
int shift = 0 ;
2001-07-22 14:18:56 +00:00
2002-09-30 09:19:54 +00:00
for ( qscale = qmin ; qscale <= qmax ; qscale ++ ){
2002-04-27 12:30:26 +00:00
int i ;
2005-12-17 18:14:38 +00:00
if ( dsp -> fdct == ff_jpeg_fdct_islow
2003-10-23 09:11:56 +00:00
#ifdef FAAN_POSTSCALE
2003-10-27 14:37:30 +00:00
|| dsp -> fdct == ff_faandct
2003-10-23 09:11:56 +00:00
#endif
) {
2002-08-29 23:55:32 +00:00
for ( i = 0 ; i < 64 ; i ++ ) {
2003-10-27 14:37:30 +00:00
const int j = dsp -> idct_permutation [ i ];
2002-08-29 23:55:32 +00:00
/* 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 */
2005-12-17 18:14:38 +00:00
qmat [ qscale ][ i ] = ( int )(( uint64_t_C ( 1 ) << QMAT_SHIFT ) /
2002-08-29 23:55:32 +00:00
( qscale * quant_matrix [ j ]));
}
2003-10-27 14:37:30 +00:00
} else if ( dsp -> fdct == fdct_ifast
2003-10-23 09:11:56 +00:00
#ifndef FAAN_POSTSCALE
2003-10-27 14:37:30 +00:00
|| dsp -> fdct == ff_faandct
2003-10-23 09:11:56 +00:00
#endif
) {
2002-04-27 12:30:26 +00:00
for ( i = 0 ; i < 64 ; i ++ ) {
2003-10-27 14:37:30 +00:00
const int j = dsp -> idct_permutation [ i ];
2002-04-27 12:30:26 +00:00
/* 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 */
2005-12-17 18:14:38 +00:00
qmat [ qscale ][ i ] = ( int )(( uint64_t_C ( 1 ) << ( QMAT_SHIFT + 14 )) /
2002-04-27 12:30:26 +00:00
( aanscales [ i ] * qscale * quant_matrix [ j ]));
}
} else {
for ( i = 0 ; i < 64 ; i ++ ) {
2003-10-27 14:37:30 +00:00
const int j = dsp -> idct_permutation [ i ];
2002-04-27 12:30:26 +00:00
/* 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
*/
2003-02-11 16:35:48 +00:00
qmat [ qscale ][ i ] = ( int )(( uint64_t_C ( 1 ) << QMAT_SHIFT ) / ( qscale * quant_matrix [ j ]));
2002-12-31 17:23:56 +00:00
// qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]);
2003-10-22 11:23:39 +00:00
qmat16 [ qscale ][ 0 ][ i ] = ( 1 << QMAT_SHIFT_MMX ) / ( qscale * quant_matrix [ j ]);
2002-04-27 12:30:26 +00:00
2003-10-22 11:23:39 +00:00
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 ]);
2002-04-27 12:30:26 +00:00
}
2001-07-22 14:18:56 +00:00
}
2005-12-17 18:14:38 +00:00
2004-12-11 18:33:18 +00:00
for ( i = intra ; i < 64 ; i ++ ){
2004-12-14 20:17:23 +00:00
int64_t max = 8191 ;
if ( dsp -> fdct == fdct_ifast
#ifndef FAAN_POSTSCALE
|| dsp -> fdct == ff_faandct
#endif
) {
max = ( 8191LL * aanscales [ i ]) >> 14 ;
}
2005-12-17 18:14:38 +00:00
while ((( max * qmat [ qscale ][ i ]) >> shift ) > INT_MAX ){
2004-12-11 18:33:18 +00:00
shift ++ ;
}
}
}
if ( shift ){
av_log ( NULL , AV_LOG_INFO , "Warning, QMAT_SHIFT is larger then %d, overflows possible \n " , QMAT_SHIFT - shift );
2001-07-22 14:18:56 +00:00
}
}
2003-10-07 11:32:40 +00:00
static inline void update_qscale ( MpegEncContext * s ){
s -> qscale = ( s -> lambda * 139 + FF_LAMBDA_SCALE * 64 ) >> ( FF_LAMBDA_SHIFT + 7 );
s -> qscale = clip ( s -> qscale , s -> avctx -> qmin , s -> avctx -> qmax );
2005-12-17 18:14:38 +00:00
2003-10-07 11:32:40 +00:00
s -> lambda2 = ( s -> lambda * s -> lambda + FF_LAMBDA_SCALE / 2 ) >> FF_LAMBDA_SHIFT ;
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2003-05-19 13:30:59 +00:00
void ff_init_scantable ( uint8_t * permutation , ScanTable * st , const uint8_t * src_scantable ){
2002-09-29 22:44:22 +00:00
int i ;
int end ;
2005-12-17 18:14:38 +00:00
2002-10-23 15:11:07 +00:00
st -> scantable = src_scantable ;
2002-09-29 22:44:22 +00:00
for ( i = 0 ; i < 64 ; i ++ ){
int j ;
j = src_scantable [ i ];
2003-05-19 13:30:59 +00:00
st -> permutated [ i ] = permutation [ j ];
2002-11-02 11:28:08 +00:00
#ifdef ARCH_POWERPC
st -> inverse [ j ] = i ;
#endif
2002-09-29 22:44:22 +00:00
}
2005-12-17 18:14:38 +00:00
2002-09-29 22:44:22 +00:00
end =- 1 ;
for ( i = 0 ; i < 64 ; i ++ ){
int j ;
j = st -> permutated [ i ];
if ( j > end ) end = j ;
st -> raster_end [ i ] = end ;
}
}
2003-10-14 04:15:53 +00:00
#ifdef CONFIG_ENCODERS
2006-09-27 19:47:39 +00:00
void ff_write_quant_matrix ( PutBitContext * pb , uint16_t * matrix ){
2003-08-22 22:18:08 +00:00
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 );
}
2003-10-14 04:15:53 +00:00
#endif //CONFIG_ENCODERS
2003-08-22 22:18:08 +00:00
2006-02-04 20:32:02 +00:00
const uint8_t * ff_find_start_code ( const uint8_t * restrict p , const uint8_t * end , uint32_t * restrict state ){
int i ;
2006-02-06 11:21:26 +00:00
assert ( p <= end );
if ( p >= end )
return end ;
2006-02-04 20:32:02 +00:00
for ( i = 0 ; i < 3 ; i ++ ){
uint32_t tmp = * state << 8 ;
* state = tmp + * ( p ++ );
if ( tmp == 0x100 || p == end )
return p ;
}
while ( p < end ){
2006-02-04 22:18:45 +00:00
if ( p [ - 1 ] > 1 ) p += 3 ;
else if ( p [ - 2 ] ) p += 2 ;
else if ( p [ - 3 ] | ( p [ - 1 ] - 1 )) p ++ ;
2006-02-04 20:32:02 +00:00
else {
p ++ ;
break ;
}
}
2006-02-04 22:18:45 +00:00
p = FFMIN ( p , end ) - 4 ;
2006-02-04 20:32:02 +00:00
* state = be2me_32 ( unaligned32 ( p ));
return p + 4 ;
}
2002-10-04 20:59:29 +00:00
/* init common dct for both encoder and decoder */
int DCT_common_init ( MpegEncContext * s )
2001-07-22 14:18:56 +00:00
{
2003-12-14 02:57:00 +00:00
s -> dct_unquantize_h263_intra = dct_unquantize_h263_intra_c ;
s -> dct_unquantize_h263_inter = dct_unquantize_h263_inter_c ;
s -> dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c ;
s -> dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c ;
s -> dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c ;
2006-04-28 17:03:52 +00:00
if ( s -> flags & CODEC_FLAG_BITEXACT )
s -> dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact ;
2003-12-14 02:57:00 +00:00
s -> dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c ;
2003-03-03 14:54:00 +00:00
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2002-08-29 23:55:32 +00:00
s -> dct_quantize = dct_quantize_c ;
2004-01-02 22:29:08 +00:00
s -> denoise_dct = denoise_dct_c ;
2005-04-19 04:29:11 +00:00
#endif //CONFIG_ENCODERS
2005-12-17 18:14:38 +00:00
2001-07-30 23:26:26 +00:00
#ifdef HAVE_MMX
2003-08-25 22:54:53 +00:00
MPV_common_init_mmx ( s );
2002-07-03 03:01:06 +00:00
#endif
#ifdef ARCH_ALPHA
MPV_common_init_axp ( s );
2001-07-30 09:04:34 +00:00
#endif
2002-08-30 18:17:20 +00:00
#ifdef HAVE_MLIB
MPV_common_init_mlib ( s );
#endif
2002-10-03 20:57:19 +00:00
#ifdef HAVE_MMI
MPV_common_init_mmi ( s );
#endif
2002-10-06 15:27:01 +00:00
#ifdef ARCH_ARMV4L
2002-11-19 07:33:36 +00:00
MPV_common_init_armv4l ( s );
2002-10-06 15:27:01 +00:00
#endif
2002-11-02 11:28:08 +00:00
#ifdef ARCH_POWERPC
MPV_common_init_ppc ( s );
#endif
2002-10-06 15:27:01 +00:00
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2003-01-15 18:05:23 +00:00
s -> fast_dct_quantize = s -> dct_quantize ;
2002-12-31 17:23:56 +00:00
if ( s -> flags & CODEC_FLAG_TRELLIS_QUANT ){
s -> dct_quantize = dct_quantize_trellis_c ; //move before MPV_common_init_*
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2002-09-29 22:44:22 +00:00
/* load & permutate scantables
2005-12-17 18:14:38 +00:00
note: only wmv uses different ones
2002-09-29 22:44:22 +00:00
*/
2003-12-30 16:07:57 +00:00
if ( s -> alternate_scan ){
ff_init_scantable ( s -> dsp . idct_permutation , & s -> inter_scantable , ff_alternate_vertical_scan );
ff_init_scantable ( s -> dsp . idct_permutation , & s -> intra_scantable , ff_alternate_vertical_scan );
} else {
ff_init_scantable ( s -> dsp . idct_permutation , & s -> inter_scantable , ff_zigzag_direct );
ff_init_scantable ( s -> dsp . idct_permutation , & s -> intra_scantable , ff_zigzag_direct );
}
2003-05-19 13:30:59 +00:00
ff_init_scantable ( s -> dsp . idct_permutation , & s -> intra_h_scantable , ff_alternate_horizontal_scan );
ff_init_scantable ( s -> dsp . idct_permutation , & s -> intra_v_scantable , ff_alternate_vertical_scan );
2002-08-02 20:27:46 +00:00
2002-10-04 20:59:29 +00:00
return 0 ;
}
2003-10-16 00:21:54 +00:00
static void copy_picture ( Picture * dst , Picture * src ){
* dst = * src ;
dst -> type = FF_BUFFER_TYPE_COPY ;
}
2006-09-27 19:54:07 +00:00
#ifdef CONFIG_ENCODERS
2004-04-16 01:01:45 +00:00
static void copy_picture_attributes ( MpegEncContext * s , AVFrame * dst , AVFrame * src ){
int i ;
2003-12-22 19:06:01 +00:00
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 ;
2004-04-16 01:01:45 +00:00
2004-04-17 19:41:49 +00:00
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 " );
2004-04-16 01:01:45 +00:00
if ( src -> motion_subsample_log2 != dst -> motion_subsample_log2 )
2005-04-24 11:13:49 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "AVFrame.motion_subsample_log2 doesn't match! (%d!=%d) \n " ,
2004-04-23 19:06:30 +00:00
src -> motion_subsample_log2 , dst -> motion_subsample_log2 );
2004-04-17 19:41:49 +00:00
memcpy ( dst -> mb_type , src -> mb_type , s -> mb_stride * s -> mb_height * sizeof ( dst -> mb_type [ 0 ]));
2005-12-17 18:14:38 +00:00
2004-04-17 19:41:49 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
2004-04-16 01:01:45 +00:00
int stride = (( 16 * s -> mb_width ) >> src -> motion_subsample_log2 ) + 1 ;
int height = (( 16 * s -> mb_height ) >> src -> motion_subsample_log2 );
2004-04-17 19:41:49 +00:00
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 ]){
2004-04-19 03:33:23 +00:00
memcpy ( dst -> ref_index [ i ], src -> ref_index [ i ], s -> b8_stride * 2 * s -> mb_height * sizeof ( int8_t ));
2004-04-17 19:41:49 +00:00
}
2004-04-16 01:01:45 +00:00
}
}
2003-12-22 19:06:01 +00:00
}
2006-09-27 19:54:07 +00:00
#endif
2003-12-22 19:06:01 +00:00
2002-12-04 10:04:03 +00:00
/**
2002-12-09 00:29:17 +00:00
* allocates a Picture
* The pixels are allocated/set by calling get_buffer() if shared=0
2002-12-04 10:04:03 +00:00
*/
2002-12-09 00:29:17 +00:00
static int alloc_picture ( MpegEncContext * s , Picture * pic , int shared ){
2003-04-10 13:18:38 +00:00
const int big_mb_num = s -> mb_stride * ( s -> mb_height + 1 ) + 1 ; //the +1 is needed so memset(,,stride*height) doesnt sig11
const int mb_array_size = s -> mb_stride * s -> mb_height ;
2003-12-04 18:34:47 +00:00
const int b8_array_size = s -> b8_stride * s -> mb_height * 2 ;
const int b4_array_size = s -> b4_stride * s -> mb_height * 4 ;
2003-04-04 14:42:28 +00:00
int i ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( shared ){
assert ( pic -> data [ 0 ]);
assert ( pic -> type == 0 || pic -> type == FF_BUFFER_TYPE_SHARED );
pic -> type = FF_BUFFER_TYPE_SHARED ;
} else {
int r ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
assert ( ! pic -> data [ 0 ]);
2005-12-17 18:14:38 +00:00
2002-12-09 12:03:43 +00:00
r = s -> avctx -> get_buffer ( s -> avctx , ( AVFrame * ) pic );
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( r < 0 || ! pic -> age || ! pic -> type || ! pic -> data [ 0 ]){
2005-12-22 01:10:11 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "get_buffer() failed (%d %d %d %p) \n " , r , pic -> age , pic -> type , pic -> data [ 0 ]);
2002-12-09 00:29:17 +00:00
return - 1 ;
}
2002-12-04 10:04:03 +00:00
2002-12-09 00:29:17 +00:00
if ( s -> linesize && ( s -> linesize != pic -> linesize [ 0 ] || s -> uvlinesize != pic -> linesize [ 1 ])){
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "get_buffer() failed (stride changed) \n " );
2002-12-09 00:29:17 +00:00
return - 1 ;
}
if ( pic -> linesize [ 1 ] != pic -> linesize [ 2 ]){
2005-06-17 15:02:53 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "get_buffer() failed (uv stride mismatch) \n " );
2002-12-09 00:29:17 +00:00
return - 1 ;
}
s -> linesize = pic -> linesize [ 0 ];
s -> uvlinesize = pic -> linesize [ 1 ];
}
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( pic -> qscale_table == NULL ){
2005-12-17 18:14:38 +00:00
if ( s -> encoding ) {
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( pic -> mb_var , mb_array_size * sizeof ( int16_t ))
CHECKED_ALLOCZ ( pic -> mc_mb_var , mb_array_size * sizeof ( int16_t ))
CHECKED_ALLOCZ ( pic -> mb_mean , mb_array_size * sizeof ( int8_t ))
2002-12-09 00:29:17 +00:00
}
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( pic -> mbskip_table , mb_array_size * sizeof ( uint8_t ) + 2 ) //the +2 is for the slice end check
2003-08-25 22:54:53 +00:00
CHECKED_ALLOCZ ( pic -> qscale_table , mb_array_size * sizeof ( uint8_t ))
2004-01-12 22:39:19 +00:00
CHECKED_ALLOCZ ( pic -> mb_type_base , big_mb_num * sizeof ( uint32_t ))
2003-04-10 13:18:38 +00:00
pic -> mb_type = pic -> mb_type_base + s -> mb_stride + 1 ;
2003-04-04 14:42:28 +00:00
if ( s -> out_format == FMT_H264 ){
for ( i = 0 ; i < 2 ; i ++ ){
2005-03-19 13:10:09 +00:00
CHECKED_ALLOCZ ( pic -> motion_val_base [ i ], 2 * ( b4_array_size + 4 ) * sizeof ( int16_t ))
pic -> motion_val [ i ] = pic -> motion_val_base [ i ] + 4 ;
2004-04-19 03:33:23 +00:00
CHECKED_ALLOCZ ( pic -> ref_index [ i ], b8_array_size * sizeof ( uint8_t ))
2003-12-04 18:34:47 +00:00
}
2003-12-09 01:55:54 +00:00
pic -> motion_subsample_log2 = 2 ;
2003-12-30 02:12:12 +00:00
} else if ( s -> out_format == FMT_H263 || s -> encoding || ( s -> avctx -> debug & FF_DEBUG_MV ) || ( s -> avctx -> debug_mv )){
2003-12-04 18:34:47 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
2005-03-19 13:10:09 +00:00
CHECKED_ALLOCZ ( pic -> motion_val_base [ i ], 2 * ( b8_array_size + 4 ) * sizeof ( int16_t ))
pic -> motion_val [ i ] = pic -> motion_val_base [ i ] + 4 ;
2004-04-19 03:33:23 +00:00
CHECKED_ALLOCZ ( pic -> ref_index [ i ], b8_array_size * sizeof ( uint8_t ))
2003-04-04 14:42:28 +00:00
}
2003-12-09 01:55:54 +00:00
pic -> motion_subsample_log2 = 3 ;
2003-04-04 14:42:28 +00:00
}
2004-02-25 18:29:17 +00:00
if ( s -> avctx -> debug & FF_DEBUG_DCT_COEFF ) {
CHECKED_ALLOCZ ( pic -> dct_coeff , 64 * mb_array_size * sizeof ( DCTELEM ) * 6 )
}
2003-04-10 13:18:38 +00:00
pic -> qstride = s -> mb_stride ;
2003-10-20 09:52:02 +00:00
CHECKED_ALLOCZ ( pic -> pan_scan , 1 * sizeof ( AVPanScan ))
2002-12-09 00:29:17 +00:00
}
2003-04-04 14:42:28 +00:00
2003-01-20 20:37:24 +00:00
//it might be nicer if the application would keep track of these but it would require a API change
memmove ( s -> prev_pict_types + 1 , s -> prev_pict_types , PREV_PICT_TYPES_BUFFER_SIZE - 1 );
s -> prev_pict_types [ 0 ] = s -> pict_type ;
if ( pic -> age < PREV_PICT_TYPES_BUFFER_SIZE && s -> prev_pict_types [ pic -> age ] == B_TYPE )
2005-04-24 17:21:11 +00:00
pic -> age = INT_MAX ; // skipped MBs in b frames are quite rare in mpeg1/2 and its a bit tricky to skip them anyway
2005-12-17 18:14:38 +00:00
2002-12-04 10:04:03 +00:00
return 0 ;
fail : //for the CHECKED_ALLOCZ macro
return - 1 ;
}
2002-12-09 00:29:17 +00:00
/**
* deallocates a picture
*/
2002-12-04 10:04:03 +00:00
static void free_picture ( MpegEncContext * s , Picture * pic ){
int i ;
2002-12-09 00:29:17 +00:00
if ( pic -> data [ 0 ] && pic -> type != FF_BUFFER_TYPE_SHARED ){
2002-12-09 12:03:43 +00:00
s -> avctx -> release_buffer ( s -> avctx , ( AVFrame * ) pic );
2002-12-09 00:29:17 +00:00
}
2002-12-04 10:04:03 +00:00
av_freep ( & pic -> mb_var );
av_freep ( & pic -> mc_mb_var );
av_freep ( & pic -> mb_mean );
av_freep ( & pic -> mbskip_table );
av_freep ( & pic -> qscale_table );
2003-04-04 14:42:28 +00:00
av_freep ( & pic -> mb_type_base );
2004-02-25 18:29:17 +00:00
av_freep ( & pic -> dct_coeff );
2003-10-20 09:52:02 +00:00
av_freep ( & pic -> pan_scan );
2003-04-04 14:42:28 +00:00
pic -> mb_type = NULL ;
for ( i = 0 ; i < 2 ; i ++ ){
2003-12-04 18:34:47 +00:00
av_freep ( & pic -> motion_val_base [ i ]);
2003-04-04 14:42:28 +00:00
av_freep ( & pic -> ref_index [ i ]);
}
2005-12-17 18:14:38 +00:00
2003-04-25 00:29:48 +00:00
if ( pic -> type == FF_BUFFER_TYPE_SHARED ){
2002-12-09 00:29:17 +00:00
for ( i = 0 ; i < 4 ; i ++ ){
pic -> base [ i ] =
pic -> data [ i ] = NULL ;
}
2005-12-17 18:14:38 +00:00
pic -> type = 0 ;
2002-12-04 10:04:03 +00:00
}
}
2004-02-13 17:54:10 +00:00
static int init_duplicate_context ( MpegEncContext * s , MpegEncContext * base ){
int i ;
2005-12-17 18:14:38 +00:00
// edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264)
2006-05-28 22:44:14 +00:00
CHECKED_ALLOCZ ( s -> allocated_edge_emu_buffer , ( s -> width + 64 ) * 2 * 21 * 2 ); //(width + edge + align)*interlaced*MBsize*tolerance
s -> edge_emu_buffer = s -> allocated_edge_emu_buffer + ( s -> width + 64 ) * 2 * 21 ;
2004-02-13 17:54:10 +00:00
//FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer()
2005-12-17 18:14:38 +00:00
CHECKED_ALLOCZ ( s -> me . scratchpad , ( s -> width + 64 ) * 4 * 16 * 2 * sizeof ( uint8_t ))
2004-02-13 17:54:10 +00:00
s -> rd_scratchpad = s -> me . scratchpad ;
s -> b_scratchpad = s -> me . scratchpad ;
s -> obmc_scratchpad = s -> me . scratchpad + 16 ;
if ( s -> encoding ) {
CHECKED_ALLOCZ ( s -> me . map , ME_MAP_SIZE * sizeof ( uint32_t ))
CHECKED_ALLOCZ ( s -> me . score_map , ME_MAP_SIZE * sizeof ( uint32_t ))
if ( s -> avctx -> noise_reduction ){
CHECKED_ALLOCZ ( s -> dct_error_sum , 2 * 64 * sizeof ( int ))
}
2005-12-17 18:14:38 +00:00
}
2004-03-01 14:55:21 +00:00
CHECKED_ALLOCZ ( s -> blocks , 64 * 12 * 2 * sizeof ( DCTELEM ))
2004-02-13 17:54:10 +00:00
s -> block = s -> blocks [ 0 ];
for ( i = 0 ; i < 12 ; i ++ ){
s -> pblocks [ i ] = ( short * )( & s -> block [ i ]);
}
return 0 ;
fail :
return - 1 ; //free() through MPV_common_end()
}
static void free_duplicate_context ( MpegEncContext * s ){
if ( s == NULL ) return ;
av_freep ( & s -> allocated_edge_emu_buffer ); s -> edge_emu_buffer = NULL ;
av_freep ( & s -> me . scratchpad );
2005-12-17 18:14:38 +00:00
s -> rd_scratchpad =
s -> b_scratchpad =
2004-02-13 17:54:10 +00:00
s -> obmc_scratchpad = NULL ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
av_freep ( & s -> dct_error_sum );
av_freep ( & s -> me . map );
av_freep ( & s -> me . score_map );
av_freep ( & s -> blocks );
s -> block = NULL ;
}
static void backup_duplicate_context ( MpegEncContext * bak , MpegEncContext * src ){
#define COPY(a) bak->a= src->a
COPY ( allocated_edge_emu_buffer );
COPY ( edge_emu_buffer );
COPY ( me . scratchpad );
COPY ( rd_scratchpad );
COPY ( b_scratchpad );
COPY ( obmc_scratchpad );
COPY ( me . map );
COPY ( me . score_map );
COPY ( blocks );
COPY ( block );
COPY ( start_mb_y );
COPY ( end_mb_y );
COPY ( me . map_generation );
COPY ( pb );
COPY ( dct_error_sum );
2004-02-17 18:57:50 +00:00
COPY ( dct_count [ 0 ]);
COPY ( dct_count [ 1 ]);
2004-02-13 17:54:10 +00:00
#undef COPY
}
2004-02-23 20:56:56 +00:00
void ff_update_duplicate_context ( MpegEncContext * dst , MpegEncContext * src ){
2004-02-13 17:54:10 +00:00
MpegEncContext bak ;
2004-02-23 20:56:56 +00:00
int i ;
2004-02-13 17:54:10 +00:00
//FIXME copy only needed parts
//START_TIMER
backup_duplicate_context ( & bak , dst );
memcpy ( dst , src , sizeof ( MpegEncContext ));
backup_duplicate_context ( dst , & bak );
2004-02-23 20:56:56 +00:00
for ( i = 0 ; i < 12 ; i ++ ){
dst -> pblocks [ i ] = ( short * )( & dst -> block [ i ]);
}
2004-02-13 17:54:10 +00:00
//STOP_TIMER("update_duplicate_context") //about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads
}
2006-09-27 19:54:07 +00:00
#ifdef CONFIG_ENCODERS
2004-02-13 17:54:10 +00:00
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 );
2005-06-17 15:02:53 +00:00
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
2004-02-13 17:54:10 +00:00
#undef COPY
}
2006-09-27 19:54:07 +00:00
#endif
2004-02-13 17:54:10 +00:00
2004-03-16 16:11:29 +00:00
/**
* sets the given MpegEncContext to common defaults (same for encoding and decoding).
* the changed fields will not depend upon the prior state of the MpegEncContext.
*/
static void MPV_common_defaults ( MpegEncContext * s ){
s -> y_dc_scale_table =
s -> c_dc_scale_table = ff_mpeg1_dc_scale_table ;
s -> chroma_qscale_table = ff_default_chroma_qscale_table ;
s -> progressive_frame = 1 ;
s -> progressive_sequence = 1 ;
s -> picture_structure = PICT_FRAME ;
s -> coded_picture_number = 0 ;
s -> picture_number = 0 ;
s -> input_picture_number = 0 ;
s -> picture_in_gop_number = 0 ;
2004-03-16 17:27:03 +00:00
s -> f_code = 1 ;
s -> b_code = 1 ;
2004-03-16 16:11:29 +00:00
}
/**
* sets the given MpegEncContext to defaults for decoding.
* the changed fields will not depend upon the prior state of the MpegEncContext.
*/
void MPV_decode_defaults ( MpegEncContext * s ){
MPV_common_defaults ( s );
}
/**
* sets the given MpegEncContext to defaults for encoding.
* the changed fields will not depend upon the prior state of the MpegEncContext.
*/
2004-03-22 12:07:02 +00:00
#ifdef CONFIG_ENCODERS
2004-05-18 17:09:46 +00:00
static void MPV_encode_defaults ( MpegEncContext * s ){
2004-03-16 16:11:29 +00:00
static int done = 0 ;
2005-12-17 18:14:38 +00:00
2004-03-16 16:11:29 +00:00
MPV_common_defaults ( s );
2005-12-17 18:14:38 +00:00
2004-03-16 16:11:29 +00:00
if ( ! done ){
int i ;
done = 1 ;
default_mv_penalty = av_mallocz ( sizeof ( uint8_t ) * ( MAX_FCODE + 1 ) * ( 2 * MAX_MV + 1 ) );
memset ( default_fcode_tab , 0 , sizeof ( uint8_t ) * ( 2 * MAX_MV + 1 ));
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 ;
}
2004-03-22 12:07:02 +00:00
#endif //CONFIG_ENCODERS
2004-03-16 16:11:29 +00:00
2005-12-17 18:14:38 +00:00
/**
2004-03-16 16:11:29 +00:00
* init common structure for both encoder and decoder.
* this assumes that some variables like width/height are already set
*/
2002-10-04 20:59:29 +00:00
int MPV_common_init ( MpegEncContext * s )
{
2003-12-30 16:07:57 +00:00
int y_size , c_size , yc_size , i , mb_array_size , mv_table_size , x , y ;
2002-10-04 20:59:29 +00:00
2006-01-28 00:57:59 +00:00
s -> mb_height = ( s -> height + 15 ) / 16 ;
if ( s -> avctx -> thread_count > MAX_THREADS || ( s -> avctx -> thread_count > s -> mb_height && s -> mb_height )){
2004-04-29 22:12:29 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "too many threads \n " );
return - 1 ;
}
2005-01-12 00:16:25 +00:00
if (( s -> width || s -> height ) && avcodec_check_dimensions ( s -> avctx , s -> width , s -> height ))
return - 1 ;
2003-03-03 14:54:00 +00:00
dsputil_init ( & s -> dsp , s -> avctx );
2002-10-04 20:59:29 +00:00
DCT_common_init ( s );
2002-11-11 09:40:17 +00:00
2002-10-16 22:18:41 +00:00
s -> flags = s -> avctx -> flags ;
2004-01-22 19:48:28 +00:00
s -> flags2 = s -> avctx -> flags2 ;
2002-10-04 20:59:29 +00:00
2002-12-04 10:04:03 +00:00
s -> mb_width = ( s -> width + 15 ) / 16 ;
2003-04-10 13:18:38 +00:00
s -> mb_stride = s -> mb_width + 1 ;
2003-12-04 18:34:47 +00:00
s -> b8_stride = s -> mb_width * 2 + 1 ;
s -> b4_stride = s -> mb_width * 4 + 1 ;
2003-04-10 13:18:38 +00:00
mb_array_size = s -> mb_height * s -> mb_stride ;
2003-12-30 16:07:57 +00:00
mv_table_size = ( s -> mb_height + 2 ) * s -> mb_stride + 1 ;
2002-11-11 09:40:17 +00:00
2004-06-11 07:59:12 +00:00
/* set chroma shifts */
avcodec_get_chroma_sub_sample ( s -> avctx -> pix_fmt , & ( s -> chroma_x_shift ),
& ( s -> chroma_y_shift ) );
2002-07-25 20:22:36 +00:00
/* set default edge pos, will be overriden in decode_header if needed */
s -> h_edge_pos = s -> mb_width * 16 ;
s -> v_edge_pos = s -> mb_height * 16 ;
2002-11-11 09:40:17 +00:00
s -> mb_num = s -> mb_width * s -> mb_height ;
2005-12-17 18:14:38 +00:00
2003-04-10 13:18:38 +00:00
s -> block_wrap [ 0 ] =
s -> block_wrap [ 1 ] =
s -> block_wrap [ 2 ] =
2004-04-16 01:01:45 +00:00
s -> block_wrap [ 3 ] = s -> b8_stride ;
2003-04-10 13:18:38 +00:00
s -> block_wrap [ 4 ] =
2004-04-16 01:01:45 +00:00
s -> block_wrap [ 5 ] = s -> mb_stride ;
2005-12-17 18:14:38 +00:00
2004-04-16 01:01:45 +00:00
y_size = s -> b8_stride * ( 2 * s -> mb_height + 1 );
c_size = s -> mb_stride * ( s -> mb_height + 1 );
2002-11-11 09:40:17 +00:00
yc_size = y_size + 2 * c_size ;
2005-12-17 18:14:38 +00:00
2002-09-27 10:27:57 +00:00
/* convert fourcc to upper case */
2005-12-17 18:14:38 +00:00
s -> avctx -> codec_tag = toupper ( s -> avctx -> codec_tag & 0xFF )
2003-03-08 01:40:52 +00:00
+ ( toupper (( s -> avctx -> codec_tag >> 8 ) & 0xFF ) << 8 )
2005-12-17 18:14:38 +00:00
+ ( toupper (( s -> avctx -> codec_tag >> 16 ) & 0xFF ) << 16 )
2003-03-08 01:40:52 +00:00
+ ( toupper (( s -> avctx -> codec_tag >> 24 ) & 0xFF ) << 24 );
2002-07-25 20:22:36 +00:00
2005-12-17 18:14:38 +00:00
s -> avctx -> stream_codec_tag = toupper ( s -> avctx -> stream_codec_tag & 0xFF )
2003-09-10 23:40:55 +00:00
+ ( toupper (( s -> avctx -> stream_codec_tag >> 8 ) & 0xFF ) << 8 )
2005-12-17 18:14:38 +00:00
+ ( toupper (( s -> avctx -> stream_codec_tag >> 16 ) & 0xFF ) << 16 )
2003-09-10 23:40:55 +00:00
+ ( toupper (( s -> avctx -> stream_codec_tag >> 24 ) & 0xFF ) << 24 );
2002-12-09 12:03:43 +00:00
s -> avctx -> coded_frame = ( AVFrame * ) & s -> current_picture ;
2002-12-04 10:04:03 +00:00
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> mb_index2xy , ( s -> mb_num + 1 ) * sizeof ( int )) //error ressilience code looks cleaner with this
for ( y = 0 ; y < s -> mb_height ; y ++ ){
for ( x = 0 ; x < s -> mb_width ; x ++ ){
s -> mb_index2xy [ x + y * s -> mb_width ] = x + y * s -> mb_stride ;
}
}
s -> mb_index2xy [ s -> mb_height * s -> mb_width ] = ( s -> mb_height - 1 ) * s -> mb_stride + s -> mb_width ; //FIXME really needed?
2005-12-17 18:14:38 +00:00
2002-02-10 01:56:50 +00:00
if ( s -> encoding ) {
2002-04-17 04:32:12 +00:00
/* Allocate MV tables */
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> p_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
CHECKED_ALLOCZ ( s -> b_forw_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
CHECKED_ALLOCZ ( s -> b_back_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
CHECKED_ALLOCZ ( s -> b_bidir_forw_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
CHECKED_ALLOCZ ( s -> b_bidir_back_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
CHECKED_ALLOCZ ( s -> b_direct_mv_table_base , mv_table_size * 2 * sizeof ( int16_t ))
s -> p_mv_table = s -> p_mv_table_base + s -> mb_stride + 1 ;
s -> b_forw_mv_table = s -> b_forw_mv_table_base + s -> mb_stride + 1 ;
s -> b_back_mv_table = s -> b_back_mv_table_base + s -> mb_stride + 1 ;
s -> b_bidir_forw_mv_table = s -> b_bidir_forw_mv_table_base + s -> mb_stride + 1 ;
s -> b_bidir_back_mv_table = s -> b_bidir_back_mv_table_base + s -> mb_stride + 1 ;
s -> b_direct_mv_table = s -> b_direct_mv_table_base + s -> mb_stride + 1 ;
2002-04-17 04:32:12 +00:00
2002-09-11 07:26:43 +00:00
if ( s -> msmpeg4_version ){
CHECKED_ALLOCZ ( s -> ac_stats , 2 * 2 * ( MAX_LEVEL + 1 ) * ( MAX_RUN + 1 ) * 2 * sizeof ( int ));
}
2002-08-25 21:19:50 +00:00
CHECKED_ALLOCZ ( s -> avctx -> stats_out , 256 );
2003-04-10 13:18:38 +00:00
/* Allocate MB type table */
2003-12-30 16:07:57 +00:00
CHECKED_ALLOCZ ( s -> mb_type , mb_array_size * sizeof ( uint16_t )) //needed for encoding
2005-12-17 18:14:38 +00:00
2003-10-07 11:32:40 +00:00
CHECKED_ALLOCZ ( s -> lambda_table , mb_array_size * sizeof ( int ))
2005-12-17 18:14:38 +00:00
2003-10-22 10:59:39 +00:00
CHECKED_ALLOCZ ( s -> q_intra_matrix , 64 * 32 * sizeof ( int ))
CHECKED_ALLOCZ ( s -> q_inter_matrix , 64 * 32 * sizeof ( int ))
2003-10-22 11:23:39 +00:00
CHECKED_ALLOCZ ( s -> q_intra_matrix16 , 64 * 32 * 2 * sizeof ( uint16_t ))
CHECKED_ALLOCZ ( s -> q_inter_matrix16 , 64 * 32 * 2 * sizeof ( uint16_t ))
2003-10-22 15:36:46 +00:00
CHECKED_ALLOCZ ( s -> input_picture , MAX_PICTURE_COUNT * sizeof ( Picture * ))
CHECKED_ALLOCZ ( s -> reordered_input_picture , MAX_PICTURE_COUNT * sizeof ( Picture * ))
2005-12-17 18:14:38 +00:00
2003-11-02 23:19:47 +00:00
if ( s -> avctx -> noise_reduction ){
CHECKED_ALLOCZ ( s -> dct_offset , 2 * 64 * sizeof ( uint16_t ))
}
2002-02-10 01:56:50 +00:00
}
2003-10-21 19:55:31 +00:00
CHECKED_ALLOCZ ( s -> picture , MAX_PICTURE_COUNT * sizeof ( Picture ))
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> error_status_table , mb_array_size * sizeof ( uint8_t ))
2005-12-17 18:14:38 +00:00
2003-12-30 16:07:57 +00:00
if ( s -> codec_id == CODEC_ID_MPEG4 || ( s -> flags & CODEC_FLAG_INTERLACED_ME )){
2002-10-13 13:16:04 +00:00
/* interlaced direct mode decoding tables */
2003-12-30 16:07:57 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
int j , k ;
for ( j = 0 ; j < 2 ; j ++ ){
for ( k = 0 ; k < 2 ; k ++ ){
CHECKED_ALLOCZ ( s -> b_field_mv_table_base [ i ][ j ][ k ] , mv_table_size * 2 * sizeof ( int16_t ))
s -> b_field_mv_table [ i ][ j ][ k ] = s -> b_field_mv_table_base [ i ][ j ][ k ] + s -> mb_stride + 1 ;
}
CHECKED_ALLOCZ ( s -> b_field_select_table [ i ][ j ] , mb_array_size * 2 * sizeof ( uint8_t ))
CHECKED_ALLOCZ ( s -> p_field_mv_table_base [ i ][ j ] , mv_table_size * 2 * sizeof ( int16_t ))
s -> p_field_mv_table [ i ][ j ] = s -> p_field_mv_table_base [ i ][ j ] + s -> mb_stride + 1 ;
}
CHECKED_ALLOCZ ( s -> p_field_select_table [ i ] , mb_array_size * 2 * sizeof ( uint8_t ))
}
2001-07-22 14:18:56 +00:00
}
2002-10-25 10:50:02 +00:00
if ( s -> out_format == FMT_H263 ) {
2001-07-22 14:18:56 +00:00
/* ac values */
2004-04-16 01:01:45 +00:00
CHECKED_ALLOCZ ( s -> ac_val_base , yc_size * sizeof ( int16_t ) * 16 );
s -> ac_val [ 0 ] = s -> ac_val_base + s -> b8_stride + 1 ;
s -> ac_val [ 1 ] = s -> ac_val_base + y_size + s -> mb_stride + 1 ;
2001-07-22 14:18:56 +00:00
s -> ac_val [ 2 ] = s -> ac_val [ 1 ] + c_size ;
2005-12-17 18:14:38 +00:00
2001-07-22 14:18:56 +00:00
/* cbp values */
2004-04-16 01:01:45 +00:00
CHECKED_ALLOCZ ( s -> coded_block_base , y_size );
s -> coded_block = s -> coded_block_base + s -> b8_stride + 1 ;
2005-12-17 18:14:38 +00:00
2002-06-02 12:20:39 +00:00
/* cbp, ac_pred, pred_dir */
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> cbp_table , mb_array_size * sizeof ( uint8_t ))
CHECKED_ALLOCZ ( s -> pred_dir_table , mb_array_size * sizeof ( uint8_t ))
2002-01-11 22:07:12 +00:00
}
2005-12-17 18:14:38 +00:00
2002-10-19 01:31:26 +00:00
if ( s -> h263_pred || s -> h263_plus || ! s -> encoding ) {
/* dc values */
//MN: we need these for error resilience of intra-frames
2004-04-16 01:01:45 +00:00
CHECKED_ALLOCZ ( s -> dc_val_base , yc_size * sizeof ( int16_t ));
s -> dc_val [ 0 ] = s -> dc_val_base + s -> b8_stride + 1 ;
s -> dc_val [ 1 ] = s -> dc_val_base + y_size + s -> mb_stride + 1 ;
2002-10-19 01:31:26 +00:00
s -> dc_val [ 2 ] = s -> dc_val [ 1 ] + c_size ;
for ( i = 0 ; i < yc_size ; i ++ )
2004-04-16 01:01:45 +00:00
s -> dc_val_base [ i ] = 1024 ;
2002-10-19 01:31:26 +00:00
}
2002-08-24 13:24:43 +00:00
/* which mb is a intra block */
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> mbintra_table , mb_array_size );
memset ( s -> mbintra_table , 1 , mb_array_size );
2005-12-17 18:14:38 +00:00
2001-07-24 20:43:41 +00:00
/* init macroblock skip table */
2003-04-10 13:18:38 +00:00
CHECKED_ALLOCZ ( s -> mbskip_table , mb_array_size + 2 );
2002-10-13 13:16:04 +00:00
//Note the +1 is for a quicker mpeg4 slice_end detection
2003-01-20 20:37:24 +00:00
CHECKED_ALLOCZ ( s -> prev_pict_types , PREV_PICT_TYPES_BUFFER_SIZE );
2005-12-17 18:14:38 +00:00
2002-11-08 18:35:39 +00:00
s -> parse_context . state = - 1 ;
2003-12-30 02:12:12 +00:00
if (( s -> avctx -> debug & ( FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE )) || ( s -> avctx -> debug_mv )){
s -> visualization_buffer [ 0 ] = av_malloc (( s -> mb_width * 16 + 2 * EDGE_WIDTH ) * s -> mb_height * 16 + 2 * EDGE_WIDTH );
s -> visualization_buffer [ 1 ] = av_malloc (( s -> mb_width * 8 + EDGE_WIDTH ) * s -> mb_height * 8 + EDGE_WIDTH );
s -> visualization_buffer [ 2 ] = av_malloc (( s -> mb_width * 8 + EDGE_WIDTH ) * s -> mb_height * 8 + EDGE_WIDTH );
}
2002-11-08 18:35:39 +00:00
2001-07-22 14:18:56 +00:00
s -> context_initialized = 1 ;
2004-02-13 17:54:10 +00:00
s -> thread_context [ 0 ] = s ;
for ( i = 1 ; i < s -> avctx -> thread_count ; i ++ ){
s -> thread_context [ i ] = av_malloc ( sizeof ( MpegEncContext ));
memcpy ( s -> thread_context [ i ], s , sizeof ( MpegEncContext ));
}
for ( i = 0 ; i < s -> avctx -> thread_count ; i ++ ){
if ( init_duplicate_context ( s -> thread_context [ i ], s ) < 0 )
goto fail ;
s -> thread_context [ i ] -> start_mb_y = ( s -> mb_height * ( i ) + s -> avctx -> thread_count / 2 ) / s -> avctx -> thread_count ;
s -> thread_context [ i ] -> end_mb_y = ( s -> mb_height * ( i + 1 ) + s -> avctx -> thread_count / 2 ) / s -> avctx -> thread_count ;
}
2001-07-22 14:18:56 +00:00
return 0 ;
fail :
2002-02-18 09:31:37 +00:00
MPV_common_end ( s );
2001-07-22 14:18:56 +00:00
return - 1 ;
}
/* init common structure for both encoder and decoder */
void MPV_common_end ( MpegEncContext * s )
{
2003-12-30 16:07:57 +00:00
int i , j , k ;
2001-07-22 14:18:56 +00:00
2004-02-13 17:54:10 +00:00
for ( i = 0 ; i < s -> avctx -> thread_count ; i ++ ){
free_duplicate_context ( s -> thread_context [ i ]);
}
for ( i = 1 ; i < s -> avctx -> thread_count ; i ++ ){
av_freep ( & s -> thread_context [ i ]);
}
2003-07-05 08:31:08 +00:00
av_freep ( & s -> parse_context . buffer );
s -> parse_context . buffer_size = 0 ;
2002-05-18 23:03:29 +00:00
av_freep ( & s -> mb_type );
2003-04-10 13:18:38 +00:00
av_freep ( & s -> p_mv_table_base );
av_freep ( & s -> b_forw_mv_table_base );
av_freep ( & s -> b_back_mv_table_base );
av_freep ( & s -> b_bidir_forw_mv_table_base );
av_freep ( & s -> b_bidir_back_mv_table_base );
av_freep ( & s -> b_direct_mv_table_base );
s -> p_mv_table = NULL ;
s -> b_forw_mv_table = NULL ;
s -> b_back_mv_table = NULL ;
s -> b_bidir_forw_mv_table = NULL ;
s -> b_bidir_back_mv_table = NULL ;
s -> b_direct_mv_table = NULL ;
2003-12-30 16:07:57 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
for ( j = 0 ; j < 2 ; j ++ ){
for ( k = 0 ; k < 2 ; k ++ ){
av_freep ( & s -> b_field_mv_table_base [ i ][ j ][ k ]);
s -> b_field_mv_table [ i ][ j ][ k ] = NULL ;
}
av_freep ( & s -> b_field_select_table [ i ][ j ]);
av_freep ( & s -> p_field_mv_table_base [ i ][ j ]);
s -> p_field_mv_table [ i ][ j ] = NULL ;
}
av_freep ( & s -> p_field_select_table [ i ]);
}
2005-12-17 18:14:38 +00:00
2004-04-16 01:01:45 +00:00
av_freep ( & s -> dc_val_base );
av_freep ( & s -> ac_val_base );
av_freep ( & s -> coded_block_base );
2002-05-18 23:03:29 +00:00
av_freep ( & s -> mbintra_table );
2002-06-02 12:20:39 +00:00
av_freep ( & s -> cbp_table );
av_freep ( & s -> pred_dir_table );
2005-12-17 18:14:38 +00:00
2002-05-18 23:03:29 +00:00
av_freep ( & s -> mbskip_table );
2003-01-20 20:37:24 +00:00
av_freep ( & s -> prev_pict_types );
2002-05-18 23:03:29 +00:00
av_freep ( & s -> bitstream_buffer );
2005-01-12 00:16:25 +00:00
s -> allocated_bitstream_buffer_size = 0 ;
2002-08-25 21:19:50 +00:00
av_freep ( & s -> avctx -> stats_out );
2002-09-11 07:26:43 +00:00
av_freep ( & s -> ac_stats );
2002-10-13 13:16:04 +00:00
av_freep ( & s -> error_status_table );
2003-04-10 13:18:38 +00:00
av_freep ( & s -> mb_index2xy );
2003-10-07 11:32:40 +00:00
av_freep ( & s -> lambda_table );
2003-10-22 10:59:39 +00:00
av_freep ( & s -> q_intra_matrix );
av_freep ( & s -> q_inter_matrix );
2003-10-22 11:23:39 +00:00
av_freep ( & s -> q_intra_matrix16 );
av_freep ( & s -> q_inter_matrix16 );
2003-10-22 15:36:46 +00:00
av_freep ( & s -> input_picture );
av_freep ( & s -> reordered_input_picture );
2003-11-02 23:19:47 +00:00
av_freep ( & s -> dct_offset );
2002-07-14 18:37:35 +00:00
2003-10-25 19:30:14 +00:00
if ( s -> picture ){
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
free_picture ( s , & s -> picture [ i ]);
}
2001-07-22 14:18:56 +00:00
}
2003-10-21 19:55:31 +00:00
av_freep ( & s -> picture );
2001-07-22 14:18:56 +00:00
s -> context_initialized = 0 ;
2003-10-12 21:32:58 +00:00
s -> last_picture_ptr =
s -> next_picture_ptr =
s -> current_picture_ptr = NULL ;
2004-09-15 00:35:18 +00:00
s -> linesize = s -> uvlinesize = 0 ;
2004-04-03 01:55:24 +00:00
2003-12-30 02:12:12 +00:00
for ( i = 0 ; i < 3 ; i ++ )
2004-04-03 01:55:24 +00:00
av_freep ( & s -> visualization_buffer [ i ]);
2004-09-15 00:35:18 +00:00
avcodec_default_free_buffers ( s -> avctx );
2001-07-22 14:18:56 +00:00
}
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2001-07-22 14:18:56 +00:00
/* init video encoder */
int MPV_encode_init ( AVCodecContext * avctx )
{
MpegEncContext * s = avctx -> priv_data ;
2005-08-14 15:42:40 +00:00
int i ;
2003-06-17 22:48:51 +00:00
int chroma_h_shift , chroma_v_shift ;
2005-12-17 18:14:38 +00:00
2004-03-16 16:11:29 +00:00
MPV_encode_defaults ( s );
2002-04-08 21:03:35 +00:00
2006-05-16 15:19:54 +00:00
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_YUV420P || avctx -> strict_std_compliance > FF_COMPLIANCE_INOFFICIAL )){
2005-01-20 00:30:20 +00:00
av_log ( avctx , AV_LOG_ERROR , "colorspace not supported in jpeg \n " );
return - 1 ;
}
2006-05-16 15:19:54 +00:00
break ;
default :
if ( avctx -> pix_fmt != PIX_FMT_YUV420P ){
av_log ( avctx , AV_LOG_ERROR , "only YUV420 is supported \n " );
2005-01-20 00:30:20 +00:00
return - 1 ;
}
}
2003-08-12 18:20:29 +00:00
2006-05-16 15:19:54 +00:00
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 ;
}
2001-07-22 14:18:56 +00:00
s -> bit_rate = avctx -> bit_rate ;
s -> width = avctx -> width ;
s -> height = avctx -> height ;
2006-05-09 08:40:38 +00:00
if ( avctx -> gop_size > 600 && avctx -> strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL ){
2005-12-22 01:10:11 +00:00
av_log ( avctx , AV_LOG_ERROR , "Warning keyframe interval too large! reducing it ... \n " );
2002-06-02 12:20:39 +00:00
avctx -> gop_size = 600 ;
}
2001-07-22 14:18:56 +00:00
s -> gop_size = avctx -> gop_size ;
2002-01-11 21:23:48 +00:00
s -> avctx = avctx ;
2002-03-27 21:25:22 +00:00
s -> flags = avctx -> flags ;
2004-01-22 19:48:28 +00:00
s -> flags2 = avctx -> flags2 ;
2002-04-17 04:32:12 +00:00
s -> max_b_frames = avctx -> max_b_frames ;
2002-04-27 12:30:26 +00:00
s -> codec_id = avctx -> codec -> id ;
2002-06-02 12:20:39 +00:00
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 ;
2002-12-27 23:51:46 +00:00
s -> quarter_sample = ( avctx -> flags & CODEC_FLAG_QPEL ) != 0 ;
2002-08-06 23:51:15 +00:00
s -> mpeg_quant = avctx -> mpeg_quant ;
2003-12-07 01:33:45 +00:00
s -> rtp_mode = !! avctx -> rtp_payload_size ;
2004-04-30 13:44:29 +00:00
s -> intra_dc_precision = avctx -> intra_dc_precision ;
2004-09-20 13:47:47 +00:00
s -> user_specified_pts = AV_NOPTS_VALUE ;
2003-08-25 22:54:53 +00:00
2001-07-22 14:18:56 +00:00
if ( s -> gop_size <= 1 ) {
s -> intra_only = 1 ;
s -> gop_size = 12 ;
} else {
s -> intra_only = 0 ;
}
2002-09-24 10:53:59 +00:00
2002-12-27 23:51:46 +00:00
s -> me_method = avctx -> me_method ;
2002-09-24 10:53:59 +00:00
2002-04-14 18:57:51 +00:00
/* Fixed QSCALE */
2003-12-30 16:07:57 +00:00
s -> fixed_qscale = !! ( avctx -> flags & CODEC_FLAG_QSCALE );
2005-12-17 18:14:38 +00:00
2002-09-23 14:56:11 +00:00
s -> adaptive_quant = ( s -> avctx -> lumi_masking
2002-09-24 10:53:59 +00:00
|| s -> avctx -> dark_masking
2005-12-17 18:14:38 +00:00
|| s -> avctx -> temporal_cplx_masking
2002-09-23 14:56:11 +00:00
|| s -> avctx -> spatial_cplx_masking
2003-11-12 12:25:44 +00:00
|| s -> avctx -> p_masking
2005-02-02 18:49:04 +00:00
|| s -> avctx -> border_masking
2003-11-12 12:25:44 +00:00
|| ( s -> flags & CODEC_FLAG_QP_RD ))
2002-09-23 14:56:11 +00:00
&& ! s -> fixed_qscale ;
2005-12-17 18:14:38 +00:00
2003-12-30 16:07:57 +00:00
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 );
2006-05-13 17:16:58 +00:00
s -> intra_vlc_format = !! ( s -> flags2 & CODEC_FLAG2_INTRA_VLC );
2002-09-24 10:53:59 +00:00
2004-01-01 15:13:44 +00: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 ;
2005-12-17 18:14:38 +00:00
}
2004-01-01 15:13:44 +00:00
if ( avctx -> rc_min_rate && avctx -> rc_max_rate != avctx -> rc_min_rate ){
2005-04-24 11:13:49 +00:00
av_log ( avctx , AV_LOG_INFO , "Warning min_rate > 0 but min_rate != max_rate isn't recommended! \n " );
2004-03-26 12:30:04 +00:00
}
2005-12-17 18:14:38 +00:00
2004-06-06 19:44:05 +00:00
if ( avctx -> rc_min_rate && avctx -> rc_min_rate > avctx -> bit_rate ){
av_log ( avctx , AV_LOG_INFO , "bitrate below min bitrate \n " );
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2004-06-06 19:44:05 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
if ( s -> avctx -> rc_max_rate && s -> avctx -> rc_min_rate == s -> avctx -> rc_max_rate
2004-03-26 12:30:04 +00:00
&& ( s -> codec_id == CODEC_ID_MPEG1VIDEO || s -> codec_id == CODEC_ID_MPEG2VIDEO )
&& 90000LL * ( avctx -> rc_buffer_size - 1 ) > s -> avctx -> rc_max_rate * 0xFFFFLL ){
2005-12-17 18:14:38 +00:00
2004-03-26 12:30:04 +00:00
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 " );
}
2005-12-17 18:14:38 +00:00
if (( s -> flags & CODEC_FLAG_4MV ) && s -> codec_id != CODEC_ID_MPEG4
2004-02-06 23:56:37 +00:00
&& s -> codec_id != CODEC_ID_H263 && s -> codec_id != CODEC_ID_H263P && s -> codec_id != CODEC_ID_FLV1 ){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "4MV not supported by codec \n " );
2003-04-14 14:06:21 +00:00
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
if ( s -> obmc && s -> avctx -> mb_decision != FF_MB_DECISION_SIMPLE ){
2005-04-24 11:13:49 +00:00
av_log ( avctx , AV_LOG_ERROR , "OBMC is only supported with simple mb decision \n " );
2003-11-28 21:31:20 +00:00
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2003-12-01 15:23:14 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
2003-04-14 14:06:21 +00:00
if ( s -> quarter_sample && s -> codec_id != CODEC_ID_MPEG4 ){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "qpel not supported by codec \n " );
2003-04-14 14:06:21 +00:00
return - 1 ;
}
if ( s -> data_partitioning && s -> codec_id != CODEC_ID_MPEG4 ){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "data partitioning not supported by codec \n " );
2003-04-14 14:06:21 +00:00
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2003-08-25 22:47:32 +00:00
if ( s -> max_b_frames && s -> codec_id != CODEC_ID_MPEG4 && s -> codec_id != CODEC_ID_MPEG1VIDEO && s -> codec_id != CODEC_ID_MPEG2VIDEO ){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "b frames not supported by codec \n " );
2003-04-14 14:06:21 +00:00
return - 1 ;
}
2004-04-23 21:17:31 +00:00
2005-12-17 18:14:38 +00:00
if (( s -> flags & ( CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME | CODEC_FLAG_ALT_SCAN ))
2004-04-23 21:17:31 +00:00
&& 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 ;
}
2005-12-17 18:14:38 +00:00
2003-04-14 14:06:21 +00:00
if ( s -> mpeg_quant && s -> codec_id != CODEC_ID_MPEG4 ){ //FIXME mpeg2 uses that too
2005-04-24 11:13:49 +00:00
av_log ( avctx , AV_LOG_ERROR , "mpeg2 style quantization not supported by codec \n " );
2003-04-14 14:06:21 +00:00
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2003-09-30 22:18:43 +00:00
if (( s -> flags & CODEC_FLAG_CBP_RD ) && ! ( s -> flags & CODEC_FLAG_TRELLIS_QUANT )){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "CBP RD needs trellis quant \n " );
2003-09-30 22:18:43 +00:00
return - 1 ;
}
2003-11-13 23:22:06 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
2004-01-22 19:48:28 +00:00
if ( s -> avctx -> scenechange_threshold < 1000000000 && ( s -> flags & CODEC_FLAG_CLOSED_GOP )){
av_log ( avctx , AV_LOG_ERROR , "closed gop with scene change detection arent supported yet \n " );
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2006-05-13 17:16:58 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
if ( s -> avctx -> thread_count > 1 && s -> codec_id != CODEC_ID_MPEG4
&& s -> codec_id != CODEC_ID_MPEG1VIDEO && s -> codec_id != CODEC_ID_MPEG2VIDEO
2004-02-13 17:54:10 +00:00
&& ( 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 ;
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
if ( s -> avctx -> thread_count > 1 )
s -> rtp_mode = 1 ;
2004-01-26 19:04:32 +00:00
2005-04-30 21:43:59 +00:00
if ( ! avctx -> time_base . den || ! avctx -> time_base . num ){
2005-01-23 14:07:25 +00:00
av_log ( avctx , AV_LOG_ERROR , "framerate not set \n " );
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2005-03-26 18:10:44 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
2005-05-12 01:31:11 +00:00
if ( avctx -> b_frame_strategy && ( avctx -> flags & CODEC_FLAG_PASS2 )){
2006-05-29 22:44:16 +00:00
av_log ( avctx , AV_LOG_INFO , "notice: b_frame_strategy only affects the first pass \n " );
avctx -> b_frame_strategy = 0 ;
2005-05-12 01:31:11 +00:00
}
2005-04-30 21:43:59 +00:00
i = ff_gcd ( avctx -> time_base . den , avctx -> time_base . num );
2004-01-26 19:04:32 +00:00
if ( i > 1 ){
av_log ( avctx , AV_LOG_INFO , "removing common factors from framerate \n " );
2005-04-30 21:43:59 +00:00
avctx -> time_base . den /= i ;
avctx -> time_base . num /= i ;
2004-01-26 19:04:32 +00:00
// return -1;
}
2005-12-17 18:14:38 +00:00
2003-03-22 12:09:02 +00:00
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 ;
2003-08-25 22:47:32 +00:00
} else if ( s -> mpeg_quant || s -> codec_id == CODEC_ID_MPEG1VIDEO || s -> codec_id == CODEC_ID_MPEG2VIDEO ){
2003-03-22 12:09:02 +00:00
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
}
2005-12-17 18:14:38 +00:00
2003-03-22 12:09:02 +00:00
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 ;
2005-12-17 18:14:38 +00:00
2003-06-17 22:48:51 +00:00
avcodec_get_chroma_sub_sample ( avctx -> pix_fmt , & chroma_h_shift , & chroma_v_shift );
2005-05-08 00:44:06 +00:00
if ( avctx -> codec_id == CODEC_ID_MPEG4 && s -> avctx -> time_base . den > ( 1 << 16 ) - 1 ){
2005-04-30 21:43:59 +00:00
av_log ( avctx , AV_LOG_ERROR , "timebase not supported by mpeg 4 standard \n " );
2005-12-17 18:14:38 +00:00
return - 1 ;
2005-04-30 21:43:59 +00:00
}
s -> time_increment_bits = av_log2 ( s -> avctx -> time_base . den - 1 ) + 1 ;
2003-08-26 20:14:28 +00:00
2001-07-22 14:18:56 +00:00
switch ( avctx -> codec -> id ) {
case CODEC_ID_MPEG1VIDEO :
s -> out_format = FMT_MPEG1 ;
2003-03-12 15:16:19 +00:00
s -> low_delay = 0 ; //s->max_b_frames ? 0 : 1;
avctx -> delay = s -> low_delay ? 0 : ( s -> max_b_frames + 1 );
2001-07-22 14:18:56 +00:00
break ;
2003-08-25 22:47:32 +00:00
case CODEC_ID_MPEG2VIDEO :
s -> out_format = FMT_MPEG1 ;
s -> low_delay = 0 ; //s->max_b_frames ? 0 : 1;
avctx -> delay = s -> low_delay ? 0 : ( s -> max_b_frames + 1 );
2003-12-07 01:33:45 +00:00
s -> rtp_mode = 1 ;
2003-08-25 22:47:32 +00:00
break ;
2003-06-17 22:48:51 +00:00
case CODEC_ID_LJPEG :
2005-12-19 03:08:08 +00:00
case CODEC_ID_JPEGLS :
2001-07-22 14:18:56 +00:00
case CODEC_ID_MJPEG :
s -> out_format = FMT_MJPEG ;
s -> intra_only = 1 ; /* force intra only for jpeg */
2005-12-19 03:08:08 +00:00
s -> mjpeg_write_tables = avctx -> codec -> id != CODEC_ID_JPEGLS ;
2005-12-22 01:10:11 +00:00
s -> mjpeg_data_only_frames = 0 ; /* write all the needed headers */
2003-06-17 22:48:51 +00:00
s -> mjpeg_vsample [ 0 ] = 1 << chroma_v_shift ;
s -> mjpeg_vsample [ 1 ] = 1 ;
2005-12-17 18:14:38 +00:00
s -> mjpeg_vsample [ 2 ] = 1 ;
2003-06-17 22:48:51 +00:00
s -> mjpeg_hsample [ 0 ] = 1 << chroma_h_shift ;
2005-12-17 18:14:38 +00:00
s -> mjpeg_hsample [ 1 ] = 1 ;
s -> mjpeg_hsample [ 2 ] = 1 ;
2001-07-22 14:18:56 +00:00
if ( mjpeg_init ( s ) < 0 )
return - 1 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2001-07-22 14:18:56 +00:00
break ;
2004-10-28 10:12:57 +00:00
case CODEC_ID_H261 :
s -> out_format = FMT_H261 ;
avctx -> delay = 0 ;
s -> low_delay = 1 ;
break ;
2001-07-22 14:18:56 +00:00
case CODEC_ID_H263 :
2002-02-10 01:56:50 +00:00
if ( h263_get_picture_format ( s -> width , s -> height ) == 7 ) {
2006-01-04 17:07:30 +00:00
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 );
2001-07-22 14:18:56 +00:00
return - 1 ;
2002-02-10 01:56:50 +00:00
}
2001-07-22 14:18:56 +00:00
s -> out_format = FMT_H263 ;
2005-12-22 01:10:11 +00:00
s -> obmc = ( avctx -> flags & CODEC_FLAG_OBMC ) ? 1 : 0 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2001-07-22 14:18:56 +00:00
break ;
case CODEC_ID_H263P :
s -> out_format = FMT_H263 ;
s -> h263_plus = 1 ;
2005-12-22 01:10:11 +00:00
/* Fx */
2003-12-01 15:23:14 +00:00
s -> umvplus = ( avctx -> flags & CODEC_FLAG_H263P_UMV ) ? 1 : 0 ;
2005-12-22 01:10:11 +00:00
s -> h263_aic = ( avctx -> flags & CODEC_FLAG_H263P_AIC ) ? 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 ;
2003-12-07 01:33:45 +00:00
s -> h263_slice_structured = ( s -> flags & CODEC_FLAG_H263P_SLICE_STRUCT ) ? 1 : 0 ;
2003-12-01 15:23:14 +00:00
2005-12-22 01:10:11 +00:00
/* /Fx */
2001-08-31 06:21:27 +00:00
/* These are just to be sure */
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2001-07-22 14:18:56 +00:00
break ;
2003-07-09 23:10:59 +00:00
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 ;
2001-07-22 14:18:56 +00:00
case CODEC_ID_RV10 :
s -> out_format = FMT_H263 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2001-07-22 14:18:56 +00:00
break ;
2004-12-07 13:14:37 +00:00
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 ;
2001-08-15 13:12:23 +00:00
case CODEC_ID_MPEG4 :
2001-07-22 14:18:56 +00:00
s -> out_format = FMT_H263 ;
s -> h263_pred = 1 ;
s -> unrestricted_mv = 1 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = s -> max_b_frames ? 0 : 1 ;
2002-10-13 13:16:04 +00:00
avctx -> delay = s -> low_delay ? 0 : ( s -> max_b_frames + 1 );
2001-07-22 14:18:56 +00:00
break ;
2002-04-05 04:09:04 +00:00
case CODEC_ID_MSMPEG4V1 :
2001-07-22 14:18:56 +00:00
s -> out_format = FMT_H263 ;
s -> h263_msmpeg4 = 1 ;
s -> h263_pred = 1 ;
s -> unrestricted_mv = 1 ;
2002-04-05 04:09:04 +00:00
s -> msmpeg4_version = 1 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2002-04-05 04:09:04 +00:00
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 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2002-04-05 04:09:04 +00:00
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 ;
2003-04-01 15:38:01 +00:00
s -> flipflop_rounding = 1 ;
2002-04-22 19:04:28 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2001-07-22 14:18:56 +00:00
break ;
2002-06-18 00:49:00 +00:00
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 ;
2003-04-01 15:38:01 +00:00
s -> flipflop_rounding = 1 ;
2002-06-18 00:49:00 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2002-06-18 00:49:00 +00:00
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 ;
2003-04-01 15:38:01 +00:00
s -> flipflop_rounding = 1 ;
2002-06-18 00:49:00 +00:00
avctx -> delay = 0 ;
2002-12-09 00:29:17 +00:00
s -> low_delay = 1 ;
2002-06-18 00:49:00 +00:00
break ;
2001-07-22 14:18:56 +00:00
default :
return - 1 ;
}
2005-12-17 18:14:38 +00:00
2004-05-29 15:16:52 +00:00
avctx -> has_b_frames = ! s -> low_delay ;
2004-01-18 21:41:44 +00:00
2001-07-24 20:43:41 +00:00
s -> encoding = 1 ;
2001-07-22 14:18:56 +00:00
/* init */
if ( MPV_common_init ( s ) < 0 )
return - 1 ;
2003-12-10 17:05:41 +00:00
if ( s -> modified_quant )
s -> chroma_qscale_table = ff_h263_chroma_qscale_table ;
2005-12-17 18:14:38 +00:00
s -> progressive_frame =
2003-12-30 16:07:57 +00:00
s -> progressive_sequence = ! ( avctx -> flags & ( CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME ));
2004-02-13 17:54:10 +00:00
s -> quant_precision = 5 ;
2005-12-17 18:14:38 +00:00
2004-01-05 22:57:07 +00:00
ff_set_cmp ( & s -> dsp , s -> dsp . ildct_cmp , s -> avctx -> ildct_cmp );
2004-12-08 18:02:56 +00:00
ff_set_cmp ( & s -> dsp , s -> dsp . frame_skip_cmp , s -> avctx -> frame_skip_cmp );
2005-12-17 18:14:38 +00:00
2005-05-02 22:14:42 +00:00
#ifdef CONFIG_H261_ENCODER
2004-10-28 10:12:57 +00:00
if ( s -> out_format == FMT_H261 )
ff_h261_encode_init ( s );
2005-05-02 22:14:42 +00:00
#endif
2002-09-29 22:44:22 +00:00
if ( s -> out_format == FMT_H263 )
h263_encode_init ( s );
if ( s -> msmpeg4_version )
ff_msmpeg4_encode_init ( s );
2003-01-29 12:00:11 +00:00
if ( s -> out_format == FMT_MPEG1 )
ff_mpeg1_encode_init ( s );
2002-09-29 22:44:22 +00:00
2004-03-16 16:11:29 +00:00
/* init q matrix */
2001-08-12 00:52:37 +00:00
for ( i = 0 ; i < 64 ; i ++ ) {
2003-03-03 14:54:00 +00:00
int j = s -> dsp . idct_permutation [ i ];
2002-08-06 23:51:15 +00:00
if ( s -> codec_id == CODEC_ID_MPEG4 && s -> mpeg_quant ){
2002-09-29 22:44:22 +00:00
s -> intra_matrix [ j ] = ff_mpeg4_default_intra_matrix [ i ];
s -> inter_matrix [ j ] = ff_mpeg4_default_non_intra_matrix [ i ];
2004-10-28 10:12:57 +00:00
} else if ( s -> out_format == FMT_H263 || s -> out_format == FMT_H261 ){
2002-09-29 22:44:22 +00:00
s -> intra_matrix [ j ] =
s -> inter_matrix [ j ] = ff_mpeg1_default_non_intra_matrix [ i ];
2003-01-29 12:00:11 +00:00
} else
2003-08-25 22:47:32 +00:00
{ /* mpeg1/2 */
2002-09-29 22:44:22 +00:00
s -> intra_matrix [ j ] = ff_mpeg1_default_intra_matrix [ i ];
s -> inter_matrix [ j ] = ff_mpeg1_default_non_intra_matrix [ i ];
2002-08-06 23:51:15 +00:00
}
2003-08-22 22:18:08 +00:00
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 ];
2002-04-27 12:30:26 +00:00
}
/* precompute matrix */
2002-05-02 04:39:45 +00:00
/* for mjpeg, we do include qscale in the matrix */
2002-04-27 12:30:26 +00:00
if ( s -> out_format != FMT_MJPEG ) {
2005-12-17 18:14:38 +00:00
convert_matrix ( & s -> dsp , s -> q_intra_matrix , s -> q_intra_matrix16 ,
2004-12-11 18:33:18 +00:00
s -> intra_matrix , s -> intra_quant_bias , avctx -> qmin , 31 , 1 );
2005-12-17 18:14:38 +00:00
convert_matrix ( & s -> dsp , s -> q_inter_matrix , s -> q_inter_matrix16 ,
2004-12-11 18:33:18 +00:00
s -> inter_matrix , s -> inter_quant_bias , avctx -> qmin , 31 , 0 );
2001-08-12 00:52:37 +00:00
}
2002-04-21 21:18:17 +00:00
if ( ff_rate_control_init ( s ) < 0 )
return - 1 ;
2005-12-17 18:14:38 +00:00
2001-07-22 14:18:56 +00:00
return 0 ;
}
int MPV_encode_end ( AVCodecContext * avctx )
{
MpegEncContext * s = avctx -> priv_data ;
2002-04-21 21:18:17 +00:00
ff_rate_control_uninit ( s );
2001-07-22 14:18:56 +00:00
MPV_common_end ( s );
if ( s -> out_format == FMT_MJPEG )
mjpeg_close ( s );
2003-09-10 23:40:55 +00:00
2003-08-26 20:14:28 +00:00
av_freep ( & avctx -> extradata );
2005-12-17 18:14:38 +00:00
2001-07-22 14:18:56 +00:00
return 0 ;
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2004-11-27 18:10:06 +00:00
void init_rl ( RLTable * rl , int use_static )
2003-01-29 12:00:11 +00:00
{
2003-02-11 16:35:48 +00:00
int8_t max_level [ MAX_RUN + 1 ], max_run [ MAX_LEVEL + 1 ];
uint8_t index_run [ MAX_RUN + 1 ];
2003-01-29 12:00:11 +00:00
int last , run , level , start , end , i ;
2004-11-27 18:10:06 +00:00
/* If table is static, we can quit if rl->max_level[0] is not NULL */
if ( use_static && rl -> max_level [ 0 ])
return ;
2003-01-29 12:00:11 +00:00
/* compute max_level[], max_run[] and index_run[] */
for ( last = 0 ; last < 2 ; last ++ ) {
if ( last == 0 ) {
start = 0 ;
end = rl -> last ;
} else {
start = rl -> last ;
end = rl -> n ;
}
memset ( max_level , 0 , MAX_RUN + 1 );
memset ( max_run , 0 , MAX_LEVEL + 1 );
memset ( index_run , rl -> n , MAX_RUN + 1 );
for ( i = start ; i < end ; i ++ ) {
run = rl -> table_run [ i ];
level = rl -> table_level [ i ];
if ( index_run [ run ] == rl -> n )
index_run [ run ] = i ;
if ( level > max_level [ run ])
max_level [ run ] = level ;
if ( run > max_run [ level ])
max_run [ level ] = run ;
}
2004-11-27 18:10:06 +00:00
if ( use_static )
rl -> max_level [ last ] = av_mallocz_static ( MAX_RUN + 1 );
else
rl -> max_level [ last ] = av_malloc ( MAX_RUN + 1 );
2003-01-29 12:00:11 +00:00
memcpy ( rl -> max_level [ last ], max_level , MAX_RUN + 1 );
2004-11-27 18:10:06 +00:00
if ( use_static )
rl -> max_run [ last ] = av_mallocz_static ( MAX_LEVEL + 1 );
else
rl -> max_run [ last ] = av_malloc ( MAX_LEVEL + 1 );
2003-01-29 12:00:11 +00:00
memcpy ( rl -> max_run [ last ], max_run , MAX_LEVEL + 1 );
2004-11-27 18:10:06 +00:00
if ( use_static )
rl -> index_run [ last ] = av_mallocz_static ( MAX_RUN + 1 );
else
rl -> index_run [ last ] = av_malloc ( MAX_RUN + 1 );
2003-01-29 12:00:11 +00:00
memcpy ( rl -> index_run [ last ], index_run , MAX_RUN + 1 );
}
}
2001-07-22 14:18:56 +00:00
/* draw the edges of width 'w' of an image of size width, height */
2002-08-27 16:28:19 +00:00
//FIXME check that this is ok for mpeg4 interlaced
2003-02-11 16:35:48 +00:00
static void draw_edges_c ( uint8_t * buf , int wrap , int width , int height , int w )
2001-07-22 14:18:56 +00:00
{
2003-02-11 16:35:48 +00:00
uint8_t * ptr , * last_line ;
2001-07-22 14:18:56 +00:00
int i ;
last_line = buf + ( height - 1 ) * wrap ;
for ( i = 0 ; i < w ; i ++ ) {
/* top and bottom */
memcpy ( buf - ( i + 1 ) * wrap , buf , width );
memcpy ( last_line + ( i + 1 ) * wrap , last_line , width );
}
/* left and right */
ptr = buf ;
for ( i = 0 ; i < height ; i ++ ) {
memset ( ptr - w , ptr [ 0 ], w );
memset ( ptr + width , ptr [ width - 1 ], w );
ptr += wrap ;
}
/* corners */
for ( i = 0 ; i < w ; i ++ ) {
memset ( buf - ( i + 1 ) * wrap - w , buf [ 0 ], w ); /* top left */
memset ( buf - ( i + 1 ) * wrap + width , buf [ width - 1 ], w ); /* top right */
memset ( last_line + ( i + 1 ) * wrap - w , last_line [ 0 ], w ); /* top left */
memset ( last_line + ( i + 1 ) * wrap + width , last_line [ width - 1 ], w ); /* top right */
}
}
2003-10-30 16:58:49 +00:00
int ff_find_unused_picture ( MpegEncContext * s , int shared ){
2002-12-09 00:29:17 +00:00
int i ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( shared ){
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
2003-10-30 16:58:49 +00:00
if ( s -> picture [ i ]. data [ 0 ] == NULL && s -> picture [ i ]. type == 0 ) return i ;
2002-12-09 00:29:17 +00:00
}
} else {
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
2003-10-30 16:58:49 +00:00
if ( s -> picture [ i ]. data [ 0 ] == NULL && s -> picture [ i ]. type != 0 ) return i ; //FIXME
2002-12-09 00:29:17 +00:00
}
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
2003-10-30 16:58:49 +00:00
if ( s -> picture [ i ]. data [ 0 ] == NULL ) return i ;
2002-12-09 00:29:17 +00:00
}
}
2003-10-30 16:58:49 +00:00
assert ( 0 );
return - 1 ;
2002-12-09 00:29:17 +00:00
}
2003-11-02 23:19:47 +00:00
static void update_noise_reduction ( MpegEncContext * s ){
int intra , i ;
for ( intra = 0 ; intra < 2 ; intra ++ ){
if ( s -> dct_count [ intra ] > ( 1 << 16 )){
for ( i = 0 ; i < 64 ; i ++ ){
s -> dct_error_sum [ intra ][ i ] >>= 1 ;
}
s -> dct_count [ intra ] >>= 1 ;
}
2005-12-17 18:14:38 +00:00
2003-11-02 23:19:47 +00:00
for ( i = 0 ; i < 64 ; i ++ ){
s -> dct_offset [ intra ][ i ] = ( s -> avctx -> noise_reduction * s -> dct_count [ intra ] + s -> dct_error_sum [ intra ][ i ] / 2 ) / ( s -> dct_error_sum [ intra ][ i ] + 1 );
}
}
}
2003-10-30 16:58:49 +00:00
/**
* generic function for encode/decode called after coding/decoding the header and before a frame is coded/decoded
*/
2002-10-27 00:02:23 +00:00
int MPV_frame_start ( MpegEncContext * s , AVCodecContext * avctx )
2001-07-22 14:18:56 +00:00
{
2002-12-09 00:29:17 +00:00
int i ;
2002-12-09 12:03:43 +00:00
AVFrame * pic ;
2005-04-24 17:21:11 +00:00
s -> mb_skipped = 0 ;
2003-04-04 14:42:28 +00:00
2003-05-09 22:16:14 +00:00
assert ( s -> last_picture_ptr == NULL || s -> out_format != FMT_H264 || s -> codec_id == CODEC_ID_SVQ3 );
2003-05-06 20:43:37 +00:00
2002-12-04 10:04:03 +00:00
/* mark&release old frames */
2004-04-17 13:36:21 +00:00
if ( s -> pict_type != B_TYPE && s -> last_picture_ptr && s -> last_picture_ptr != s -> next_picture_ptr && s -> last_picture_ptr -> data [ 0 ]) {
2003-03-16 20:22:22 +00:00
avctx -> release_buffer ( avctx , ( AVFrame * ) s -> last_picture_ptr );
2002-12-04 10:04:03 +00:00
/* release forgotten pictures */
/* if(mpeg124/h263) */
if ( ! s -> encoding ){
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
2003-03-16 20:22:22 +00:00
if ( s -> picture [ i ]. data [ 0 ] && & s -> picture [ i ] != s -> next_picture_ptr && s -> picture [ i ]. reference ){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "releasing zombie picture \n " );
2005-12-17 18:14:38 +00:00
avctx -> release_buffer ( avctx , ( AVFrame * ) & s -> picture [ i ]);
2002-12-04 10:04:03 +00:00
}
}
}
}
2002-12-04 22:16:24 +00:00
alloc :
if ( ! s -> encoding ){
2005-06-17 15:02:53 +00:00
/* release non reference frames */
2003-05-06 20:43:37 +00:00
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
if ( s -> picture [ i ]. data [ 0 ] && ! s -> picture [ i ]. reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/ ){
s -> avctx -> release_buffer ( s -> avctx , ( AVFrame * ) & s -> picture [ i ]);
}
}
2003-10-30 16:58:49 +00:00
if ( s -> current_picture_ptr && s -> current_picture_ptr -> data [ 0 ] == NULL )
pic = ( AVFrame * ) s -> current_picture_ptr ; //we allready have a unused image (maybe it was set before reading the header)
else {
i = ff_find_unused_picture ( s , 0 );
pic = ( AVFrame * ) & s -> picture [ i ];
}
2005-03-04 12:47:38 +00:00
pic -> reference = ( s -> pict_type != B_TYPE || s -> codec_id == CODEC_ID_H264 )
&& ! s -> dropable ? 3 : 0 ;
2003-03-16 20:22:22 +00:00
2003-12-29 22:25:08 +00:00
pic -> coded_picture_number = s -> coded_picture_number ++ ;
2005-12-17 18:14:38 +00:00
2003-07-26 23:31:13 +00:00
if ( alloc_picture ( s , ( Picture * ) pic , 0 ) < 0 )
return - 1 ;
2002-12-04 10:04:03 +00:00
2003-10-30 16:58:49 +00:00
s -> current_picture_ptr = ( Picture * ) pic ;
2003-12-05 00:19:46 +00:00
s -> current_picture_ptr -> top_field_first = s -> top_field_first ; //FIXME use only the vars from current_pic
2003-12-05 01:03:12 +00:00
s -> current_picture_ptr -> interlaced_frame = ! s -> progressive_frame && ! s -> progressive_sequence ;
2002-12-04 10:04:03 +00:00
}
2002-06-02 12:20:39 +00:00
2003-04-06 21:03:24 +00:00
s -> current_picture_ptr -> pict_type = s -> pict_type ;
2005-12-17 18:14:38 +00:00
// if(s->flags && CODEC_FLAG_QSCALE)
2003-10-07 11:32:40 +00:00
// s->current_picture_ptr->quality= s->new_picture_ptr->quality;
2003-04-10 13:18:38 +00:00
s -> current_picture_ptr -> key_frame = s -> pict_type == I_TYPE ;
2003-04-06 21:03:24 +00:00
2003-10-16 00:21:54 +00:00
copy_picture ( & s -> current_picture , s -> current_picture_ptr );
2005-12-17 18:14:38 +00:00
2003-05-09 22:16:14 +00:00
if ( s -> out_format != FMT_H264 || s -> codec_id == CODEC_ID_SVQ3 ){
2002-12-04 10:04:03 +00:00
if ( s -> pict_type != B_TYPE ) {
2003-03-16 20:22:22 +00:00
s -> last_picture_ptr = s -> next_picture_ptr ;
2004-04-17 13:36:21 +00:00
if ( ! s -> dropable )
s -> next_picture_ptr = s -> current_picture_ptr ;
2003-03-16 20:22:22 +00:00
}
2004-04-17 13:36:21 +00:00
/* av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
2005-12-17 18:14:38 +00:00
s->last_picture_ptr ? s->last_picture_ptr->data[0] : NULL,
s->next_picture_ptr ? s->next_picture_ptr->data[0] : NULL,
2004-04-17 13:36:21 +00:00
s->current_picture_ptr ? s->current_picture_ptr->data[0] : NULL,
s->pict_type, s->dropable);*/
2005-12-17 18:14:38 +00:00
2003-10-16 00:21:54 +00:00
if ( s -> last_picture_ptr ) copy_picture ( & s -> last_picture , s -> last_picture_ptr );
if ( s -> next_picture_ptr ) copy_picture ( & s -> next_picture , s -> next_picture_ptr );
2005-12-17 18:14:38 +00:00
2003-10-16 00:21:54 +00:00
if ( s -> pict_type != I_TYPE && ( s -> last_picture_ptr == NULL || s -> last_picture_ptr -> data [ 0 ] == NULL )){
2003-11-03 13:26:22 +00:00
av_log ( avctx , AV_LOG_ERROR , "warning: first frame is no keyframe \n " );
2005-06-17 15:02:53 +00:00
assert ( s -> pict_type != B_TYPE ); //these should have been dropped if we don't have a reference
2003-08-01 11:00:03 +00:00
goto alloc ;
}
assert ( s -> pict_type == I_TYPE || ( s -> last_picture_ptr && s -> last_picture_ptr -> data [ 0 ]));
2003-03-16 20:22:22 +00:00
if ( s -> picture_structure != PICT_FRAME ){
int i ;
for ( i = 0 ; i < 4 ; i ++ ){
if ( s -> picture_structure == PICT_BOTTOM_FIELD ){
s -> current_picture . data [ i ] += s -> current_picture . linesize [ i ];
2005-12-17 18:14:38 +00:00
}
2003-03-16 20:22:22 +00:00
s -> current_picture . linesize [ i ] *= 2 ;
s -> last_picture . linesize [ i ] *= 2 ;
s -> next_picture . linesize [ i ] *= 2 ;
}
2001-07-22 14:18:56 +00:00
}
2003-04-04 14:42:28 +00:00
}
2005-12-17 18:14:38 +00:00
2002-12-04 22:16:24 +00:00
s -> hurry_up = s -> avctx -> hurry_up ;
s -> error_resilience = avctx -> error_resilience ;
2005-06-17 15:02:53 +00:00
/* set dequantizer, we can't do it during init as it might change for mpeg4
and we can't do it in the header decode as init isnt called for mpeg4 there yet */
2003-12-14 02:57:00 +00:00
if ( s -> mpeg_quant || s -> codec_id == CODEC_ID_MPEG2VIDEO ){
s -> dct_unquantize_intra = s -> dct_unquantize_mpeg2_intra ;
s -> dct_unquantize_inter = s -> dct_unquantize_mpeg2_inter ;
2004-11-12 01:21:34 +00:00
} else if ( s -> out_format == FMT_H263 || s -> out_format == FMT_H261 ){
2003-12-14 02:57:00 +00:00
s -> dct_unquantize_intra = s -> dct_unquantize_h263_intra ;
s -> dct_unquantize_inter = s -> dct_unquantize_h263_inter ;
} else {
s -> dct_unquantize_intra = s -> dct_unquantize_mpeg1_intra ;
s -> dct_unquantize_inter = s -> dct_unquantize_mpeg1_inter ;
}
2002-10-27 00:02:23 +00:00
2003-11-02 23:19:47 +00:00
if ( s -> dct_error_sum ){
assert ( s -> avctx -> noise_reduction && s -> encoding );
update_noise_reduction ( s );
}
2005-12-17 18:14:38 +00:00
2003-07-26 01:28:49 +00:00
#ifdef HAVE_XVMC
if ( s -> avctx -> xvmc_acceleration )
return XVMC_field_start ( s , avctx );
#endif
2002-10-27 00:02:23 +00:00
return 0 ;
2001-07-22 14:18:56 +00:00
}
2001-07-30 23:26:26 +00:00
2001-07-22 14:18:56 +00:00
/* generic function for encode/decode called after a frame has been coded/decoded */
void MPV_frame_end ( MpegEncContext * s )
{
2002-12-04 10:04:03 +00:00
int i ;
2001-07-22 14:18:56 +00:00
/* draw edge for correct motion prediction if outside */
2003-07-26 01:28:49 +00:00
#ifdef HAVE_XVMC
//just to make sure that all data is rendered.
if ( s -> avctx -> xvmc_acceleration ){
XVMC_field_end ( s );
} else
#endif
2005-03-04 12:47:38 +00:00
if ( s -> unrestricted_mv && s -> current_picture . reference && ! s -> intra_only && ! ( s -> flags & CODEC_FLAG_EMU_EDGE )) {
2002-12-04 10:04:03 +00:00
draw_edges ( s -> current_picture . data [ 0 ], s -> linesize , s -> h_edge_pos , s -> v_edge_pos , EDGE_WIDTH );
draw_edges ( s -> current_picture . data [ 1 ], s -> uvlinesize , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 , EDGE_WIDTH / 2 );
draw_edges ( s -> current_picture . data [ 2 ], s -> uvlinesize , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 , EDGE_WIDTH / 2 );
2001-07-22 14:18:56 +00:00
}
2002-01-15 05:02:26 +00:00
emms_c ();
2005-12-17 18:14:38 +00:00
2002-08-25 21:19:50 +00:00
s -> last_pict_type = s -> pict_type ;
2005-12-29 15:46:23 +00:00
s -> last_lambda_for [ s -> pict_type ] = s -> current_picture_ptr -> quality ;
2002-04-21 21:18:17 +00:00
if ( s -> pict_type != B_TYPE ){
s -> last_non_b_pict_type = s -> pict_type ;
}
2003-03-16 20:22:22 +00:00
#if 0
/* copy back current_picture variables */
2002-12-04 10:04:03 +00:00
for(i=0; i<MAX_PICTURE_COUNT; i++){
if(s->picture[i].data[0] == s->current_picture.data[0]){
s->picture[i]= s->current_picture;
break;
2005-12-17 18:14:38 +00:00
}
2002-12-04 10:04:03 +00:00
}
assert(i<MAX_PICTURE_COUNT);
2005-12-17 18:14:38 +00:00
#endif
2002-12-04 10:04:03 +00:00
2003-05-06 20:43:37 +00:00
if ( s -> encoding ){
2005-06-17 15:02:53 +00:00
/* release non-reference frames */
2003-05-06 20:43:37 +00:00
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
if ( s -> picture [ i ]. data [ 0 ] && ! s -> picture [ i ]. reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/ ){
s -> avctx -> release_buffer ( s -> avctx , ( AVFrame * ) & s -> picture [ i ]);
}
}
2002-12-04 10:04:03 +00:00
}
2003-03-16 20:22:22 +00:00
// clear copies, to avoid confusion
#if 0
memset(&s->last_picture, 0, sizeof(Picture));
memset(&s->next_picture, 0, sizeof(Picture));
memset(&s->current_picture, 0, sizeof(Picture));
#endif
2004-09-08 10:07:08 +00:00
s -> avctx -> coded_frame = ( AVFrame * ) s -> current_picture_ptr ;
2001-07-22 14:18:56 +00:00
}
2003-05-27 12:31:03 +00:00
/**
* draws an line from (ex, ey) -> (sx, sy).
* @param w width of the image
* @param h height of the image
* @param stride stride/linesize of the image
* @param color color of the arrow
*/
static void draw_line ( uint8_t * buf , int sx , int sy , int ex , int ey , int w , int h , int stride , int color ){
2006-08-19 20:55:02 +00:00
int x , y , fr , f ;
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
sx = clip ( sx , 0 , w - 1 );
sy = clip ( sy , 0 , h - 1 );
ex = clip ( ex , 0 , w - 1 );
ey = clip ( ey , 0 , h - 1 );
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
buf [ sy * stride + sx ] += color ;
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
if ( ABS ( ex - sx ) > ABS ( ey - sy )){
if ( sx > ex ){
2006-08-19 20:55:02 +00:00
SWAP ( int , sx , ex );
SWAP ( int , sy , ey );
2003-05-27 12:31:03 +00:00
}
buf += sx + sy * stride ;
ex -= sx ;
f = (( ey - sy ) << 16 ) / ex ;
for ( x = 0 ; x <= ex ; x ++ ){
2004-04-03 01:55:24 +00:00
y = ( x * f ) >> 16 ;
fr = ( x * f ) & 0xFFFF ;
buf [ y * stride + x ] += ( color * ( 0x10000 - fr )) >> 16 ;
buf [( y + 1 ) * stride + x ] += ( color * fr ) >> 16 ;
2003-05-27 12:31:03 +00:00
}
} else {
if ( sy > ey ){
2006-08-19 20:55:02 +00:00
SWAP ( int , sx , ex );
SWAP ( int , sy , ey );
2003-05-27 12:31:03 +00:00
}
buf += sx + sy * stride ;
ey -= sy ;
if ( ey ) f = (( ex - sx ) << 16 ) / ey ;
else f = 0 ;
for ( y = 0 ; y <= ey ; y ++ ){
2004-04-03 01:55:24 +00:00
x = ( y * f ) >> 16 ;
fr = ( y * f ) & 0xFFFF ;
buf [ y * stride + x ] += ( color * ( 0x10000 - fr )) >> 16 ;;
buf [ y * stride + x + 1 ] += ( color * fr ) >> 16 ;;
2003-05-27 12:31:03 +00:00
}
}
}
/**
* draws an arrow from (ex, ey) -> (sx, sy).
* @param w width of the image
* @param h height of the image
* @param stride stride/linesize of the image
* @param color color of the arrow
*/
2005-12-17 18:14:38 +00:00
static void draw_arrow ( uint8_t * buf , int sx , int sy , int ex , int ey , int w , int h , int stride , int color ){
2003-05-27 12:31:03 +00:00
int dx , dy ;
sx = clip ( sx , - 100 , w + 100 );
sy = clip ( sy , - 100 , h + 100 );
ex = clip ( ex , - 100 , w + 100 );
ey = clip ( ey , - 100 , h + 100 );
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
dx = ex - sx ;
dy = ey - sy ;
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
if ( dx * dx + dy * dy > 3 * 3 ){
int rx = dx + dy ;
int ry = - dx + dy ;
int length = ff_sqrt (( rx * rx + ry * ry ) << 8 );
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
//FIXME subpixel accuracy
rx = ROUNDED_DIV ( rx * 3 << 4 , length );
ry = ROUNDED_DIV ( ry * 3 << 4 , length );
2005-12-17 18:14:38 +00:00
2003-05-27 12:31:03 +00:00
draw_line ( buf , sx , sy , sx + rx , sy + ry , w , h , stride , color );
draw_line ( buf , sx , sy , sx - ry , sy + rx , w , h , stride , color );
}
draw_line ( buf , sx , sy , ex , ey , w , h , stride , color );
}
2003-04-10 13:18:38 +00:00
/**
* prints debuging info for the given picture.
*/
2003-12-30 02:12:12 +00:00
void ff_print_debug_info ( MpegEncContext * s , AVFrame * pict ){
2003-04-10 13:18:38 +00:00
if ( ! pict || ! pict -> mb_type ) return ;
if ( s -> avctx -> debug & ( FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE )){
int x , y ;
2005-12-17 18:14:38 +00:00
2003-12-30 02:12:12 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "New frame, type: " );
switch ( pict -> pict_type ) {
case FF_I_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "I \n " ); break ;
case FF_P_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "P \n " ); break ;
case FF_B_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "B \n " ); break ;
case FF_S_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "S \n " ); break ;
case FF_SI_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "SI \n " ); break ;
2005-12-17 18:14:38 +00:00
case FF_SP_TYPE : av_log ( s -> avctx , AV_LOG_DEBUG , "SP \n " ); break ;
2003-12-30 02:12:12 +00:00
}
2003-04-10 13:18:38 +00:00
for ( y = 0 ; y < s -> mb_height ; y ++ ){
for ( x = 0 ; x < s -> mb_width ; x ++ ){
if ( s -> avctx -> debug & FF_DEBUG_SKIP ){
int count = s -> mbskip_table [ x + y * s -> mb_stride ];
if ( count > 9 ) count = 9 ;
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "%1d" , count );
2003-04-10 13:18:38 +00:00
}
if ( s -> avctx -> debug & FF_DEBUG_QP ){
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "%2d" , pict -> qscale_table [ x + y * s -> mb_stride ]);
2003-04-10 13:18:38 +00:00
}
if ( s -> avctx -> debug & FF_DEBUG_MB_TYPE ){
int mb_type = pict -> mb_type [ x + y * s -> mb_stride ];
//Type & MV direction
if ( IS_PCM ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "P" );
2003-04-10 13:18:38 +00:00
else if ( IS_INTRA ( mb_type ) && IS_ACPRED ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "A" );
2003-04-10 13:18:38 +00:00
else if ( IS_INTRA4x4 ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "i" );
2003-04-10 13:18:38 +00:00
else if ( IS_INTRA16x16 ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "I" );
2003-04-10 13:18:38 +00:00
else if ( IS_DIRECT ( mb_type ) && IS_SKIP ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "d" );
2003-04-10 13:18:38 +00:00
else if ( IS_DIRECT ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "D" );
2003-04-10 13:18:38 +00:00
else if ( IS_GMC ( mb_type ) && IS_SKIP ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "g" );
2003-04-10 13:18:38 +00:00
else if ( IS_GMC ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "G" );
2003-04-10 13:18:38 +00:00
else if ( IS_SKIP ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "S" );
2003-04-10 13:18:38 +00:00
else if ( ! USES_LIST ( mb_type , 1 ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , ">" );
2003-04-10 13:18:38 +00:00
else if ( ! USES_LIST ( mb_type , 0 ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "<" );
2003-04-10 13:18:38 +00:00
else {
assert ( USES_LIST ( mb_type , 0 ) && USES_LIST ( mb_type , 1 ));
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "X" );
2003-04-10 13:18:38 +00:00
}
2005-12-17 18:14:38 +00:00
2003-04-10 13:18:38 +00:00
//segmentation
if ( IS_8X8 ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "+" );
2003-04-10 13:18:38 +00:00
else if ( IS_16X8 ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "-" );
2003-04-10 13:18:38 +00:00
else if ( IS_8X16 ( mb_type ))
2005-05-13 21:04:16 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "|" );
2003-04-10 13:18:38 +00:00
else if ( IS_INTRA ( mb_type ) || IS_16X16 ( mb_type ))
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , " " );
2003-04-10 13:18:38 +00:00
else
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "?" );
2005-12-17 18:14:38 +00:00
2003-04-10 13:18:38 +00:00
if ( IS_INTERLACED ( mb_type ) && s -> codec_id == CODEC_ID_H264 )
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , "=" );
2003-04-10 13:18:38 +00:00
else
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , " " );
2003-04-10 13:18:38 +00:00
}
2003-11-03 13:26:22 +00:00
// av_log(s->avctx, AV_LOG_DEBUG, " ");
2003-04-10 13:18:38 +00:00
}
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_DEBUG , " \n " );
2003-04-10 13:18:38 +00:00
}
}
2003-12-09 01:49:56 +00:00
2003-12-30 02:12:12 +00:00
if (( s -> avctx -> debug & ( FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE )) || ( s -> avctx -> debug_mv )){
2003-05-27 12:31:03 +00:00
const int shift = 1 + s -> quarter_sample ;
int mb_y ;
2003-12-30 02:12:12 +00:00
uint8_t * ptr ;
int i ;
2004-01-04 17:13:14 +00:00
int h_chroma_shift , v_chroma_shift ;
2004-09-27 02:39:55 +00:00
const int width = s -> avctx -> width ;
const int height = s -> avctx -> height ;
2004-12-20 03:03:37 +00:00
const int mv_sample_log2 = 4 - pict -> motion_subsample_log2 ;
2006-04-21 19:22:14 +00:00
const int mv_stride = ( s -> mb_width << mv_sample_log2 ) + ( s -> codec_id == CODEC_ID_H264 ? 0 : 1 );
2003-12-30 15:29:38 +00:00
s -> low_delay = 0 ; //needed to see the vectors without trashing the buffers
2003-12-30 02:12:12 +00:00
2004-01-04 17:13:14 +00:00
avcodec_get_chroma_sub_sample ( s -> avctx -> pix_fmt , & h_chroma_shift , & v_chroma_shift );
2003-12-30 02:12:12 +00:00
for ( i = 0 ; i < 3 ; i ++ ){
2004-09-27 02:39:55 +00:00
memcpy ( s -> visualization_buffer [ i ], pict -> data [ i ], ( i == 0 ) ? pict -> linesize [ i ] * height : pict -> linesize [ i ] * height >> v_chroma_shift );
2003-12-30 02:12:12 +00:00
pict -> data [ i ] = s -> visualization_buffer [ i ];
}
pict -> type = FF_BUFFER_TYPE_COPY ;
ptr = pict -> data [ 0 ];
2003-05-27 12:31:03 +00:00
for ( mb_y = 0 ; mb_y < s -> mb_height ; mb_y ++ ){
int mb_x ;
for ( mb_x = 0 ; mb_x < s -> mb_width ; mb_x ++ ){
const int mb_index = mb_x + mb_y * s -> mb_stride ;
2003-12-30 02:12:12 +00:00
if (( s -> avctx -> debug_mv ) && pict -> motion_val ){
int type ;
for ( type = 0 ; type < 3 ; type ++ ){
2004-05-18 17:09:46 +00:00
int direction = 0 ;
2003-12-30 02:12:12 +00:00
switch ( type ) {
case 0 : if (( ! ( s -> avctx -> debug_mv & FF_DEBUG_VIS_MV_P_FOR )) || ( pict -> pict_type != FF_P_TYPE ))
continue ;
direction = 0 ;
break ;
case 1 : if (( ! ( s -> avctx -> debug_mv & FF_DEBUG_VIS_MV_B_FOR )) || ( pict -> pict_type != FF_B_TYPE ))
continue ;
direction = 0 ;
break ;
case 2 : if (( ! ( s -> avctx -> debug_mv & FF_DEBUG_VIS_MV_B_BACK )) || ( pict -> pict_type != FF_B_TYPE ))
continue ;
direction = 1 ;
break ;
}
2004-01-01 16:56:04 +00:00
if ( ! USES_LIST ( pict -> mb_type [ mb_index ], direction ))
continue ;
2003-12-30 02:12:12 +00:00
if ( IS_8X8 ( pict -> mb_type [ mb_index ])){
int i ;
for ( i = 0 ; i < 4 ; i ++ ){
2003-05-27 12:31:03 +00:00
int sx = mb_x * 16 + 4 + 8 * ( i & 1 );
int sy = mb_y * 16 + 4 + 8 * ( i >> 1 );
2005-02-24 19:08:50 +00:00
int xy = ( mb_x * 2 + ( i & 1 ) + ( mb_y * 2 + ( i >> 1 )) * mv_stride ) << ( mv_sample_log2 - 1 );
2003-12-30 02:12:12 +00:00
int mx = ( pict -> motion_val [ direction ][ xy ][ 0 ] >> shift ) + sx ;
int my = ( pict -> motion_val [ direction ][ xy ][ 1 ] >> shift ) + sy ;
2004-09-27 02:39:55 +00:00
draw_arrow ( ptr , sx , sy , mx , my , width , height , s -> linesize , 100 );
2003-12-30 02:12:12 +00:00
}
} else if ( IS_16X8 ( pict -> mb_type [ mb_index ])){
int i ;
for ( i = 0 ; i < 2 ; i ++ ){
2003-11-25 00:35:18 +00:00
int sx = mb_x * 16 + 8 ;
int sy = mb_y * 16 + 4 + 8 * i ;
2005-02-24 19:08:50 +00:00
int xy = ( mb_x * 2 + ( mb_y * 2 + i ) * mv_stride ) << ( mv_sample_log2 - 1 );
2004-12-20 03:03:37 +00:00
int mx = ( pict -> motion_val [ direction ][ xy ][ 0 ] >> shift );
int my = ( pict -> motion_val [ direction ][ xy ][ 1 ] >> shift );
2005-12-17 18:14:38 +00:00
2004-12-20 03:03:37 +00:00
if ( IS_INTERLACED ( pict -> mb_type [ mb_index ]))
my *= 2 ;
2005-12-17 18:14:38 +00:00
2004-12-20 03:03:37 +00:00
draw_arrow ( ptr , sx , sy , mx + sx , my + sy , width , height , s -> linesize , 100 );
}
} else if ( IS_8X16 ( pict -> mb_type [ mb_index ])){
int i ;
for ( i = 0 ; i < 2 ; i ++ ){
int sx = mb_x * 16 + 4 + 8 * i ;
int sy = mb_y * 16 + 8 ;
2005-02-24 19:08:50 +00:00
int xy = ( mb_x * 2 + i + mb_y * 2 * mv_stride ) << ( mv_sample_log2 - 1 );
2004-04-18 18:30:05 +00:00
int mx = ( pict -> motion_val [ direction ][ xy ][ 0 ] >> shift );
int my = ( pict -> motion_val [ direction ][ xy ][ 1 ] >> shift );
2005-12-17 18:14:38 +00:00
2004-04-18 18:30:05 +00:00
if ( IS_INTERLACED ( pict -> mb_type [ mb_index ]))
my *= 2 ;
2005-12-17 18:14:38 +00:00
2004-09-27 02:39:55 +00:00
draw_arrow ( ptr , sx , sy , mx + sx , my + sy , width , height , s -> linesize , 100 );
2003-12-30 02:12:12 +00:00
}
} else {
int sx = mb_x * 16 + 8 ;
int sy = mb_y * 16 + 8 ;
2004-12-20 03:03:37 +00:00
int xy = ( mb_x + mb_y * mv_stride ) << mv_sample_log2 ;
2003-12-30 02:12:12 +00:00
int mx = ( pict -> motion_val [ direction ][ xy ][ 0 ] >> shift ) + sx ;
int my = ( pict -> motion_val [ direction ][ xy ][ 1 ] >> shift ) + sy ;
2004-09-27 02:39:55 +00:00
draw_arrow ( ptr , sx , sy , mx , my , width , height , s -> linesize , 100 );
2003-11-25 00:35:18 +00:00
}
2005-12-17 18:14:38 +00:00
}
2003-12-13 01:33:52 +00:00
}
if (( s -> avctx -> debug & FF_DEBUG_VIS_QP ) && pict -> motion_val ){
uint64_t c = ( pict -> qscale_table [ mb_index ] * 128 / 31 ) * 0x0101010101010101ULL ;
int y ;
for ( y = 0 ; y < 8 ; y ++ ){
* ( uint64_t * )( pict -> data [ 1 ] + 8 * mb_x + ( 8 * mb_y + y ) * pict -> linesize [ 1 ]) = c ;
* ( uint64_t * )( pict -> data [ 2 ] + 8 * mb_x + ( 8 * mb_y + y ) * pict -> linesize [ 2 ]) = c ;
}
}
if (( s -> avctx -> debug & FF_DEBUG_VIS_MB_TYPE ) && pict -> motion_val ){
int mb_type = pict -> mb_type [ mb_index ];
uint64_t u , v ;
int y ;
#define COLOR(theta, r)\
u= (int)(128 + r*cos(theta*3.141592/180));\
v= (int)(128 + r*sin(theta*3.141592/180));
2005-12-17 18:14:38 +00:00
2003-12-13 01:33:52 +00:00
u = v = 128 ;
if ( IS_PCM ( mb_type )){
COLOR ( 120 , 48 )
} else if (( IS_INTRA ( mb_type ) && IS_ACPRED ( mb_type )) || IS_INTRA16x16 ( mb_type )){
COLOR ( 30 , 48 )
} else if ( IS_INTRA4x4 ( mb_type )){
COLOR ( 90 , 48 )
} else if ( IS_DIRECT ( mb_type ) && IS_SKIP ( mb_type )){
// COLOR(120,48)
} else if ( IS_DIRECT ( mb_type )){
COLOR ( 150 , 48 )
} else if ( IS_GMC ( mb_type ) && IS_SKIP ( mb_type )){
COLOR ( 170 , 48 )
} else if ( IS_GMC ( mb_type )){
COLOR ( 190 , 48 )
} else if ( IS_SKIP ( mb_type )){
// COLOR(180,48)
} else if ( ! USES_LIST ( mb_type , 1 )){
COLOR ( 240 , 48 )
} else if ( ! USES_LIST ( mb_type , 0 )){
COLOR ( 0 , 48 )
} else {
assert ( USES_LIST ( mb_type , 0 ) && USES_LIST ( mb_type , 1 ));
COLOR ( 300 , 48 )
}
u *= 0x0101010101010101ULL ;
v *= 0x0101010101010101ULL ;
for ( y = 0 ; y < 8 ; y ++ ){
* ( uint64_t * )( pict -> data [ 1 ] + 8 * mb_x + ( 8 * mb_y + y ) * pict -> linesize [ 1 ]) = u ;
* ( uint64_t * )( pict -> data [ 2 ] + 8 * mb_x + ( 8 * mb_y + y ) * pict -> linesize [ 2 ]) = v ;
}
//segmentation
if ( IS_8X8 ( mb_type ) || IS_16X8 ( mb_type )){
* ( uint64_t * )( pict -> data [ 0 ] + 16 * mb_x + 0 + ( 16 * mb_y + 8 ) * pict -> linesize [ 0 ]) ^= 0x8080808080808080ULL ;
* ( uint64_t * )( pict -> data [ 0 ] + 16 * mb_x + 8 + ( 16 * mb_y + 8 ) * pict -> linesize [ 0 ]) ^= 0x8080808080808080ULL ;
}
if ( IS_8X8 ( mb_type ) || IS_8X16 ( mb_type )){
for ( y = 0 ; y < 16 ; y ++ )
pict -> data [ 0 ][ 16 * mb_x + 8 + ( 16 * mb_y + y ) * pict -> linesize [ 0 ]] ^= 0x80 ;
}
2005-03-03 06:57:17 +00:00
if ( IS_8X8 ( mb_type ) && mv_sample_log2 >= 2 ){
int dm = 1 << ( mv_sample_log2 - 2 );
for ( i = 0 ; i < 4 ; i ++ ){
int sx = mb_x * 16 + 8 * ( i & 1 );
int sy = mb_y * 16 + 8 * ( i >> 1 );
int xy = ( mb_x * 2 + ( i & 1 ) + ( mb_y * 2 + ( i >> 1 )) * mv_stride ) << ( mv_sample_log2 - 1 );
//FIXME bidir
int32_t * mv = ( int32_t * ) & pict -> motion_val [ 0 ][ xy ];
if ( mv [ 0 ] != mv [ dm ] || mv [ dm * mv_stride ] != mv [ dm * ( mv_stride + 1 )])
for ( y = 0 ; y < 8 ; y ++ )
pict -> data [ 0 ][ sx + 4 + ( sy + y ) * pict -> linesize [ 0 ]] ^= 0x80 ;
if ( mv [ 0 ] != mv [ dm * mv_stride ] || mv [ dm ] != mv [ dm * ( mv_stride + 1 )])
* ( uint64_t * )( pict -> data [ 0 ] + sx + ( sy + 4 ) * pict -> linesize [ 0 ]) ^= 0x8080808080808080ULL ;
}
}
2005-12-17 18:14:38 +00:00
2003-12-13 01:33:52 +00:00
if ( IS_INTERLACED ( mb_type ) && s -> codec_id == CODEC_ID_H264 ){
// hmm
}
2003-05-27 12:31:03 +00:00
}
s -> mbskip_table [ mb_index ] = 0 ;
}
}
}
2003-04-10 13:18:38 +00:00
}
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2002-12-06 13:30:13 +00:00
static int get_sae ( uint8_t * src , int ref , int stride ){
int x , y ;
int acc = 0 ;
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
for ( y = 0 ; y < 16 ; y ++ ){
for ( x = 0 ; x < 16 ; x ++ ){
acc += ABS ( src [ x + y * stride ] - ref );
}
}
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
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 ;
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
w = s -> width &~ 15 ;
h = s -> height &~ 15 ;
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
for ( y = 0 ; y < h ; y += 16 ){
for ( x = 0 ; x < w ; x += 16 ){
int offset = x + y * stride ;
2003-12-30 16:07:57 +00:00
int sad = s -> dsp . sad [ 0 ]( NULL , src + offset , ref + offset , stride , 16 );
2002-12-06 13:30:13 +00:00
int mean = ( s -> dsp . pix_sum ( src + offset , stride ) + 128 ) >> 8 ;
int sae = get_sae ( src + offset , mean , stride );
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
acc += sae + 500 < sad ;
}
}
return acc ;
}
2002-12-09 00:29:17 +00:00
2002-12-09 12:03:43 +00:00
static int load_input_picture ( MpegEncContext * s , AVFrame * pic_arg ){
2003-07-23 10:41:07 +00:00
AVFrame * pic = NULL ;
2005-01-13 11:59:19 +00:00
int64_t pts ;
2002-12-09 00:29:17 +00:00
int i ;
2002-12-04 10:04:03 +00:00
const int encoding_delay = s -> max_b_frames ;
2002-12-09 00:29:17 +00:00
int direct = 1 ;
2005-12-17 18:14:38 +00:00
2005-01-10 23:41:25 +00:00
if ( pic_arg ){
2005-01-13 11:59:19 +00:00
pts = pic_arg -> pts ;
pic_arg -> display_picture_number = s -> input_picture_number ++ ;
2005-12-17 18:14:38 +00:00
if ( pts != AV_NOPTS_VALUE ){
2005-01-10 23:41:25 +00:00
if ( s -> user_specified_pts != AV_NOPTS_VALUE ){
2005-04-30 21:43:59 +00:00
int64_t time = pts ;
int64_t last = s -> user_specified_pts ;
2005-12-17 18:14:38 +00:00
if ( time <= last ){
2005-12-12 01:56:46 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "Error, Invalid timestamp=%" PRId64 ", last=%" PRId64 " \n " , pts , s -> user_specified_pts );
2005-01-10 23:41:25 +00:00
return - 1 ;
}
}
2005-01-13 11:59:19 +00:00
s -> user_specified_pts = pts ;
2005-01-10 23:41:25 +00:00
} else {
if ( s -> user_specified_pts != AV_NOPTS_VALUE ){
2005-12-17 18:14:38 +00:00
s -> user_specified_pts =
2005-04-30 21:43:59 +00:00
pts = s -> user_specified_pts + 1 ;
2005-12-12 01:56:46 +00:00
av_log ( s -> avctx , AV_LOG_INFO , "Warning: AVFrame.pts=? trying to guess (%" PRId64 ") \n " , pts );
2005-01-10 23:41:25 +00:00
} else {
2005-04-30 21:43:59 +00:00
pts = pic_arg -> display_picture_number ;
2005-01-10 23:41:25 +00:00
}
}
}
2003-07-23 10:41:07 +00:00
if ( pic_arg ){
2002-12-09 00:29:17 +00:00
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 ;
2005-12-17 18:14:38 +00:00
2003-11-03 13:26:22 +00:00
// av_log(AV_LOG_DEBUG, "%d %d %d %d\n",pic_arg->linesize[0], pic_arg->linesize[1], s->linesize, s->uvlinesize);
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( direct ){
2003-10-30 16:58:49 +00:00
i = ff_find_unused_picture ( s , 1 );
2002-12-09 00:29:17 +00:00
2002-12-09 12:03:43 +00:00
pic = ( AVFrame * ) & s -> picture [ i ];
2003-04-04 14:42:28 +00:00
pic -> reference = 3 ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
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 {
2003-10-30 16:58:49 +00:00
i = ff_find_unused_picture ( s , 0 );
2002-12-09 00:29:17 +00:00
2002-12-09 12:03:43 +00:00
pic = ( AVFrame * ) & s -> picture [ i ];
2003-04-04 14:42:28 +00:00
pic -> reference = 3 ;
2002-12-09 00:29:17 +00:00
alloc_picture ( s , ( Picture * ) pic , 0 );
2006-01-27 13:19:13 +00:00
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 ]){
2002-12-09 00:29:17 +00:00
// empty
} else {
int h_chroma_shift , v_chroma_shift ;
avcodec_get_chroma_sub_sample ( s -> avctx -> pix_fmt , & h_chroma_shift , & v_chroma_shift );
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
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 ];
2006-01-27 13:19:13 +00:00
uint8_t * dst = pic -> data [ i ] + INPLACE_OFFSET ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
if ( src_stride == dst_stride )
memcpy ( dst , src , src_stride * h );
else {
while ( h -- ){
memcpy ( dst , src , w );
dst += dst_stride ;
src += src_stride ;
}
}
}
}
2002-04-17 04:32:12 +00:00
}
2004-04-16 01:01:45 +00:00
copy_picture_attributes ( s , pic , pic_arg );
2005-01-13 11:59:19 +00:00
pic -> pts = pts ; //we set this here to avoid modifiying pic_arg
2003-07-23 10:41:07 +00:00
}
2005-12-17 18:14:38 +00:00
2002-12-04 10:04:03 +00:00
/* shift buffer entries */
for ( i = 1 ; i < MAX_PICTURE_COUNT /*s->encoding_delay+1*/ ; i ++ )
s -> input_picture [ i - 1 ] = s -> input_picture [ i ];
2005-12-17 18:14:38 +00:00
2002-12-04 10:04:03 +00:00
s -> input_picture [ encoding_delay ] = ( Picture * ) pic ;
2002-04-17 04:32:12 +00:00
2002-12-04 10:04:03 +00:00
return 0 ;
}
2004-12-08 11:46:16 +00:00
static int skip_check ( MpegEncContext * s , Picture * p , Picture * ref ){
int x , y , plane ;
int score = 0 ;
2004-12-08 18:02:56 +00:00
int64_t score64 = 0 ;
2004-12-08 11:46:16 +00:00
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 ++ ){
2005-11-05 00:16:03 +00:00
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 );
2005-12-17 18:14:38 +00:00
2004-12-08 18:02:56 +00:00
switch ( s -> avctx -> frame_skip_exp ){
case 0 : score = FFMAX ( score , v ); break ;
case 1 : score += ABS ( v ); break ;
case 2 : score += v * v ; break ;
case 3 : score64 += ABS ( v * v * ( int64_t ) v ); break ;
case 4 : score64 += v * v * ( int64_t )( v * v ); break ;
}
2004-12-08 11:46:16 +00:00
}
}
}
2005-12-17 18:14:38 +00:00
2004-12-08 18:02:56 +00:00
if ( score ) score64 = score ;
2004-12-08 11:46:16 +00:00
2004-12-08 18:02:56 +00:00
if ( score64 < s -> avctx -> frame_skip_threshold )
2004-12-08 11:46:16 +00:00
return 1 ;
2004-12-08 18:02:56 +00:00
if ( score64 < (( s -> avctx -> frame_skip_factor * ( int64_t ) s -> lambda ) >> 8 ))
2004-12-08 11:46:16 +00:00
return 1 ;
return 0 ;
}
2005-12-25 17:30:52 +00:00
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 ];
2005-12-25 18:34:02 +00:00
const int scale = s -> avctx -> brd_scale ;
2006-01-27 13:19:13 +00:00
int i , j , out_size , p_lambda , b_lambda , lambda2 ;
2005-12-25 18:34:02 +00:00
int outbuf_size = s -> width * s -> height ; //FIXME
2005-12-25 17:30:52 +00:00
uint8_t * outbuf = av_malloc ( outbuf_size );
int64_t best_rd = INT64_MAX ;
int best_b_count = - 1 ;
2006-01-27 13:19:13 +00:00
2006-03-31 20:43:37 +00:00
assert ( scale >= 0 && scale <= 3 );
2006-01-27 13:19:13 +00:00
// emms_c();
p_lambda = s -> last_lambda_for [ P_TYPE ]; //s->next_picture_ptr->quality;
b_lambda = s -> last_lambda_for [ B_TYPE ]; //p_lambda *ABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset;
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 ;
2005-12-25 17:30:52 +00:00
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 );
2006-01-27 13:19:13 +00:00
Picture pre_input , * pre_input_ptr = i ? s -> input_picture [ i - 1 ] : s -> next_picture_ptr ;
if ( pre_input_ptr )
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 ;
}
2005-12-25 17:30:52 +00:00
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 ;
2006-03-31 20:43:37 +00:00
if ( ! i || s -> input_picture [ i - 1 ]){
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 );
}
2005-12-25 17:30:52 +00:00
}
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 ;
input [ 0 ]. pict_type = I_TYPE ;
2006-01-27 13:19:13 +00:00
input [ 0 ]. quality = 1 * FF_QP2LAMBDA ;
2005-12-25 17:30:52 +00:00
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , & input [ 0 ]);
2006-01-27 13:19:13 +00:00
// rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT;
2005-12-25 17:30:52 +00:00
for ( i = 0 ; i < s -> max_b_frames + 1 ; i ++ ){
int is_p = i % ( j + 1 ) == j || i == s -> max_b_frames ;
input [ i + 1 ]. pict_type = is_p ? P_TYPE : B_TYPE ;
2006-01-27 13:19:13 +00:00
input [ i + 1 ]. quality = is_p ? p_lambda : b_lambda ;
2005-12-25 17:30:52 +00:00
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , & input [ i + 1 ]);
2006-01-27 13:19:13 +00:00
rd += ( out_size * lambda2 ) >> ( FF_LAMBDA_SHIFT - 3 );
2005-12-25 17:30:52 +00:00
}
/* get the delayed frames */
while ( out_size ){
out_size = avcodec_encode_video ( c , outbuf , outbuf_size , NULL );
2006-01-27 13:19:13 +00:00
rd += ( out_size * lambda2 ) >> ( FF_LAMBDA_SHIFT - 3 );
2005-12-25 17:30:52 +00:00
}
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 ;
}
2002-12-04 10:04:03 +00:00
static void select_input_picture ( MpegEncContext * s ){
int i ;
2002-12-09 00:29:17 +00:00
2002-12-04 10:04:03 +00:00
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 ;
2005-06-17 15:02:53 +00:00
/* set next picture type & ordering */
2002-12-04 10:04:03 +00:00
if ( s -> reordered_input_picture [ 0 ] == NULL && s -> input_picture [ 0 ]){
2003-03-16 20:22:22 +00:00
if ( /*s->picture_in_gop_number >= s->gop_size ||*/ s -> next_picture_ptr == NULL || s -> intra_only ){
2002-12-06 13:30:13 +00:00
s -> reordered_input_picture [ 0 ] = s -> input_picture [ 0 ];
s -> reordered_input_picture [ 0 ] -> pict_type = I_TYPE ;
2003-12-29 22:25:08 +00:00
s -> reordered_input_picture [ 0 ] -> coded_picture_number = s -> coded_picture_number ++ ;
2002-12-06 13:30:13 +00:00
} else {
int b_frames ;
2004-12-08 11:46:16 +00:00
if ( s -> avctx -> frame_skip_threshold || s -> avctx -> frame_skip_factor ){
2005-11-05 00:16:03 +00:00
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
2004-12-08 11:46:16 +00:00
//av_log(NULL, AV_LOG_DEBUG, "skip %p %Ld\n", s->input_picture[0]->data[0], s->input_picture[0]->pts);
2005-12-17 18:14:38 +00:00
2004-12-08 11:46:16 +00:00
if ( s -> input_picture [ 0 ] -> type == FF_BUFFER_TYPE_SHARED ){
for ( i = 0 ; i < 4 ; i ++ )
s -> input_picture [ 0 ] -> data [ i ] = NULL ;
2005-12-17 18:14:38 +00:00
s -> input_picture [ 0 ] -> type = 0 ;
2004-12-08 11:46:16 +00:00
} else {
2005-12-17 18:14:38 +00:00
assert ( s -> input_picture [ 0 ] -> type == FF_BUFFER_TYPE_USER
2004-12-08 11:46:16 +00:00
|| s -> input_picture [ 0 ] -> type == FF_BUFFER_TYPE_INTERNAL );
2005-12-17 18:14:38 +00:00
2004-12-08 11:46:16 +00:00
s -> avctx -> release_buffer ( s -> avctx , ( AVFrame * ) s -> input_picture [ 0 ]);
}
2005-12-17 18:14:38 +00:00
2005-11-05 00:16:03 +00:00
emms_c ();
ff_vbv_update ( s , 0 );
2004-12-08 11:46:16 +00:00
goto no_output_pic ;
}
}
2002-12-06 13:30:13 +00:00
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 ;
2004-11-23 23:58:54 +00:00
2005-12-17 18:14:38 +00:00
if ( pict_num >= s -> rc_context . num_entries )
2004-11-24 00:15:49 +00:00
break ;
2004-11-23 23:58:54 +00:00
if ( ! s -> input_picture [ i ]){
2004-11-24 00:15:49 +00:00
s -> rc_context . entry [ pict_num - 1 ]. new_pict_type = P_TYPE ;
2004-11-23 23:58:54 +00:00
break ;
}
2004-11-24 00:15:49 +00:00
2005-12-17 18:14:38 +00:00
s -> input_picture [ i ] -> pict_type =
2004-11-24 00:15:49 +00:00
s -> rc_context . entry [ pict_num ]. new_pict_type ;
2002-12-06 13:30:13 +00:00
}
}
2002-12-09 00:29:17 +00:00
2004-10-14 12:24:16 +00:00
if ( s -> avctx -> b_frame_strategy == 0 ){
2002-12-06 13:30:13 +00:00
b_frames = s -> max_b_frames ;
2003-07-23 10:41:07 +00:00
while ( b_frames && ! s -> input_picture [ b_frames ]) b_frames -- ;
2003-12-13 20:41:33 +00:00
} else if ( s -> avctx -> b_frame_strategy == 1 ){
2002-12-06 13:30:13 +00:00
for ( i = 1 ; i < s -> max_b_frames + 1 ; i ++ ){
2003-07-23 10:41:07 +00:00
if ( s -> input_picture [ i ] && s -> input_picture [ i ] -> b_frame_score == 0 ){
2005-12-17 18:14:38 +00:00
s -> input_picture [ i ] -> b_frame_score =
get_intra_count ( s , s -> input_picture [ i ] -> data [ 0 ],
2002-12-09 00:29:17 +00:00
s -> input_picture [ i - 1 ] -> data [ 0 ], s -> linesize ) + 1 ;
2002-12-06 13:30:13 +00:00
}
}
2005-05-21 22:20:26 +00:00
for ( i = 0 ; i < s -> max_b_frames + 1 ; i ++ ){
2006-06-03 06:26:04 +00:00
if ( s -> input_picture [ i ] == NULL || s -> input_picture [ i ] -> b_frame_score - 1 > s -> mb_num / s -> avctx -> b_sensitivity ) break ;
2002-12-06 13:30:13 +00:00
}
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
b_frames = FFMAX ( 0 , i - 1 );
2005-12-17 18:14:38 +00:00
2002-12-06 13:30:13 +00:00
/* reset scores */
for ( i = 0 ; i < b_frames + 1 ; i ++ ){
s -> input_picture [ i ] -> b_frame_score = 0 ;
}
2005-12-25 17:30:52 +00:00
} else if ( s -> avctx -> b_frame_strategy == 2 ){
b_frames = estimate_best_b_count ( s );
2002-12-06 13:30:13 +00:00
} else {
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "illegal b frame strategy \n " );
2002-12-06 13:30:13 +00:00
b_frames = 0 ;
}
emms_c ();
//static int b_count=0;
//b_count+= b_frames;
2003-11-03 13:26:22 +00:00
//av_log(s->avctx, AV_LOG_DEBUG, "b_frames: %d\n", b_count);
2004-10-14 12:24:16 +00:00
for ( i = b_frames - 1 ; i >= 0 ; i -- ){
int type = s -> input_picture [ i ] -> pict_type ;
if ( type && type != B_TYPE )
b_frames = i ;
}
if ( s -> input_picture [ b_frames ] -> pict_type == B_TYPE && b_frames == s -> max_b_frames ){
2005-04-24 11:13:49 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "warning, too many b frames in a row \n " );
2004-10-14 12:24:16 +00:00
}
2004-01-22 19:48:28 +00:00
if ( s -> picture_in_gop_number + b_frames >= s -> gop_size ){
2004-10-15 02:37:04 +00:00
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 {
2004-01-22 19:48:28 +00:00
if ( s -> flags & CODEC_FLAG_CLOSED_GOP )
b_frames = 0 ;
s -> input_picture [ b_frames ] -> pict_type = I_TYPE ;
2004-10-15 02:37:04 +00:00
}
2004-01-22 19:48:28 +00:00
}
2005-12-17 18:14:38 +00:00
2004-01-22 19:48:28 +00:00
if ( ( s -> flags & CODEC_FLAG_CLOSED_GOP )
&& b_frames
&& s -> input_picture [ b_frames ] -> pict_type == I_TYPE )
b_frames -- ;
2002-12-06 13:30:13 +00:00
s -> reordered_input_picture [ 0 ] = s -> input_picture [ b_frames ];
2004-01-22 19:48:28 +00:00
if ( s -> reordered_input_picture [ 0 ] -> pict_type != I_TYPE )
2002-12-06 13:30:13 +00:00
s -> reordered_input_picture [ 0 ] -> pict_type = P_TYPE ;
2003-12-29 22:25:08 +00:00
s -> reordered_input_picture [ 0 ] -> coded_picture_number = s -> coded_picture_number ++ ;
2002-12-06 13:30:13 +00:00
for ( i = 0 ; i < b_frames ; i ++ ){
s -> reordered_input_picture [ i + 1 ] = s -> input_picture [ i ];
s -> reordered_input_picture [ i + 1 ] -> pict_type = B_TYPE ;
2003-12-29 22:25:08 +00:00
s -> reordered_input_picture [ i + 1 ] -> coded_picture_number = s -> coded_picture_number ++ ;
2002-12-04 10:04:03 +00:00
}
}
}
2004-12-08 11:46:16 +00:00
no_output_pic :
2002-12-04 10:04:03 +00:00
if ( s -> reordered_input_picture [ 0 ]){
2003-04-04 14:42:28 +00:00
s -> reordered_input_picture [ 0 ] -> reference = s -> reordered_input_picture [ 0 ] -> pict_type != B_TYPE ? 3 : 0 ;
2003-03-16 20:22:22 +00:00
2003-10-16 00:21:54 +00:00
copy_picture ( & s -> new_picture , s -> reordered_input_picture [ 0 ]);
2002-12-09 00:29:17 +00:00
if ( s -> reordered_input_picture [ 0 ] -> type == FF_BUFFER_TYPE_SHARED ){
2005-06-17 15:02:53 +00:00
// input is a shared pix, so we can't modifiy it -> alloc a new one & ensure that the shared one is reuseable
2005-12-17 18:14:38 +00:00
2003-10-30 16:58:49 +00:00
int i = ff_find_unused_picture ( s , 0 );
2002-12-09 00:29:17 +00:00
Picture * pic = & s -> picture [ i ];
/* mark us unused / free shared pic */
for ( i = 0 ; i < 4 ; i ++ )
s -> reordered_input_picture [ 0 ] -> data [ i ] = NULL ;
s -> reordered_input_picture [ 0 ] -> type = 0 ;
2005-12-17 18:14:38 +00:00
2003-12-22 19:06:01 +00:00
pic -> reference = s -> reordered_input_picture [ 0 ] -> reference ;
2005-12-17 18:14:38 +00:00
2002-12-09 00:29:17 +00:00
alloc_picture ( s , pic , 0 );
2004-04-23 19:06:30 +00:00
copy_picture_attributes ( s , ( AVFrame * ) pic , ( AVFrame * ) s -> reordered_input_picture [ 0 ]);
2003-03-16 20:22:22 +00:00
s -> current_picture_ptr = pic ;
2002-12-09 00:29:17 +00:00
} else {
2003-03-16 20:22:22 +00:00
// input is not a shared pix -> reuse buffer for current_pix
2005-12-17 18:14:38 +00:00
assert ( s -> reordered_input_picture [ 0 ] -> type == FF_BUFFER_TYPE_USER
2002-12-09 00:29:17 +00:00
|| s -> reordered_input_picture [ 0 ] -> type == FF_BUFFER_TYPE_INTERNAL );
2005-12-17 18:14:38 +00:00
2003-03-16 20:22:22 +00:00
s -> current_picture_ptr = s -> reordered_input_picture [ 0 ];
2002-12-09 00:29:17 +00:00
for ( i = 0 ; i < 4 ; i ++ ){
2006-01-27 13:19:13 +00:00
s -> new_picture . data [ i ] += INPLACE_OFFSET ;
2002-12-09 00:29:17 +00:00
}
2002-12-04 10:04:03 +00:00
}
2003-10-16 00:21:54 +00:00
copy_picture ( & s -> current_picture , s -> current_picture_ptr );
2005-12-17 18:14:38 +00:00
2002-12-04 10:04:03 +00:00
s -> picture_number = s -> new_picture . display_picture_number ;
//printf("dpn:%d\n", s->picture_number);
} else {
memset ( & s -> new_picture , 0 , sizeof ( Picture ));
2002-04-17 04:32:12 +00:00
}
}
int MPV_encode_picture ( AVCodecContext * avctx ,
unsigned char * buf , int buf_size , void * data )
{
MpegEncContext * s = avctx -> priv_data ;
2002-12-09 12:03:43 +00:00
AVFrame * pic_arg = data ;
2003-12-12 21:30:47 +00:00
int i , stuffing_count ;
2002-04-17 04:32:12 +00:00
2004-02-13 17:54:10 +00:00
for ( i = 0 ; i < avctx -> thread_count ; i ++ ){
2004-02-26 19:11:21 +00:00
int start_y = s -> thread_context [ i ] -> start_mb_y ;
int end_y = s -> thread_context [ i ] -> end_mb_y ;
2004-02-13 17:54:10 +00:00
int h = s -> mb_height ;
2005-07-25 23:07:27 +00:00
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 );
2004-02-13 17:54:10 +00:00
init_put_bits ( & s -> thread_context [ i ] -> pb , start , end - start );
}
2002-04-17 04:32:12 +00:00
2002-12-04 10:04:03 +00:00
s -> picture_in_gop_number ++ ;
2001-07-22 14:18:56 +00:00
2004-09-20 13:47:47 +00:00
if ( load_input_picture ( s , pic_arg ) < 0 )
return - 1 ;
2005-12-17 18:14:38 +00:00
2002-12-04 10:04:03 +00:00
select_input_picture ( s );
2005-12-17 18:14:38 +00:00
2002-04-17 04:32:12 +00:00
/* output? */
2002-12-04 10:04:03 +00:00
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);
2002-07-14 18:37:35 +00:00
MPV_frame_start ( s , avctx );
2002-04-17 04:32:12 +00:00
2006-09-26 14:04:36 +00:00
if ( encode_picture ( s , s -> picture_number ) < 0 )
return - 1 ;
2005-12-17 18:14:38 +00:00
2002-05-11 23:42:16 +00:00
avctx -> real_pict_num = s -> picture_number ;
2002-04-17 04:32:12 +00:00
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 ;
2002-09-12 12:26:09 +00:00
avctx -> p_count = s -> mb_num - s -> i_count - s -> skip_count ; //FIXME f/b_count in avctx
2002-04-17 04:32:12 +00:00
avctx -> skip_count = s -> skip_count ;
MPV_frame_end ( s );
if ( s -> out_format == FMT_MJPEG )
mjpeg_picture_trailer ( s );
2005-12-17 18:14:38 +00:00
2002-04-21 21:18:17 +00:00
if ( s -> flags & CODEC_FLAG_PASS1 )
ff_write_pass1_stats ( s );
2003-03-16 20:22:22 +00:00
for ( i = 0 ; i < 4 ; i ++ ){
2005-12-07 18:21:16 +00:00
s -> current_picture_ptr -> error [ i ] = s -> current_picture . error [ i ];
2003-03-16 20:22:22 +00:00
avctx -> error [ i ] += s -> current_picture_ptr -> error [ i ];
}
2002-04-17 04:32:12 +00:00
2005-01-14 23:48:12 +00:00
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 ));
2003-12-12 21:30:47 +00:00
flush_put_bits ( & s -> pb );
2004-02-13 20:59:48 +00:00
s -> frame_bits = put_bits_count ( & s -> pb );
2004-01-29 15:50:54 +00:00
stuffing_count = ff_vbv_update ( s , s -> frame_bits );
if ( stuffing_count ){
2005-01-12 00:16:25 +00:00
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 ;
}
2004-01-29 15:50:54 +00:00
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 );
2004-02-13 20:59:48 +00:00
s -> frame_bits = put_bits_count ( & s -> pb );
2004-01-29 15:50:54 +00:00
}
2005-12-17 18:14:38 +00:00
/* update mpeg1/2 vbv_delay for CBR */
2004-03-26 12:30:04 +00:00
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 ){
2004-01-29 15:50:54 +00:00
int vbv_delay ;
assert ( s -> repeat_first_field == 0 );
2005-12-17 18:14:38 +00:00
2004-01-29 15:50:54 +00:00
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 ;
2003-12-12 21:30:47 +00:00
}
2004-01-29 15:50:54 +00:00
assert (( s -> frame_bits & 7 ) == 0 );
2005-12-17 18:14:38 +00:00
2003-12-12 21:30:47 +00:00
return s -> frame_bits / 8 ;
2001-07-22 14:18:56 +00:00
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2002-03-09 13:01:16 +00:00
static inline void gmc1_motion ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2004-02-29 00:37:36 +00:00
uint8_t ** ref_picture )
2002-03-09 13:01:16 +00:00
{
2003-02-11 16:35:48 +00:00
uint8_t * ptr ;
2002-07-15 14:15:10 +00:00
int offset , src_x , src_y , linesize , uvlinesize ;
2002-03-09 13:01:16 +00:00
int motion_x , motion_y ;
2002-07-17 12:42:50 +00:00
int emu = 0 ;
2002-03-09 13:01:16 +00:00
motion_x = s -> sprite_offset [ 0 ][ 0 ];
motion_y = s -> sprite_offset [ 0 ][ 1 ];
src_x = s -> mb_x * 16 + ( motion_x >> ( s -> sprite_warping_accuracy + 1 ));
src_y = s -> mb_y * 16 + ( motion_y >> ( s -> sprite_warping_accuracy + 1 ));
motion_x <<= ( 3 - s -> sprite_warping_accuracy );
motion_y <<= ( 3 - s -> sprite_warping_accuracy );
src_x = clip ( src_x , - 16 , s -> width );
if ( src_x == s -> width )
motion_x = 0 ;
src_y = clip ( src_y , - 16 , s -> height );
if ( src_y == s -> height )
motion_y = 0 ;
2002-10-16 19:55:49 +00:00
2002-03-09 13:01:16 +00:00
linesize = s -> linesize ;
2002-07-15 14:15:10 +00:00
uvlinesize = s -> uvlinesize ;
2005-12-17 18:14:38 +00:00
2004-02-29 00:37:36 +00:00
ptr = ref_picture [ 0 ] + ( src_y * linesize ) + src_x ;
2002-03-09 13:01:16 +00:00
2002-07-17 12:42:50 +00:00
if ( s -> flags & CODEC_FLAG_EMU_EDGE ){
2003-10-17 18:56:01 +00:00
if ( ( unsigned ) src_x >= s -> h_edge_pos - 17
|| ( unsigned ) src_y >= s -> v_edge_pos - 17 ){
2003-06-18 22:00:23 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , linesize , 17 , 17 , src_x , src_y , s -> h_edge_pos , s -> v_edge_pos );
2002-07-17 12:42:50 +00:00
ptr = s -> edge_emu_buffer ;
}
}
2005-12-17 18:14:38 +00:00
2002-10-16 19:55:49 +00:00
if (( motion_x | motion_y ) & 7 ){
2002-11-11 09:40:17 +00:00
s -> dsp . gmc1 ( dest_y , ptr , linesize , 16 , motion_x & 15 , motion_y & 15 , 128 - s -> no_rounding );
s -> dsp . gmc1 ( dest_y + 8 , ptr + 8 , linesize , 16 , motion_x & 15 , motion_y & 15 , 128 - s -> no_rounding );
2002-10-16 19:55:49 +00:00
} else {
int dxy ;
2005-12-17 18:14:38 +00:00
2002-10-16 19:55:49 +00:00
dxy = (( motion_x >> 3 ) & 1 ) | (( motion_y >> 2 ) & 2 );
if ( s -> no_rounding ){
2005-12-22 01:10:11 +00:00
s -> dsp . put_no_rnd_pixels_tab [ 0 ][ dxy ]( dest_y , ptr , linesize , 16 );
2002-10-16 19:55:49 +00:00
} else {
2002-11-11 09:40:17 +00:00
s -> dsp . put_pixels_tab [ 0 ][ dxy ]( dest_y , ptr , linesize , 16 );
}
2002-10-16 19:55:49 +00:00
}
2005-12-17 18:14:38 +00:00
2002-10-16 19:55:49 +00:00
if ( s -> flags & CODEC_FLAG_GRAY ) return ;
2002-03-09 13:01:16 +00:00
motion_x = s -> sprite_offset [ 1 ][ 0 ];
motion_y = s -> sprite_offset [ 1 ][ 1 ];
src_x = s -> mb_x * 8 + ( motion_x >> ( s -> sprite_warping_accuracy + 1 ));
src_y = s -> mb_y * 8 + ( motion_y >> ( s -> sprite_warping_accuracy + 1 ));
motion_x <<= ( 3 - s -> sprite_warping_accuracy );
motion_y <<= ( 3 - s -> sprite_warping_accuracy );
src_x = clip ( src_x , - 8 , s -> width >> 1 );
if ( src_x == s -> width >> 1 )
motion_x = 0 ;
src_y = clip ( src_y , - 8 , s -> height >> 1 );
if ( src_y == s -> height >> 1 )
motion_y = 0 ;
2004-02-29 00:37:36 +00:00
offset = ( src_y * uvlinesize ) + src_x ;
2002-03-09 13:01:16 +00:00
ptr = ref_picture [ 1 ] + offset ;
2003-01-13 12:55:05 +00:00
if ( s -> flags & CODEC_FLAG_EMU_EDGE ){
2003-10-17 18:56:01 +00:00
if ( ( unsigned ) src_x >= ( s -> h_edge_pos >> 1 ) - 9
|| ( unsigned ) src_y >= ( s -> v_edge_pos >> 1 ) - 9 ){
2003-06-18 22:00:23 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , uvlinesize , 9 , 9 , src_x , src_y , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
2003-01-13 12:55:05 +00:00
ptr = s -> edge_emu_buffer ;
emu = 1 ;
}
2002-07-17 12:42:50 +00:00
}
2004-02-29 00:37:36 +00:00
s -> dsp . gmc1 ( dest_cb , ptr , uvlinesize , 8 , motion_x & 15 , motion_y & 15 , 128 - s -> no_rounding );
2005-12-17 18:14:38 +00:00
2002-03-09 13:01:16 +00:00
ptr = ref_picture [ 2 ] + offset ;
2002-07-17 12:42:50 +00:00
if ( emu ){
2003-06-18 22:00:23 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , uvlinesize , 9 , 9 , src_x , src_y , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
2002-07-17 12:42:50 +00:00
ptr = s -> edge_emu_buffer ;
}
2004-02-29 00:37:36 +00:00
s -> dsp . gmc1 ( dest_cr , ptr , uvlinesize , 8 , motion_x & 15 , motion_y & 15 , 128 - s -> no_rounding );
2005-12-17 18:14:38 +00:00
2002-03-09 13:01:16 +00:00
return ;
}
2002-10-16 19:55:49 +00:00
static inline void gmc_motion ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2004-02-29 00:37:36 +00:00
uint8_t ** ref_picture )
2002-10-16 19:55:49 +00:00
{
2003-02-11 16:35:48 +00:00
uint8_t * ptr ;
2002-10-16 19:55:49 +00:00
int linesize , uvlinesize ;
const int a = s -> sprite_warping_accuracy ;
int ox , oy ;
linesize = s -> linesize ;
uvlinesize = s -> uvlinesize ;
2004-02-29 00:37:36 +00:00
ptr = ref_picture [ 0 ];
2002-10-16 19:55:49 +00:00
ox = s -> sprite_offset [ 0 ][ 0 ] + s -> sprite_delta [ 0 ][ 0 ] * s -> mb_x * 16 + s -> sprite_delta [ 0 ][ 1 ] * s -> mb_y * 16 ;
oy = s -> sprite_offset [ 0 ][ 1 ] + s -> sprite_delta [ 1 ][ 0 ] * s -> mb_x * 16 + s -> sprite_delta [ 1 ][ 1 ] * s -> mb_y * 16 ;
2002-11-11 09:40:17 +00:00
s -> dsp . gmc ( dest_y , ptr , linesize , 16 ,
2005-12-17 18:14:38 +00:00
ox ,
oy ,
2002-10-16 19:55:49 +00:00
s -> sprite_delta [ 0 ][ 0 ], s -> sprite_delta [ 0 ][ 1 ],
2005-12-17 18:14:38 +00:00
s -> sprite_delta [ 1 ][ 0 ], s -> sprite_delta [ 1 ][ 1 ],
2002-10-16 19:55:49 +00:00
a + 1 , ( 1 << ( 2 * a + 1 )) - s -> no_rounding ,
s -> h_edge_pos , s -> v_edge_pos );
2002-11-11 09:40:17 +00:00
s -> dsp . gmc ( dest_y + 8 , ptr , linesize , 16 ,
2005-12-17 18:14:38 +00:00
ox + s -> sprite_delta [ 0 ][ 0 ] * 8 ,
oy + s -> sprite_delta [ 1 ][ 0 ] * 8 ,
2002-10-16 19:55:49 +00:00
s -> sprite_delta [ 0 ][ 0 ], s -> sprite_delta [ 0 ][ 1 ],
2005-12-17 18:14:38 +00:00
s -> sprite_delta [ 1 ][ 0 ], s -> sprite_delta [ 1 ][ 1 ],
2002-10-16 19:55:49 +00:00
a + 1 , ( 1 << ( 2 * a + 1 )) - s -> no_rounding ,
s -> h_edge_pos , s -> v_edge_pos );
if ( s -> flags & CODEC_FLAG_GRAY ) return ;
ox = s -> sprite_offset [ 1 ][ 0 ] + s -> sprite_delta [ 0 ][ 0 ] * s -> mb_x * 8 + s -> sprite_delta [ 0 ][ 1 ] * s -> mb_y * 8 ;
oy = s -> sprite_offset [ 1 ][ 1 ] + s -> sprite_delta [ 1 ][ 0 ] * s -> mb_x * 8 + s -> sprite_delta [ 1 ][ 1 ] * s -> mb_y * 8 ;
2004-02-29 00:37:36 +00:00
ptr = ref_picture [ 1 ];
2002-11-11 09:40:17 +00:00
s -> dsp . gmc ( dest_cb , ptr , uvlinesize , 8 ,
2005-12-17 18:14:38 +00:00
ox ,
oy ,
2002-10-16 19:55:49 +00:00
s -> sprite_delta [ 0 ][ 0 ], s -> sprite_delta [ 0 ][ 1 ],
2005-12-17 18:14:38 +00:00
s -> sprite_delta [ 1 ][ 0 ], s -> sprite_delta [ 1 ][ 1 ],
2002-10-16 19:55:49 +00:00
a + 1 , ( 1 << ( 2 * a + 1 )) - s -> no_rounding ,
s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
2005-12-17 18:14:38 +00:00
2004-02-29 00:37:36 +00:00
ptr = ref_picture [ 2 ];
2002-11-11 09:40:17 +00:00
s -> dsp . gmc ( dest_cr , ptr , uvlinesize , 8 ,
2005-12-17 18:14:38 +00:00
ox ,
oy ,
2002-10-16 19:55:49 +00:00
s -> sprite_delta [ 0 ][ 0 ], s -> sprite_delta [ 0 ][ 1 ],
2005-12-17 18:14:38 +00:00
s -> sprite_delta [ 1 ][ 0 ], s -> sprite_delta [ 1 ][ 1 ],
2002-10-16 19:55:49 +00:00
a + 1 , ( 1 << ( 2 * a + 1 )) - s -> no_rounding ,
s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
}
2003-06-18 22:00:23 +00:00
/**
* Copies a rectangular area of samples to a temporary buffer and replicates the boarder samples.
* @param buf destination buffer
* @param src source buffer
* @param linesize number of bytes between 2 vertically adjacent samples in both the source and destination buffers
* @param block_w width of block
* @param block_h height of block
* @param src_x x coordinate of the top left sample of the block in the source buffer
* @param src_y y coordinate of the top left sample of the block in the source buffer
* @param w width of the source buffer
* @param h height of the source buffer
*/
2005-12-17 18:14:38 +00:00
void ff_emulated_edge_mc ( uint8_t * buf , uint8_t * src , int linesize , int block_w , int block_h ,
2002-07-14 18:37:35 +00:00
int src_x , int src_y , int w , int h ){
int x , y ;
int start_y , start_x , end_y , end_x ;
2002-11-11 09:40:17 +00:00
2002-07-14 18:37:35 +00:00
if ( src_y >= h ){
src += ( h - 1 - src_y ) * linesize ;
src_y = h - 1 ;
2002-07-15 00:25:53 +00:00
} else if ( src_y <=- block_h ){
src += ( 1 - block_h - src_y ) * linesize ;
src_y = 1 - block_h ;
2002-07-14 18:37:35 +00:00
}
if ( src_x >= w ){
src += ( w - 1 - src_x );
src_x = w - 1 ;
2002-07-15 00:25:53 +00:00
} else if ( src_x <=- block_w ){
src += ( 1 - block_w - src_x );
src_x = 1 - block_w ;
2002-07-14 18:37:35 +00:00
}
2002-11-10 11:46:59 +00:00
start_y = FFMAX ( 0 , - src_y );
start_x = FFMAX ( 0 , - src_x );
end_y = FFMIN ( block_h , h - src_y );
end_x = FFMIN ( block_w , w - src_x );
2002-07-17 12:42:50 +00:00
2002-07-14 18:37:35 +00:00
// copy existing part
for ( y = start_y ; y < end_y ; y ++ ){
for ( x = start_x ; x < end_x ; x ++ ){
buf [ x + y * linesize ] = src [ x + y * linesize ];
}
}
//top
for ( y = 0 ; y < start_y ; y ++ ){
for ( x = start_x ; x < end_x ; x ++ ){
buf [ x + y * linesize ] = buf [ x + start_y * linesize ];
}
}
//bottom
for ( y = end_y ; y < block_h ; y ++ ){
for ( x = start_x ; x < end_x ; x ++ ){
buf [ x + y * linesize ] = buf [ x + ( end_y - 1 ) * linesize ];
}
}
2005-12-17 18:14:38 +00:00
2002-07-14 18:37:35 +00:00
for ( y = 0 ; y < block_h ; y ++ ){
//left
for ( x = 0 ; x < start_x ; x ++ ){
buf [ x + y * linesize ] = buf [ start_x + y * linesize ];
}
2005-12-17 18:14:38 +00:00
2002-07-14 18:37:35 +00:00
//right
for ( x = end_x ; x < block_w ; x ++ ){
buf [ x + y * linesize ] = buf [ end_x - 1 + y * linesize ];
}
}
}
2005-12-17 18:14:38 +00:00
static inline int hpel_motion ( MpegEncContext * s ,
2004-02-29 00:37:36 +00:00
uint8_t * dest , uint8_t * src ,
int field_based , int field_select ,
2003-11-28 21:31:20 +00:00
int src_x , int src_y ,
int width , int height , int stride ,
int h_edge_pos , int v_edge_pos ,
int w , int h , op_pixels_func * pix_op ,
int motion_x , int motion_y )
{
int dxy ;
int emu = 0 ;
dxy = (( motion_y & 1 ) << 1 ) | ( motion_x & 1 );
src_x += motion_x >> 1 ;
src_y += motion_y >> 1 ;
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
/* WARNING: do no forget half pels */
src_x = clip ( src_x , - 16 , width ); //FIXME unneeded for emu?
if ( src_x == width )
dxy &= ~ 1 ;
src_y = clip ( src_y , - 16 , height );
if ( src_y == height )
dxy &= ~ 2 ;
src += src_y * stride + src_x ;
if ( s -> unrestricted_mv && ( s -> flags & CODEC_FLAG_EMU_EDGE )){
if ( ( unsigned ) src_x > h_edge_pos - ( motion_x & 1 ) - w
|| ( unsigned ) src_y > v_edge_pos - ( motion_y & 1 ) - h ){
2004-02-29 00:37:36 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , src , s -> linesize , w + 1 , ( h + 1 ) << field_based ,
src_x , src_y << field_based , h_edge_pos , s -> v_edge_pos );
2003-11-28 21:31:20 +00:00
src = s -> edge_emu_buffer ;
emu = 1 ;
}
}
2004-02-29 00:37:36 +00:00
if ( field_select )
src += s -> linesize ;
2003-11-28 21:31:20 +00:00
pix_op [ dxy ]( dest , src , stride , h );
return emu ;
}
2002-07-14 18:37:35 +00:00
2005-12-17 18:14:38 +00:00
static inline int hpel_motion_lowres ( MpegEncContext * s ,
2004-10-09 12:02:19 +00:00
uint8_t * dest , uint8_t * src ,
int field_based , int field_select ,
int src_x , int src_y ,
int width , int height , int stride ,
int h_edge_pos , int v_edge_pos ,
int w , int h , h264_chroma_mc_func * pix_op ,
int motion_x , int motion_y )
{
const int lowres = s -> avctx -> lowres ;
const int s_mask = ( 2 << lowres ) - 1 ;
int emu = 0 ;
int sx , sy ;
if ( s -> quarter_sample ){
motion_x /= 2 ;
motion_y /= 2 ;
}
sx = motion_x & s_mask ;
sy = motion_y & s_mask ;
src_x += motion_x >> ( lowres + 1 );
src_y += motion_y >> ( lowres + 1 );
2005-12-17 18:14:38 +00:00
2004-10-09 12:02:19 +00:00
src += src_y * stride + src_x ;
if ( ( unsigned ) src_x > h_edge_pos - ( !! sx ) - w
|| ( unsigned ) src_y > ( v_edge_pos >> field_based ) - ( !! sy ) - h ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , src , s -> linesize , w + 1 , ( h + 1 ) << field_based ,
src_x , src_y << field_based , h_edge_pos , v_edge_pos );
src = s -> edge_emu_buffer ;
emu = 1 ;
}
sx <<= 2 - lowres ;
sy <<= 2 - lowres ;
if ( field_select )
src += s -> linesize ;
pix_op [ lowres ]( dest , src , stride , h , sx , sy );
return emu ;
}
2001-07-22 14:18:56 +00:00
/* apply one mpeg motion vector to the three components */
2004-06-11 07:59:12 +00:00
static always_inline void mpeg_motion ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2004-02-29 00:37:36 +00:00
int field_based , int bottom_field , int field_select ,
uint8_t ** ref_picture , op_pixels_func ( * pix_op )[ 4 ],
2001-07-22 14:18:56 +00:00
int motion_x , int motion_y , int h )
{
2004-02-29 22:14:46 +00:00
uint8_t * ptr_y , * ptr_cb , * ptr_cr ;
int dxy , uvdxy , mx , my , src_x , src_y , uvsrc_x , uvsrc_y , v_edge_pos , uvlinesize , linesize ;
2005-12-17 18:14:38 +00:00
#if 0
2002-03-09 13:01:16 +00:00
if(s->quarter_sample)
{
motion_x>>=1;
motion_y>>=1;
}
2002-09-11 12:39:53 +00:00
#endif
2003-11-28 21:31:20 +00:00
2002-07-25 20:22:36 +00:00
v_edge_pos = s -> v_edge_pos >> field_based ;
2004-02-29 22:14:46 +00:00
linesize = s -> current_picture . linesize [ 0 ] << field_based ;
2003-03-16 20:22:22 +00:00
uvlinesize = s -> current_picture . linesize [ 1 ] << field_based ;
2002-07-14 18:37:35 +00:00
2004-02-29 22:14:46 +00:00
dxy = (( motion_y & 1 ) << 1 ) | ( motion_x & 1 );
src_x = s -> mb_x * 16 + ( motion_x >> 1 );
2004-06-11 07:59:12 +00:00
src_y = ( s -> mb_y << ( 4 - field_based )) + ( motion_y >> 1 );
2002-06-09 13:35:56 +00:00
2001-07-22 14:18:56 +00:00
if ( s -> out_format == FMT_H263 ) {
2004-04-02 19:54:33 +00:00
if (( s -> workaround_bugs & FF_BUG_HPEL_CHROMA ) && field_based ){
mx = ( motion_x >> 1 ) | ( motion_x & 1 );
my = motion_y >> 1 ;
uvdxy = (( my & 1 ) << 1 ) | ( mx & 1 );
uvsrc_x = s -> mb_x * 8 + ( mx >> 1 );
2004-06-11 07:59:12 +00:00
uvsrc_y = ( s -> mb_y << ( 3 - field_based )) + ( my >> 1 );
2004-04-02 19:54:33 +00:00
} else {
uvdxy = dxy | ( motion_y & 2 ) | (( motion_x & 2 ) >> 1 );
uvsrc_x = src_x >> 1 ;
uvsrc_y = src_y >> 1 ;
}
2004-05-30 20:37:15 +00:00
} else if ( s -> out_format == FMT_H261 ){ //even chroma mv's are full pel in H261
mx = motion_x / 4 ;
my = motion_y / 4 ;
uvdxy = 0 ;
uvsrc_x = s -> mb_x * 8 + mx ;
uvsrc_y = s -> mb_y * 8 + my ;
2001-07-22 14:18:56 +00:00
} else {
2004-06-11 07:59:12 +00:00
if ( s -> chroma_y_shift ){
mx = motion_x / 2 ;
my = motion_y / 2 ;
uvdxy = (( my & 1 ) << 1 ) | ( mx & 1 );
uvsrc_x = s -> mb_x * 8 + ( mx >> 1 );
uvsrc_y = ( s -> mb_y << ( 3 - field_based )) + ( my >> 1 );
} else {
if ( s -> chroma_x_shift ){
//Chroma422
mx = motion_x / 2 ;
uvdxy = (( motion_y & 1 ) << 1 ) | ( mx & 1 );
uvsrc_x = s -> mb_x * 8 + ( mx >> 1 );
uvsrc_y = src_y ;
} else {
//Chroma444
uvdxy = dxy ;
uvsrc_x = src_x ;
uvsrc_y = src_y ;
}
}
2001-07-22 14:18:56 +00:00
}
2002-07-14 18:37:35 +00:00
2004-02-29 22:14:46 +00:00
ptr_y = ref_picture [ 0 ] + src_y * linesize + src_x ;
ptr_cb = ref_picture [ 1 ] + uvsrc_y * uvlinesize + uvsrc_x ;
ptr_cr = ref_picture [ 2 ] + uvsrc_y * uvlinesize + uvsrc_x ;
if ( ( unsigned ) src_x > s -> h_edge_pos - ( motion_x & 1 ) - 16
|| ( unsigned ) src_y > v_edge_pos - ( motion_y & 1 ) - h ){
2004-06-11 07:59:12 +00:00
if ( s -> codec_id == CODEC_ID_MPEG2VIDEO ||
s -> codec_id == CODEC_ID_MPEG1VIDEO ){
av_log ( s -> avctx , AV_LOG_DEBUG , "MPEG motion vector out of boundary \n " );
return ;
}
2004-02-29 22:14:46 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr_y , s -> linesize , 17 , 17 + field_based ,
src_x , src_y << field_based , s -> h_edge_pos , s -> v_edge_pos );
ptr_y = s -> edge_emu_buffer ;
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2004-03-11 13:22:39 +00:00
uint8_t * uvbuf = s -> edge_emu_buffer + 18 * s -> linesize ;
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf , ptr_cb , s -> uvlinesize , 9 , 9 + field_based ,
2004-02-29 22:14:46 +00:00
uvsrc_x , uvsrc_y << field_based , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf + 16 , ptr_cr , s -> uvlinesize , 9 , 9 + field_based ,
2004-02-29 22:14:46 +00:00
uvsrc_x , uvsrc_y << field_based , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
ptr_cb = uvbuf ;
ptr_cr = uvbuf + 16 ;
}
}
if ( bottom_field ){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
dest_y += s -> linesize ;
dest_cb += s -> uvlinesize ;
dest_cr += s -> uvlinesize ;
}
if ( field_select ){
ptr_y += s -> linesize ;
ptr_cb += s -> uvlinesize ;
ptr_cr += s -> uvlinesize ;
}
pix_op [ 0 ][ dxy ]( dest_y , ptr_y , linesize , h );
2005-12-17 18:14:38 +00:00
2004-02-29 22:14:46 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2004-06-11 07:59:12 +00:00
pix_op [ s -> chroma_x_shift ][ uvdxy ]( dest_cb , ptr_cb , uvlinesize , h >> s -> chroma_y_shift );
pix_op [ s -> chroma_x_shift ][ uvdxy ]( dest_cr , ptr_cr , uvlinesize , h >> s -> chroma_y_shift );
2002-07-14 18:37:35 +00:00
}
2005-05-02 22:14:42 +00:00
#if defined(CONFIG_H261_ENCODER) || defined(CONFIG_H261_DECODER)
2004-10-08 22:57:39 +00:00
if ( s -> out_format == FMT_H261 ){
ff_h261_loop_filter ( s );
}
2005-05-02 22:14:42 +00:00
#endif
2001-07-22 14:18:56 +00:00
}
2004-09-25 23:18:58 +00:00
/* apply one mpeg motion vector to the three components */
static always_inline void mpeg_motion_lowres ( MpegEncContext * s ,
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
int field_based , int bottom_field , int field_select ,
uint8_t ** ref_picture , h264_chroma_mc_func * pix_op ,
int motion_x , int motion_y , int h )
{
uint8_t * ptr_y , * ptr_cb , * ptr_cr ;
int mx , my , src_x , src_y , uvsrc_x , uvsrc_y , uvlinesize , linesize , sx , sy , uvsx , uvsy ;
const int lowres = s -> avctx -> lowres ;
const int block_s = 8 >> lowres ;
const int s_mask = ( 2 << lowres ) - 1 ;
const int h_edge_pos = s -> h_edge_pos >> lowres ;
const int v_edge_pos = s -> v_edge_pos >> lowres ;
linesize = s -> current_picture . linesize [ 0 ] << field_based ;
uvlinesize = s -> current_picture . linesize [ 1 ] << field_based ;
2004-09-26 11:05:35 +00:00
if ( s -> quarter_sample ){ //FIXME obviously not perfect but qpel wont work in lowres anyway
motion_x /= 2 ;
motion_y /= 2 ;
}
2005-12-17 18:14:38 +00:00
2004-09-26 11:05:35 +00:00
if ( field_based ){
motion_y += ( bottom_field - field_select ) * (( 1 << lowres ) - 1 );
}
2004-09-25 23:18:58 +00:00
sx = motion_x & s_mask ;
sy = motion_y & s_mask ;
src_x = s -> mb_x * 2 * block_s + ( motion_x >> ( lowres + 1 ));
2004-09-26 11:05:35 +00:00
src_y = ( s -> mb_y * 2 * block_s >> field_based ) + ( motion_y >> ( lowres + 1 ));
2005-12-17 18:14:38 +00:00
2004-09-25 23:18:58 +00:00
if ( s -> out_format == FMT_H263 ) {
2004-09-26 23:01:42 +00:00
uvsx = (( motion_x >> 1 ) & s_mask ) | ( sx & 1 );
uvsy = (( motion_y >> 1 ) & s_mask ) | ( sy & 1 );
2004-09-25 23:18:58 +00:00
uvsrc_x = src_x >> 1 ;
uvsrc_y = src_y >> 1 ;
} else if ( s -> out_format == FMT_H261 ){ //even chroma mv's are full pel in H261
mx = motion_x / 4 ;
my = motion_y / 4 ;
uvsx = ( 2 * mx ) & s_mask ;
uvsy = ( 2 * my ) & s_mask ;
uvsrc_x = s -> mb_x * block_s + ( mx >> lowres );
uvsrc_y = s -> mb_y * block_s + ( my >> lowres );
} else {
mx = motion_x / 2 ;
my = motion_y / 2 ;
uvsx = mx & s_mask ;
uvsy = my & s_mask ;
uvsrc_x = s -> mb_x * block_s + ( mx >> ( lowres + 1 ));
2004-09-26 11:05:35 +00:00
uvsrc_y = ( s -> mb_y * block_s >> field_based ) + ( my >> ( lowres + 1 ));
2004-09-25 23:18:58 +00:00
}
ptr_y = ref_picture [ 0 ] + src_y * linesize + src_x ;
ptr_cb = ref_picture [ 1 ] + uvsrc_y * uvlinesize + uvsrc_x ;
ptr_cr = ref_picture [ 2 ] + uvsrc_y * uvlinesize + uvsrc_x ;
if ( ( unsigned ) src_x > h_edge_pos - ( !! sx ) - 2 * block_s
|| ( unsigned ) src_y > ( v_edge_pos >> field_based ) - ( !! sy ) - h ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr_y , s -> linesize , 17 , 17 + field_based ,
src_x , src_y << field_based , h_edge_pos , v_edge_pos );
ptr_y = s -> edge_emu_buffer ;
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
uint8_t * uvbuf = s -> edge_emu_buffer + 18 * s -> linesize ;
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf , ptr_cb , s -> uvlinesize , 9 , 9 + field_based ,
2004-09-25 23:18:58 +00:00
uvsrc_x , uvsrc_y << field_based , h_edge_pos >> 1 , v_edge_pos >> 1 );
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf + 16 , ptr_cr , s -> uvlinesize , 9 , 9 + field_based ,
2004-09-25 23:18:58 +00:00
uvsrc_x , uvsrc_y << field_based , h_edge_pos >> 1 , v_edge_pos >> 1 );
ptr_cb = uvbuf ;
ptr_cr = uvbuf + 16 ;
}
}
2004-09-26 11:05:35 +00:00
if ( bottom_field ){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
dest_y += s -> linesize ;
dest_cb += s -> uvlinesize ;
dest_cr += s -> uvlinesize ;
}
if ( field_select ){
ptr_y += s -> linesize ;
ptr_cb += s -> uvlinesize ;
ptr_cr += s -> uvlinesize ;
}
2004-09-25 23:18:58 +00:00
sx <<= 2 - lowres ;
sy <<= 2 - lowres ;
pix_op [ lowres - 1 ]( dest_y , ptr_y , linesize , h , sx , sy );
2005-12-17 18:14:38 +00:00
2004-09-25 23:18:58 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
uvsx <<= 2 - lowres ;
uvsy <<= 2 - lowres ;
pix_op [ lowres ]( dest_cb , ptr_cb , uvlinesize , h >> s -> chroma_y_shift , uvsx , uvsy );
pix_op [ lowres ]( dest_cr , ptr_cr , uvlinesize , h >> s -> chroma_y_shift , uvsx , uvsy );
}
2004-10-08 22:57:39 +00:00
//FIXME h261 lowres loop filter
2004-09-25 23:18:58 +00:00
}
2003-11-28 21:31:20 +00:00
//FIXME move to dsputil, avg variant, 16x16 version
static inline void put_obmc ( uint8_t * dst , uint8_t * src [ 5 ], int stride ){
int x ;
uint8_t * const top = src [ 1 ];
uint8_t * const left = src [ 2 ];
uint8_t * const mid = src [ 0 ];
uint8_t * const right = src [ 3 ];
uint8_t * const bottom = src [ 4 ];
#define OBMC_FILTER(x, t, l, m, r, b)\
dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
#define OBMC_FILTER4(x, t, l, m, r, b)\
OBMC_FILTER(x , t, l, m, r, b);\
OBMC_FILTER(x+1 , t, l, m, r, b);\
OBMC_FILTER(x +stride, t, l, m, r, b);\
OBMC_FILTER(x+1+stride, t, l, m, r, b);
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
x = 0 ;
OBMC_FILTER ( x , 2 , 2 , 4 , 0 , 0 );
OBMC_FILTER ( x + 1 , 2 , 1 , 5 , 0 , 0 );
OBMC_FILTER4 ( x + 2 , 2 , 1 , 5 , 0 , 0 );
OBMC_FILTER4 ( x + 4 , 2 , 0 , 5 , 1 , 0 );
OBMC_FILTER ( x + 6 , 2 , 0 , 5 , 1 , 0 );
OBMC_FILTER ( x + 7 , 2 , 0 , 4 , 2 , 0 );
x += stride ;
OBMC_FILTER ( x , 1 , 2 , 5 , 0 , 0 );
OBMC_FILTER ( x + 1 , 1 , 2 , 5 , 0 , 0 );
OBMC_FILTER ( x + 6 , 1 , 0 , 5 , 2 , 0 );
OBMC_FILTER ( x + 7 , 1 , 0 , 5 , 2 , 0 );
x += stride ;
OBMC_FILTER4 ( x , 1 , 2 , 5 , 0 , 0 );
OBMC_FILTER4 ( x + 2 , 1 , 1 , 6 , 0 , 0 );
OBMC_FILTER4 ( x + 4 , 1 , 0 , 6 , 1 , 0 );
OBMC_FILTER4 ( x + 6 , 1 , 0 , 5 , 2 , 0 );
x += 2 * stride ;
OBMC_FILTER4 ( x , 0 , 2 , 5 , 0 , 1 );
OBMC_FILTER4 ( x + 2 , 0 , 1 , 6 , 0 , 1 );
OBMC_FILTER4 ( x + 4 , 0 , 0 , 6 , 1 , 1 );
OBMC_FILTER4 ( x + 6 , 0 , 0 , 5 , 2 , 1 );
x += 2 * stride ;
OBMC_FILTER ( x , 0 , 2 , 5 , 0 , 1 );
OBMC_FILTER ( x + 1 , 0 , 2 , 5 , 0 , 1 );
OBMC_FILTER4 ( x + 2 , 0 , 1 , 5 , 0 , 2 );
OBMC_FILTER4 ( x + 4 , 0 , 0 , 5 , 1 , 2 );
OBMC_FILTER ( x + 6 , 0 , 0 , 5 , 2 , 1 );
OBMC_FILTER ( x + 7 , 0 , 0 , 5 , 2 , 1 );
x += stride ;
OBMC_FILTER ( x , 0 , 2 , 4 , 0 , 2 );
OBMC_FILTER ( x + 1 , 0 , 1 , 5 , 0 , 2 );
OBMC_FILTER ( x + 6 , 0 , 0 , 5 , 1 , 2 );
OBMC_FILTER ( x + 7 , 0 , 0 , 4 , 2 , 2 );
}
/* obmc for 1 8x8 luma block */
static inline void obmc_motion ( MpegEncContext * s ,
uint8_t * dest , uint8_t * src ,
int src_x , int src_y ,
op_pixels_func * pix_op ,
int16_t mv [ 5 ][ 2 ] /* mid top left right bottom*/ )
#define MID 0
{
int i ;
uint8_t * ptr [ 5 ];
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
assert ( s -> quarter_sample == 0 );
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
for ( i = 0 ; i < 5 ; i ++ ){
if ( i && mv [ i ][ 0 ] == mv [ MID ][ 0 ] && mv [ i ][ 1 ] == mv [ MID ][ 1 ]){
ptr [ i ] = ptr [ MID ];
} else {
2004-02-13 17:54:10 +00:00
ptr [ i ] = s -> obmc_scratchpad + 8 * ( i & 1 ) + s -> linesize * 8 * ( i >> 1 );
2004-02-29 00:37:36 +00:00
hpel_motion ( s , ptr [ i ], src , 0 , 0 ,
2003-11-28 21:31:20 +00:00
src_x , src_y ,
s -> width , s -> height , s -> linesize ,
s -> h_edge_pos , s -> v_edge_pos ,
8 , 8 , pix_op ,
mv [ i ][ 0 ], mv [ i ][ 1 ]);
}
}
2005-12-17 18:14:38 +00:00
put_obmc ( dest , ptr , s -> linesize );
2003-11-28 21:31:20 +00:00
}
2001-07-22 14:18:56 +00:00
2002-03-09 13:01:16 +00:00
static inline void qpel_motion ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2004-02-29 00:37:36 +00:00
int field_based , int bottom_field , int field_select ,
uint8_t ** ref_picture , op_pixels_func ( * pix_op )[ 4 ],
2002-09-11 12:39:53 +00:00
qpel_mc_func ( * qpix_op )[ 16 ],
2002-03-09 13:01:16 +00:00
int motion_x , int motion_y , int h )
{
2004-02-29 22:14:46 +00:00
uint8_t * ptr_y , * ptr_cb , * ptr_cr ;
int dxy , uvdxy , mx , my , src_x , src_y , uvsrc_x , uvsrc_y , v_edge_pos , linesize , uvlinesize ;
2004-02-29 00:37:36 +00:00
2002-03-09 13:01:16 +00:00
dxy = (( motion_y & 3 ) << 2 ) | ( motion_x & 3 );
2004-02-29 22:14:46 +00:00
src_x = s -> mb_x * 16 + ( motion_x >> 2 );
2002-03-09 13:01:16 +00:00
src_y = s -> mb_y * ( 16 >> field_based ) + ( motion_y >> 2 );
2002-07-25 20:22:36 +00:00
v_edge_pos = s -> v_edge_pos >> field_based ;
2002-03-09 13:01:16 +00:00
linesize = s -> linesize << field_based ;
2002-09-14 10:11:05 +00:00
uvlinesize = s -> uvlinesize << field_based ;
2005-12-17 18:14:38 +00:00
2002-09-14 10:11:05 +00:00
if ( field_based ){
mx = motion_x / 2 ;
my = motion_y >> 1 ;
2003-02-02 23:34:30 +00:00
} else if ( s -> workaround_bugs & FF_BUG_QPEL_CHROMA2 ){
static const int rtab [ 8 ] = { 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 };
mx = ( motion_x >> 1 ) + rtab [ motion_x & 7 ];
my = ( motion_y >> 1 ) + rtab [ motion_y & 7 ];
2002-10-22 18:55:20 +00:00
} else if ( s -> workaround_bugs & FF_BUG_QPEL_CHROMA ){
2002-09-14 10:11:05 +00:00
mx = ( motion_x >> 1 ) | ( motion_x & 1 );
my = ( motion_y >> 1 ) | ( motion_y & 1 );
} else {
mx = motion_x / 2 ;
my = motion_y / 2 ;
}
mx = ( mx >> 1 ) | ( mx & 1 );
my = ( my >> 1 ) | ( my & 1 );
2003-02-02 23:34:30 +00:00
2004-02-29 22:14:46 +00:00
uvdxy = ( mx & 1 ) | (( my & 1 ) << 1 );
2002-09-14 10:11:05 +00:00
mx >>= 1 ;
my >>= 1 ;
2002-03-09 13:01:16 +00:00
2004-02-29 22:14:46 +00:00
uvsrc_x = s -> mb_x * 8 + mx ;
uvsrc_y = s -> mb_y * ( 8 >> field_based ) + my ;
2002-03-09 13:01:16 +00:00
2004-02-29 22:14:46 +00:00
ptr_y = ref_picture [ 0 ] + src_y * linesize + src_x ;
ptr_cb = ref_picture [ 1 ] + uvsrc_y * uvlinesize + uvsrc_x ;
ptr_cr = ref_picture [ 2 ] + uvsrc_y * uvlinesize + uvsrc_x ;
2005-12-17 18:14:38 +00:00
if ( ( unsigned ) src_x > s -> h_edge_pos - ( motion_x & 3 ) - 16
2004-02-29 22:14:46 +00:00
|| ( unsigned ) src_y > v_edge_pos - ( motion_y & 3 ) - h ){
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr_y , s -> linesize , 17 , 17 + field_based ,
2004-02-29 22:14:46 +00:00
src_x , src_y << field_based , s -> h_edge_pos , s -> v_edge_pos );
ptr_y = s -> edge_emu_buffer ;
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2004-03-11 13:22:39 +00:00
uint8_t * uvbuf = s -> edge_emu_buffer + 18 * s -> linesize ;
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf , ptr_cb , s -> uvlinesize , 9 , 9 + field_based ,
2004-02-29 22:14:46 +00:00
uvsrc_x , uvsrc_y << field_based , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
2005-12-17 18:14:38 +00:00
ff_emulated_edge_mc ( uvbuf + 16 , ptr_cr , s -> uvlinesize , 9 , 9 + field_based ,
2004-02-29 22:14:46 +00:00
uvsrc_x , uvsrc_y << field_based , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
ptr_cb = uvbuf ;
ptr_cr = uvbuf + 16 ;
}
2002-07-15 00:25:53 +00:00
}
2004-02-29 22:14:46 +00:00
if ( ! field_based )
qpix_op [ 0 ][ dxy ]( dest_y , ptr_y , linesize );
else {
if ( bottom_field ){
dest_y += s -> linesize ;
dest_cb += s -> uvlinesize ;
dest_cr += s -> uvlinesize ;
}
if ( field_select ){
ptr_y += s -> linesize ;
ptr_cb += s -> uvlinesize ;
ptr_cr += s -> uvlinesize ;
}
//damn interlaced mode
//FIXME boundary mirroring is not exactly correct here
qpix_op [ 1 ][ dxy ]( dest_y , ptr_y , linesize );
qpix_op [ 1 ][ dxy ]( dest_y + 8 , ptr_y + 8 , linesize );
}
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
pix_op [ 1 ][ uvdxy ]( dest_cr , ptr_cr , uvlinesize , h >> 1 );
pix_op [ 1 ][ uvdxy ]( dest_cb , ptr_cb , uvlinesize , h >> 1 );
2002-07-15 00:25:53 +00:00
}
2002-03-09 13:01:16 +00:00
}
2003-01-19 17:55:13 +00:00
inline int ff_h263_round_chroma ( int x ){
if ( x >= 0 )
return ( h263_chroma_roundtab [ x & 0xf ] + (( x >> 3 ) & ~ 1 ));
else {
x = - x ;
return - ( h263_chroma_roundtab [ x & 0xf ] + (( x >> 3 ) & ~ 1 ));
}
}
2002-03-09 13:01:16 +00:00
2003-11-28 21:31:20 +00:00
/**
* h263 chorma 4mv motion compensation.
*/
static inline void chroma_4mv_motion ( MpegEncContext * s ,
uint8_t * dest_cb , uint8_t * dest_cr ,
uint8_t ** ref_picture ,
op_pixels_func * pix_op ,
int mx , int my ){
int dxy , emu = 0 , src_x , src_y , offset ;
uint8_t * ptr ;
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
/* In case of 8X8, we construct a single chroma motion vector
with a special rounding */
mx = ff_h263_round_chroma ( mx );
my = ff_h263_round_chroma ( my );
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
dxy = (( my & 1 ) << 1 ) | ( mx & 1 );
mx >>= 1 ;
my >>= 1 ;
src_x = s -> mb_x * 8 + mx ;
src_y = s -> mb_y * 8 + my ;
src_x = clip ( src_x , - 8 , s -> width / 2 );
if ( src_x == s -> width / 2 )
dxy &= ~ 1 ;
src_y = clip ( src_y , - 8 , s -> height / 2 );
if ( src_y == s -> height / 2 )
dxy &= ~ 2 ;
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
offset = ( src_y * ( s -> uvlinesize )) + src_x ;
ptr = ref_picture [ 1 ] + offset ;
if ( s -> flags & CODEC_FLAG_EMU_EDGE ){
if ( ( unsigned ) src_x > ( s -> h_edge_pos >> 1 ) - ( dxy & 1 ) - 8
|| ( unsigned ) src_y > ( s -> v_edge_pos >> 1 ) - ( dxy >> 1 ) - 8 ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , s -> uvlinesize , 9 , 9 , src_x , src_y , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
ptr = s -> edge_emu_buffer ;
emu = 1 ;
}
}
pix_op [ dxy ]( dest_cb , ptr , s -> uvlinesize , 8 );
ptr = ref_picture [ 2 ] + offset ;
if ( emu ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , s -> uvlinesize , 9 , 9 , src_x , src_y , s -> h_edge_pos >> 1 , s -> v_edge_pos >> 1 );
ptr = s -> edge_emu_buffer ;
}
pix_op [ dxy ]( dest_cr , ptr , s -> uvlinesize , 8 );
}
2004-10-09 12:02:19 +00:00
static inline void chroma_4mv_motion_lowres ( MpegEncContext * s ,
uint8_t * dest_cb , uint8_t * dest_cr ,
uint8_t ** ref_picture ,
h264_chroma_mc_func * pix_op ,
int mx , int my ){
const int lowres = s -> avctx -> lowres ;
const int block_s = 8 >> lowres ;
const int s_mask = ( 2 << lowres ) - 1 ;
const int h_edge_pos = s -> h_edge_pos >> ( lowres + 1 );
const int v_edge_pos = s -> v_edge_pos >> ( lowres + 1 );
int emu = 0 , src_x , src_y , offset , sx , sy ;
uint8_t * ptr ;
2005-12-17 18:14:38 +00:00
2004-10-09 12:02:19 +00:00
if ( s -> quarter_sample ){
mx /= 2 ;
my /= 2 ;
}
/* In case of 8X8, we construct a single chroma motion vector
with a special rounding */
mx = ff_h263_round_chroma ( mx );
my = ff_h263_round_chroma ( my );
2005-12-17 18:14:38 +00:00
2004-10-09 12:02:19 +00:00
sx = mx & s_mask ;
sy = my & s_mask ;
src_x = s -> mb_x * block_s + ( mx >> ( lowres + 1 ));
src_y = s -> mb_y * block_s + ( my >> ( lowres + 1 ));
2005-12-17 18:14:38 +00:00
2004-10-09 12:02:19 +00:00
offset = src_y * s -> uvlinesize + src_x ;
ptr = ref_picture [ 1 ] + offset ;
if ( s -> flags & CODEC_FLAG_EMU_EDGE ){
if ( ( unsigned ) src_x > h_edge_pos - ( !! sx ) - block_s
|| ( unsigned ) src_y > v_edge_pos - ( !! sy ) - block_s ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , s -> uvlinesize , 9 , 9 , src_x , src_y , h_edge_pos , v_edge_pos );
ptr = s -> edge_emu_buffer ;
emu = 1 ;
}
2005-12-17 18:14:38 +00:00
}
2004-10-09 12:02:19 +00:00
sx <<= 2 - lowres ;
sy <<= 2 - lowres ;
pix_op [ lowres ]( dest_cb , ptr , s -> uvlinesize , block_s , sx , sy );
2005-12-17 18:14:38 +00:00
2004-10-09 12:02:19 +00:00
ptr = ref_picture [ 2 ] + offset ;
if ( emu ){
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , s -> uvlinesize , 9 , 9 , src_x , src_y , h_edge_pos , v_edge_pos );
ptr = s -> edge_emu_buffer ;
}
pix_op [ lowres ]( dest_cr , ptr , s -> uvlinesize , block_s , sx , sy );
}
2006-03-23 21:54:46 +00:00
static inline void prefetch_motion ( MpegEncContext * s , uint8_t ** pix , int dir ){
/* fetch pixels for estimated mv 4 macroblocks ahead
* optimized for 64byte cache lines */
const int shift = s -> quarter_sample ? 2 : 1 ;
const int mx = ( s -> mv [ dir ][ 0 ][ 0 ] >> shift ) + 16 * s -> mb_x + 8 ;
const int my = ( s -> mv [ dir ][ 0 ][ 1 ] >> shift ) + 16 * s -> mb_y ;
int off = mx + ( my + ( s -> mb_x & 3 ) * 4 ) * s -> linesize + 64 ;
s -> dsp . prefetch ( pix [ 0 ] + off , s -> linesize , 4 );
off = ( mx >> 1 ) + (( my >> 1 ) + ( s -> mb_x & 7 )) * s -> uvlinesize + 64 ;
s -> dsp . prefetch ( pix [ 1 ] + off , pix [ 2 ] - pix [ 1 ], 2 );
}
2003-05-05 10:00:57 +00:00
/**
2005-06-17 15:02:53 +00:00
* motion compensation of a single macroblock
2003-05-05 10:00:57 +00:00
* @param s context
* @param dest_y luma destination pointer
* @param dest_cb chroma cb/u destination pointer
* @param dest_cr chroma cr/v destination pointer
* @param dir direction (0->forward, 1->backward)
* @param ref_picture array[3] of pointers to the 3 planes of the reference picture
* @param pic_op halfpel motion compensation function (average or put normally)
* @param pic_op qpel motion compensation function (average or put normally)
* the motion vectors are taken from s->mv and the MV type from s->mv_type
*/
2005-12-17 18:14:38 +00:00
static inline void MPV_motion ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2005-12-17 18:14:38 +00:00
int dir , uint8_t ** ref_picture ,
2002-09-11 12:39:53 +00:00
op_pixels_func ( * pix_op )[ 4 ], qpel_mc_func ( * qpix_op )[ 16 ])
2001-07-22 14:18:56 +00:00
{
2003-11-28 21:31:20 +00:00
int dxy , mx , my , src_x , src_y , motion_x , motion_y ;
2001-07-22 14:18:56 +00:00
int mb_x , mb_y , i ;
2003-02-11 16:35:48 +00:00
uint8_t * ptr , * dest ;
2001-07-22 14:18:56 +00:00
mb_x = s -> mb_x ;
mb_y = s -> mb_y ;
2006-03-23 21:54:46 +00:00
prefetch_motion ( s , ref_picture , dir );
2003-12-04 18:34:47 +00:00
if ( s -> obmc && s -> pict_type != B_TYPE ){
2003-11-28 21:31:20 +00:00
int16_t mv_cache [ 4 ][ 4 ][ 2 ];
const int xy = s -> mb_x + s -> mb_y * s -> mb_stride ;
2004-04-16 01:01:45 +00:00
const int mot_stride = s -> b8_stride ;
const int mot_xy = mb_x * 2 + mb_y * 2 * mot_stride ;
2003-11-28 21:31:20 +00:00
2005-04-24 17:21:11 +00:00
assert ( ! s -> mb_skipped );
2005-12-17 18:14:38 +00:00
2003-12-09 01:49:56 +00:00
memcpy ( mv_cache [ 1 ][ 1 ], s -> current_picture . motion_val [ 0 ][ mot_xy ], sizeof ( int16_t ) * 4 );
memcpy ( mv_cache [ 2 ][ 1 ], s -> current_picture . motion_val [ 0 ][ mot_xy + mot_stride ], sizeof ( int16_t ) * 4 );
memcpy ( mv_cache [ 3 ][ 1 ], s -> current_picture . motion_val [ 0 ][ mot_xy + mot_stride ], sizeof ( int16_t ) * 4 );
2003-11-28 21:31:20 +00:00
if ( mb_y == 0 || IS_INTRA ( s -> current_picture . mb_type [ xy - s -> mb_stride ])){
memcpy ( mv_cache [ 0 ][ 1 ], mv_cache [ 1 ][ 1 ], sizeof ( int16_t ) * 4 );
} else {
2003-12-09 01:49:56 +00:00
memcpy ( mv_cache [ 0 ][ 1 ], s -> current_picture . motion_val [ 0 ][ mot_xy - mot_stride ], sizeof ( int16_t ) * 4 );
2003-11-28 21:31:20 +00:00
}
if ( mb_x == 0 || IS_INTRA ( s -> current_picture . mb_type [ xy - 1 ])){
* ( int32_t * ) mv_cache [ 1 ][ 0 ] = * ( int32_t * ) mv_cache [ 1 ][ 1 ];
* ( int32_t * ) mv_cache [ 2 ][ 0 ] = * ( int32_t * ) mv_cache [ 2 ][ 1 ];
} else {
2003-12-09 01:49:56 +00:00
* ( int32_t * ) mv_cache [ 1 ][ 0 ] = * ( int32_t * ) s -> current_picture . motion_val [ 0 ][ mot_xy - 1 ];
* ( int32_t * ) mv_cache [ 2 ][ 0 ] = * ( int32_t * ) s -> current_picture . motion_val [ 0 ][ mot_xy - 1 + mot_stride ];
2003-11-28 21:31:20 +00:00
}
if ( mb_x + 1 >= s -> mb_width || IS_INTRA ( s -> current_picture . mb_type [ xy + 1 ])){
* ( int32_t * ) mv_cache [ 1 ][ 3 ] = * ( int32_t * ) mv_cache [ 1 ][ 2 ];
* ( int32_t * ) mv_cache [ 2 ][ 3 ] = * ( int32_t * ) mv_cache [ 2 ][ 2 ];
} else {
2003-12-09 01:49:56 +00:00
* ( int32_t * ) mv_cache [ 1 ][ 3 ] = * ( int32_t * ) s -> current_picture . motion_val [ 0 ][ mot_xy + 2 ];
* ( int32_t * ) mv_cache [ 2 ][ 3 ] = * ( int32_t * ) s -> current_picture . motion_val [ 0 ][ mot_xy + 2 + mot_stride ];
2003-11-28 21:31:20 +00:00
}
2005-12-17 18:14:38 +00:00
2003-11-28 21:31:20 +00:00
mx = 0 ;
my = 0 ;
for ( i = 0 ; i < 4 ; i ++ ) {
const int x = ( i & 1 ) + 1 ;
const int y = ( i >> 1 ) + 1 ;
int16_t mv [ 5 ][ 2 ] = {
{ mv_cache [ y ][ x ][ 0 ], mv_cache [ y ][ x ][ 1 ]},
{ mv_cache [ y - 1 ][ x ][ 0 ], mv_cache [ y - 1 ][ x ][ 1 ]},
{ mv_cache [ y ][ x - 1 ][ 0 ], mv_cache [ y ][ x - 1 ][ 1 ]},
{ mv_cache [ y ][ x + 1 ][ 0 ], mv_cache [ y ][ x + 1 ][ 1 ]},
{ mv_cache [ y + 1 ][ x ][ 0 ], mv_cache [ y + 1 ][ x ][ 1 ]}};
//FIXME cleanup
obmc_motion ( s , dest_y + (( i & 1 ) * 8 ) + ( i >> 1 ) * 8 * s -> linesize ,
ref_picture [ 0 ],
mb_x * 16 + ( i & 1 ) * 8 , mb_y * 16 + ( i >> 1 ) * 8 ,
pix_op [ 1 ],
mv );
mx += mv [ 0 ][ 0 ];
my += mv [ 0 ][ 1 ];
}
if ( ! ( s -> flags & CODEC_FLAG_GRAY ))
chroma_4mv_motion ( s , dest_cb , dest_cr , ref_picture , pix_op [ 1 ], mx , my );
return ;
}
2005-12-17 18:14:38 +00:00
2001-07-22 14:18:56 +00:00
switch ( s -> mv_type ) {
case MV_TYPE_16X16 :
2002-03-09 13:01:16 +00:00
if ( s -> mcsel ){
2002-10-16 19:55:49 +00:00
if ( s -> real_sprite_warping_points == 1 ){
2004-02-29 00:37:36 +00:00
gmc1_motion ( s , dest_y , dest_cb , dest_cr ,
ref_picture );
2002-10-16 19:55:49 +00:00
} else {
2004-02-29 00:37:36 +00:00
gmc_motion ( s , dest_y , dest_cb , dest_cr ,
ref_picture );
2002-10-16 19:55:49 +00:00
}
2002-09-11 12:39:53 +00:00
} else if ( s -> quarter_sample ){
2005-12-17 18:14:38 +00:00
qpel_motion ( s , dest_y , dest_cb , dest_cr ,
2004-02-29 00:37:36 +00:00
0 , 0 , 0 ,
ref_picture , pix_op , qpix_op ,
2002-03-09 13:01:16 +00:00
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 16 );
2002-12-27 23:51:46 +00:00
} else if ( s -> mspel ){
ff_mspel_motion ( s , dest_y , dest_cb , dest_cr ,
ref_picture , pix_op ,
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 16 );
2003-01-29 12:00:11 +00:00
} else
{
2005-12-17 18:14:38 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
2004-02-29 00:37:36 +00:00
0 , 0 , 0 ,
ref_picture , pix_op ,
2002-03-09 13:01:16 +00:00
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 16 );
2005-12-17 18:14:38 +00:00
}
2001-07-22 14:18:56 +00:00
break ;
case MV_TYPE_8X8 :
2002-09-14 12:36:54 +00:00
mx = 0 ;
my = 0 ;
if ( s -> quarter_sample ){
for ( i = 0 ; i < 4 ; i ++ ) {
motion_x = s -> mv [ dir ][ i ][ 0 ];
motion_y = s -> mv [ dir ][ i ][ 1 ];
2001-07-22 14:18:56 +00:00
2002-09-14 12:36:54 +00:00
dxy = (( motion_y & 3 ) << 2 ) | ( motion_x & 3 );
src_x = mb_x * 16 + ( motion_x >> 2 ) + ( i & 1 ) * 8 ;
src_y = mb_y * 16 + ( motion_y >> 2 ) + ( i >> 1 ) * 8 ;
2005-12-17 18:14:38 +00:00
2002-09-14 12:36:54 +00:00
/* WARNING: do no forget half pels */
src_x = clip ( src_x , - 16 , s -> width );
if ( src_x == s -> width )
dxy &= ~ 3 ;
src_y = clip ( src_y , - 16 , s -> height );
if ( src_y == s -> height )
dxy &= ~ 12 ;
2005-12-17 18:14:38 +00:00
2002-09-14 12:36:54 +00:00
ptr = ref_picture [ 0 ] + ( src_y * s -> linesize ) + ( src_x );
if ( s -> flags & CODEC_FLAG_EMU_EDGE ){
2005-12-17 18:14:38 +00:00
if ( ( unsigned ) src_x > s -> h_edge_pos - ( motion_x & 3 ) - 8
2003-10-17 18:56:01 +00:00
|| ( unsigned ) src_y > s -> v_edge_pos - ( motion_y & 3 ) - 8 ){
2003-06-18 22:00:23 +00:00
ff_emulated_edge_mc ( s -> edge_emu_buffer , ptr , s -> linesize , 9 , 9 , src_x , src_y , s -> h_edge_pos , s -> v_edge_pos );
2002-09-14 12:36:54 +00:00
ptr = s -> edge_emu_buffer ;
}
2002-07-15 00:25:53 +00:00
}
2002-09-14 12:36:54 +00:00
dest = dest_y + (( i & 1 ) * 8 ) + ( i >> 1 ) * 8 * s -> linesize ;
qpix_op [ 1 ][ dxy ]( dest , ptr , s -> linesize );
mx += s -> mv [ dir ][ i ][ 0 ] / 2 ;
my += s -> mv [ dir ][ i ][ 1 ] / 2 ;
}
} else {
for ( i = 0 ; i < 4 ; i ++ ) {
2003-11-28 21:31:20 +00:00
hpel_motion ( s , dest_y + (( i & 1 ) * 8 ) + ( i >> 1 ) * 8 * s -> linesize ,
2004-02-29 00:37:36 +00:00
ref_picture [ 0 ], 0 , 0 ,
2003-11-28 21:31:20 +00:00
mb_x * 16 + ( i & 1 ) * 8 , mb_y * 16 + ( i >> 1 ) * 8 ,
s -> width , s -> height , s -> linesize ,
s -> h_edge_pos , s -> v_edge_pos ,
8 , 8 , pix_op [ 1 ],
s -> mv [ dir ][ i ][ 0 ], s -> mv [ dir ][ i ][ 1 ]);
2002-09-14 12:36:54 +00:00
mx += s -> mv [ dir ][ i ][ 0 ];
my += s -> mv [ dir ][ i ][ 1 ];
2002-07-15 00:25:53 +00:00
}
2001-07-22 14:18:56 +00:00
}
2002-09-14 12:36:54 +00:00
2003-11-28 21:31:20 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY ))
chroma_4mv_motion ( s , dest_cb , dest_cr , ref_picture , pix_op [ 1 ], mx , my );
2001-07-22 14:18:56 +00:00
break ;
case MV_TYPE_FIELD :
if ( s -> picture_structure == PICT_FRAME ) {
2002-09-14 10:11:05 +00:00
if ( s -> quarter_sample ){
2004-02-29 02:08:28 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
qpel_motion ( s , dest_y , dest_cb , dest_cr ,
1 , i , s -> field_select [ dir ][ i ],
ref_picture , pix_op , qpix_op ,
s -> mv [ dir ][ i ][ 0 ], s -> mv [ dir ][ i ][ 1 ], 8 );
}
2002-09-14 10:11:05 +00:00
} else {
2005-12-17 18:14:38 +00:00
/* top field */
2004-02-29 00:37:36 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
1 , 0 , s -> field_select [ dir ][ 0 ],
ref_picture , pix_op ,
2002-09-14 10:11:05 +00:00
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 8 );
/* bottom field */
2004-02-29 00:37:36 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
1 , 1 , s -> field_select [ dir ][ 1 ],
ref_picture , pix_op ,
2002-09-14 10:11:05 +00:00
s -> mv [ dir ][ 1 ][ 0 ], s -> mv [ dir ][ 1 ][ 1 ], 8 );
}
2001-07-22 14:18:56 +00:00
} else {
2004-02-29 00:37:36 +00:00
if ( s -> picture_structure != s -> field_select [ dir ][ 0 ] + 1 && s -> pict_type != B_TYPE && ! s -> first_field ){
ref_picture = s -> current_picture_ptr -> data ;
2005-12-17 18:14:38 +00:00
}
2001-07-22 14:18:56 +00:00
2004-02-29 00:37:36 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
0 , 0 , s -> field_select [ dir ][ 0 ],
ref_picture , pix_op ,
2003-03-05 17:48:19 +00:00
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 16 );
2001-07-22 14:18:56 +00:00
}
2003-07-03 23:29:00 +00:00
break ;
2004-02-29 02:08:28 +00:00
case MV_TYPE_16X8 :
for ( i = 0 ; i < 2 ; i ++ ){
uint8_t ** ref2picture ;
2003-07-03 23:29:00 +00:00
2004-02-29 02:08:28 +00:00
if ( s -> picture_structure == s -> field_select [ dir ][ i ] + 1 || s -> pict_type == B_TYPE || s -> first_field ){
2003-07-03 23:29:00 +00:00
ref2picture = ref_picture ;
} else {
2004-02-29 00:37:36 +00:00
ref2picture = s -> current_picture_ptr -> data ;
2005-12-17 18:14:38 +00:00
}
2003-07-03 23:29:00 +00:00
2005-12-17 18:14:38 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
2004-02-29 02:08:28 +00:00
0 , 0 , s -> field_select [ dir ][ i ],
2004-02-29 00:37:36 +00:00
ref2picture , pix_op ,
2004-02-29 02:08:28 +00:00
s -> mv [ dir ][ i ][ 0 ], s -> mv [ dir ][ i ][ 1 ] + 16 * i , 8 );
2005-12-17 18:14:38 +00:00
2004-02-29 02:08:28 +00:00
dest_y += 16 * s -> linesize ;
2004-06-11 07:59:12 +00:00
dest_cb += ( 16 >> s -> chroma_y_shift ) * s -> uvlinesize ;
dest_cr += ( 16 >> s -> chroma_y_shift ) * s -> uvlinesize ;
2005-12-17 18:14:38 +00:00
}
2001-07-22 14:18:56 +00:00
break ;
2003-06-23 22:32:15 +00:00
case MV_TYPE_DMV :
if ( s -> picture_structure == PICT_FRAME ){
2004-02-29 02:08:28 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
int j ;
for ( j = 0 ; j < 2 ; j ++ ){
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
1 , j , j ^ i ,
ref_picture , pix_op ,
s -> mv [ dir ][ 2 * i + j ][ 0 ], s -> mv [ dir ][ 2 * i + j ][ 1 ], 8 );
}
2005-12-17 18:14:38 +00:00
pix_op = s -> dsp . avg_pixels_tab ;
2004-02-29 00:37:36 +00:00
}
2004-02-29 02:08:28 +00:00
} else {
for ( i = 0 ; i < 2 ; i ++ ){
2005-12-17 18:14:38 +00:00
mpeg_motion ( s , dest_y , dest_cb , dest_cr ,
2004-02-29 02:08:28 +00:00
0 , 0 , s -> picture_structure != i + 1 ,
ref_picture , pix_op ,
s -> mv [ dir ][ 2 * i ][ 0 ], s -> mv [ dir ][ 2 * i ][ 1 ], 16 );
2003-06-23 22:32:15 +00:00
2004-02-29 02:08:28 +00:00
// after put we make avg of the same block
2005-12-17 18:14:38 +00:00
pix_op = s -> dsp . avg_pixels_tab ;
2004-02-29 02:08:28 +00:00
//opposite parity is always in the same frame if this is second field
if ( ! s -> first_field ){
2005-12-17 18:14:38 +00:00
ref_picture = s -> current_picture_ptr -> data ;
2004-02-29 02:08:28 +00:00
}
}
2003-06-23 22:32:15 +00:00
}
break ;
2003-11-28 21:31:20 +00:00
default : assert ( 0 );
2001-07-22 14:18:56 +00:00
}
}
2004-09-25 23:18:58 +00:00
/**
2005-06-17 15:02:53 +00:00
* motion compensation of a single macroblock
2004-09-25 23:18:58 +00:00
* @param s context
* @param dest_y luma destination pointer
* @param dest_cb chroma cb/u destination pointer
* @param dest_cr chroma cr/v destination pointer
* @param dir direction (0->forward, 1->backward)
* @param ref_picture array[3] of pointers to the 3 planes of the reference picture
* @param pic_op halfpel motion compensation function (average or put normally)
* the motion vectors are taken from s->mv and the MV type from s->mv_type
*/
2005-12-17 18:14:38 +00:00
static inline void MPV_motion_lowres ( MpegEncContext * s ,
2004-09-25 23:18:58 +00:00
uint8_t * dest_y , uint8_t * dest_cb , uint8_t * dest_cr ,
2005-12-17 18:14:38 +00:00
int dir , uint8_t ** ref_picture ,
2004-09-25 23:18:58 +00:00
h264_chroma_mc_func * pix_op )
{
2004-10-09 12:02:19 +00:00
int mx , my ;
2004-09-26 11:05:35 +00:00
int mb_x , mb_y , i ;
const int lowres = s -> avctx -> lowres ;
2005-12-17 18:14:38 +00:00
const int block_s = 8 >> lowres ;
2004-09-26 11:05:35 +00:00
mb_x = s -> mb_x ;
mb_y = s -> mb_y ;
switch ( s -> mv_type ) {
case MV_TYPE_16X16 :
2005-12-17 18:14:38 +00:00
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
2004-09-26 11:05:35 +00:00
0 , 0 , 0 ,
ref_picture , pix_op ,
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 2 * block_s );
break ;
2004-10-09 12:02:19 +00:00
case MV_TYPE_8X8 :
2004-09-26 11:05:35 +00:00
mx = 0 ;
my = 0 ;
for ( i = 0 ; i < 4 ; i ++ ) {
2004-10-09 12:02:19 +00:00
hpel_motion_lowres ( s , dest_y + (( i & 1 ) + ( i >> 1 ) * s -> linesize ) * block_s ,
2004-09-26 11:05:35 +00:00
ref_picture [ 0 ], 0 , 0 ,
2004-10-09 12:02:19 +00:00
( 2 * mb_x + ( i & 1 )) * block_s , ( 2 * mb_y + ( i >> 1 )) * block_s ,
2004-09-26 11:05:35 +00:00
s -> width , s -> height , s -> linesize ,
2004-10-09 12:02:19 +00:00
s -> h_edge_pos >> lowres , s -> v_edge_pos >> lowres ,
block_s , block_s , pix_op ,
2004-09-26 11:05:35 +00:00
s -> mv [ dir ][ i ][ 0 ], s -> mv [ dir ][ i ][ 1 ]);
mx += s -> mv [ dir ][ i ][ 0 ];
my += s -> mv [ dir ][ i ][ 1 ];
}
if ( ! ( s -> flags & CODEC_FLAG_GRAY ))
2004-10-09 12:02:19 +00:00
chroma_4mv_motion_lowres ( s , dest_cb , dest_cr , ref_picture , pix_op , mx , my );
break ;
2004-09-26 11:05:35 +00:00
case MV_TYPE_FIELD :
if ( s -> picture_structure == PICT_FRAME ) {
2005-12-17 18:14:38 +00:00
/* top field */
2004-09-26 11:05:35 +00:00
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
1 , 0 , s -> field_select [ dir ][ 0 ],
ref_picture , pix_op ,
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], block_s );
/* bottom field */
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
1 , 1 , s -> field_select [ dir ][ 1 ],
ref_picture , pix_op ,
s -> mv [ dir ][ 1 ][ 0 ], s -> mv [ dir ][ 1 ][ 1 ], block_s );
} else {
if ( s -> picture_structure != s -> field_select [ dir ][ 0 ] + 1 && s -> pict_type != B_TYPE && ! s -> first_field ){
ref_picture = s -> current_picture_ptr -> data ;
2005-12-17 18:14:38 +00:00
}
2004-09-26 11:05:35 +00:00
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
0 , 0 , s -> field_select [ dir ][ 0 ],
ref_picture , pix_op ,
s -> mv [ dir ][ 0 ][ 0 ], s -> mv [ dir ][ 0 ][ 1 ], 2 * block_s );
}
break ;
case MV_TYPE_16X8 :
for ( i = 0 ; i < 2 ; i ++ ){
uint8_t ** ref2picture ;
if ( s -> picture_structure == s -> field_select [ dir ][ i ] + 1 || s -> pict_type == B_TYPE || s -> first_field ){
ref2picture = ref_picture ;
} else {
ref2picture = s -> current_picture_ptr -> data ;
2005-12-17 18:14:38 +00:00
}
2004-09-26 11:05:35 +00:00
2005-12-17 18:14:38 +00:00
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
2004-09-26 11:05:35 +00:00
0 , 0 , s -> field_select [ dir ][ i ],
ref2picture , pix_op ,
s -> mv [ dir ][ i ][ 0 ], s -> mv [ dir ][ i ][ 1 ] + 2 * block_s * i , block_s );
2005-12-17 18:14:38 +00:00
2004-09-26 11:05:35 +00:00
dest_y += 2 * block_s * s -> linesize ;
dest_cb += ( 2 * block_s >> s -> chroma_y_shift ) * s -> uvlinesize ;
dest_cr += ( 2 * block_s >> s -> chroma_y_shift ) * s -> uvlinesize ;
2005-12-17 18:14:38 +00:00
}
2004-09-26 11:05:35 +00:00
break ;
case MV_TYPE_DMV :
if ( s -> picture_structure == PICT_FRAME ){
for ( i = 0 ; i < 2 ; i ++ ){
int j ;
for ( j = 0 ; j < 2 ; j ++ ){
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
1 , j , j ^ i ,
ref_picture , pix_op ,
s -> mv [ dir ][ 2 * i + j ][ 0 ], s -> mv [ dir ][ 2 * i + j ][ 1 ], block_s );
}
pix_op = s -> dsp . avg_h264_chroma_pixels_tab ;
}
} else {
for ( i = 0 ; i < 2 ; i ++ ){
2005-12-17 18:14:38 +00:00
mpeg_motion_lowres ( s , dest_y , dest_cb , dest_cr ,
2004-09-26 11:05:35 +00:00
0 , 0 , s -> picture_structure != i + 1 ,
ref_picture , pix_op ,
s -> mv [ dir ][ 2 * i ][ 0 ], s -> mv [ dir ][ 2 * i ][ 1 ], 2 * block_s );
// after put we make avg of the same block
pix_op = s -> dsp . avg_h264_chroma_pixels_tab ;
//opposite parity is always in the same frame if this is second field
if ( ! s -> first_field ){
2005-12-17 18:14:38 +00:00
ref_picture = s -> current_picture_ptr -> data ;
2004-09-26 11:05:35 +00:00
}
}
}
break ;
default : assert ( 0 );
}
2004-09-25 23:18:58 +00:00
}
2001-07-22 14:18:56 +00:00
/* put block[] to dest[] */
2005-12-17 18:14:38 +00:00
static inline void put_dct ( MpegEncContext * s ,
2003-12-03 16:07:41 +00:00
DCTELEM * block , int i , uint8_t * dest , int line_size , int qscale )
2001-07-22 14:18:56 +00:00
{
2003-12-14 02:57:00 +00:00
s -> dct_unquantize_intra ( s , block , i , qscale );
2003-03-03 14:54:00 +00:00
s -> dsp . idct_put ( dest , line_size , block );
2001-07-22 14:18:56 +00:00
}
/* add block[] to dest[] */
2005-12-17 18:14:38 +00:00
static inline void add_dct ( MpegEncContext * s ,
2003-02-11 16:35:48 +00:00
DCTELEM * block , int i , uint8_t * dest , int line_size )
2001-07-22 14:18:56 +00:00
{
if ( s -> block_last_index [ i ] >= 0 ) {
2003-03-03 14:54:00 +00:00
s -> dsp . idct_add ( dest , line_size , block );
2002-06-05 23:43:56 +00:00
}
}
2005-12-17 18:14:38 +00:00
static inline void add_dequant_dct ( MpegEncContext * s ,
2003-12-01 15:23:14 +00:00
DCTELEM * block , int i , uint8_t * dest , int line_size , int qscale )
2002-06-05 23:43:56 +00:00
{
if ( s -> block_last_index [ i ] >= 0 ) {
2003-12-14 02:57:00 +00:00
s -> dct_unquantize_inter ( s , block , i , qscale );
2002-04-17 04:32:12 +00:00
2003-03-03 14:54:00 +00:00
s -> dsp . idct_add ( dest , line_size , block );
2001-07-22 14:18:56 +00:00
}
}
2002-06-02 12:20:39 +00:00
/**
* cleans dc, ac, coded_block for the current non intra MB
*/
void ff_clean_intra_table_entries ( MpegEncContext * s )
{
2004-04-16 01:01:45 +00:00
int wrap = s -> b8_stride ;
2002-06-02 12:20:39 +00:00
int xy = s -> block_index [ 0 ];
2005-12-17 18:14:38 +00:00
s -> dc_val [ 0 ][ xy ] =
s -> dc_val [ 0 ][ xy + 1 ] =
2002-06-02 12:20:39 +00:00
s -> dc_val [ 0 ][ xy + wrap ] =
s -> dc_val [ 0 ][ xy + 1 + wrap ] = 1024 ;
/* ac pred */
2003-02-11 16:35:48 +00:00
memset ( s -> ac_val [ 0 ][ xy ], 0 , 32 * sizeof ( int16_t ));
memset ( s -> ac_val [ 0 ][ xy + wrap ], 0 , 32 * sizeof ( int16_t ));
2002-06-02 12:20:39 +00:00
if ( s -> msmpeg4_version >= 3 ) {
s -> coded_block [ xy ] =
s -> coded_block [ xy + 1 ] =
s -> coded_block [ xy + wrap ] =
s -> coded_block [ xy + 1 + wrap ] = 0 ;
}
/* chroma */
2004-04-16 01:01:45 +00:00
wrap = s -> mb_stride ;
xy = s -> mb_x + s -> mb_y * wrap ;
2002-06-02 12:20:39 +00:00
s -> dc_val [ 1 ][ xy ] =
s -> dc_val [ 2 ][ xy ] = 1024 ;
/* ac pred */
2003-02-11 16:35:48 +00:00
memset ( s -> ac_val [ 1 ][ xy ], 0 , 16 * sizeof ( int16_t ));
memset ( s -> ac_val [ 2 ][ xy ], 0 , 16 * sizeof ( int16_t ));
2005-12-17 18:14:38 +00:00
2004-04-16 01:01:45 +00:00
s -> mbintra_table [ xy ] = 0 ;
2002-06-02 12:20:39 +00:00
}
2001-07-22 14:18:56 +00:00
/* generic function called after a macroblock has been parsed by the
decoder or after it has been encoded by the encoder.
Important variables used:
s->mb_intra : true if intra macroblock
s->mv_dir : motion vector direction
s->mv_type : motion vector type
s->mv : motion vector
s->interlaced_dct : true if interlaced dct used (mpeg2)
*/
2004-09-25 23:18:58 +00:00
static always_inline void MPV_decode_mb_internal ( MpegEncContext * s , DCTELEM block [ 12 ][ 64 ], int lowres_flag )
2001-07-22 14:18:56 +00:00
{
2002-02-18 09:31:37 +00:00
int mb_x , mb_y ;
2003-04-10 13:18:38 +00:00
const int mb_xy = s -> mb_y * s -> mb_stride + s -> mb_x ;
2003-07-26 01:28:49 +00:00
#ifdef HAVE_XVMC
if ( s -> avctx -> xvmc_acceleration ){
2003-10-27 23:22:43 +00:00
XVMC_decode_mb ( s ); //xvmc uses pblocks
2003-07-26 01:28:49 +00:00
return ;
}
#endif
2001-07-22 14:18:56 +00:00
mb_x = s -> mb_x ;
mb_y = s -> mb_y ;
2004-02-25 18:29:17 +00:00
if ( s -> avctx -> debug & FF_DEBUG_DCT_COEFF ) {
/* save DCT coefficients */
int i , j ;
DCTELEM * dct = & s -> current_picture . dct_coeff [ mb_xy * 64 * 6 ];
for ( i = 0 ; i < 6 ; i ++ )
for ( j = 0 ; j < 64 ; j ++ )
* dct ++ = block [ i ][ s -> dsp . idct_permutation [ j ]];
}
2002-12-04 10:04:03 +00:00
s -> current_picture . qscale_table [ mb_xy ] = s -> qscale ;
2001-10-16 23:10:38 +00:00
2001-07-22 14:18:56 +00:00
/* update DC predictors for P macroblocks */
if ( ! s -> mb_intra ) {
2002-02-19 19:23:34 +00:00
if ( s -> h263_pred || s -> h263_aic ) {
2002-06-05 23:43:56 +00:00
if ( s -> mbintra_table [ mb_xy ])
2002-06-02 12:20:39 +00:00
ff_clean_intra_table_entries ( s );
2001-07-22 14:18:56 +00:00
} else {
2002-06-02 12:20:39 +00:00
s -> last_dc [ 0 ] =
s -> last_dc [ 1 ] =
2001-07-22 14:18:56 +00:00
s -> last_dc [ 2 ] = 128 << s -> intra_dc_precision ;
}
}
2002-02-19 19:23:34 +00:00
else if ( s -> h263_pred || s -> h263_aic )
2002-06-05 23:43:56 +00:00
s -> mbintra_table [ mb_xy ] = 1 ;
2002-01-10 00:53:21 +00:00
2002-12-04 21:13:02 +00:00
if (( s -> flags & CODEC_FLAG_PSNR ) || ! ( s -> encoding && ( s -> intra_only || s -> pict_type == B_TYPE ))) { //FIXME precalc
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , * dest_cb , * dest_cr ;
2002-06-05 23:43:56 +00:00
int dct_linesize , dct_offset ;
2002-09-11 12:39:53 +00:00
op_pixels_func ( * op_pix )[ 4 ];
qpel_mc_func ( * op_qpix )[ 16 ];
2005-04-24 11:13:49 +00:00
const int linesize = s -> current_picture . linesize [ 0 ]; //not s->linesize as this would be wrong for field pics
2003-03-16 20:22:22 +00:00
const int uvlinesize = s -> current_picture . linesize [ 1 ];
2004-09-25 23:18:58 +00:00
const int readable = s -> pict_type != B_TYPE || s -> encoding || s -> avctx -> draw_horiz_band || lowres_flag ;
const int block_size = lowres_flag ? 8 >> s -> avctx -> lowres : 8 ;
2001-07-24 20:43:41 +00:00
2002-12-04 10:04:03 +00:00
/* avoid copy if macroblock skipped in last frame too */
/* skip only during decoding as we might trash the buffers during encoding a bit */
if ( ! s -> encoding ){
2003-02-11 16:35:48 +00:00
uint8_t * mbskip_ptr = & s -> mbskip_table [ mb_xy ];
2002-12-04 10:04:03 +00:00
const int age = s -> current_picture . age ;
assert ( age );
2005-04-24 17:21:11 +00:00
if ( s -> mb_skipped ) {
s -> mb_skipped = 0 ;
2002-12-04 10:04:03 +00:00
assert ( s -> pict_type != I_TYPE );
2005-12-17 18:14:38 +00:00
2005-04-24 17:21:11 +00:00
( * mbskip_ptr ) ++ ; /* indicate that this time we skipped it */
2002-07-15 14:15:10 +00:00
if ( * mbskip_ptr > 99 ) * mbskip_ptr = 99 ;
2002-12-04 10:04:03 +00:00
/* if previous was skipped too, then nothing to do ! */
2003-01-20 20:37:24 +00:00
if ( * mbskip_ptr >= age && s -> current_picture . reference ){
return ;
2002-12-04 10:04:03 +00:00
}
2003-01-20 20:37:24 +00:00
} else if ( ! s -> current_picture . reference ){
( * mbskip_ptr ) ++ ; /* increase counter so the age can be compared cleanly */
if ( * mbskip_ptr > 99 ) * mbskip_ptr = 99 ;
} else {
2001-07-24 20:43:41 +00:00
* mbskip_ptr = 0 ; /* not skipped */
}
2002-10-02 17:07:39 +00:00
}
2005-12-17 18:14:38 +00:00
2004-06-11 07:59:12 +00:00
dct_linesize = linesize << s -> interlaced_dct ;
2004-09-25 23:18:58 +00:00
dct_offset = ( s -> interlaced_dct ) ? linesize : linesize * block_size ;
2005-12-17 18:14:38 +00:00
2003-11-27 13:38:00 +00:00
if ( readable ){
dest_y = s -> dest [ 0 ];
dest_cb = s -> dest [ 1 ];
dest_cr = s -> dest [ 2 ];
} else {
2004-02-13 17:54:10 +00:00
dest_y = s -> b_scratchpad ;
2004-02-26 02:48:07 +00:00
dest_cb = s -> b_scratchpad + 16 * linesize ;
2004-06-11 07:59:12 +00:00
dest_cr = s -> b_scratchpad + 32 * linesize ;
2003-11-27 13:38:00 +00:00
}
2004-09-25 23:18:58 +00:00
2001-07-22 14:18:56 +00:00
if ( ! s -> mb_intra ) {
/* motion handling */
2005-04-24 11:13:49 +00:00
/* decoding or more than one mb_type (MC was already done otherwise) */
2003-07-29 02:09:12 +00:00
if ( ! s -> encoding ){
2004-09-25 23:18:58 +00:00
if ( lowres_flag ){
h264_chroma_mc_func * op_pix = s -> dsp . put_h264_chroma_pixels_tab ;
2001-07-22 14:18:56 +00:00
2004-09-25 23:18:58 +00:00
if ( s -> mv_dir & MV_DIR_FORWARD ) {
MPV_motion_lowres ( s , dest_y , dest_cb , dest_cr , 0 , s -> last_picture . data , op_pix );
op_pix = s -> dsp . avg_h264_chroma_pixels_tab ;
}
if ( s -> mv_dir & MV_DIR_BACKWARD ) {
MPV_motion_lowres ( s , dest_y , dest_cb , dest_cr , 1 , s -> next_picture . data , op_pix );
}
} else {
2006-10-01 21:25:17 +00:00
op_qpix = s -> me . qpel_put ;
2005-12-17 18:14:38 +00:00
if (( ! s -> no_rounding ) || s -> pict_type == B_TYPE ){
2004-09-25 23:18:58 +00:00
op_pix = s -> dsp . put_pixels_tab ;
} else {
op_pix = s -> dsp . put_no_rnd_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 ;
2006-10-01 21:25:17 +00:00
op_qpix = s -> me . qpel_avg ;
2004-09-25 23:18:58 +00:00
}
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 );
}
2002-04-17 04:32:12 +00:00
}
2001-07-22 14:18:56 +00:00
}
2002-06-05 23:43:56 +00:00
/* skip dequant / idct if we are really late ;) */
2005-07-14 21:39:36 +00:00
if ( s -> hurry_up > 1 ) goto skip_idct ;
if ( s -> avctx -> skip_idct ){
if ( ( s -> avctx -> skip_idct >= AVDISCARD_NONREF && s -> pict_type == B_TYPE )
|| ( s -> avctx -> skip_idct >= AVDISCARD_NONKEY && s -> pict_type != I_TYPE )
|| s -> avctx -> skip_idct >= AVDISCARD_ALL )
goto skip_idct ;
}
2001-07-22 14:18:56 +00:00
2002-06-05 23:43:56 +00:00
/* add dct residue */
2003-08-25 22:47:32 +00:00
if ( s -> encoding || ! ( s -> h263_msmpeg4 || s -> codec_id == CODEC_ID_MPEG1VIDEO || s -> codec_id == CODEC_ID_MPEG2VIDEO
2002-09-30 16:14:14 +00:00
|| ( s -> codec_id == CODEC_ID_MPEG4 && ! s -> mpeg_quant ))){
2004-09-25 23:18:58 +00:00
add_dequant_dct ( s , block [ 0 ], 0 , dest_y , dct_linesize , s -> qscale );
add_dequant_dct ( s , block [ 1 ], 1 , dest_y + block_size , dct_linesize , s -> qscale );
add_dequant_dct ( s , block [ 2 ], 2 , dest_y + dct_offset , dct_linesize , s -> qscale );
add_dequant_dct ( s , block [ 3 ], 3 , dest_y + dct_offset + block_size , dct_linesize , s -> qscale );
2002-06-05 23:43:56 +00:00
2002-06-09 13:35:56 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2006-05-16 15:19:54 +00:00
if ( s -> chroma_y_shift ){
add_dequant_dct ( s , block [ 4 ], 4 , dest_cb , uvlinesize , s -> chroma_qscale );
add_dequant_dct ( s , block [ 5 ], 5 , dest_cr , uvlinesize , s -> chroma_qscale );
} else {
dct_linesize >>= 1 ;
dct_offset >>= 1 ;
add_dequant_dct ( s , block [ 4 ], 4 , dest_cb , dct_linesize , s -> chroma_qscale );
add_dequant_dct ( s , block [ 5 ], 5 , dest_cr , dct_linesize , s -> chroma_qscale );
add_dequant_dct ( s , block [ 6 ], 6 , dest_cb + dct_offset , dct_linesize , s -> chroma_qscale );
add_dequant_dct ( s , block [ 7 ], 7 , dest_cr + dct_offset , dct_linesize , s -> chroma_qscale );
}
2002-06-09 13:35:56 +00:00
}
2002-12-27 23:51:46 +00:00
} else if ( s -> codec_id != CODEC_ID_WMV2 ){
2004-09-25 23:18:58 +00:00
add_dct ( s , block [ 0 ], 0 , dest_y , dct_linesize );
add_dct ( s , block [ 1 ], 1 , dest_y + block_size , dct_linesize );
add_dct ( s , block [ 2 ], 2 , dest_y + dct_offset , dct_linesize );
add_dct ( s , block [ 3 ], 3 , dest_y + dct_offset + block_size , dct_linesize );
2002-06-05 23:43:56 +00:00
2002-06-09 13:35:56 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2004-06-11 07:59:12 +00:00
if ( s -> chroma_y_shift ){ //Chroma420
add_dct ( s , block [ 4 ], 4 , dest_cb , uvlinesize );
add_dct ( s , block [ 5 ], 5 , dest_cr , uvlinesize );
} else {
//chroma422
dct_linesize = uvlinesize << s -> interlaced_dct ;
dct_offset = ( s -> interlaced_dct ) ? uvlinesize : uvlinesize * 8 ;
add_dct ( s , block [ 4 ], 4 , dest_cb , dct_linesize );
add_dct ( s , block [ 5 ], 5 , dest_cr , dct_linesize );
add_dct ( s , block [ 6 ], 6 , dest_cb + dct_offset , dct_linesize );
add_dct ( s , block [ 7 ], 7 , dest_cr + dct_offset , dct_linesize );
if ( ! s -> chroma_x_shift ){ //Chroma444
add_dct ( s , block [ 8 ], 8 , dest_cb + 8 , dct_linesize );
add_dct ( s , block [ 9 ], 9 , dest_cr + 8 , dct_linesize );
add_dct ( s , block [ 10 ], 10 , dest_cb + 8 + dct_offset , dct_linesize );
add_dct ( s , block [ 11 ], 11 , dest_cr + 8 + dct_offset , dct_linesize );
}
}
} //fi gray
}
2003-01-29 12:00:11 +00:00
else {
2002-12-27 23:51:46 +00:00
ff_wmv2_add_mb ( s , block , dest_y , dest_cb , dest_cr );
2002-06-05 23:43:56 +00:00
}
2001-07-22 14:18:56 +00:00
} else {
/* dct only in intra block */
2003-08-25 22:47:32 +00:00
if ( s -> encoding || ! ( s -> codec_id == CODEC_ID_MPEG1VIDEO || s -> codec_id == CODEC_ID_MPEG2VIDEO )){
2004-09-25 23:18:58 +00:00
put_dct ( s , block [ 0 ], 0 , dest_y , dct_linesize , s -> qscale );
put_dct ( s , block [ 1 ], 1 , dest_y + block_size , dct_linesize , s -> qscale );
put_dct ( s , block [ 2 ], 2 , dest_y + dct_offset , dct_linesize , s -> qscale );
put_dct ( s , block [ 3 ], 3 , dest_y + dct_offset + block_size , dct_linesize , s -> qscale );
2001-07-22 14:18:56 +00:00
2002-09-30 16:14:14 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2006-05-16 15:19:54 +00:00
if ( s -> chroma_y_shift ){
put_dct ( s , block [ 4 ], 4 , dest_cb , uvlinesize , s -> chroma_qscale );
put_dct ( s , block [ 5 ], 5 , dest_cr , uvlinesize , s -> chroma_qscale );
} else {
dct_offset >>= 1 ;
dct_linesize >>= 1 ;
put_dct ( s , block [ 4 ], 4 , dest_cb , dct_linesize , s -> chroma_qscale );
put_dct ( s , block [ 5 ], 5 , dest_cr , dct_linesize , s -> chroma_qscale );
put_dct ( s , block [ 6 ], 6 , dest_cb + dct_offset , dct_linesize , s -> chroma_qscale );
put_dct ( s , block [ 7 ], 7 , dest_cr + dct_offset , dct_linesize , s -> chroma_qscale );
}
2002-09-30 16:14:14 +00:00
}
} else {
2004-09-25 23:18:58 +00:00
s -> dsp . idct_put ( dest_y , dct_linesize , block [ 0 ]);
s -> dsp . idct_put ( dest_y + block_size , dct_linesize , block [ 1 ]);
s -> dsp . idct_put ( dest_y + dct_offset , dct_linesize , block [ 2 ]);
s -> dsp . idct_put ( dest_y + dct_offset + block_size , dct_linesize , block [ 3 ]);
2002-09-30 16:14:14 +00:00
if ( ! ( s -> flags & CODEC_FLAG_GRAY )){
2004-06-11 07:59:12 +00:00
if ( s -> chroma_y_shift ){
s -> dsp . idct_put ( dest_cb , uvlinesize , block [ 4 ]);
s -> dsp . idct_put ( dest_cr , uvlinesize , block [ 5 ]);
} else {
dct_linesize = uvlinesize << s -> interlaced_dct ;
dct_offset = ( s -> interlaced_dct ) ? uvlinesize : uvlinesize * 8 ;
s -> dsp . idct_put ( dest_cb , dct_linesize , block [ 4 ]);
s -> dsp . idct_put ( dest_cr , dct_linesize , block [ 5 ]);
s -> dsp . idct_put ( dest_cb + dct_offset , dct_linesize , block [ 6 ]);
s -> dsp . idct_put ( dest_cr + dct_offset , dct_linesize , block [ 7 ]);
if ( ! s -> chroma_x_shift ){ //Chroma444
s -> dsp . idct_put ( dest_cb + 8 , dct_linesize , block [ 8 ]);
s -> dsp . idct_put ( dest_cr + 8 , dct_linesize , block [ 9 ]);
s -> dsp . idct_put ( dest_cb + 8 + dct_offset , dct_linesize , block [ 10 ]);
s -> dsp . idct_put ( dest_cr + 8 + dct_offset , dct_linesize , block [ 11 ]);
}
}
} //gray
2002-06-09 13:35:56 +00:00
}
2001-07-22 14:18:56 +00:00
}
2005-07-14 21:39:36 +00:00
skip_idct :
2003-11-27 13:38:00 +00:00
if ( ! readable ){
s -> dsp . put_pixels_tab [ 0 ][ 0 ]( s -> dest [ 0 ], dest_y , linesize , 16 );
2004-06-11 07:59:12 +00:00
s -> dsp . put_pixels_tab [ s -> chroma_x_shift ][ 0 ]( s -> dest [ 1 ], dest_cb , uvlinesize , 16 >> s -> chroma_y_shift );
s -> dsp . put_pixels_tab [ s -> chroma_x_shift ][ 0 ]( s -> dest [ 2 ], dest_cr , uvlinesize , 16 >> s -> chroma_y_shift );
2003-11-27 13:38:00 +00:00
}
2001-07-22 14:18:56 +00:00
}
2002-03-27 21:25:22 +00:00
}
2004-09-25 23:18:58 +00:00
void MPV_decode_mb ( MpegEncContext * s , DCTELEM block [ 12 ][ 64 ]){
if ( s -> avctx -> lowres ) MPV_decode_mb_internal ( s , block , 1 );
else MPV_decode_mb_internal ( s , block , 0 );
}
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2002-08-18 00:42:58 +00:00
static inline void dct_single_coeff_elimination ( MpegEncContext * s , int n , int threshold )
2002-06-02 12:20:39 +00:00
{
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 ];
2002-08-18 00:42:58 +00:00
int skip_dc ;
2002-06-02 12:20:39 +00:00
2002-08-17 20:10:27 +00:00
if ( threshold < 0 ){
skip_dc = 0 ;
threshold = - threshold ;
2002-08-18 00:42:58 +00:00
} else
skip_dc = 1 ;
2002-08-17 20:10:27 +00:00
2002-06-02 12:20:39 +00:00
/* are all which we could set to zero are allready zero? */
if ( last_index <= skip_dc - 1 ) return ;
for ( i = 0 ; i <= last_index ; i ++ ){
2002-09-29 22:44:22 +00:00
const int j = s -> intra_scantable . permutated [ i ];
2002-06-02 12:20:39 +00:00
const int level = ABS ( 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 ++ ){
2002-09-29 22:44:22 +00:00
const int j = s -> intra_scantable . permutated [ i ];
2002-06-02 12:20:39 +00:00
block [ j ] = 0 ;
}
if ( block [ 0 ]) s -> block_last_index [ n ] = 0 ;
else s -> block_last_index [ n ] = - 1 ;
}
2002-04-27 12:30:26 +00:00
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 ;
2004-01-04 14:43:52 +00:00
int overflow = 0 ;
2005-12-17 18:14:38 +00:00
2002-09-29 22:44:22 +00:00
if ( s -> mb_intra ){
i = 1 ; //skip clipping of intra dc
} else
i = 0 ;
2005-12-17 18:14:38 +00:00
2002-09-29 22:44:22 +00:00
for (; i <= last_index ; i ++ ){
const int j = s -> intra_scantable . permutated [ i ];
2002-04-27 12:30:26 +00:00
int level = block [ j ];
2005-12-17 18:14:38 +00:00
2004-01-04 14:43:52 +00:00
if ( level > maxlevel ){
level = maxlevel ;
overflow ++ ;
} else if ( level < minlevel ){
level = minlevel ;
overflow ++ ;
}
2005-12-17 18:14:38 +00:00
2002-04-27 12:30:26 +00:00
block [ j ] = level ;
}
2005-12-17 18:14:38 +00:00
2004-01-04 14:43:52 +00:00
if ( overflow && s -> avctx -> mb_decision == FF_MB_DECISION_SIMPLE )
2005-04-24 11:13:49 +00:00
av_log ( s -> avctx , AV_LOG_INFO , "warning, clipping %d dct coefficients to %d..%d \n " , overflow , minlevel , maxlevel );
2002-04-27 12:30:26 +00:00
}
2002-04-17 04:32:12 +00:00
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2003-03-05 20:03:15 +00:00
/**
*
* @param h is the normal height, this will be reduced automatically if needed for the last row
*/
void ff_draw_horiz_band ( MpegEncContext * s , int y , int h ){
2003-07-17 12:29:07 +00:00
if ( s -> avctx -> draw_horiz_band ) {
2003-07-20 14:48:05 +00:00
AVFrame * src ;
2003-07-17 12:29:07 +00:00
int offset [ 4 ];
2005-12-17 18:14:38 +00:00
2003-07-20 14:48:05 +00:00
if ( s -> picture_structure != PICT_FRAME ){
h <<= 1 ;
y <<= 1 ;
if ( s -> first_field && ! ( s -> avctx -> slice_flags & SLICE_FLAG_ALLOW_FIELD )) return ;
}
2004-09-27 02:39:55 +00:00
h = FFMIN ( h , s -> avctx -> height - y );
2002-10-13 13:16:04 +00:00
2005-12-17 18:14:38 +00:00
if ( s -> pict_type == B_TYPE || s -> low_delay || ( s -> avctx -> slice_flags & SLICE_FLAG_CODED_ORDER ))
2003-07-20 14:48:05 +00:00
src = ( AVFrame * ) s -> current_picture_ptr ;
else if ( s -> last_picture_ptr )
src = ( AVFrame * ) s -> last_picture_ptr ;
else
return ;
2005-12-17 18:14:38 +00:00
2003-07-18 11:47:14 +00:00
if ( s -> pict_type == B_TYPE && s -> picture_structure == PICT_FRAME && s -> out_format != FMT_H264 ){
2003-07-17 12:29:07 +00:00
offset [ 0 ] =
offset [ 1 ] =
offset [ 2 ] =
offset [ 3 ] = 0 ;
} else {
offset [ 0 ] = y * s -> linesize ;;
2005-12-17 18:14:38 +00:00
offset [ 1 ] =
2004-06-11 07:59:12 +00:00
offset [ 2 ] = ( y >> s -> chroma_y_shift ) * s -> uvlinesize ;
2003-07-17 12:29:07 +00:00
offset [ 3 ] = 0 ;
2002-10-13 13:16:04 +00:00
}
2003-07-17 12:29:07 +00:00
2002-10-31 11:47:58 +00:00
emms_c ();
2003-07-20 14:48:05 +00:00
s -> avctx -> draw_horiz_band ( s -> avctx , src , offset ,
y , s -> picture_structure , h );
2002-10-13 13:16:04 +00:00
}
}
2003-07-29 02:09:12 +00:00
void ff_init_block_index ( MpegEncContext * s ){ //FIXME maybe rename
2005-06-17 15:02:53 +00:00
const int linesize = s -> current_picture . linesize [ 0 ]; //not s->linesize as this would be wrong for field pics
2003-07-29 02:09:12 +00:00
const int uvlinesize = s -> current_picture . linesize [ 1 ];
2004-09-25 23:18:58 +00:00
const int mb_size = 4 - s -> avctx -> lowres ;
2005-12-17 18:14:38 +00:00
2004-04-16 01:01:45 +00:00
s -> block_index [ 0 ] = s -> b8_stride * ( s -> mb_y * 2 ) - 2 + s -> mb_x * 2 ;
s -> block_index [ 1 ] = s -> b8_stride * ( s -> mb_y * 2 ) - 1 + s -> mb_x * 2 ;
s -> block_index [ 2 ] = s -> b8_stride * ( s -> mb_y * 2 + 1 ) - 2 + s -> mb_x * 2 ;
s -> block_index [ 3 ] = s -> b8_stride * ( s -> mb_y * 2 + 1 ) - 1 + s -> mb_x * 2 ;
s -> block_index [ 4 ] = s -> mb_stride * ( s -> mb_y + 1 ) + s -> b8_stride * s -> mb_height * 2 + s -> mb_x - 1 ;
s -> block_index [ 5 ] = s -> mb_stride * ( s -> mb_y + s -> mb_height + 2 ) + s -> b8_stride * s -> mb_height * 2 + s -> mb_x - 1 ;
2004-06-11 07:59:12 +00:00
//block_index is not used by mpeg2, so it is not affected by chroma_format
2004-09-25 23:18:58 +00:00
s -> dest [ 0 ] = s -> current_picture . data [ 0 ] + (( s -> mb_x - 1 ) << mb_size );
s -> dest [ 1 ] = s -> current_picture . data [ 1 ] + (( s -> mb_x - 1 ) << ( mb_size - s -> chroma_x_shift ));
s -> dest [ 2 ] = s -> current_picture . data [ 2 ] + (( s -> mb_x - 1 ) << ( mb_size - s -> chroma_x_shift ));
2004-08-13 14:40:33 +00:00
2004-06-11 07:59:12 +00:00
if ( ! ( s -> pict_type == B_TYPE && s -> avctx -> draw_horiz_band && s -> picture_structure == PICT_FRAME ))
{
2004-09-25 23:18:58 +00:00
s -> dest [ 0 ] += s -> mb_y * linesize << mb_size ;
s -> dest [ 1 ] += s -> mb_y * uvlinesize << ( mb_size - s -> chroma_y_shift );
s -> dest [ 2 ] += s -> mb_y * uvlinesize << ( mb_size - s -> chroma_y_shift );
2004-06-11 07:59:12 +00:00
}
2003-07-29 02:09:12 +00:00
}
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2004-02-02 03:52:58 +00:00
static void get_vissual_weight ( int16_t * weight , uint8_t * ptr , int stride ){
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 ;
}
}
}
2006-05-16 15:19:54 +00:00
static always_inline void encode_mb_internal ( MpegEncContext * s , int motion_x , int motion_y , int mb_block_height , int mb_block_count )
2002-03-27 21:25:22 +00:00
{
2006-05-16 15:19:54 +00:00
int16_t weight [ 8 ][ 64 ];
DCTELEM orig [ 8 ][ 64 ];
2002-03-27 21:25:22 +00:00
const int mb_x = s -> mb_x ;
const int mb_y = s -> mb_y ;
int i ;
2006-05-16 15:19:54 +00:00
int skip_dct [ 8 ];
2002-09-26 00:22:25 +00:00
int dct_offset = s -> linesize * 8 ; //default for progressive frames
2004-02-02 14:59:43 +00:00
uint8_t * ptr_y , * ptr_cb , * ptr_cr ;
int wrap_y , wrap_c ;
2005-12-17 18:14:38 +00:00
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < mb_block_count ; i ++ ) skip_dct [ i ] = 0 ;
2005-12-17 18:14:38 +00:00
2002-09-23 14:56:11 +00:00
if ( s -> adaptive_quant ){
2003-10-07 11:32:40 +00:00
const int last_qp = s -> qscale ;
const int mb_xy = mb_x + mb_y * s -> mb_stride ;
2002-09-26 00:22:25 +00:00
2003-10-07 11:32:40 +00:00
s -> lambda = s -> lambda_table [ mb_xy ];
update_qscale ( s );
2005-12-17 18:14:38 +00:00
2003-11-12 12:25:44 +00:00
if ( ! ( s -> flags & CODEC_FLAG_QP_RD )){
s -> dquant = s -> qscale - last_qp ;
2003-10-07 11:32:40 +00:00
2004-02-14 03:49:43 +00:00
if ( s -> out_format == FMT_H263 ){
2003-11-12 12:25:44 +00:00
s -> dquant = clip ( s -> dquant , - 2 , 2 ); //FIXME RD
2005-12-17 18:14:38 +00:00
if ( s -> codec_id == CODEC_ID_MPEG4 ){
2004-02-14 03:49:43 +00:00
if ( ! s -> mb_intra ){
if ( s -> pict_type == B_TYPE ){
2005-12-17 18:14:38 +00:00
if ( s -> dquant & 1 )
2004-02-14 03:49:43 +00:00
s -> dquant = ( s -> dquant / 2 ) * 2 ;
if ( s -> mv_dir & MV_DIRECT )
s -> dquant = 0 ;
}
if ( s -> mv_type == MV_TYPE_8X8 )
s -> dquant = 0 ;
}
2003-11-12 12:25:44 +00:00
}
2002-09-23 14:56:11 +00:00
}
}
2003-12-03 16:47:17 +00:00
ff_set_qscale ( s , last_qp + s -> dquant );
2004-06-05 18:10:23 +00:00
} else if ( s -> flags & CODEC_FLAG_QP_RD )
ff_set_qscale ( s , s -> qscale + s -> dquant );
2002-04-17 04:32:12 +00:00
2004-02-02 14:59:43 +00:00
wrap_y = s -> linesize ;
wrap_c = s -> uvlinesize ;
ptr_y = s -> new_picture . data [ 0 ] + ( mb_y * 16 * wrap_y ) + mb_x * 16 ;
2006-05-16 15:19:54 +00:00
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 ;
2004-02-02 14:59:43 +00:00
if ( mb_x * 16 + 16 > s -> width || mb_y * 16 + 16 > s -> height ){
2004-08-11 19:32:34 +00:00
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 ;
2006-05-16 15:19:54 +00:00
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 );
2004-08-11 19:32:34 +00:00
ptr_cb = ebuf + 18 * wrap_y ;
2006-05-16 15:19:54 +00:00
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 );
2004-08-11 19:32:34 +00:00
ptr_cr = ebuf + 18 * wrap_y + 8 ;
2004-02-02 14:59:43 +00:00
}
2002-04-17 04:32:12 +00:00
if ( s -> mb_intra ) {
2002-09-26 00:22:25 +00:00
if ( s -> flags & CODEC_FLAG_INTERLACED_DCT ){
int progressive_score , interlaced_score ;
2003-12-30 16:07:57 +00:00
2004-01-05 22:57:07 +00:00
s -> interlaced_dct = 0 ;
2005-12-17 18:14:38 +00:00
progressive_score = s -> dsp . ildct_cmp [ 4 ]( s , ptr_y , NULL , wrap_y , 8 )
2004-02-02 03:52:58 +00:00
+ s -> dsp . ildct_cmp [ 4 ]( s , ptr_y + wrap_y * 8 , NULL , wrap_y , 8 ) - 400 ;
2004-01-05 22:57:07 +00:00
if ( progressive_score > 0 ){
2005-12-17 18:14:38 +00:00
interlaced_score = s -> dsp . ildct_cmp [ 4 ]( s , ptr_y , NULL , wrap_y * 2 , 8 )
2004-02-02 03:52:58 +00:00
+ s -> dsp . ildct_cmp [ 4 ]( s , ptr_y + wrap_y , NULL , wrap_y * 2 , 8 );
2004-01-05 22:57:07 +00:00
if ( progressive_score > interlaced_score ){
s -> interlaced_dct = 1 ;
2005-12-17 18:14:38 +00:00
2004-01-05 22:57:07 +00:00
dct_offset = wrap_y ;
wrap_y <<= 1 ;
2006-05-16 15:19:54 +00:00
if ( s -> chroma_format == CHROMA_422 )
wrap_c <<= 1 ;
2004-01-05 22:57:07 +00:00
}
}
2002-09-26 00:22:25 +00:00
}
2005-12-17 18:14:38 +00:00
2005-12-22 01:10:11 +00:00
s -> dsp . get_pixels ( s -> block [ 0 ], ptr_y , wrap_y );
2004-02-02 03:52:58 +00:00
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 );
2002-04-17 04:32:12 +00:00
2002-06-09 14:04:36 +00:00
if ( s -> flags & CODEC_FLAG_GRAY ){
skip_dct [ 4 ] = 1 ;
skip_dct [ 5 ] = 1 ;
} else {
2005-12-22 01:10:11 +00:00
s -> dsp . get_pixels ( s -> block [ 4 ], ptr_cb , wrap_c );
2004-02-02 03:52:58 +00:00
s -> dsp . get_pixels ( s -> block [ 5 ], ptr_cr , wrap_c );
2006-05-16 15:19:54 +00:00
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 );
}
2004-02-02 03:52:58 +00:00
}
2002-04-17 04:32:12 +00:00
} else {
2002-09-11 12:39:53 +00:00
op_pixels_func ( * op_pix )[ 4 ];
qpel_mc_func ( * op_qpix )[ 16 ];
2003-02-11 16:35:48 +00:00
uint8_t * dest_y , * dest_cb , * dest_cr ;
2002-04-17 04:32:12 +00:00
2003-07-29 02:09:12 +00:00
dest_y = s -> dest [ 0 ];
dest_cb = s -> dest [ 1 ];
dest_cr = s -> dest [ 2 ];
2002-04-17 04:32:12 +00:00
2002-04-19 03:25:20 +00:00
if (( ! s -> no_rounding ) || s -> pict_type == B_TYPE ){
2005-12-22 01:10:11 +00:00
op_pix = s -> dsp . put_pixels_tab ;
2002-11-11 09:40:17 +00:00
op_qpix = s -> dsp . put_qpel_pixels_tab ;
2002-04-17 04:32:12 +00:00
} else {
2002-11-11 09:40:17 +00:00
op_pix = s -> dsp . put_no_rnd_pixels_tab ;
op_qpix = s -> dsp . put_no_rnd_qpel_pixels_tab ;
2002-04-17 04:32:12 +00:00
}
if ( s -> mv_dir & MV_DIR_FORWARD ) {
2002-12-04 10:04:03 +00:00
MPV_motion ( s , dest_y , dest_cb , dest_cr , 0 , s -> last_picture . data , op_pix , op_qpix );
2002-11-11 09:40:17 +00:00
op_pix = s -> dsp . avg_pixels_tab ;
op_qpix = s -> dsp . avg_qpel_pixels_tab ;
2002-04-17 04:32:12 +00:00
}
if ( s -> mv_dir & MV_DIR_BACKWARD ) {
2002-12-04 10:04:03 +00:00
MPV_motion ( s , dest_y , dest_cb , dest_cr , 1 , s -> next_picture . data , op_pix , op_qpix );
2002-04-17 04:32:12 +00:00
}
2002-09-26 00:22:25 +00:00
if ( s -> flags & CODEC_FLAG_INTERLACED_DCT ){
int progressive_score , interlaced_score ;
2004-01-05 22:57:07 +00:00
s -> interlaced_dct = 0 ;
2005-12-17 18:14:38 +00:00
progressive_score = s -> dsp . ildct_cmp [ 0 ]( s , dest_y , ptr_y , wrap_y , 8 )
2004-01-05 22:57:07 +00:00
+ s -> dsp . ildct_cmp [ 0 ]( s , dest_y + wrap_y * 8 , ptr_y + wrap_y * 8 , wrap_y , 8 ) - 400 ;
2005-12-17 18:14:38 +00:00
2004-01-05 22:57:07 +00:00
if ( s -> avctx -> ildct_cmp == FF_CMP_VSSE ) progressive_score -= 400 ;
if ( progressive_score > 0 ){
2005-12-17 18:14:38 +00:00
interlaced_score = s -> dsp . ildct_cmp [ 0 ]( s , dest_y , ptr_y , wrap_y * 2 , 8 )
2004-01-05 22:57:07 +00:00
+ s -> dsp . ildct_cmp [ 0 ]( s , dest_y + wrap_y , ptr_y + wrap_y , wrap_y * 2 , 8 );
2005-12-17 18:14:38 +00:00
2004-01-05 22:57:07 +00:00
if ( progressive_score > interlaced_score ){
s -> interlaced_dct = 1 ;
2005-12-17 18:14:38 +00:00
2004-01-05 22:57:07 +00:00
dct_offset = wrap_y ;
wrap_y <<= 1 ;
2006-05-16 15:19:54 +00:00
if ( s -> chroma_format == CHROMA_422 )
wrap_c <<= 1 ;
2004-01-05 22:57:07 +00:00
}
}
2002-09-26 00:22:25 +00:00
}
2005-12-17 18:14:38 +00:00
2005-12-22 01:10:11 +00:00
s -> dsp . diff_pixels ( s -> block [ 0 ], ptr_y , dest_y , wrap_y );
2002-11-11 09:40:17 +00:00
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 );
2005-12-17 18:14:38 +00:00
2002-06-09 14:04:36 +00:00
if ( s -> flags & CODEC_FLAG_GRAY ){
skip_dct [ 4 ] = 1 ;
skip_dct [ 5 ] = 1 ;
} else {
2002-11-11 09:40:17 +00:00
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 );
2006-05-16 15:19:54 +00:00
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 );
}
2002-06-09 14:04:36 +00:00
}
2005-12-17 18:14:38 +00:00
/* pre quantization */
2003-04-10 13:18:38 +00:00
if ( s -> current_picture . mc_mb_var [ s -> mb_stride * mb_y + mb_x ] < 2 * s -> qscale * s -> qscale ){
2002-09-26 00:22:25 +00:00
//FIXME optimize
2005-12-22 01:10:11 +00:00
if ( s -> dsp . sad [ 1 ]( NULL , ptr_y , dest_y , wrap_y , 8 ) < 20 * s -> qscale ) skip_dct [ 0 ] = 1 ;
2003-12-30 16:07:57 +00:00
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 ;
2006-05-16 15:19:54 +00:00
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 ;
}
2002-06-02 12:20:39 +00:00
}
2004-02-02 14:59:43 +00:00
}
2002-04-17 04:32:12 +00:00
2004-02-02 14:59:43 +00:00
if ( s -> avctx -> quantizer_noise_shaping ){
if ( ! skip_dct [ 0 ]) get_vissual_weight ( weight [ 0 ], ptr_y , wrap_y );
if ( ! skip_dct [ 1 ]) get_vissual_weight ( weight [ 1 ], ptr_y + 8 , wrap_y );
if ( ! skip_dct [ 2 ]) get_vissual_weight ( weight [ 2 ], ptr_y + dct_offset , wrap_y );
if ( ! skip_dct [ 3 ]) get_vissual_weight ( weight [ 3 ], ptr_y + dct_offset + 8 , wrap_y );
if ( ! skip_dct [ 4 ]) get_vissual_weight ( weight [ 4 ], ptr_cb , wrap_c );
if ( ! skip_dct [ 5 ]) get_vissual_weight ( weight [ 5 ], ptr_cr , wrap_c );
2006-05-16 15:19:54 +00:00
if ( ! s -> chroma_y_shift ){ /* 422 */
if ( ! skip_dct [ 6 ]) get_vissual_weight ( weight [ 6 ], ptr_cb + ( dct_offset >> 1 ), wrap_c );
if ( ! skip_dct [ 7 ]) get_vissual_weight ( weight [ 7 ], ptr_cr + ( dct_offset >> 1 ), wrap_c );
}
memcpy ( orig [ 0 ], s -> block [ 0 ], sizeof ( DCTELEM ) * 64 * mb_block_count );
2002-03-27 21:25:22 +00:00
}
2005-12-17 18:14:38 +00:00
2002-03-27 21:25:22 +00:00
/* DCT & quantize */
2004-02-02 14:59:43 +00:00
assert ( s -> out_format != FMT_MJPEG || s -> qscale == 8 );
{
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < mb_block_count ; i ++ ) {
2002-06-02 12:20:39 +00:00
if ( ! skip_dct [ i ]){
int overflow ;
2002-08-29 23:55:32 +00:00
s -> block_last_index [ i ] = s -> dct_quantize ( s , s -> block [ i ], i , s -> qscale , & overflow );
2002-04-27 12:30:26 +00:00
// FIXME we could decide to change to quantizer instead of clipping
2002-05-02 04:39:45 +00:00
// 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
2002-06-02 12:20:39 +00:00
if ( overflow ) clip_coeffs ( s , s -> block [ i ], s -> block_last_index [ i ]);
} else
s -> block_last_index [ i ] = - 1 ;
2002-04-27 12:30:26 +00:00
}
2004-02-02 03:52:58 +00:00
if ( s -> avctx -> quantizer_noise_shaping ){
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < mb_block_count ; i ++ ) {
2004-02-02 03:52:58 +00:00
if ( ! skip_dct [ i ]){
s -> block_last_index [ i ] = dct_quantize_refine ( s , s -> block [ i ], weight [ i ], orig [ i ], i , s -> qscale );
}
}
}
2005-12-17 18:14:38 +00:00
2002-06-02 12:20:39 +00:00
if ( s -> luma_elim_threshold && ! s -> mb_intra )
for ( i = 0 ; i < 4 ; i ++ )
2002-08-18 00:42:58 +00:00
dct_single_coeff_elimination ( s , i , s -> luma_elim_threshold );
2002-06-02 12:20:39 +00:00
if ( s -> chroma_elim_threshold && ! s -> mb_intra )
2006-05-16 15:19:54 +00:00
for ( i = 4 ; i < mb_block_count ; i ++ )
2002-08-18 00:42:58 +00:00
dct_single_coeff_elimination ( s , i , s -> chroma_elim_threshold );
2003-10-02 08:52:37 +00:00
if ( s -> flags & CODEC_FLAG_CBP_RD ){
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < mb_block_count ; i ++ ) {
2003-10-02 08:52:37 +00:00
if ( s -> block_last_index [ i ] == - 1 )
s -> coded_score [ i ] = INT_MAX / 256 ;
}
}
2002-03-27 21:25:22 +00:00
}
2002-06-09 14:04:36 +00:00
if (( s -> flags & CODEC_FLAG_GRAY ) && s -> mb_intra ){
s -> block_last_index [ 4 ] =
s -> block_last_index [ 5 ] = 0 ;
s -> block [ 4 ][ 0 ] =
2003-01-18 01:37:42 +00:00
s -> block [ 5 ][ 0 ] = ( 1024 + s -> c_dc_scale / 2 ) / s -> c_dc_scale ;
2002-06-09 14:04:36 +00:00
}
2003-12-30 16:07:57 +00:00
//non c quantize code returns incorrect block_last_index FIXME
if ( s -> alternate_scan && s -> dct_quantize != dct_quantize_c ){
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < mb_block_count ; i ++ ){
2003-12-30 16:07:57 +00:00
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 ;
}
}
}
2002-03-27 21:25:22 +00:00
/* huffman encode */
2002-12-27 23:51:46 +00:00
switch ( s -> codec_id ){ //FIXME funct ptr could be slightly faster
case CODEC_ID_MPEG1VIDEO :
2003-08-25 22:47:32 +00:00
case CODEC_ID_MPEG2VIDEO :
2002-12-27 23:51:46 +00:00
mpeg1_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
case CODEC_ID_MPEG4 :
mpeg4_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
case CODEC_ID_MSMPEG4V2 :
case CODEC_ID_MSMPEG4V3 :
case CODEC_ID_WMV1 :
msmpeg4_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
case CODEC_ID_WMV2 :
ff_wmv2_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
2005-05-02 22:14:42 +00:00
#ifdef CONFIG_H261_ENCODER
2004-10-28 10:12:57 +00:00
case CODEC_ID_H261 :
ff_h261_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
2005-05-02 22:14:42 +00:00
#endif
2002-12-27 23:51:46 +00:00
case CODEC_ID_H263 :
case CODEC_ID_H263P :
2003-07-09 23:10:59 +00:00
case CODEC_ID_FLV1 :
2002-12-27 23:51:46 +00:00
case CODEC_ID_RV10 :
2004-12-07 13:14:37 +00:00
case CODEC_ID_RV20 :
2002-12-27 23:51:46 +00:00
h263_encode_mb ( s , s -> block , motion_x , motion_y ); break ;
2003-01-29 12:00:11 +00:00
case CODEC_ID_MJPEG :
mjpeg_encode_mb ( s , s -> block ); break ;
2002-12-27 23:51:46 +00:00
default :
assert ( 0 );
2002-03-27 21:25:22 +00:00
}
}
2006-05-16 15:19:54 +00:00
static 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 );
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2003-07-17 12:29:07 +00:00
void ff_mpeg_flush ( AVCodecContext * avctx ){
int i ;
MpegEncContext * s = avctx -> priv_data ;
2005-12-17 18:14:38 +00:00
if ( s == NULL || s -> picture == NULL )
2004-01-19 14:41:34 +00:00
return ;
2005-12-17 18:14:38 +00:00
2003-07-17 12:29:07 +00:00
for ( i = 0 ; i < MAX_PICTURE_COUNT ; i ++ ){
if ( s -> picture [ i ]. data [ 0 ] && ( s -> picture [ i ]. type == FF_BUFFER_TYPE_INTERNAL
|| s -> picture [ i ]. type == FF_BUFFER_TYPE_USER ))
avctx -> release_buffer ( avctx , ( AVFrame * ) & s -> picture [ i ]);
}
2003-11-03 17:42:50 +00:00
s -> current_picture_ptr = s -> last_picture_ptr = s -> next_picture_ptr = NULL ;
2005-12-17 18:14:38 +00:00
2004-12-07 13:14:37 +00:00
s -> mb_x = s -> mb_y = 0 ;
2005-12-17 18:14:38 +00:00
2003-08-02 22:01:02 +00:00
s -> parse_context . state = - 1 ;
s -> parse_context . frame_start_found = 0 ;
s -> parse_context . overread = 0 ;
s -> parse_context . overread_index = 0 ;
s -> parse_context . index = 0 ;
s -> parse_context . last_index = 0 ;
2004-03-02 03:18:03 +00:00
s -> bitstream_buffer_size = 0 ;
2003-07-17 12:29:07 +00:00
}
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2003-02-11 16:35:48 +00:00
void ff_copy_bits ( PutBitContext * pb , uint8_t * src , int length )
2002-03-27 21:25:22 +00:00
{
2004-02-17 18:57:50 +00:00
const uint16_t * srcw = ( uint16_t * ) src ;
2004-02-13 17:54:10 +00:00
int words = length >> 4 ;
2002-04-17 18:19:50 +00:00
int bits = length & 15 ;
int i ;
2002-06-02 12:20:39 +00:00
if ( length == 0 ) return ;
2005-12-17 18:14:38 +00:00
2004-02-14 01:25:41 +00:00
if ( words < 16 ){
for ( i = 0 ; i < words ; i ++ ) put_bits ( pb , 16 , be2me_16 ( srcw [ i ]));
} else if ( put_bits_count ( pb ) & 7 ){
for ( i = 0 ; i < words ; i ++ ) put_bits ( pb , 16 , be2me_16 ( srcw [ i ]));
2004-02-13 21:07:31 +00:00
} else {
2004-02-14 01:25:41 +00:00
for ( i = 0 ; put_bits_count ( pb ) & 31 ; i ++ )
put_bits ( pb , 8 , src [ i ]);
2004-02-13 17:54:10 +00:00
flush_put_bits ( pb );
2004-02-14 01:25:41 +00:00
memcpy ( pbBufPtr ( pb ), src + i , 2 * words - i );
skip_put_bytes ( pb , 2 * words - i );
2004-02-13 21:07:31 +00:00
}
2005-12-17 18:14:38 +00:00
2004-02-14 01:25:41 +00:00
put_bits ( pb , bits , be2me_16 ( srcw [ words ]) >> ( 16 - bits ));
2001-07-22 14:18:56 +00:00
}
2002-06-02 12:20:39 +00:00
static inline void copy_context_before_encode ( MpegEncContext * d , MpegEncContext * s , int type ){
2002-04-17 18:19:50 +00:00
int i ;
memcpy ( d -> last_mv , s -> last_mv , 2 * 2 * 2 * sizeof ( int )); //FIXME is memcpy faster then a loop?
/* mpeg1 */
2003-03-30 19:26:01 +00:00
d -> mb_skip_run = s -> mb_skip_run ;
2002-04-17 18:19:50 +00:00
for ( i = 0 ; i < 3 ; i ++ )
d -> last_dc [ i ] = s -> last_dc [ i ];
2005-12-17 18:14:38 +00:00
2002-04-17 18:19:50 +00:00
/* 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 ;
2002-09-12 12:26:09 +00:00
d -> f_count = s -> f_count ;
d -> b_count = s -> b_count ;
2002-04-17 18:19:50 +00:00
d -> skip_count = s -> skip_count ;
d -> misc_bits = s -> misc_bits ;
2002-04-21 21:18:17 +00:00
d -> last_bits = 0 ;
2002-04-19 03:25:20 +00:00
2005-04-24 17:21:11 +00:00
d -> mb_skipped = 0 ;
2002-12-05 19:18:13 +00:00
d -> qscale = s -> qscale ;
2003-11-12 12:25:44 +00:00
d -> dquant = s -> dquant ;
2002-04-17 18:19:50 +00:00
}
2002-06-02 12:20:39 +00:00
static inline void copy_context_after_encode ( MpegEncContext * d , MpegEncContext * s , int type ){
2002-04-17 18:19:50 +00:00
int i ;
2005-12-17 18:14:38 +00:00
memcpy ( d -> mv , s -> mv , 2 * 4 * 2 * sizeof ( int ));
2002-04-17 18:19:50 +00:00
memcpy ( d -> last_mv , s -> last_mv , 2 * 2 * 2 * sizeof ( int )); //FIXME is memcpy faster then a loop?
2005-12-17 18:14:38 +00:00
2002-04-17 18:19:50 +00:00
/* mpeg1 */
2003-03-30 19:26:01 +00:00
d -> mb_skip_run = s -> mb_skip_run ;
2002-04-17 18:19:50 +00:00
for ( i = 0 ; i < 3 ; i ++ )
d -> last_dc [ i ] = s -> last_dc [ i ];
2005-12-17 18:14:38 +00:00
2002-04-17 18:19:50 +00:00
/* 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 ;
2002-09-12 12:26:09 +00:00
d -> f_count = s -> f_count ;
d -> b_count = s -> b_count ;
2002-04-17 18:19:50 +00:00
d -> skip_count = s -> skip_count ;
d -> misc_bits = s -> misc_bits ;
d -> mb_intra = s -> mb_intra ;
2005-04-24 17:21:11 +00:00
d -> mb_skipped = s -> mb_skipped ;
2002-04-17 18:19:50 +00:00
d -> mv_type = s -> mv_type ;
d -> mv_dir = s -> mv_dir ;
d -> pb = s -> pb ;
2002-06-02 12:20:39 +00:00
if ( s -> data_partitioning ){
d -> pb2 = s -> pb2 ;
d -> tex_pb = s -> tex_pb ;
}
2002-04-17 18:19:50 +00:00
d -> block = s -> block ;
2006-05-16 15:19:54 +00:00
for ( i = 0 ; i < 8 ; i ++ )
2002-04-17 18:19:50 +00:00
d -> block_last_index [ i ] = s -> block_last_index [ i ];
2002-10-18 18:32:50 +00:00
d -> interlaced_dct = s -> interlaced_dct ;
2002-12-05 19:18:13 +00:00
d -> qscale = s -> qscale ;
2002-04-17 18:19:50 +00:00
}
2005-12-17 18:14:38 +00:00
static inline void encode_mb_hq ( MpegEncContext * s , MpegEncContext * backup , MpegEncContext * best , int type ,
2002-06-02 12:20:39 +00:00
PutBitContext pb [ 2 ], PutBitContext pb2 [ 2 ], PutBitContext tex_pb [ 2 ],
int * dmin , int * next_block , int motion_x , int motion_y )
{
2003-07-29 02:09:12 +00:00
int score ;
uint8_t * dest_backup [ 3 ];
2005-12-17 18:14:38 +00:00
2002-06-02 12:20:39 +00:00
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 ];
}
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
if ( * next_block ){
memcpy ( dest_backup , s -> dest , sizeof ( s -> dest ));
2004-02-13 17:54:10 +00:00
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
2002-06-02 12:20:39 +00:00
}
2003-07-29 02:09:12 +00:00
encode_mb ( s , motion_x , motion_y );
2005-12-17 18:14:38 +00:00
2004-02-06 15:27:31 +00:00
score = put_bits_count ( & s -> pb );
2003-07-29 02:09:12 +00:00
if ( s -> data_partitioning ){
2004-02-06 15:27:31 +00:00
score += put_bits_count ( & s -> pb2 );
score += put_bits_count ( & s -> tex_pb );
2003-07-29 02:09:12 +00:00
}
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
if ( s -> avctx -> mb_decision == FF_MB_DECISION_RD ){
MPV_decode_mb ( s , s -> block );
2003-10-07 11:32:40 +00:00
score *= s -> lambda2 ;
score += sse_mb ( s ) << FF_LAMBDA_SHIFT ;
2003-07-29 02:09:12 +00:00
}
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
if ( * next_block ){
memcpy ( s -> dest , dest_backup , sizeof ( s -> dest ));
}
if ( score <* dmin ){
* dmin = score ;
2002-06-02 12:20:39 +00:00
* next_block ^= 1 ;
copy_context_after_encode ( best , s , type );
}
}
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
static int sse ( MpegEncContext * s , uint8_t * src1 , uint8_t * src2 , int w , int h , int stride ){
2002-12-04 21:13:02 +00:00
uint32_t * sq = squareTbl + 256 ;
int acc = 0 ;
int x , y ;
2005-12-17 18:14:38 +00:00
if ( w == 16 && h == 16 )
2003-12-30 16:07:57 +00:00
return s -> dsp . sse [ 0 ]( NULL , src1 , src2 , stride , 16 );
2002-12-27 23:51:46 +00:00
else if ( w == 8 && h == 8 )
2003-12-30 16:07:57 +00:00
return s -> dsp . sse [ 1 ]( NULL , src1 , src2 , stride , 8 );
2005-12-17 18:14:38 +00:00
2002-12-04 21:13:02 +00:00
for ( y = 0 ; y < h ; y ++ ){
for ( x = 0 ; x < w ; x ++ ){
acc += sq [ src1 [ x + y * stride ] - src2 [ x + y * stride ]];
2005-12-17 18:14:38 +00:00
}
2002-12-04 21:13:02 +00:00
}
2005-12-17 18:14:38 +00:00
2002-12-27 23:51:46 +00:00
assert ( acc >= 0 );
2005-12-17 18:14:38 +00:00
2002-12-04 21:13:02 +00:00
return acc ;
}
2002-04-17 18:19:50 +00:00
2003-07-29 02:09:12 +00:00
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 )
2004-06-07 03:23:31 +00:00
if ( s -> avctx -> mb_cmp == FF_CMP_NSSE ){
2004-06-07 17:30:02 +00:00
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 );
2004-06-07 03:23:31 +00:00
} else {
2003-12-30 16:07:57 +00:00
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 );
2004-06-07 03:23:31 +00:00
}
2003-07-29 02:09:12 +00:00
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 );
}
2004-02-13 17:54:10 +00:00
static int pre_estimate_motion_thread ( AVCodecContext * c , void * arg ){
MpegEncContext * s = arg ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
s -> me . pre_pass = 0 ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
return 0 ;
}
static int estimate_motion_thread ( AVCodecContext * c , void * arg ){
MpegEncContext * s = arg ;
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 ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
/* compute motion vector & mb_type and store in context */
if ( s -> pict_type == B_TYPE )
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 ;
}
2004-02-14 03:21:03 +00:00
static int mb_var_thread ( AVCodecContext * c , void * arg ){
MpegEncContext * s = arg ;
int mb_x , mb_y ;
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 );
2005-12-17 18:14:38 +00:00
2004-02-14 03:21:03 +00:00
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 ;
2004-05-11 01:38:46 +00:00
s -> me . mb_var_sum_temp += varc ;
2004-02-14 03:21:03 +00:00
}
}
2004-02-14 03:49:43 +00:00
return 0 ;
2004-02-14 03:21:03 +00:00
}
2004-02-13 17:54:10 +00:00
static void write_slice_end ( MpegEncContext * s ){
if ( s -> codec_id == CODEC_ID_MPEG4 ){
if ( s -> partitioned_frame ){
ff_mpeg4_merge_partitions ( s );
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
ff_mpeg4_stuffing ( & s -> pb );
} else if ( s -> out_format == FMT_MJPEG ){
ff_mjpeg_stuffing ( & s -> pb );
}
align_put_bits ( & s -> pb );
flush_put_bits ( & s -> pb );
2005-12-17 18:14:38 +00:00
2005-01-14 23:48:12 +00:00
if (( s -> flags & CODEC_FLAG_PASS1 ) && ! s -> partitioned_frame )
s -> misc_bits += get_bits_diff ( s );
2004-02-13 17:54:10 +00:00
}
static int encode_thread ( AVCodecContext * c , void * arg ){
MpegEncContext * s = arg ;
2002-10-25 00:08:32 +00:00
int mb_x , mb_y , pdif = 0 ;
2003-12-30 16:07:57 +00:00
int i , j ;
2002-04-17 18:19:50 +00:00
MpegEncContext best_s , backup_s ;
2005-01-12 00:16:25 +00:00
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 ];
2002-06-02 12:20:39 +00:00
PutBitContext pb [ 2 ], pb2 [ 2 ], tex_pb [ 2 ];
2004-02-13 17:54:10 +00:00
//printf("%d->%d\n", s->resync_mb_y, s->end_mb_y);
2002-06-02 12:20:39 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
2005-01-12 00:16:25 +00:00
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 );
2002-06-02 12:20:39 +00:00
}
2001-07-22 14:18:56 +00:00
2004-02-06 15:27:31 +00:00
s -> last_bits = put_bits_count ( & s -> pb );
2002-03-23 17:43:30 +00:00
s -> mv_bits = 0 ;
s -> misc_bits = 0 ;
s -> i_tex_bits = 0 ;
s -> p_tex_bits = 0 ;
s -> i_count = 0 ;
2002-09-12 12:26:09 +00:00
s -> f_count = 0 ;
s -> b_count = 0 ;
2002-03-23 17:43:30 +00:00
s -> skip_count = 0 ;
2002-12-04 21:13:02 +00:00
for ( i = 0 ; i < 3 ; i ++ ){
/* init last dc values */
/* note: quant matrix value (8) is implied here */
2004-04-30 13:44:29 +00:00
s -> last_dc [ i ] = 128 << s -> intra_dc_precision ;
2005-12-17 18:14:38 +00:00
2005-12-07 18:21:16 +00:00
s -> current_picture . error [ i ] = 0 ;
2002-12-04 21:13:02 +00:00
}
2003-03-30 19:26:01 +00:00
s -> mb_skip_run = 0 ;
2003-12-30 16:07:57 +00:00
memset ( s -> last_mv , 0 , sizeof ( s -> last_mv ));
2005-12-17 18:14:38 +00:00
2003-02-08 12:00:57 +00:00
s -> last_mv_dir = 0 ;
2001-07-22 14:18:56 +00:00
2003-07-09 23:10:59 +00:00
switch ( s -> codec_id ){
case CODEC_ID_H263 :
case CODEC_ID_H263P :
case CODEC_ID_FLV1 :
2002-10-13 13:16:04 +00:00
s -> gob_index = ff_h263_get_gob_height ( s );
2003-07-09 23:10:59 +00:00
break ;
case CODEC_ID_MPEG4 :
if ( s -> partitioned_frame )
ff_mpeg4_init_partitions ( s );
break ;
}
2002-06-02 12:20:39 +00:00
s -> resync_mb_x = 0 ;
2005-12-17 18:14:38 +00:00
s -> resync_mb_y = 0 ;
2002-10-13 13:16:04 +00:00
s -> first_slice_line = 1 ;
2002-10-25 00:08:32 +00:00
s -> ptr_lastgob = s -> pb . buf ;
2004-02-13 17:54:10 +00:00
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);
2003-07-29 02:09:12 +00:00
s -> mb_x = 0 ;
s -> mb_y = mb_y ;
2003-12-03 16:47:17 +00:00
ff_set_qscale ( s , s -> qscale );
2003-07-29 02:09:12 +00:00
ff_init_block_index ( s );
2005-12-17 18:14:38 +00:00
2002-02-10 01:56:50 +00:00
for ( mb_x = 0 ; mb_x < s -> mb_width ; mb_x ++ ) {
2004-10-28 10:12:57 +00:00
int xy = mb_y * s -> mb_stride + mb_x ; // removed const, H261 needs to adjust this
2003-04-10 13:18:38 +00:00
int mb_type = s -> mb_type [ xy ];
2002-06-02 12:20:39 +00:00
// int d;
2003-07-29 02:09:12 +00:00
int dmin = INT_MAX ;
2003-12-30 16:07:57 +00:00
int dir ;
2001-07-22 14:18:56 +00:00
2005-01-12 00:16:25 +00:00
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 ;
}
}
2002-02-10 01:56:50 +00:00
s -> mb_x = mb_x ;
2004-10-28 10:12:57 +00:00
s -> mb_y = mb_y ; // moved into loop, can get changed by H.261
2003-07-29 02:09:12 +00:00
ff_update_block_index ( s );
2002-06-02 12:20:39 +00:00
2005-05-02 22:14:42 +00:00
#ifdef CONFIG_H261_ENCODER
2004-10-28 10:12:57 +00:00
if ( s -> codec_id == CODEC_ID_H261 ){
ff_h261_reorder_mb_index ( s );
xy = s -> mb_y * s -> mb_stride + s -> mb_x ;
2004-11-12 01:21:34 +00:00
mb_type = s -> mb_type [ xy ];
2004-10-28 10:12:57 +00:00
}
2005-05-02 22:14:42 +00:00
#endif
2004-10-28 10:12:57 +00:00
2002-10-25 00:08:32 +00:00
/* write gob / video packet header */
2003-12-07 01:33:45 +00:00
if ( s -> rtp_mode ){
2002-10-25 00:08:32 +00:00
int current_packet_size , is_gob_start ;
2005-12-17 18:14:38 +00:00
2004-02-13 20:59:48 +00:00
current_packet_size = (( put_bits_count ( & s -> pb ) + 7 ) >> 3 ) - ( s -> ptr_lastgob - s -> pb . buf );
2005-12-17 18:14:38 +00:00
is_gob_start = s -> avctx -> rtp_payload_size && current_packet_size >= s -> avctx -> rtp_payload_size && mb_y + mb_x > 0 ;
2004-02-13 17:54:10 +00:00
if ( s -> start_mb_y == mb_y && mb_y > 0 && mb_x == 0 ) is_gob_start = 1 ;
2005-12-17 18:14:38 +00:00
2003-12-07 01:33:45 +00:00
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 ;
2002-10-25 00:08:32 +00:00
}
2004-02-13 17:54:10 +00:00
2002-10-25 00:08:32 +00:00
if ( is_gob_start ){
2004-02-13 17:54:10 +00:00
if ( s -> start_mb_y != mb_y || mb_x != 0 ){
write_slice_end ( s );
if ( s -> codec_id == CODEC_ID_MPEG4 && s -> partitioned_frame ){
ff_mpeg4_init_partitions ( s );
}
2003-12-07 01:33:45 +00:00
}
2005-12-17 18:14:38 +00:00
2004-02-06 15:27:31 +00:00
assert (( put_bits_count ( & s -> pb ) & 7 ) == 0 );
2003-12-07 01:33:45 +00:00
current_packet_size = pbBufPtr ( & s -> pb ) - s -> ptr_lastgob ;
2005-12-17 18:14:38 +00:00
2003-12-14 01:42:00 +00:00
if ( s -> avctx -> error_rate && s -> resync_mb_x + s -> resync_mb_y > 0 ){
2004-11-28 14:58:50 +00:00
int r = put_bits_count ( & s -> pb ) / 8 + s -> picture_number + 16 + s -> mb_x + s -> mb_y ;
2003-12-14 01:42:00 +00:00
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 );
}
}
2005-02-02 18:14:59 +00:00
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 );
}
2005-12-17 18:14:38 +00:00
2003-12-07 01:33:45 +00:00
switch ( s -> codec_id ){
case CODEC_ID_MPEG4 :
ff_mpeg4_encode_video_packet_header ( s );
ff_mpeg4_clean_buffers ( s );
break ;
case CODEC_ID_MPEG1VIDEO :
case CODEC_ID_MPEG2VIDEO :
ff_mpeg1_encode_slice_header ( s );
ff_mpeg1_clean_buffers ( s );
break ;
case CODEC_ID_H263 :
case CODEC_ID_H263P :
2005-12-17 18:14:38 +00:00
h263_encode_gob_header ( s , mb_y );
2003-12-07 01:33:45 +00:00
break ;
}
if ( s -> flags & CODEC_FLAG_PASS1 ){
2004-02-06 15:27:31 +00:00
int bits = put_bits_count ( & s -> pb );
2003-12-07 01:33:45 +00:00
s -> misc_bits += bits - s -> last_bits ;
s -> last_bits = bits ;
}
2005-12-17 18:14:38 +00:00
2003-12-07 02:10:30 +00:00
s -> ptr_lastgob += current_packet_size ;
2002-06-02 12:20:39 +00:00
s -> first_slice_line = 1 ;
s -> resync_mb_x = mb_x ;
s -> resync_mb_y = mb_y ;
}
2002-10-13 13:16:04 +00:00
}
2002-06-02 12:20:39 +00:00
2002-10-13 13:16:04 +00:00
if ( ( s -> resync_mb_x == s -> mb_x )
&& s -> resync_mb_y + 1 == s -> mb_y ){
2005-12-17 18:14:38 +00:00
s -> first_slice_line = 0 ;
2002-06-02 12:20:39 +00:00
}
2005-04-24 17:21:11 +00:00
s -> mb_skipped = 0 ;
2003-11-12 12:25:44 +00:00
s -> dquant = 0 ; //only for QP_RD
2003-07-29 02:09:12 +00:00
2004-09-14 18:35:03 +00:00
if ( mb_type & ( mb_type - 1 ) || ( s -> flags & CODEC_FLAG_QP_RD )){ // more than 1 MB type possible or CODEC_FLAG_QP_RD
2002-04-19 03:25:20 +00:00
int next_block = 0 ;
2002-06-02 12:20:39 +00:00
int pb_bits_count , pb2_bits_count , tex_pb_bits_count ;
2002-04-17 18:19:50 +00:00
copy_context_before_encode ( & backup_s , s , - 1 );
2002-06-02 12:20:39 +00:00
backup_s . pb = s -> pb ;
best_s . data_partitioning = s -> data_partitioning ;
2002-10-13 13:16:04 +00:00
best_s . partitioned_frame = s -> partitioned_frame ;
2002-06-02 12:20:39 +00:00
if ( s -> data_partitioning ){
backup_s . pb2 = s -> pb2 ;
backup_s . tex_pb = s -> tex_pb ;
}
2002-04-17 18:19:50 +00:00
2003-12-30 16:07:57 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_INTER ){
2002-04-19 03:25:20 +00:00
s -> mv_dir = MV_DIR_FORWARD ;
2002-03-28 04:25:35 +00:00
s -> mv_type = MV_TYPE_16X16 ;
2002-03-27 21:25:22 +00:00
s -> mb_intra = 0 ;
2002-04-17 04:32:12 +00:00
s -> mv [ 0 ][ 0 ][ 0 ] = s -> p_mv_table [ xy ][ 0 ];
s -> mv [ 0 ][ 0 ][ 1 ] = s -> p_mv_table [ xy ][ 1 ];
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , s -> mv [ 0 ][ 0 ][ 0 ], s -> mv [ 0 ][ 0 ][ 1 ]);
2003-10-02 00:24:34 +00:00
}
2005-12-17 18:14:38 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_INTER_I ){
2003-12-30 16:07:57 +00:00
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 ];
}
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER_I , pb , pb2 , tex_pb ,
2003-12-30 16:07:57 +00:00
& dmin , & next_block , 0 , 0 );
}
2005-04-24 17:21:11 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_SKIPPED ){
2003-10-02 00:24:34 +00:00
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 ;
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_SKIPPED , pb , pb2 , tex_pb ,
2003-10-02 00:24:34 +00:00
& dmin , & next_block , s -> mv [ 0 ][ 0 ][ 0 ], s -> mv [ 0 ][ 0 ][ 1 ]);
2001-07-22 14:18:56 +00:00
}
2005-12-17 18:14:38 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_INTER4V ){
2002-04-19 03:25:20 +00:00
s -> mv_dir = MV_DIR_FORWARD ;
2002-03-28 04:25:35 +00:00
s -> mv_type = MV_TYPE_8X8 ;
s -> mb_intra = 0 ;
for ( i = 0 ; i < 4 ; i ++ ){
2003-12-09 01:49:56 +00:00
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 ];
2002-03-28 04:25:35 +00:00
}
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER4V , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , 0 , 0 );
2002-04-19 03:25:20 +00:00
}
2003-12-30 16:07:57 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_FORWARD ){
2002-04-19 03:25:20 +00:00
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 ];
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_FORWARD , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , s -> mv [ 0 ][ 0 ][ 0 ], s -> mv [ 0 ][ 0 ][ 1 ]);
2002-04-19 03:25:20 +00:00
}
2003-12-30 16:07:57 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_BACKWARD ){
2002-04-19 03:25:20 +00:00
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 ];
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BACKWARD , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , s -> mv [ 1 ][ 0 ][ 0 ], s -> mv [ 1 ][ 0 ][ 1 ]);
2002-04-19 03:25:20 +00:00
}
2003-12-30 16:07:57 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_BIDIR ){
2002-04-19 03:25:20 +00:00
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 ];
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BIDIR , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , 0 , 0 );
2002-04-19 03:25:20 +00:00
}
2003-12-30 16:07:57 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_DIRECT ){
2002-12-27 23:51:46 +00:00
int mx = s -> b_direct_mv_table [ xy ][ 0 ];
int my = s -> b_direct_mv_table [ xy ][ 1 ];
2005-12-17 18:14:38 +00:00
2002-04-19 03:25:20 +00:00
s -> mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s -> mb_intra = 0 ;
2002-12-27 23:51:46 +00:00
ff_mpeg4_set_direct_mv ( s , mx , my );
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_DIRECT , pb , pb2 , tex_pb ,
2002-12-27 23:51:46 +00:00
& dmin , & next_block , mx , my );
2002-03-28 04:25:35 +00:00
}
2005-12-17 18:14:38 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_FORWARD_I ){
2003-12-30 16:07:57 +00:00
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 ];
}
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_FORWARD_I , pb , pb2 , tex_pb ,
2003-12-30 16:07:57 +00:00
& dmin , & next_block , 0 , 0 );
}
2005-12-17 18:14:38 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_BACKWARD_I ){
2003-12-30 16:07:57 +00:00
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 ];
}
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BACKWARD_I , pb , pb2 , tex_pb ,
2003-12-30 16:07:57 +00:00
& dmin , & next_block , 0 , 0 );
}
2005-12-17 18:14:38 +00:00
if ( mb_type & CANDIDATE_MB_TYPE_BIDIR_I ){
2003-12-30 16:07:57 +00:00
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 ];
}
}
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_BIDIR_I , pb , pb2 , tex_pb ,
2003-12-30 16:07:57 +00:00
& dmin , & next_block , 0 , 0 );
}
if ( mb_type & CANDIDATE_MB_TYPE_INTRA ){
2003-02-08 12:00:57 +00:00
s -> mv_dir = 0 ;
2002-03-28 04:25:35 +00:00
s -> mv_type = MV_TYPE_16X16 ;
2002-03-27 21:25:22 +00:00
s -> mb_intra = 1 ;
s -> mv [ 0 ][ 0 ][ 0 ] = 0 ;
s -> mv [ 0 ][ 0 ][ 1 ] = 0 ;
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTRA , pb , pb2 , tex_pb ,
2002-06-02 12:20:39 +00:00
& dmin , & next_block , 0 , 0 );
2003-07-29 02:09:12 +00:00
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?
}
2002-03-27 21:25:22 +00:00
}
2003-11-12 12:25:44 +00:00
if ( s -> flags & CODEC_FLAG_QP_RD ){
if ( best_s . mv_type == MV_TYPE_16X16 && ! ( best_s . mv_dir & MV_DIRECT )){
const int last_qp = backup_s . qscale ;
int dquant , dir , qp , dc [ 6 ];
2003-11-12 13:03:51 +00:00
DCTELEM ac [ 6 ][ 16 ];
2003-11-13 23:45:25 +00:00
const int mvdir = ( best_s . mv_dir & MV_DIR_BACKWARD ) ? 1 : 0 ;
2005-12-17 18:14:38 +00:00
2003-11-12 12:25:44 +00:00
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 ];
2005-12-17 18:14:38 +00:00
2003-11-12 12:25:44 +00:00
dir = s -> pict_type == B_TYPE ? 2 : 1 ;
2003-11-13 23:45:25 +00:00
if ( last_qp + dir > s -> avctx -> qmax ) dir = - dir ;
2003-11-12 12:25:44 +00:00
for ( dquant = dir ; dquant <= 2 && dquant >=- 2 ; dquant += dir ){
qp = last_qp + dquant ;
if ( qp < s -> avctx -> qmin || qp > s -> avctx -> qmax )
break ;
backup_s . dquant = dquant ;
2004-09-14 17:17:12 +00:00
if ( s -> mb_intra && s -> dc_val [ 0 ]){
2003-11-12 13:03:51 +00:00
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 );
}
2003-11-12 12:25:44 +00:00
}
2003-11-12 13:03:51 +00:00
2005-12-17 18:14:38 +00:00
encode_mb_hq ( s , & backup_s , & best_s , CANDIDATE_MB_TYPE_INTER /* wrong but unused */ , pb , pb2 , tex_pb ,
2003-11-13 23:45:25 +00:00
& dmin , & next_block , s -> mv [ mvdir ][ 0 ][ 0 ], s -> mv [ mvdir ][ 0 ][ 1 ]);
2003-11-12 12:25:44 +00:00
if ( best_s . qscale != qp ){
2004-09-14 17:17:12 +00:00
if ( s -> mb_intra && s -> dc_val [ 0 ]){
2003-11-12 13:03:51 +00:00
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 );
}
2003-11-12 12:25:44 +00:00
}
if ( dir > 0 && dquant == dir ){
dquant = 0 ;
dir = - dir ;
} else
break ;
}
}
qp = best_s . qscale ;
s -> current_picture . qscale_table [ xy ] = qp ;
}
}
2002-04-17 18:19:50 +00:00
copy_context_after_encode ( s , & best_s , - 1 );
2005-12-17 18:14:38 +00:00
2004-02-06 15:27:31 +00:00
pb_bits_count = put_bits_count ( & s -> pb );
2002-06-02 12:20:39 +00:00
flush_put_bits ( & s -> pb );
ff_copy_bits ( & backup_s . pb , bit_buf [ next_block ^ 1 ], pb_bits_count );
s -> pb = backup_s . pb ;
2005-12-17 18:14:38 +00:00
2002-06-02 12:20:39 +00:00
if ( s -> data_partitioning ){
2004-02-06 15:27:31 +00:00
pb2_bits_count = put_bits_count ( & s -> pb2 );
2002-06-02 12:20:39 +00:00
flush_put_bits ( & s -> pb2 );
ff_copy_bits ( & backup_s . pb2 , bit_buf2 [ next_block ^ 1 ], pb2_bits_count );
s -> pb2 = backup_s . pb2 ;
2005-12-17 18:14:38 +00:00
2004-02-06 15:27:31 +00:00
tex_pb_bits_count = put_bits_count ( & s -> tex_pb );
2002-06-02 12:20:39 +00:00
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 ;
}
2004-02-06 15:27:31 +00:00
s -> last_bits = put_bits_count ( & s -> pb );
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
if ( s -> out_format == FMT_H263 && s -> pict_type != B_TYPE )
ff_h263_update_motion_val ( s );
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
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 );
2003-07-29 02:09:12 +00:00
}
if ( s -> avctx -> mb_decision == FF_MB_DECISION_BITS )
MPV_decode_mb ( s , s -> block );
2001-07-22 14:18:56 +00:00
} else {
2002-04-17 04:32:12 +00:00
int motion_x , motion_y ;
s -> mv_type = MV_TYPE_16X16 ;
2002-03-27 21:25:22 +00:00
// only one MB-Type possible
2005-12-17 18:14:38 +00:00
2002-04-19 03:25:20 +00:00
switch ( mb_type ){
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_INTRA :
2003-02-08 12:00:57 +00:00
s -> mv_dir = 0 ;
2002-03-27 21:25:22 +00:00
s -> mb_intra = 1 ;
2002-04-17 04:32:12 +00:00
motion_x = s -> mv [ 0 ][ 0 ][ 0 ] = 0 ;
motion_y = s -> mv [ 0 ][ 0 ][ 1 ] = 0 ;
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_INTER :
2002-04-17 04:32:12 +00:00
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 ];
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
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 ];
}
motion_x = motion_y = 0 ;
break ;
case CANDIDATE_MB_TYPE_INTER4V :
2002-06-02 12:20:39 +00:00
s -> mv_dir = MV_DIR_FORWARD ;
s -> mv_type = MV_TYPE_8X8 ;
s -> mb_intra = 0 ;
for ( i = 0 ; i < 4 ; i ++ ){
2003-12-09 01:49:56 +00:00
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 ];
2002-06-02 12:20:39 +00:00
}
motion_x = motion_y = 0 ;
break ;
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_DIRECT :
2002-04-17 04:32:12 +00:00
s -> mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT ;
s -> mb_intra = 0 ;
2002-04-19 03:25:20 +00:00
motion_x = s -> b_direct_mv_table [ xy ][ 0 ];
motion_y = s -> b_direct_mv_table [ xy ][ 1 ];
2002-12-27 23:51:46 +00:00
ff_mpeg4_set_direct_mv ( s , motion_x , motion_y );
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_BIDIR :
2002-04-17 04:32:12 +00:00
s -> mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD ;
2002-03-27 21:25:22 +00:00
s -> mb_intra = 0 ;
2002-04-17 04:32:12 +00:00
motion_x = 0 ;
motion_y = 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 ];
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_BACKWARD :
2002-04-17 04:32:12 +00:00
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 ];
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
case CANDIDATE_MB_TYPE_FORWARD :
2002-04-17 04:32:12 +00:00
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);
2002-04-19 03:25:20 +00:00
break ;
2003-12-30 16:07:57 +00:00
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 ];
}
motion_x = motion_y = 0 ;
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 ];
}
motion_x = motion_y = 0 ;
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 ];
}
}
motion_x = motion_y = 0 ;
break ;
2002-04-19 03:25:20 +00:00
default :
2002-04-17 04:32:12 +00:00
motion_x = motion_y = 0 ; //gcc warning fix
2003-11-03 13:26:22 +00:00
av_log ( s -> avctx , AV_LOG_ERROR , "illegal MB type \n " );
2002-03-27 21:25:22 +00:00
}
2003-02-08 12:00:57 +00:00
2002-04-17 04:32:12 +00:00
encode_mb ( s , motion_x , motion_y );
2003-02-08 12:00:57 +00:00
2005-04-24 11:13:49 +00:00
// RAL: Update last macroblock type
2003-02-08 12:00:57 +00:00
s -> last_mv_dir = s -> mv_dir ;
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
if ( s -> out_format == FMT_H263 && s -> pict_type != B_TYPE )
ff_h263_update_motion_val ( s );
2005-12-17 18:14:38 +00:00
2003-07-29 02:09:12 +00:00
MPV_decode_mb ( s , s -> block );
2001-07-22 14:18:56 +00:00
}
2003-02-08 12:00:57 +00:00
2002-04-19 03:25:20 +00:00
/* 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 ;
}
2005-12-17 18:14:38 +00:00
2002-12-04 21:13:02 +00:00
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 ;
2002-12-27 23:51:46 +00:00
2005-12-07 18:21:16 +00:00
s -> current_picture . error [ 0 ] += sse (
2003-07-29 02:09:12 +00:00
s , s -> new_picture . data [ 0 ] + s -> mb_x * 16 + s -> mb_y * s -> linesize * 16 ,
s -> dest [ 0 ], w , h , s -> linesize );
2005-12-07 18:21:16 +00:00
s -> current_picture . error [ 1 ] += sse (
2003-07-29 02:09:12 +00:00
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 );
2005-12-07 18:21:16 +00:00
s -> current_picture . error [ 2 ] += sse (
2003-07-29 02:09:12 +00:00
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 );
2002-12-04 21:13:02 +00:00
}
2004-11-12 01:21:34 +00:00
if ( s -> loop_filter ){
if ( s -> out_format == FMT_H263 )
ff_h263_loop_filter ( s );
}
2004-02-06 15:27:31 +00:00
//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_stride, put_bits_count(&s->pb));
2001-07-22 14:18:56 +00:00
}
}
2002-03-23 17:43:30 +00:00
2005-04-24 11:13:49 +00:00
//not beautiful here but we must write it before flushing so it has to be here
2002-06-02 12:20:39 +00:00
if ( s -> msmpeg4_version && s -> msmpeg4_version < 4 && s -> pict_type == I_TYPE )
2002-01-15 22:22:41 +00:00
msmpeg4_encode_ext_header ( s );
2002-06-02 12:20:39 +00:00
2004-02-13 17:54:10 +00:00
write_slice_end ( s );
2005-12-17 18:14:38 +00:00
/* Send the last GOB if RTP */
2003-12-07 01:33:45 +00:00
if ( s -> avctx -> rtp_callback ) {
2005-02-02 18:14:59 +00:00
int number_mb = ( mb_y - s -> resync_mb_y ) * s -> mb_width - s -> resync_mb_x ;
2002-02-12 15:43:16 +00:00
pdif = pbBufPtr ( & s -> pb ) - s -> ptr_lastgob ;
2002-02-09 16:59:56 +00:00
/* Call the RTP callback to send the last GOB */
2004-02-13 17:54:10 +00:00
emms_c ();
2005-02-02 18:14:59 +00:00
s -> avctx -> rtp_callback ( s -> avctx , s -> ptr_lastgob , pdif , number_mb );
2002-02-09 16:59:56 +00:00
}
2004-02-13 17:54:10 +00:00
return 0 ;
}
#define MERGE(field) dst->field += src->field; src->field=0
static void merge_context_after_me ( MpegEncContext * dst , MpegEncContext * src ){
2004-05-11 01:38:46 +00:00
MERGE ( me . scene_change_score );
MERGE ( me . mc_mb_var_sum_temp );
MERGE ( me . mb_var_sum_temp );
2004-02-13 17:54:10 +00:00
}
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 );
2005-12-07 18:21:16 +00:00
MERGE ( current_picture . error [ 0 ]);
MERGE ( current_picture . error [ 1 ]);
MERGE ( current_picture . error [ 2 ]);
2004-02-13 17:54:10 +00:00
if ( dst -> avctx -> noise_reduction ){
for ( i = 0 ; i < 64 ; i ++ ){
MERGE ( dct_error_sum [ 0 ][ i ]);
MERGE ( dct_error_sum [ 1 ][ i ]);
}
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
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 );
}
2006-09-26 14:04:36 +00:00
static int estimate_qp ( MpegEncContext * s , int dry_run ){
if ( ! s -> fixed_qscale ) {
2005-12-19 13:41:27 +00:00
s -> current_picture_ptr -> quality =
s -> current_picture . quality = ff_rate_estimate_qscale ( s , dry_run );
2006-09-26 14:04:36 +00:00
if ( s -> current_picture . quality < 0 )
return - 1 ;
}
2005-12-19 13:41:27 +00:00
if ( s -> adaptive_quant ){
switch ( s -> codec_id ){
case CODEC_ID_MPEG4 :
ff_clean_mpeg4_qscales ( s );
break ;
case CODEC_ID_H263 :
case CODEC_ID_H263P :
case CODEC_ID_FLV1 :
ff_clean_h263_qscales ( s );
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 );
2006-09-27 22:12:08 +00:00
return 0 ;
2005-12-19 13:41:27 +00:00
}
2006-09-26 14:04:36 +00:00
static int encode_picture ( MpegEncContext * s , int picture_number )
2004-02-13 17:54:10 +00:00
{
2004-05-18 17:09:46 +00:00
int i ;
2004-02-13 17:54:10 +00:00
int bits ;
s -> picture_number = picture_number ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
/* Reset the average MB variance */
2004-05-11 01:38:46 +00:00
s -> me . mb_var_sum_temp =
s -> me . mc_mb_var_sum_temp = 0 ;
2004-02-13 17:54:10 +00:00
/* 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 ))
2004-02-26 02:48:07 +00:00
ff_set_mpeg4_time ( s , s -> picture_number ); //FIXME rename and use has_b_frames or similar
2005-12-17 18:14:38 +00:00
2004-05-11 01:38:46 +00:00
s -> me . scene_change_score = 0 ;
2005-12-17 18:14:38 +00:00
2004-06-03 19:29:47 +00:00
// s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME ratedistoration
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
if ( s -> pict_type == I_TYPE ){
if ( s -> msmpeg4_version >= 3 ) s -> no_rounding = 1 ;
else s -> no_rounding = 0 ;
} else if ( s -> pict_type != B_TYPE ){
if ( s -> flipflop_rounding || s -> codec_id == CODEC_ID_H263P || s -> codec_id == CODEC_ID_MPEG4 )
2005-12-17 18:14:38 +00:00
s -> no_rounding ^= 1 ;
2004-02-13 17:54:10 +00:00
}
2005-12-17 18:14:38 +00:00
2005-12-22 22:48:09 +00:00
if ( s -> flags & CODEC_FLAG_PASS2 ){
2006-09-26 14:04:36 +00:00
if ( estimate_qp ( s , 1 ) < 0 )
return - 1 ;
2005-12-22 22:48:09 +00:00
ff_get_2pass_fcode ( s );
} else if ( ! ( s -> flags & CODEC_FLAG_QSCALE )){
2005-12-22 14:17:54 +00:00
if ( s -> pict_type == B_TYPE )
2005-12-29 15:46:23 +00:00
s -> lambda = s -> last_lambda_for [ s -> pict_type ];
2005-12-22 14:17:54 +00:00
else
2005-12-29 15:46:23 +00:00
s -> lambda = s -> last_lambda_for [ s -> last_non_b_pict_type ];
2005-12-22 14:17:54 +00:00
update_qscale ( s );
}
2005-12-19 13:41:27 +00:00
2005-04-24 11:13:49 +00:00
s -> mb_intra = 0 ; //for the rate distortion & bit compare functions
2004-02-13 17:54:10 +00:00
for ( i = 1 ; i < s -> avctx -> thread_count ; i ++ ){
2004-02-23 20:56:56 +00:00
ff_update_duplicate_context ( s -> thread_context [ i ], s );
2004-02-13 17:54:10 +00:00
}
2004-04-24 03:36:37 +00:00
ff_init_me ( s );
2004-02-13 17:54:10 +00:00
/* Estimate motion for every MB */
if ( s -> pict_type != I_TYPE ){
2005-03-27 12:19:59 +00:00
s -> lambda = ( s -> lambda * s -> avctx -> me_penalty_compensation + 128 ) >> 8 ;
s -> lambda2 = ( s -> lambda2 * s -> avctx -> me_penalty_compensation + 128 ) >> 8 ;
2004-04-23 19:06:30 +00:00
if ( s -> pict_type != B_TYPE && s -> avctx -> me_threshold == 0 ){
2004-02-13 17:54:10 +00:00
if (( s -> avctx -> pre_me && s -> last_non_b_pict_type == I_TYPE ) || s -> avctx -> pre_me == 2 ){
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 );
} else /* if(s->pict_type == I_TYPE) */ {
/* I-Frame */
for ( i = 0 ; i < s -> mb_stride * s -> mb_height ; i ++ )
s -> mb_type [ i ] = CANDIDATE_MB_TYPE_INTRA ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
if ( ! s -> fixed_qscale ){
/* finding spatial complexity for I-frame rate control */
2004-02-14 03:21:03 +00:00
s -> avctx -> execute ( s -> avctx , mb_var_thread , ( void ** ) & ( s -> thread_context [ 0 ]), NULL , s -> avctx -> thread_count );
2004-02-13 17:54:10 +00:00
}
}
2004-02-14 03:21:03 +00:00
for ( i = 1 ; i < s -> avctx -> thread_count ; i ++ ){
merge_context_after_me ( s , s -> thread_context [ i ]);
}
2004-05-11 01:38:46 +00:00
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 ;
2004-02-13 17:54:10 +00:00
emms_c ();
2004-05-11 01:38:46 +00:00
if ( s -> me . scene_change_score > s -> avctx -> scenechange_threshold && s -> pict_type == P_TYPE ){
2004-02-13 17:54:10 +00:00
s -> pict_type = I_TYPE ;
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 ){
if ( s -> pict_type == P_TYPE || s -> pict_type == S_TYPE ) {
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 );
s -> f_code = FFMAX ( s -> f_code , FFMAX ( a , b ));
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00: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 ){
2004-05-18 17:09:46 +00:00
int j ;
2004-02-13 17:54:10 +00:00
for ( i = 0 ; i < 2 ; i ++ ){
for ( j = 0 ; j < 2 ; j ++ )
2005-12-17 18:14:38 +00:00
ff_fix_long_mvs ( s , s -> p_field_select_table [ i ], j ,
2004-02-13 17:54:10 +00:00
s -> p_field_mv_table [ i ][ j ], s -> f_code , CANDIDATE_MB_TYPE_INTER_I , 0 );
}
}
}
if ( s -> pict_type == B_TYPE ){
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 ){
2004-05-18 17:09:46 +00:00
int dir , j ;
2004-02-13 17:54:10 +00:00
for ( dir = 0 ; dir < 2 ; dir ++ ){
for ( i = 0 ; i < 2 ; i ++ ){
for ( j = 0 ; j < 2 ; j ++ ){
2005-12-17 18:14:38 +00:00
int type = dir ? ( CANDIDATE_MB_TYPE_BACKWARD_I | CANDIDATE_MB_TYPE_BIDIR_I )
2004-02-13 17:54:10 +00:00
: ( CANDIDATE_MB_TYPE_FORWARD_I | CANDIDATE_MB_TYPE_BIDIR_I );
2005-12-17 18:14:38 +00:00
ff_fix_long_mvs ( s , s -> b_field_select_table [ dir ][ i ], j ,
2004-02-13 17:54:10 +00:00
s -> b_field_mv_table [ dir ][ i ][ j ], dir ? s -> b_code : s -> f_code , type , 1 );
}
}
}
}
}
}
2006-09-26 14:04:36 +00:00
if ( estimate_qp ( s , 0 ) < 0 )
return - 1 ;
2005-12-17 18:14:38 +00:00
if ( s -> qscale < 3 && s -> max_qcoeff <= 128 && s -> pict_type == I_TYPE && ! ( s -> flags & CODEC_FLAG_QSCALE ))
2005-04-24 11:13:49 +00:00
s -> qscale = 3 ; //reduce clipping problems
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
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 ];
2006-05-01 00:28:36 +00:00
s -> intra_matrix [ j ] = clip_uint8 (( ff_mpeg1_default_intra_matrix [ i ] * s -> qscale ) >> 3 );
2004-02-13 17:54:10 +00:00
}
2005-12-17 18:14:38 +00:00
convert_matrix ( & s -> dsp , s -> q_intra_matrix , s -> q_intra_matrix16 ,
2004-12-11 18:33:18 +00:00
s -> intra_matrix , s -> intra_quant_bias , 8 , 8 , 1 );
2004-02-13 17:54:10 +00:00
s -> qscale = 8 ;
}
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
//FIXME var duplication
2004-09-16 17:36:39 +00:00
s -> current_picture_ptr -> key_frame =
2004-02-13 17:54:10 +00:00
s -> current_picture . key_frame = s -> pict_type == I_TYPE ; //FIXME pic_ptr
2004-09-16 17:36:39 +00:00
s -> current_picture_ptr -> pict_type =
2004-02-13 17:54:10 +00:00
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 :
mjpeg_picture_header ( s );
break ;
2005-05-02 22:14:42 +00:00
#ifdef CONFIG_H261_ENCODER
2004-10-28 10:12:57 +00:00
case FMT_H261 :
ff_h261_encode_picture_header ( s , picture_number );
break ;
2005-05-02 22:14:42 +00:00
#endif
2004-02-13 17:54:10 +00:00
case FMT_H263 :
2005-12-17 18:14:38 +00:00
if ( s -> codec_id == CODEC_ID_WMV2 )
2004-02-13 17:54:10 +00:00
ff_wmv2_encode_picture_header ( s , picture_number );
2005-12-17 18:14:38 +00:00
else if ( s -> h263_msmpeg4 )
2004-02-13 17:54:10 +00:00
msmpeg4_encode_picture_header ( s , picture_number );
else if ( s -> h263_pred )
mpeg4_encode_picture_header ( s , picture_number );
2005-05-02 22:14:42 +00:00
#ifdef CONFIG_RV10_ENCODER
2005-12-17 18:14:38 +00:00
else if ( s -> codec_id == CODEC_ID_RV10 )
2004-02-13 17:54:10 +00:00
rv10_encode_picture_header ( s , picture_number );
2005-05-02 22:14:42 +00:00
#endif
#ifdef CONFIG_RV20_ENCODER
2005-12-17 18:14:38 +00:00
else if ( s -> codec_id == CODEC_ID_RV20 )
2004-12-07 13:14:37 +00:00
rv20_encode_picture_header ( s , picture_number );
2005-05-02 22:14:42 +00:00
#endif
2004-02-13 17:54:10 +00:00
else if ( s -> codec_id == CODEC_ID_FLV1 )
ff_flv_encode_picture_header ( s , picture_number );
else
h263_encode_picture_header ( s , picture_number );
break ;
case FMT_MPEG1 :
mpeg1_encode_picture_header ( s , picture_number );
break ;
case FMT_H264 :
break ;
default :
assert ( 0 );
}
bits = put_bits_count ( & s -> pb );
s -> header_bits = bits - s -> last_bits ;
2005-12-17 18:14:38 +00:00
2004-02-13 17:54:10 +00:00
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 ();
2006-09-27 22:12:08 +00:00
return 0 ;
2001-07-22 14:18:56 +00:00
}
2004-01-02 22:29:08 +00:00
static void denoise_dct_c ( MpegEncContext * s , DCTELEM * block ){
2003-11-02 23:19:47 +00:00
const int intra = s -> mb_intra ;
int i ;
2003-11-03 13:31:02 +00:00
s -> dct_count [ intra ] ++ ;
2003-11-02 23:19:47 +00:00
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 ;
}
}
}
2005-12-17 18:14:38 +00:00
static int dct_quantize_trellis_c ( MpegEncContext * s ,
2002-12-31 17:23:56 +00:00
DCTELEM * block , int n ,
int qscale , int * overflow ){
const int * qmat ;
2003-02-11 16:35:48 +00:00
const uint8_t * scantable = s -> intra_scantable . scantable ;
2004-01-02 19:22:00 +00:00
const uint8_t * perm_scantable = s -> intra_scantable . permutated ;
2002-12-31 17:23:56 +00:00
int max = 0 ;
unsigned int threshold1 , threshold2 ;
int bias = 0 ;
int run_tab [ 65 ];
int level_tab [ 65 ];
int score_tab [ 65 ];
2004-01-02 19:22:00 +00:00
int survivor [ 65 ];
int survivor_count ;
2002-12-31 22:58:41 +00:00
int last_run = 0 ;
int last_level = 0 ;
int last_score = 0 ;
2004-01-02 19:22:00 +00:00
int last_i ;
2004-01-02 02:39:05 +00:00
int coeff [ 2 ][ 64 ];
2002-12-31 17:23:56 +00:00
int coeff_count [ 64 ];
2003-10-07 11:32:40 +00:00
int qmul , qadd , start_i , last_non_zero , i , dc ;
2002-12-31 17:23:56 +00:00
const int esc_length = s -> ac_esc_length ;
uint8_t * length ;
uint8_t * last_length ;
2003-10-07 11:32:40 +00:00
const int lambda = s -> lambda2 >> ( FF_LAMBDA_SHIFT - 6 );
2005-12-17 18:14:38 +00:00
2003-03-03 14:54:00 +00:00
s -> dsp . fdct ( block );
2005-12-17 18:14:38 +00:00
2003-11-02 23:19:47 +00:00
if ( s -> dct_error_sum )
2004-01-02 22:29:08 +00:00
s -> denoise_dct ( s , block );
2002-12-31 17:23:56 +00:00
qmul = qscale * 16 ;
qadd = (( qscale - 1 ) | 1 ) * 8 ;
2002-12-31 22:58:41 +00:00
2002-12-31 17:23:56 +00:00
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 ;
}
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
/* 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 ];
2003-08-25 22:54:53 +00:00
if ( s -> mpeg_quant || s -> out_format == FMT_MPEG1 )
2002-12-31 17:23:56 +00:00
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 ;
}
2004-01-02 19:22:00 +00:00
last_i = start_i ;
2002-12-31 17:23:56 +00:00
threshold1 = ( 1 << QMAT_SHIFT ) - bias - 1 ;
threshold2 = ( threshold1 << 1 );
2002-12-31 22:58:41 +00:00
2004-01-02 02:39:05 +00:00
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 ++ ) {
2002-12-31 17:23:56 +00:00
const int j = scantable [ i ];
2004-01-02 02:39:05 +00:00
int level = block [ j ] * qmat [ j ];
2002-12-31 17:23:56 +00:00
// 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 ;
2004-01-02 19:22:00 +00:00
coeff [ 0 ][ i ] = level ;
coeff [ 1 ][ i ] = level - 1 ;
2002-12-31 22:58:41 +00:00
// coeff[2][k]= level-2;
2002-12-31 17:23:56 +00:00
} else {
level = ( bias - level ) >> QMAT_SHIFT ;
2004-01-02 19:22:00 +00:00
coeff [ 0 ][ i ] = - level ;
coeff [ 1 ][ i ] = - level + 1 ;
2002-12-31 22:58:41 +00:00
// coeff[2][k]= -level+2;
2002-12-31 17:23:56 +00:00
}
2004-01-02 19:22:00 +00:00
coeff_count [ i ] = FFMIN ( level , 2 );
assert ( coeff_count [ i ]);
2002-12-31 17:23:56 +00:00
max |= level ;
} else {
2004-01-02 19:22:00 +00:00
coeff [ 0 ][ i ] = ( level >> 31 ) | 1 ;
coeff_count [ i ] = 1 ;
2002-12-31 17:23:56 +00:00
}
}
2005-12-17 18:14:38 +00:00
2005-04-24 11:13:49 +00:00
* overflow = s -> max_qcoeff < max ; //overflow might have happened
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
if ( last_non_zero < start_i ){
memset ( block + start_i , 0 , ( 64 - start_i ) * sizeof ( DCTELEM ));
return last_non_zero ;
}
2004-01-02 19:22:00 +00:00
score_tab [ start_i ] = 0 ;
survivor [ 0 ] = start_i ;
survivor_count = 1 ;
2005-12-17 18:14:38 +00:00
2004-01-02 19:22:00 +00:00
for ( i = start_i ; i <= last_non_zero ; i ++ ){
int level_index , j ;
const int dct_coeff = ABS ( block [ scantable [ i ] ]);
2002-12-31 17:23:56 +00:00
const int zero_distoration = dct_coeff * dct_coeff ;
2002-12-31 22:58:41 +00:00
int best_score = 256 * 256 * 256 * 120 ;
2002-12-31 17:23:56 +00:00
for ( level_index = 0 ; level_index < coeff_count [ i ]; level_index ++ ){
int distoration ;
int level = coeff [ level_index ][ i ];
2004-01-02 03:02:34 +00:00
const int alevel = ABS ( level );
2002-12-31 17:23:56 +00:00
int unquant_coeff ;
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
assert ( level );
if ( s -> out_format == FMT_H263 ){
2004-01-02 03:02:34 +00:00
unquant_coeff = alevel * qmul + qadd ;
2003-01-01 00:42:18 +00:00
} else { //MPEG1
2004-01-02 19:22:00 +00:00
j = s -> dsp . idct_permutation [ scantable [ i ] ]; //FIXME optimize
2003-01-01 00:42:18 +00:00
if ( s -> mb_intra ){
2004-01-02 03:02:34 +00:00
unquant_coeff = ( int )( alevel * qscale * s -> intra_matrix [ j ]) >> 3 ;
2003-01-01 00:42:18 +00:00
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
} else {
2004-01-02 03:02:34 +00:00
unquant_coeff = ((( alevel << 1 ) + 1 ) * qscale * (( int ) s -> inter_matrix [ j ])) >> 4 ;
2003-01-01 00:42:18 +00:00
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
}
unquant_coeff <<= 3 ;
}
2002-12-31 22:58:41 +00:00
2004-01-02 02:39:05 +00:00
distoration = ( unquant_coeff - dct_coeff ) * ( unquant_coeff - dct_coeff ) - zero_distoration ;
2002-12-31 17:23:56 +00:00
level += 64 ;
if (( level & ( ~ 127 )) == 0 ){
2004-01-02 19:22:00 +00:00
for ( j = survivor_count - 1 ; j >= 0 ; j -- ){
int run = i - survivor [ j ];
2003-01-01 00:42:18 +00:00
int score = distoration + length [ UNI_AC_ENC_INDEX ( run , level )] * lambda ;
2002-12-31 17:23:56 +00:00
score += score_tab [ i - run ];
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
if ( score < best_score ){
2004-01-02 19:22:00 +00:00
best_score = score ;
2002-12-31 17:23:56 +00:00
run_tab [ i + 1 ] = run ;
level_tab [ i + 1 ] = level - 64 ;
}
}
if ( s -> out_format == FMT_H263 ){
2004-01-02 19:22:00 +00:00
for ( j = survivor_count - 1 ; j >= 0 ; j -- ){
int run = i - survivor [ j ];
2003-01-01 00:42:18 +00:00
int score = distoration + last_length [ UNI_AC_ENC_INDEX ( run , level )] * lambda ;
2002-12-31 17:23:56 +00:00
score += score_tab [ i - run ];
2002-12-31 22:58:41 +00:00
if ( score < last_score ){
last_score = score ;
last_run = run ;
last_level = level - 64 ;
last_i = i + 1 ;
2002-12-31 17:23:56 +00:00
}
}
}
} else {
distoration += esc_length * lambda ;
2004-01-02 19:22:00 +00:00
for ( j = survivor_count - 1 ; j >= 0 ; j -- ){
int run = i - survivor [ j ];
2002-12-31 17:23:56 +00:00
int score = distoration + score_tab [ i - run ];
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
if ( score < best_score ){
2004-01-02 19:22:00 +00:00
best_score = score ;
2002-12-31 17:23:56 +00:00
run_tab [ i + 1 ] = run ;
level_tab [ i + 1 ] = level - 64 ;
}
}
if ( s -> out_format == FMT_H263 ){
2004-01-02 19:22:00 +00:00
for ( j = survivor_count - 1 ; j >= 0 ; j -- ){
int run = i - survivor [ j ];
2002-12-31 17:23:56 +00:00
int score = distoration + score_tab [ i - run ];
2002-12-31 22:58:41 +00:00
if ( score < last_score ){
last_score = score ;
last_run = run ;
last_level = level - 64 ;
last_i = i + 1 ;
2002-12-31 17:23:56 +00:00
}
}
}
}
}
2005-12-17 18:14:38 +00:00
2004-01-02 19:22:00 +00:00
score_tab [ i + 1 ] = best_score ;
2002-12-31 22:58:41 +00:00
//Note: there is a vlc code in mpeg4 which is 1 bit shorter then another one with a shorter run and the same level
2004-01-02 19:22:00 +00:00
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 ;
}
2003-10-07 11:32:40 +00:00
}
2004-01-02 19:22:00 +00:00
survivor [ survivor_count ++ ] = i + 1 ;
2002-12-31 17:23:56 +00:00
}
2002-12-31 22:58:41 +00:00
2002-12-31 17:23:56 +00:00
if ( s -> out_format != FMT_H263 ){
2002-12-31 22:58:41 +00:00
last_score = 256 * 256 * 256 * 120 ;
2004-01-02 19:22:00 +00:00
for ( i = survivor [ 0 ]; i <= last_non_zero + 1 ; i ++ ){
2002-12-31 22:58:41 +00:00
int score = score_tab [ i ];
2003-01-01 00:42:18 +00:00
if ( i ) score += lambda * 2 ; //FIXME exacter?
2002-12-31 22:58:41 +00:00
if ( score < last_score ){
last_score = score ;
last_i = i ;
last_level = level_tab [ i ];
last_run = run_tab [ i ];
}
2002-12-31 17:23:56 +00:00
}
}
2003-09-30 22:18:43 +00:00
2004-01-02 02:39:05 +00:00
s -> coded_score [ n ] = last_score ;
2005-12-17 18:14:38 +00:00
2004-01-02 03:02:34 +00:00
dc = ABS ( block [ 0 ]);
2004-01-02 19:22:00 +00:00
last_non_zero = last_i - 1 ;
2002-12-31 17:23:56 +00:00
memset ( block + start_i , 0 , ( 64 - start_i ) * sizeof ( DCTELEM ));
2005-12-17 18:14:38 +00:00
2002-12-31 17:23:56 +00:00
if ( last_non_zero < start_i )
return last_non_zero ;
2003-09-30 22:18:43 +00:00
2003-09-24 19:45:57 +00:00
if ( last_non_zero == 0 && start_i == 0 ){
int best_level = 0 ;
int best_score = dc * dc ;
2005-12-17 18:14:38 +00:00
2003-09-24 19:45:57 +00:00
for ( i = 0 ; i < coeff_count [ 0 ]; i ++ ){
2003-09-30 22:18:43 +00:00
int level = coeff [ i ][ 0 ];
2004-01-02 03:02:34 +00:00
int alevel = ABS ( level );
int unquant_coeff , score , distortion ;
2003-09-24 19:45:57 +00:00
if ( s -> out_format == FMT_H263 ){
2004-01-02 03:02:34 +00:00
unquant_coeff = ( alevel * qmul + qadd ) >> 3 ;
2003-09-24 19:45:57 +00:00
} else { //MPEG1
2004-01-02 03:02:34 +00:00
unquant_coeff = ((( alevel << 1 ) + 1 ) * qscale * (( int ) s -> inter_matrix [ 0 ])) >> 4 ;
unquant_coeff = ( unquant_coeff - 1 ) | 1 ;
2003-09-24 19:45:57 +00:00
}
unquant_coeff = ( unquant_coeff + 4 ) >> 3 ;
unquant_coeff <<= 3 + 3 ;
2004-01-02 03:02:34 +00:00
distortion = ( unquant_coeff - dc ) * ( unquant_coeff - dc );
2003-09-30 22:18:43 +00:00
level += 64 ;
2004-01-02 03:02:34 +00:00
if (( level & ( ~ 127 )) == 0 ) score = distortion + last_length [ UNI_AC_ENC_INDEX ( 0 , level )] * lambda ;
else score = distortion + esc_length * lambda ;
2003-09-30 22:18:43 +00:00
2003-09-24 19:45:57 +00:00
if ( score < best_score ){
best_score = score ;
2003-09-30 22:18:43 +00:00
best_level = level - 64 ;
2003-09-24 19:45:57 +00:00
}
}
block [ 0 ] = best_level ;
2003-09-30 22:18:43 +00:00
s -> coded_score [ n ] = best_score - dc * dc ;
if ( best_level == 0 ) return - 1 ;
else return last_non_zero ;
2003-09-24 19:45:57 +00:00
}
2003-09-30 22:18:43 +00:00
2002-12-31 22:58:41 +00:00
i = last_i ;
assert ( last_level );
2004-01-02 19:22:00 +00:00
block [ perm_scantable [ last_non_zero ] ] = last_level ;
2002-12-31 22:58:41 +00:00
i -= last_run + 1 ;
2005-12-17 18:14:38 +00:00
2004-01-02 19:22:00 +00:00
for (; i > start_i ; i -= run_tab [ i ] + 1 ){
block [ perm_scantable [ i - 1 ] ] = level_tab [ i ];
2002-12-31 17:23:56 +00:00
}
return last_non_zero ;
}
2004-02-02 03:52:58 +00:00
//#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 ];
2006-02-05 13:35:17 +00:00
DECLARE_ALIGNED_16 ( DCTELEM , d1 [ 64 ]);
2004-02-02 03:52:58 +00:00
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 , sum ;
#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 );
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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
2004-02-06 02:12:37 +00:00
dc += ( 1 << ( RECON_SHIFT - 1 ));
for ( i = 0 ; i < 64 ; i ++ ){
2005-04-24 11:13:49 +00:00
rem [ i ] = dc - ( orig [ i ] << RECON_SHIFT ); //FIXME use orig dirrectly instead of copying to rem[]
2004-02-02 03:52:58 +00:00
}
#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 = ABS ( 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;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
if ( level ){
if ( level < 0 ) coeff = qmul * level - qadd ;
else coeff = qmul * level + qadd ;
run_tab [ rle_index ++ ] = run ;
run = 0 ;
2004-02-06 02:12:37 +00:00
s -> dsp . add_8x8basis ( rem , basis [ j ], coeff );
2004-02-02 03:52:58 +00:00
} else {
run ++ ;
}
}
#ifdef REFINE_STATS
if ( last_non_zero > 0 ){
STOP_TIMER ( "init rem[]" )
}
}
{ START_TIMER
#endif
for (;;){
2004-02-06 02:12:37 +00:00
int best_score = s -> dsp . try_8x8basis ( rem , weight , basis [ 0 ], 0 );
2004-02-02 03:52:58 +00:00
int best_coeff = 0 ;
int best_change = 0 ;
2004-05-18 17:09:46 +00:00
int run2 , best_unquant_change = 0 , analyze_gradient ;
2004-02-02 03:52:58 +00:00
#ifdef REFINE_STATS
{ START_TIMER
#endif
2004-02-06 03:56:05 +00:00
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 ];
2005-12-17 18:14:38 +00:00
2004-02-06 03:56:05 +00:00
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
}
2004-02-02 03:52:58 +00:00
if ( start_i ){
const int level = block [ 0 ];
int change , old_coeff ;
assert ( s -> mb_intra );
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
old_coeff = q * level ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
for ( change =- 1 ; change <= 1 ; change += 2 ){
int new_level = level + change ;
int score , new_coeff ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
new_coeff = q * new_level ;
if ( new_coeff >= 2048 || new_coeff < 0 )
continue ;
2004-02-06 02:12:37 +00:00
score = s -> dsp . try_8x8basis ( rem , weight , basis [ 0 ], new_coeff - old_coeff );
2004-02-02 03:52:58 +00:00
if ( score < best_score ){
best_score = score ;
best_coeff = 0 ;
best_change = change ;
best_unquant_change = new_coeff - old_coeff ;
}
}
}
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 );
}
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
for ( change =- 1 ; change <= 1 ; change += 2 ){
int new_level = level + change ;
int score , new_coeff , unquant_change ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
score = 0 ;
if ( s -> avctx -> quantizer_noise_shaping < 2 && ABS ( new_level ) > ABS ( 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
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 ( ABS ( new_level ) == 1 );
2005-12-17 18:14:38 +00:00
2004-02-06 03:56:05 +00:00
if ( analyze_gradient ){
int g = d1 [ scantable [ i ] ];
if ( g && ( g ^ new_level ) >= 0 )
continue ;
}
2004-02-02 03:52:58 +00:00
if ( i < last_non_zero ){
int next_i = i + run2 + 1 ;
int next_level = block [ perm_scantable [ next_i ] ] + 64 ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 ( ABS ( level ) == 1 );
if ( i < last_non_zero ){
int next_i = i + run2 + 1 ;
int next_level = block [ perm_scantable [ next_i ] ] + 64 ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 )];
}
}
}
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
score *= lambda ;
unquant_change = new_coeff - old_coeff ;
assert (( score < 100 * lambda && score > - 100 * lambda ) || lambda == 0 );
2005-12-17 18:14:38 +00:00
2004-02-06 02:12:37 +00:00
score += s -> dsp . try_8x8basis ( rem , weight , basis [ j ], unquant_change );
2004-02-02 03:52:58 +00:00
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 ];
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
block [ j ] += best_change ;
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
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 ( ABS ( block [ j ]) > ABS ( 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 ];
2005-12-17 18:14:38 +00:00
2004-02-02 03:52:58 +00:00
if ( level ){
run_tab [ rle_index ++ ] = run ;
run = 0 ;
} else {
run ++ ;
}
}
2005-12-17 18:14:38 +00:00
2004-02-06 02:12:37 +00:00
s -> dsp . add_8x8basis ( rem , basis [ j ], best_unquant_change );
2004-02-02 03:52:58 +00:00
} else {
break ;
}
}
#ifdef REFINE_STATS
if ( last_non_zero > 0 ){
STOP_TIMER ( "iterative search" )
}
}
#endif
return last_non_zero ;
}
2005-12-17 18:14:38 +00:00
static int dct_quantize_c ( MpegEncContext * s ,
2001-07-22 14:18:56 +00:00
DCTELEM * block , int n ,
2002-04-27 12:30:26 +00:00
int qscale , int * overflow )
2001-07-22 14:18:56 +00:00
{
2004-01-02 02:39:05 +00:00
int i , j , level , last_non_zero , q , start_i ;
2001-07-22 14:18:56 +00:00
const int * qmat ;
2003-02-11 16:35:48 +00:00
const uint8_t * scantable = s -> intra_scantable . scantable ;
2002-04-27 12:30:26 +00:00
int bias ;
int max = 0 ;
unsigned int threshold1 , threshold2 ;
2002-11-02 11:28:08 +00:00
2003-03-03 14:54:00 +00:00
s -> dsp . fdct ( block );
2001-07-22 14:18:56 +00:00
2003-11-02 23:19:47 +00:00
if ( s -> dct_error_sum )
2004-01-02 22:29:08 +00:00
s -> denoise_dct ( s , block );
2003-11-02 23:19:47 +00:00
2001-07-22 14:18:56 +00:00
if ( s -> mb_intra ) {
2002-05-02 04:39:45 +00:00
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 ;
2005-12-17 18:14:38 +00:00
2001-07-22 14:18:56 +00:00
/* note: block[0] is assumed to be positive */
block [ 0 ] = ( block [ 0 ] + ( q >> 1 )) / q ;
2004-01-02 02:39:05 +00:00
start_i = 1 ;
2001-07-22 14:18:56 +00:00
last_non_zero = 0 ;
2002-04-27 12:30:26 +00:00
qmat = s -> q_intra_matrix [ qscale ];
2002-09-01 16:52:33 +00:00
bias = s -> intra_quant_bias << ( QMAT_SHIFT - QUANT_BIAS_SHIFT );
2001-07-22 14:18:56 +00:00
} else {
2004-01-02 02:39:05 +00:00
start_i = 0 ;
2001-07-22 14:18:56 +00:00
last_non_zero = - 1 ;
2002-04-27 12:30:26 +00:00
qmat = s -> q_inter_matrix [ qscale ];
2002-09-01 16:52:33 +00:00
bias = s -> inter_quant_bias << ( QMAT_SHIFT - QUANT_BIAS_SHIFT );
2001-07-22 14:18:56 +00:00
}
2002-09-01 16:52:33 +00:00
threshold1 = ( 1 << QMAT_SHIFT ) - bias - 1 ;
threshold2 = ( threshold1 << 1 );
2004-01-02 02:39:05 +00:00
for ( i = 63 ; i >= start_i ; i -- ) {
2002-10-23 15:11:07 +00:00
j = scantable [ i ];
2004-01-02 02:39:05 +00:00
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 ];
2001-07-22 14:18:56 +00:00
2003-04-25 16:18:35 +00:00
// if( bias+level >= (1<<QMAT_SHIFT)
// || bias-level >= (1<<QMAT_SHIFT)){
2002-04-27 12:30:26 +00:00
if ((( unsigned )( level + threshold1 )) > threshold2 ){
if ( level > 0 ){
2002-09-01 16:52:33 +00:00
level = ( bias + level ) >> QMAT_SHIFT ;
2002-04-27 12:30:26 +00:00
block [ j ] = level ;
} else {
2002-09-01 16:52:33 +00:00
level = ( bias - level ) >> QMAT_SHIFT ;
2002-04-27 12:30:26 +00:00
block [ j ] = - level ;
}
max |= level ;
} else {
block [ j ] = 0 ;
2001-07-22 14:18:56 +00:00
}
}
2005-04-24 11:13:49 +00:00
* overflow = s -> max_qcoeff < max ; //overflow might have happened
2005-12-17 18:14:38 +00:00
2002-10-23 15:11:07 +00:00
/* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */
2003-03-03 14:54:00 +00:00
if ( s -> dsp . idct_permutation_type != FF_NO_IDCT_PERM )
2005-12-22 01:10:11 +00:00
ff_block_permute ( block , s -> dsp . idct_permutation , scantable , last_non_zero );
2002-10-23 15:11:07 +00:00
2001-07-22 14:18:56 +00:00
return last_non_zero ;
}
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg1_intra_c ( MpegEncContext * s ,
2001-07-30 23:26:26 +00:00
DCTELEM * block , int n , int qscale )
2001-07-22 14:18:56 +00:00
{
2002-01-13 04:59:37 +00:00
int i , level , nCoeffs ;
2003-02-11 16:35:48 +00:00
const uint16_t * quant_matrix ;
2001-07-22 14:18:56 +00:00
2002-09-29 22:44:22 +00:00
nCoeffs = s -> block_last_index [ n ];
2005-12-17 18:14:38 +00:00
if ( n < 4 )
2003-12-14 02:57:00 +00:00
block [ 0 ] = block [ 0 ] * s -> y_dc_scale ;
else
block [ 0 ] = block [ 0 ] * s -> c_dc_scale ;
/* XXX: only mpeg1 */
quant_matrix = s -> intra_matrix ;
for ( i = 1 ; i <= nCoeffs ; i ++ ) {
int j = s -> intra_scantable . permutated [ i ];
level = block [ j ];
if ( level ) {
if ( level < 0 ) {
level = - level ;
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
level = ( level - 1 ) | 1 ;
level = - level ;
} else {
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
level = ( level - 1 ) | 1 ;
2001-07-22 14:18:56 +00:00
}
2003-12-14 02:57:00 +00:00
block [ j ] = level ;
2001-07-22 14:18:56 +00:00
}
}
}
2001-07-30 23:26:26 +00:00
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg1_inter_c ( MpegEncContext * s ,
2003-12-14 02:57:00 +00:00
DCTELEM * block , int n , int qscale )
{
int i , level , nCoeffs ;
const uint16_t * quant_matrix ;
nCoeffs = s -> block_last_index [ n ];
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
quant_matrix = s -> inter_matrix ;
for ( i = 0 ; i <= nCoeffs ; i ++ ) {
int j = s -> intra_scantable . permutated [ i ];
level = block [ j ];
if ( level ) {
if ( level < 0 ) {
level = - level ;
level = ((( level << 1 ) + 1 ) * qscale *
(( int ) ( quant_matrix [ j ]))) >> 4 ;
level = ( level - 1 ) | 1 ;
level = - level ;
} else {
level = ((( level << 1 ) + 1 ) * qscale *
(( int ) ( quant_matrix [ j ]))) >> 4 ;
level = ( level - 1 ) | 1 ;
}
block [ j ] = level ;
}
}
}
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg2_intra_c ( MpegEncContext * s ,
2002-04-17 16:30:31 +00:00
DCTELEM * block , int n , int qscale )
{
int i , level , nCoeffs ;
2003-02-11 16:35:48 +00:00
const uint16_t * quant_matrix ;
2002-04-17 16:30:31 +00:00
2002-09-29 22:44:22 +00:00
if ( s -> alternate_scan ) nCoeffs = 63 ;
else nCoeffs = s -> block_last_index [ n ];
2005-12-17 18:14:38 +00:00
if ( n < 4 )
2003-12-14 02:57:00 +00:00
block [ 0 ] = block [ 0 ] * s -> y_dc_scale ;
else
block [ 0 ] = block [ 0 ] * s -> c_dc_scale ;
quant_matrix = s -> intra_matrix ;
for ( i = 1 ; i <= nCoeffs ; i ++ ) {
int j = s -> intra_scantable . permutated [ i ];
level = block [ j ];
if ( level ) {
if ( level < 0 ) {
level = - level ;
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
level = - level ;
} else {
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
}
block [ j ] = level ;
}
}
}
2006-04-28 17:03:52 +00:00
static void dct_unquantize_mpeg2_intra_bitexact ( MpegEncContext * s ,
DCTELEM * block , int n , int qscale )
{
int i , level , nCoeffs ;
const uint16_t * quant_matrix ;
int sum =- 1 ;
if ( s -> alternate_scan ) nCoeffs = 63 ;
else nCoeffs = s -> block_last_index [ n ];
if ( n < 4 )
block [ 0 ] = block [ 0 ] * s -> y_dc_scale ;
else
block [ 0 ] = block [ 0 ] * s -> c_dc_scale ;
quant_matrix = s -> intra_matrix ;
for ( i = 1 ; i <= nCoeffs ; i ++ ) {
int j = s -> intra_scantable . permutated [ i ];
level = block [ j ];
if ( level ) {
if ( level < 0 ) {
level = - level ;
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
level = - level ;
} else {
level = ( int )( level * qscale * quant_matrix [ j ]) >> 3 ;
}
block [ j ] = level ;
sum += level ;
}
}
block [ 63 ] ^= sum & 1 ;
}
2005-12-17 18:14:38 +00:00
static void dct_unquantize_mpeg2_inter_c ( MpegEncContext * s ,
2003-12-14 02:57:00 +00:00
DCTELEM * block , int n , int qscale )
{
int i , level , nCoeffs ;
const uint16_t * quant_matrix ;
int sum =- 1 ;
if ( s -> alternate_scan ) nCoeffs = 63 ;
else nCoeffs = s -> block_last_index [ n ];
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
quant_matrix = s -> inter_matrix ;
for ( i = 0 ; i <= nCoeffs ; i ++ ) {
int j = s -> intra_scantable . permutated [ i ];
level = block [ j ];
if ( level ) {
if ( level < 0 ) {
level = - level ;
level = ((( level << 1 ) + 1 ) * qscale *
(( int ) ( quant_matrix [ j ]))) >> 4 ;
level = - level ;
} else {
level = ((( level << 1 ) + 1 ) * qscale *
(( int ) ( quant_matrix [ j ]))) >> 4 ;
}
block [ j ] = level ;
sum += level ;
}
}
block [ 63 ] ^= sum & 1 ;
}
2005-12-17 18:14:38 +00:00
static void dct_unquantize_h263_intra_c ( MpegEncContext * s ,
2003-12-14 02:57:00 +00:00
DCTELEM * block , int n , int qscale )
{
int i , level , qmul , qadd ;
int nCoeffs ;
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
assert ( s -> block_last_index [ n ] >= 0 );
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
qmul = qscale << 1 ;
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
if ( ! s -> h263_aic ) {
2005-12-17 18:14:38 +00:00
if ( n < 4 )
2002-04-17 16:30:31 +00:00
block [ 0 ] = block [ 0 ] * s -> y_dc_scale ;
else
block [ 0 ] = block [ 0 ] * s -> c_dc_scale ;
2003-12-14 02:57:00 +00:00
qadd = ( qscale - 1 ) | 1 ;
} else {
qadd = 0 ;
}
if ( s -> ac_pred )
nCoeffs = 63 ;
else
nCoeffs = s -> inter_scantable . raster_end [ s -> block_last_index [ n ] ];
for ( i = 1 ; i <= nCoeffs ; i ++ ) {
level = block [ i ];
if ( level ) {
if ( level < 0 ) {
level = level * qmul - qadd ;
} else {
level = level * qmul + qadd ;
2002-04-17 16:30:31 +00:00
}
2003-12-14 02:57:00 +00:00
block [ i ] = level ;
2002-04-17 16:30:31 +00:00
}
}
}
2005-12-17 18:14:38 +00:00
static void dct_unquantize_h263_inter_c ( MpegEncContext * s ,
2001-07-30 23:26:26 +00:00
DCTELEM * block , int n , int qscale )
{
int i , level , qmul , qadd ;
2002-01-13 04:59:37 +00:00
int nCoeffs ;
2005-12-17 18:14:38 +00:00
2002-09-29 22:44:22 +00:00
assert ( s -> block_last_index [ n ] >= 0 );
2005-12-17 18:14:38 +00:00
2002-09-29 22:44:22 +00:00
qadd = ( qscale - 1 ) | 1 ;
qmul = qscale << 1 ;
2005-12-17 18:14:38 +00:00
2003-12-14 02:57:00 +00:00
nCoeffs = s -> inter_scantable . raster_end [ s -> block_last_index [ n ] ];
2001-07-30 23:26:26 +00:00
2003-12-14 02:57:00 +00:00
for ( i = 0 ; i <= nCoeffs ; i ++ ) {
2001-07-30 23:26:26 +00:00
level = block [ i ];
if ( level ) {
if ( level < 0 ) {
level = level * qmul - qadd ;
} else {
level = level * qmul + qadd ;
}
block [ i ] = level ;
}
}
}
2001-07-22 14:18:56 +00:00
2003-02-16 23:05:38 +00:00
#ifdef CONFIG_ENCODERS
2001-07-22 14:18:56 +00:00
AVCodec h263_encoder = {
"h263" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_H263 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2001-07-22 14:18:56 +00:00
};
AVCodec h263p_encoder = {
"h263p" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_H263P ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2001-07-22 14:18:56 +00:00
};
2003-07-09 23:10:59 +00:00
AVCodec flv_encoder = {
"flv" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_FLV1 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2003-07-09 23:10:59 +00:00
};
2001-07-22 14:18:56 +00:00
AVCodec rv10_encoder = {
"rv10" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_RV10 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2001-07-22 14:18:56 +00:00
};
2004-12-07 13:14:37 +00:00
AVCodec rv20_encoder = {
"rv20" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_RV20 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2004-12-07 13:14:37 +00:00
};
2001-08-15 13:12:23 +00:00
AVCodec mpeg4_encoder = {
"mpeg4" ,
2001-07-22 14:18:56 +00:00
CODEC_TYPE_VIDEO ,
2001-08-15 13:12:23 +00:00
CODEC_ID_MPEG4 ,
2001-07-22 14:18:56 +00:00
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2004-06-30 23:12:21 +00:00
. capabilities = CODEC_CAP_DELAY ,
2001-07-22 14:18:56 +00:00
};
2002-04-05 04:09:04 +00:00
AVCodec msmpeg4v1_encoder = {
"msmpeg4v1" ,
2001-07-22 14:18:56 +00:00
CODEC_TYPE_VIDEO ,
2002-04-05 04:09:04 +00:00
CODEC_ID_MSMPEG4V1 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2002-04-05 04:09:04 +00:00
};
AVCodec msmpeg4v2_encoder = {
"msmpeg4v2" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MSMPEG4V2 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2002-04-05 04:09:04 +00:00
};
AVCodec msmpeg4v3_encoder = {
"msmpeg4" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MSMPEG4V3 ,
2001-07-22 14:18:56 +00:00
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2001-07-22 14:18:56 +00:00
};
2002-06-18 00:49:00 +00:00
AVCodec wmv1_encoder = {
"wmv1" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_WMV1 ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUV420P , - 1 },
2002-06-18 00:49:00 +00:00
};
2003-01-29 12:00:11 +00:00
AVCodec mjpeg_encoder = {
"mjpeg" ,
CODEC_TYPE_VIDEO ,
CODEC_ID_MJPEG ,
sizeof ( MpegEncContext ),
MPV_encode_init ,
MPV_encode_picture ,
MPV_encode_end ,
2005-02-25 15:06:21 +00:00
. pix_fmts = ( enum PixelFormat []){ PIX_FMT_YUVJ420P , - 1 },
2003-01-29 12:00:11 +00:00
};
2003-02-16 23:05:38 +00:00
#endif //CONFIG_ENCODERS