📄 encoder.c
字号:
/* x264: h264 encoder */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stdint.h"
//#include "malloc.h"
#include <math.h>
#include "common.h"
#include "x264.h"
#include "me.h"
#include "set.h"
#include "analyse.h"
#include "ratecontrol.h"
#include "macroblock.h"
/****************************************************************************
*
******************************* x264 libs **********************************
*
****************************************************************************/
static float x264_psnr( uint8_t *pix1, int i_pix_stride, uint8_t *pix2, int i_pix2_stride, int i_width, int i_height )
{
int64_t i_sqe = 0;
int x, y;
for( y = 0; y < i_height; y++ )
{
for( x = 0; x < i_width; x++ )
{
int tmp;
tmp = pix1[y*i_pix_stride+x] - pix2[y*i_pix2_stride+x];
i_sqe += tmp * tmp;
}
}
if( i_sqe == 0 )
{
return -1.0;
}
return (float)(10.0 * log( (double)65025.0 * (double)i_height * (double)i_width / (double)i_sqe ) / log( 10.0 ));
}
/* Fill "default" values */
static void x264_slice_header_init( x264_slice_header_t *sh, x264_param_t *param,
x264_sps_t *sps, x264_pps_t *pps,
int i_type, int i_idr_pic_id, int i_frame )
{
/* First we fill all field */
sh->sps = sps;
sh->pps = pps;
sh->i_type = i_type;
sh->i_first_mb = 0;
sh->i_pps_id = pps->i_id;
sh->i_frame_num = i_frame;
sh->b_field_pic = 0; /* Not field support for now */
sh->b_bottom_field = 1; /* not yet used */
sh->i_idr_pic_id = i_idr_pic_id;
/* poc stuff, fixed later */
sh->i_poc_lsb = 0;
sh->i_delta_poc_bottom = 0;
sh->i_delta_poc[0] = 0;
sh->i_delta_poc[1] = 0;
sh->i_redundant_pic_cnt = 0;
sh->b_direct_spatial_mv_pred = 0;
sh->b_num_ref_idx_override = 0;
sh->i_num_ref_idx_l0_active = 1;
sh->i_num_ref_idx_l1_active = 1;
sh->i_cabac_init_idc = param->i_cabac_init_idc;
sh->i_qp_delta = 0;
sh->b_sp_for_swidth = 0;
sh->i_qs_delta = 0;
if( param->b_deblocking_filter )
{
sh->i_disable_deblocking_filter_idc = 0;
}
else
{
sh->i_disable_deblocking_filter_idc = 1;
}
sh->i_alpha_c0_offset = 0;
sh->i_beta_offset = 0;
}
static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc )
{
bs_write_ue( s, sh->i_first_mb );
bs_write_ue( s, sh->i_type + 5 ); /* same type things */
bs_write_ue( s, sh->i_pps_id );
bs_write( s, sh->sps->i_log2_max_frame_num, sh->i_frame_num );
if( sh->i_idr_pic_id >= 0 ) /* NAL IDR */
{
bs_write_ue( s, sh->i_idr_pic_id );
}
if( sh->sps->i_poc_type == 0 )
{
bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc_lsb );
if( sh->pps->b_pic_order && !sh->b_field_pic )
{
bs_write_se( s, sh->i_delta_poc_bottom );
}
}
else if( sh->sps->i_poc_type == 1 && !sh->sps->b_delta_pic_order_always_zero )
{
bs_write_se( s, sh->i_delta_poc[0] );
if( sh->pps->b_pic_order && !sh->b_field_pic )
{
bs_write_se( s, sh->i_delta_poc[1] );
}
}
if( sh->pps->b_redundant_pic_cnt )
{
bs_write_ue( s, sh->i_redundant_pic_cnt );
}
if( sh->i_type == SLICE_TYPE_B )
{
bs_write1( s, sh->b_direct_spatial_mv_pred );
}
if( sh->i_type == SLICE_TYPE_P || sh->i_type == SLICE_TYPE_SP || sh->i_type == SLICE_TYPE_B )
{
bs_write1( s, sh->b_num_ref_idx_override );
if( sh->b_num_ref_idx_override )
{
bs_write_ue( s, sh->i_num_ref_idx_l0_active - 1 );
if( sh->i_type == SLICE_TYPE_B )
{
bs_write_ue( s, sh->i_num_ref_idx_l1_active - 1 );
}
}
}
/* ref pic list reordering */
if( sh->i_type != SLICE_TYPE_I )
{
int b_ref_pic_list_reordering_l0 = 0;
bs_write1( s, b_ref_pic_list_reordering_l0 );
if( b_ref_pic_list_reordering_l0 )
{
/* FIXME */
}
}
if( sh->i_type == SLICE_TYPE_B )
{
int b_ref_pic_list_reordering_l1 = 0;
bs_write1( s, b_ref_pic_list_reordering_l1 );
if( b_ref_pic_list_reordering_l1 )
{
/* FIXME */
}
}
if( ( sh->pps->b_weighted_pred && ( sh->i_type == SLICE_TYPE_P || sh->i_type == SLICE_TYPE_SP ) ) ||
( sh->pps->b_weighted_bipred == 1 && sh->i_type == SLICE_TYPE_B ) )
{
/* FIXME */
}
if( i_nal_ref_idc != 0 )
{
if( sh->i_idr_pic_id >= 0 )
{
bs_write1( s, 0 ); /* no output of prior pics flag */
bs_write1( s, 0 ); /* long term reference flag */
}
else
{
bs_write1( s, 0 ); /* adaptive_ref_pic_marking_mode_flag */
/* FIXME */
}
}
if( sh->pps->b_cabac && sh->i_type != SLICE_TYPE_I )
{
bs_write_ue( s, sh->i_cabac_init_idc );
}
bs_write_se( s, sh->i_qp_delta ); /* slice qp delta */
#if 0
if( sh->i_type == SLICE_TYPE_SP || sh->i_type == SLICE_TYPE_SI )
{
if( sh->i_type == SLICE_TYPE_SP )
{
bs_write1( s, sh->b_sp_for_swidth );
}
bs_write_se( s, sh->i_qs_delta );
}
#endif
if( sh->pps->b_deblocking_filter_control )
{
bs_write_ue( s, sh->i_disable_deblocking_filter_idc );
if( sh->i_disable_deblocking_filter_idc != 1 )
{
bs_write_se( s, sh->i_alpha_c0_offset >> 1 );
bs_write_se( s, sh->i_beta_offset >> 1 );
}
}
}
#if 0
static void x264_frame_dump( x264_t *h, x264_frame_t *fr, char *name )
{
FILE * f = fopen( name, "a" );
int i, y;
fseek( f, 0, SEEK_END );
for( i = 0; i < fr->i_plane; i++ )
{
for( y = 0; y < h->param.i_height / ( i == 0 ? 1 : 2 ); y++ )
{
fwrite( &fr->plane[i][y*fr->i_stride[i]], 1, h->param.i_width / ( i == 0 ? 1 : 2 ), f );
}
}
fclose( f );
}
#endif
/*
static void x264_write_recon( x264_t *h, x264_frame_t *fr, char* recY, char* recU, char* recV)
{
int y;
for( y = 0; y < h->param.i_height; y++ )
{
// fwrite( &fr->plane[0][y*fr->i_stride[0]], 1, h->param.i_width, f );
memcpy(&recY[y*fr->i_stride[0]], &fr->plane[0][y*fr->i_stride[0]], h->param.i_width);
}
for( y = 0; y < h->param.i_height/2; y++ )
{
memcpy(&recU[y*fr->i_stride[1]], &fr->plane[1][y*fr->i_stride[1]], h->param.i_width/2);
}
for( y = 0; y < h->param.i_height/2; y++ )
{
memcpy(&recV[y*fr->i_stride[2]], &fr->plane[2][y*fr->i_stride[2]], h->param.i_width/2);
}
}
*/
/****************************************************************************
*
****************************************************************************
****************************** External API*********************************
****************************************************************************
*
****************************************************************************/
/****************************************************************************
* x264_encoder_open:
****************************************************************************/
x264_t *x264_encoder_open ( x264_param_t *param )
{
int i;
x264_me_t me[2];
x264_t *h;
h =(x264_t * )x264_malloc(sizeof( x264_t ));
if( param->i_width <= 0 || param->i_height <= 0 )
{
fprintf( stderr, "invalid width x height (%dx%d)\n",
param->i_width, param->i_height );
free( h );
return NULL;
}
if( param->i_width % 16 != 0 || param->i_height % 16 != 0 )
{
fprintf( stderr, "width %% 16 != 0 pr height %% 16 != 0 (%dx%d)\n",
param->i_width, param->i_height );
free( h );
return NULL;
}
// h->param.b_cabac=param->b_cabac;
/* h->param.b_deblocking_filter=param->b_deblocking_filter;
h->param.cpu = param->cpu ;
h->param.f_fps = param->f_fps;
h->param.i_bframe = param->i_bframe;
h->param.i_bitrate = param->i_bitrate;
h->param.i_cabac_init_idc = param->i_cabac_init_idc;
h->param.i_frame_reference = param->i_frame_reference;
h->param.i_height = param->i_height ;
h->param.i_idrframe = param->i_idrframe;
h->param.i_iframe = param->i_iframe ;
h->param.i_me = param->i_me ;
h->param.i_qp_constant = param->i_qp_constant ;
h->param.i_width = param->i_width ;
h->param.vui = param->vui ;
*/
memcpy( &h->param, param, sizeof(x264_param_t ));
if( h->param.i_frame_reference <= 0 )
{
h->param.i_frame_reference = 1;
}
else if( h->param.i_frame_reference > 15 )
{
h->param.i_frame_reference = 15;
}
if( h->param.i_idrframe <= 0 )
{
h->param.i_idrframe = 1;
}
if( h->param.i_iframe <= 0 )
{
h->param.i_iframe = 1;
}
if( h->param.i_bframe < 0 )
{
h->param.i_bframe = 0;
}
else if( h->param.i_bframe > X264_BFRAME_MAX )
{
h->param.i_bframe = X264_BFRAME_MAX;
}
/* XXX for now we use fixed patern IB...BPB...BPB...BP */
if( h->param.i_bframe > 0 )
{
h->param.i_iframe = ((h->param.i_iframe - 1)/(h->param.i_bframe+1))*(h->param.i_bframe+1) + 1;
if( h->param.b_cabac )
{
fprintf( stderr, "cabac not supported with B frame (cabac disabled)\n" );
h->param.b_cabac = 0;
}
}
if( h->param.i_cabac_init_idc < -1 )
{
h->param.i_cabac_init_idc = -1;
}
else if( h->param.i_cabac_init_idc > 2 )
{
h->param.i_cabac_init_idc = 2;
}
// h->cpu = param->cpu;
h->i_nal = 0;
h->i_bitstream = 1000000; /* FIXME calculate max size from width/height */
h->p_bitstream =(uint8_t *) x264_malloc( h->i_bitstream );
h->i_frame = 0;
h->i_frame_num = 0;
h->i_poc = 0;
h->i_idr_pic_id = 0;
h->sps = &h->sps_array[0];
x264_sps_init( h->sps, 0, &h->param );
h->pps = &h->pps_array[0];
x264_pps_init( h->pps, 0, &h->param, h->sps);
/* init picture and bframe context */
h->picture = NULL;
for( i = 0; i < X264_BFRAME_MAX; i++ )
{
h->bframe_current[i]= NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -