?? x264.c
字號:
/*****************************************************************************
* x264: h264 encoder/decoder testing program.
*****************************************************************************
* Copyright (C) 2003 Laurent Aimar
* $Id: x264.c,v 1.1 2004/06/03 19:24:12 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#define _GNU_SOURCE
#include "getopt.h"
#ifdef _MSC_VER
#include <io.h> /* _setmode() */
#include <fcntl.h> /* _O_BINARY */
#endif
//#ifndef _MSC_VER
//#include "config.h"
//#endif
#include "common.h"
#include "x264.h"
#include "muxers.h"
#define DATA_MAX 3000000
uint8_t data[DATA_MAX];
/* Ctrl-C handler */
static int b_ctrl_c = 0;
static int b_exit_on_ctrl_c = 0;
static void SigIntHandler( int a )
{
if( b_exit_on_ctrl_c )
exit(0);
b_ctrl_c = 1;
}
typedef struct {
int b_progress;
int i_seek;
hnd_t hin;
hnd_t hout;
FILE *qpfile;
} cli_opt_t;
/* input file operation function pointers */
int (*p_open_infile)( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param );
int (*p_get_frame_total)( hnd_t handle );
int (*p_read_frame)( x264_picture_t *p_pic, hnd_t handle, int i_frame );
int (*p_close_infile)( hnd_t handle );
/* output file operation function pointers */
static int (*p_open_outfile)( char *psz_filename, hnd_t *p_handle );
static int (*p_set_outfile_param)( hnd_t handle, x264_param_t *p_param );
static int (*p_write_nalu)( hnd_t handle, uint8_t *p_nal, int i_size );
static int (*p_set_eop)( hnd_t handle, x264_picture_t *p_picture );
static int (*p_close_outfile)( hnd_t handle );
static void Help( x264_param_t *defaults, int b_longhelp );
static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
static int Encode( x264_param_t *param, cli_opt_t *opt );
/****************************************************************************
* main:
****************************************************************************/
int main( int argc, char **argv )
{
x264_param_t param;
cli_opt_t opt;
#ifdef _MSC_VER
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
#endif
x264_param_default( ¶m );//對編碼器進行參數設定(初始化參數)
/* Parse command line */
if( Parse( argc, argv, ¶m, &opt ) < 0 )
return -1;
/* Control-C handler */
signal( SIGINT, SigIntHandler );
return Encode( ¶m, &opt );
}
static char const *strtable_lookup( const char * const table[], int index )
{
int i = 0; while( table[i] ) i++;
return ( ( index >= 0 && index < i ) ? table[ index ] : "???" );
}
/*****************************************************************************
* Help:
*****************************************************************************/
/*static void Help( x264_param_t *defaults, int b_longhelp )
/*****************************************************************************
* Parse:
*****************************************************************************/
static int Parse( int argc, char **argv,
x264_param_t *param, cli_opt_t *opt )
{
char *psz_filename = NULL;
x264_param_t defaults = *param;
memset( opt, 0, sizeof(cli_opt_t) );//清0初始化
/* Default input file driver */
p_open_infile = open_file_yuv;
p_get_frame_total = get_frame_total_yuv;
p_read_frame = read_frame_yuv;
p_close_infile = close_file_yuv;
/* Default output file driver */
p_open_outfile = open_file_bsf;
p_set_outfile_param = set_param_bsf;
p_write_nalu = write_nalu_bsf;
p_set_eop = set_eop_bsf;
p_close_outfile = close_file_bsf;
optarg="testtest.264";
if( p_open_outfile( optarg, &opt->hout ) )
{
fprintf( stderr, "x264 [error]: can't open output file `%s'\n", optarg );
return -1;
}
psz_filename ="foreman3.yuv";//football_cif_ori90.yuv
if( p_open_infile( psz_filename, &opt->hin, param ) )
{
fprintf( stderr, "x264 [error]: could not open input file '%s'\n", psz_filename );
return -1;
}
return 0;
}
static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
{
int num = -1, qp;
char type;
while( num < i_frame )
{
int ret = fscanf( opt->qpfile, "%d %c %d\n", &num, &type, &qp );
if( num < i_frame )
continue;
pic->i_qpplus1 = qp+1;
if ( type == 'I' ) pic->i_type = X264_TYPE_IDR;
else if( type == 'i' ) pic->i_type = X264_TYPE_I;
else if( type == 'P' ) pic->i_type = X264_TYPE_P;
else if( type == 'B' ) pic->i_type = X264_TYPE_BREF;
else if( type == 'b' ) pic->i_type = X264_TYPE_B;
else ret = 0;
if( ret != 3 || qp < 0 || qp > 51 || num > i_frame )
{
fprintf( stderr, "x264 [error]: can't parse qpfile for frame %d\n", i_frame );
fclose( opt->qpfile );
opt->qpfile = NULL;
pic->i_type = X264_TYPE_AUTO;
pic->i_qpplus1 = 0;
break;
}
}
}
/*****************************************************************************
* Decode:
*****************************************************************************/
static int Encode_frame( x264_t *h, hnd_t hout, x264_picture_t *pic )
{
x264_picture_t pic_out;
x264_nal_t *nal;
int i_nal, i;
int i_file = 0;
if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) < 0 )//對幀進行編碼
{
fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
}
fprintf(stderr,"Encode_frame:i_nal=%d\n",i_nal);//add
for( i = 0; i < i_nal; i++ )
{
int i_size;
int i_data;
int a;
i_data = DATA_MAX;
fprintf(stderr,"**********before x264_nal_encode()******************\n");//add
for(a=0;a<=i_size;a++)//add
{//add
fprintf(stderr,"Encode_frame:data=%d\n",data[a]);//add
}//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_payload);//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_ref_idc);//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_type);//add
fprintf(stderr,"Encode_frame:nal=%d\n",*nal[i].p_payload);//add
if( ( i_size = x264_nal_encode( data, &i_data, 1, &nal[i] ) ) > 0 )//編碼NAL層,網絡打包編碼
{
fprintf(stderr,"***********after x264_nal_encode()***************\n");//add
fprintf(stderr,"Encode_frame:hout=%d\n",hout);//add
fprintf(stderr,"Encode_frame:i_size=%d\n",i_size);//add
for(a=0;a<=i_size;a++)//add
{//add
fprintf(stderr,"Encode_frame:data=%d\n",data[a]);//add
}//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_payload);//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_ref_idc);//add
fprintf(stderr,"Encode_frame:nal=%d\n",nal[i].i_type);//add
fprintf(stderr,"Encode_frame:nal=%d\n",*nal[i].p_payload);//add
i_file += p_write_nalu( hout, data, i_size );//把網絡包寫入到輸出文件中去
}
else if( i_size < 0 )
{
fprintf(stderr, "x264 [error]: need to increase buffer size (size=%d)\n", -i_size );
}
}
if (i_nal)
p_set_eop( hout, &pic_out );
return i_file;
}
/*****************************************************************************
* Encode:
*****************************************************************************/
static int Encode( x264_param_t *param, cli_opt_t *opt )
{
x264_t *h;
x264_picture_t pic;
int i;//add
int i_frame, i_frame_total;
int64_t i_start, i_end;
int64_t i_file;
int i_frame_size;
int i_progress;
i_frame_total = p_get_frame_total( opt->hin );//得到總幀數
i_frame_total -= opt->i_seek;
if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )
&& param->i_frame_total > 0 )
i_frame_total = param->i_frame_total;
param->i_frame_total = i_frame_total;
if( ( h = x264_encoder_open( param ) ) == NULL )//這個函數是對不正確的參數進行修改,并對各結構體參數和CABAC編碼、預測等需要的參數進行初始化(初始化編碼器)。
{
fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
p_close_infile( opt->hin );
p_close_outfile( opt->hout );
return -1;
}
if( p_set_outfile_param( opt->hout, param ) )//此函數設置輸出文件參數
{
fprintf( stderr, "x264 [error]: can't set outfile param\n" );
p_close_infile( opt->hin );
p_close_outfile( opt->hout );
return -1;
}
/* Create a new pic */
x264_picture_alloc( &pic, X264_CSP_I420, param->i_width, param->i_height );//為新圖分配空間
// i_start = x264_mdate();
/* Encode frames */
for( i_frame = 0, i_file = 0, i_progress = 0;
b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )
{
if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )//此函數讀取一幀,并把這幀設為prev
break;
pic.i_pts = (int64_t)i_frame * param->i_fps_den;
if( opt->qpfile )
parse_qpfile( opt, &pic, i_frame + opt->i_seek );
else
{
/* Do not force any parameters */
pic.i_type = X264_TYPE_AUTO;
pic.i_qpplus1 = 0;
}
i_file += Encode_frame( h, opt->hout, &pic );//進入編碼層,對幀編碼
i_frame++;
/* update status line (up to 1000 times per input file) */
/* if( opt->b_progress && param->i_log_level < X264_LOG_DEBUG &&
( i_frame_total ? i_frame * 1000 / i_frame_total > i_progress
: i_frame % 10 == 0 ) )
{
/// int64_t i_elapsed = x264_mdate() - i_start;
double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0;
if( i_frame_total )
{
int eta = i_elapsed * (i_frame_total - i_frame) / ((int64_t)i_frame * 1000000);
i_progress = i_frame * 1000 / i_frame_total;
fprintf( stderr, "encoded frames: %d/%d (%.1f%%), %.2f fps, eta %d:%02d:%02d \r",
i_frame, i_frame_total, (float)i_progress / 10, fps,
eta/3600, (eta/60)%60, eta%60 );
}
else
fprintf( stderr, "encoded frames: %d, %.2f fps \r", i_frame, fps );
fflush( stderr ); // needed in windows
}*/
}
/* Flush delayed B-frames */
do {
i_file +=
i_frame_size = Encode_frame( h, opt->hout, NULL );
} while( i_frame_size );
/// i_end = x264_mdate();
x264_picture_clean( &pic );//清理圖片區
x264_encoder_close( h );//關閉編碼器
fprintf( stderr, "\n" );
if( b_ctrl_c )
fprintf( stderr, "aborted at input frame %d\n", opt->i_seek + i_frame );
p_close_infile( opt->hin );//關閉輸入文件
p_close_outfile( opt->hout );//關閉輸出文件
if( i_frame > 0 )
{
double fps = (double)i_frame * (double)1000000 /
(double)( i_end - i_start );
fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps,
(double) i_file * 8 * param->i_fps_num /
( (double) param->i_fps_den * i_frame * 1000 ) );
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -