@ -43,6 +43,7 @@
# include "flv.h"
# include "mpeg4video.h"
# include "internal.h"
# include "bytestream.h"
# include <limits.h>
//#undef NDEBUG
@ -1426,6 +1427,12 @@ int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
if ( ! pkt - > data & &
( ret = ff_alloc_packet ( pkt , s - > mb_width * s - > mb_height * MAX_MB_BYTES ) ) < 0 )
return ret ;
if ( s - > mb_info ) {
s - > mb_info_ptr = av_packet_new_side_data ( pkt ,
AV_PKT_DATA_H263_MB_INFO ,
s - > mb_width * s - > mb_height * 12 ) ;
s - > prev_mb_info = s - > last_mb_info = s - > mb_info_size = 0 ;
}
for ( i = 0 ; i < context_count ; i + + ) {
int start_y = s - > thread_context [ i ] - > start_mb_y ;
@ -1593,6 +1600,8 @@ vbv_retry:
pkt - > dts = pkt - > pts ;
if ( s - > current_picture . f . key_frame )
pkt - > flags | = AV_PKT_FLAG_KEY ;
if ( s - > mb_info )
av_packet_shrink_side_data ( pkt , AV_PKT_DATA_H263_MB_INFO , s - > mb_info_size ) ;
} else {
assert ( ( put_bits_ptr ( & s - > pb ) = = s - > pb . buf ) ) ;
s - > frame_bits = 0 ;
@ -2336,6 +2345,49 @@ static void write_slice_end(MpegEncContext *s){
s - > misc_bits + = get_bits_diff ( s ) ;
}
static void write_mb_info ( MpegEncContext * s )
{
uint8_t * ptr = s - > mb_info_ptr + s - > mb_info_size - 12 ;
int offset = put_bits_count ( & s - > pb ) ;
int mba = s - > mb_x + s - > mb_width * ( s - > mb_y % s - > gob_index ) ;
int gobn = s - > mb_y / s - > gob_index ;
int pred_x , pred_y ;
if ( CONFIG_H263_ENCODER )
ff_h263_pred_motion ( s , 0 , 0 , & pred_x , & pred_y ) ;
bytestream_put_le32 ( & ptr , offset ) ;
bytestream_put_byte ( & ptr , s - > qscale ) ;
bytestream_put_byte ( & ptr , gobn ) ;
bytestream_put_le16 ( & ptr , mba ) ;
bytestream_put_byte ( & ptr , pred_x ) ; /* hmv1 */
bytestream_put_byte ( & ptr , pred_y ) ; /* vmv1 */
/* 4MV not implemented */
bytestream_put_byte ( & ptr , 0 ) ; /* hmv2 */
bytestream_put_byte ( & ptr , 0 ) ; /* vmv2 */
}
static void update_mb_info ( MpegEncContext * s , int startcode )
{
if ( ! s - > mb_info )
return ;
if ( put_bits_count ( & s - > pb ) - s - > prev_mb_info * 8 > = s - > mb_info * 8 ) {
s - > mb_info_size + = 12 ;
s - > prev_mb_info = s - > last_mb_info ;
}
if ( startcode ) {
s - > prev_mb_info = put_bits_count ( & s - > pb ) / 8 ;
/* This might have incremented mb_info_size above, and we return without
* actually writing any info into that slot yet . But in that case ,
* this will be called again at the start of the after writing the
* start code , actually writing the mb info . */
return ;
}
s - > last_mb_info = put_bits_count ( & s - > pb ) / 8 ;
if ( ! s - > mb_info_size )
s - > mb_info_size + = 12 ;
write_mb_info ( s ) ;
}
static int encode_thread ( AVCodecContext * c , void * arg ) {
MpegEncContext * s = * ( void * * ) arg ;
int mb_x , mb_y , pdif = 0 ;
@ -2481,6 +2533,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
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 ) ;
}
update_mb_info ( s , 1 ) ;
switch ( s - > codec_id ) {
case CODEC_ID_MPEG4 :
@ -2524,6 +2577,8 @@ static int encode_thread(AVCodecContext *c, void *arg){
s - > mb_skipped = 0 ;
s - > dquant = 0 ; //only for QP_RD
update_mb_info ( s , 0 ) ;
if ( mb_type & ( mb_type - 1 ) | | ( s - > mpv_flags & FF_MPV_FLAG_QP_RD ) ) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD
int next_block = 0 ;
int pb_bits_count , pb2_bits_count , tex_pb_bits_count ;
@ -4074,6 +4129,7 @@ int ff_dct_quantize_c(MpegEncContext *s,
static const AVOption h263_options [ ] = {
{ " obmc " , " use overlapped block motion compensation. " , OFFSET ( obmc ) , AV_OPT_TYPE_INT , { 0 } , 0 , 1 , VE } ,
{ " structured_slices " , " Write slice start position at every GOB header instead of just GOB number. " , OFFSET ( h263_slice_structured ) , AV_OPT_TYPE_INT , { 0 } , 0 , 1 , VE } ,
{ " mb_info " , " emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size " , OFFSET ( mb_info ) , AV_OPT_TYPE_INT , { 0 } , 0 , INT_MAX , VE } ,
FF_MPV_COMMON_OPTS
{ NULL } ,
} ;