#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>
//#include "portab.h" /* for pthread */
#include "xvid.h"
// Equivalent to vfw's pmvfast_presets
static const int motion_presets[] = {
/* quality 0 */
0,
/* quality 1 */
0,
/* quality 2 */
0,
/* quality 3 */
0,
/* quality 4 */
0 | XVID_ME_HALFPELREFINE16 | 0,
/* quality 5 */
0 | XVID_ME_HALFPELREFINE16 | 0 | XVID_ME_ADVANCEDDIAMOND16,
/* quality 6 */
XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 | XVID_ME_HALFPELREFINE8 | 0 | XVID_ME_USESQUARES16
};
#define ME_ELEMENTS (sizeof(motion_presets)/sizeof(motion_presets[0]))
static const int vop_presets[] = {
/* quality 0 */
0,
/* quality 1 */
0,
/* quality 2 */
0,
/* quality 3 */
0,
/* quality 4 */
0,
/* quality 5 */
XVID_VOP_INTER4V,
/* quality 6 */
XVID_VOP_INTER4V,
};
#define VOP_ELEMENTS (sizeof(vop_presets)/sizeof(vop_presets[0]))
#define MAX_XDIM 4096
#define MAX_YDIM 4096
#ifndef READ_PNM
#define IMAGE_SIZE(x,y) ((x)*(y)*3/2)
#else
#define IMAGE_SIZE(x,y) ((x)*(y)*3)
#endif
typedef struct
{
void *enc_handle; /**< Handle for Xvid encoder */
int xsize; /**< Frame x size */
int ysize; /**< Frame y size */
int bitrate;
float framerate;
int me_quality; /**< Motion estimation quality. 0: fast 6: best. */
//int vop_flags; /**< VOP flags for Xvid encoder */
//int vol_flags; /**< VOL flags for Xvid encoder */
//int me_flags; /**< Motion Estimation flags */
//int qscale; /**< Do we use constant scale? */
//int quicktime_format; /**< Are we in a QT-based format? */
//char *twopassbuffer; /**< Character buffer for two-pass */
//char *old_twopassbuffer; /**< Old character buffer (two-pass) */
//char *twopassfile; /**< second pass temp file name */
//int twopassfd;
//unsigned char *intra_matrix; /**< P-Frame Quant Matrix */
//unsigned char *inter_matrix; /**< I-Frame Quant Matrix */
//int lumi_aq; /**< Lumi masking as an aq method */
//int variance_aq; /**< Variance adaptive quantization */
//int ssim; /**< SSIM information display mode */
//int ssim_acc; /**< SSIM accuracy. 0: accurate. 4: fast. */
//int gmc;
//int mpeg_quant; /**< Quantization type. 0: H.263, 1: MPEG */
} xvid_context;
static int ARG_DWRATE = 25;
static int ARG_DWSCALE = 1;
static int ARG_MAXKEYINTERVAL = 300;
//static int ARG_NUM_APP_THREADS = 1;
static char *ARG_INPUTFILE = NULL;
static char *ARG_OUTPUTFILE = NULL;
static int ARG_QUANTS[6] = {2, 31, 2, 31, 2, 31};
const char userdata_start_code[] = "\0\0\x01\xb2";
static double msecond();
int gcd(int a, int b);
static int read_yuvdata(FILE * handle, xvid_context *x, unsigned char *image);
static void enc_gbl(int use_assembler);
static int xvid_encode_init(xvid_context *x);
static int xvid_encode_frame(xvid_context *x,
unsigned char *image,
unsigned char *bitstream,
int *key,
int *stats_type);
static int xvid_encode_close(xvid_context* x);
void removedivxp(char *buf, int size);
static double msecond()
{
#ifndef WIN32
struct timeval tv;
gettimeofday(&tv, 0);
return (tv.tv_sec * 1.0e3 + tv.tv_usec * 1.0e-3);
#else
clock_t clk;
clk = clock();
return (clk * 1000.0 / CLOCKS_PER_SEC);
#endif
}
int gcd(int a, int b)
{
int r ;
if (b > a) {
r = a;
a = b;
b = r;
}
while ((r = a % b)) {
a = b;
b = r;
}
return b;
}
static int read_yuvdata(FILE * handle, xvid_context* x, unsigned char *image)
{
if (fread(image, 1, IMAGE_SIZE(x->xsize, x->ysize), handle) !=
(unsigned int) IMAGE_SIZE(x->xsize, x->ysize))
return (1);
else
return (0);
}
static void enc_gbl(int use_assembler)
{
xvid_gbl_init_t xvid_gbl_init;
/*------------------------------------------------------------------------
* Xvid core initialization
*----------------------------------------------------------------------*/
/* Set version -- version checking will done by xvidcore */
memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
xvid_gbl_init.version = XVID_VERSION;
xvid_gbl_init.debug = 0;//ARG_DEBUG;
if (use_assembler)
xvid_gbl_init.cpu_flags = 0;
else
xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
/* Initialize Xvid core -- Should be done once per __process__ */
xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
//ARG_CPU_FLAGS = xvid_gbl_init.cpu_flags;
----------------------------------------------
xvid_gbl_info_t xvid_gbl_info;
int ret;
memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info));
xvid_gbl_info.version = XVID_VERSION;
ret = xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL);
}
void removedivxp(char *buf, int bufsize) {
int i;
char* userdata;
for (i=0; i <= (int)(bufsize-sizeof(userdata_start_code)); i++) {
if (memcmp((void*)userdata_start_code, (void*)(buf+i), strlen(userdata_start_code))==0) {
if ((userdata = strstr(buf+i+4, "DivX"))!=NULL) {
userdata[strlen(userdata)-1] = '\0';
return;
}
}
}
}
int main(int argc, char *argv[])
{
int i;
int result;
int key;
int type;
int m4v_size;
FILE *in_file;
FILE *out_file;
//memset(framestats, 0, sizeof(framestats));
xvid_context *x = (xvid_context*)malloc(sizeof(xvid_context));
for (i = 1; i < argc; i++)
{
if (strcmp("-w", argv[i]) == 0 && i < argc - 1) {
i++;
x->xsize = atoi(argv[i]);
} else if (strcmp("-h", argv[i]) == 0 && i < argc - 1) {
i++;
x->ysize = atoi(argv[i]);
} else if (strcmp("-bitrate", argv[i]) == 0) {
i++;
x->bitrate = atoi(argv[i]);
} else if (strcmp("-framerate", argv[i]) == 0 && i < argc - 1) {
int exponent;
i++;
x->framerate = (float) atof(argv[i]);
exponent = (int) strcspn(argv[i], ".");
if (exponent<(int)strlen(argv[i]))
exponent=(int)pow(10.0, (int)(strlen(argv[i])-1-exponent));
else
exponent=1;
ARG_DWRATE = (int)(atof(argv[i])*exponent);
ARG_DWSCALE = exponent;
exponent = gcd(ARG_DWRATE, ARG_DWSCALE);
ARG_DWRATE /= exponent;
ARG_DWSCALE /= exponent;
} else if (strcmp("-i", argv[i]) == 0 && i < argc - 1) {
i++;
ARG_INPUTFILE = argv[i];
} else if (strcmp("-o", argv[i]) == 0 && i < argc - 1) {
i++;
ARG_OUTPUTFILE = argv[i];
}
}
fprintf(stdout, "xsize value - ysize value %d - %d \n", x->xsize, x->ysize);
//---------------------------------------------------------------------------//
if (ARG_INPUTFILE != NULL) {
in_file = fopen(ARG_INPUTFILE, "rb");
if (in_file == NULL) {
fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
return (-1);
}
}
if (ARG_OUTPUTFILE != NULL) {
out_file = fopen(ARG_OUTPUTFILE, "w+b");
if (out_file == NULL) {
fprintf(stderr, "Error opening output file %s\n", ARG_OUTPUTFILE);
return (-1);
}
}
fseek(in_file, 0, SEEK_SET);
/* now we know the sizes, so allocate memory */
unsigned char *image = (unsigned char *) malloc(4*x->xsize*x->ysize);
if (!image)
goto release_all;
/* this should really be enough memory ! */
unsigned char *mp4_buffer = (unsigned char *) malloc(IMAGE_SIZE(x->xsize, x->ysize) * 2);
if (!mp4_buffer)
goto release_all;
// ------------------------------------------------------------------------//
result = xvid_encode_init(x);
if (result) {
fprintf(stderr, "Encore INIT problem, return value %d\n", result);
goto release_all;
}
// ------------------------------------------------------------------------//
i = 0;
do {
result = read_yuvdata(in_file, x, image);
double enctime = msecond();
m4v_size = xvid_encode_frame(x, !result ? image : 0, mp4_buffer, &key, &type);
enctime = msecond() - enctime;
fprintf(stdout, "frame_num= %d, ", ++i);
//fprintf(stdout, "m4v_size= %d\n", m4v_size);
if (m4v_size < 0)
break;
if (m4v_size > 0) {
/* Save ES stream */
//fprintf(stdout, "type= %d\n", type);
if (out_file && (type != XVID_TYPE_BVOP) || (m4v_size > 8) )
{
fwrite(mp4_buffer, 1, m4v_size, out_file);
}
}
} while(1);
// ----------------------------------------------------------------------------//
result = xvid_encode_close(x);
//----------------------------------------------------------//
release_all:
if (in_file)
fclose(in_file);
if (out_file)
fclose(out_file);
if (mp4_buffer)
free(mp4_buffer);
if (image)
free(image);
return (0);
//-------------------------------------------------------------------------------------------//
}
static int xvid_encode_init(xvid_context *x)
{
/* Init xvidcore */
enc_gbl(/*use_assembler*/ 1);
int xerr;
//xvid_plugin_cbr_t cbr;
xvid_plugin_single_t single;
//xvid_plugin_fixed_t rcfixed;
xvid_enc_plugin_t plugins[8];
xvid_enc_create_t xvid_enc_create;
/*------------------------------------------------------------------------
* Xvid encoder initialization
*----------------------------------------------------------------------*/
/* Version again */
memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
xvid_enc_create.version = XVID_VERSION;
/* Width and Height of input frames */
xvid_enc_create.width = x->xsize;
xvid_enc_create.height = x->ysize;
xvid_enc_create.profile = 0xf5; /* Unrestricted */
/* init plugins */
xvid_enc_create.plugins = plugins;
xvid_enc_create.num_plugins = 0;
if (1/*ARG_SINGLE*/) {
memset(&single, 0, sizeof(xvid_plugin_single_t));
single.version = XVID_VERSION;
single.bitrate = x->bitrate;
single.reaction_delay_factor = 16;//ARG_REACTION;
single.averaging_period = 100;//ARG_AVERAGING;
single.buffer = 100;//ARG_SMOOTHER;
plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
plugins[xvid_enc_create.num_plugins].param = &single;
xvid_enc_create.num_plugins++;
}
/* We don't use zones */
xvid_enc_create.zones = NULL;
xvid_enc_create.num_zones = 0;
xvid_enc_create.num_threads = 1;//ARG_THREADS;
xvid_enc_create.num_slices = 1;//ARG_SLICES;
/* Frame rate */
xvid_enc_create.fincr = ARG_DWSCALE;
xvid_enc_create.fbase = ARG_DWRATE;
/* Maximum key frame interval */
if (ARG_MAXKEYINTERVAL > 0) {
xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;
}else {
xvid_enc_create.max_key_interval = (int) x->framerate *10;
}
xvid_enc_create.min_quant[0]=ARG_QUANTS[0];
xvid_enc_create.min_quant[1]=ARG_QUANTS[2];
xvid_enc_create.min_quant[2]=ARG_QUANTS[4];
xvid_enc_create.max_quant[0]=ARG_QUANTS[1];
xvid_enc_create.max_quant[1]=ARG_QUANTS[3];
xvid_enc_create.max_quant[2]=ARG_QUANTS[5];
/* Bframes settings */
xvid_enc_create.max_bframes = 2;//ARG_MAXBFRAMES;
xvid_enc_create.bquant_ratio = 150;//ARG_BQRATIO;
xvid_enc_create.bquant_offset = 100;//ARG_BQOFFSET;
/* Frame drop ratio */
xvid_enc_create.frame_drop_ratio = 0;//ARG_FRAMEDROP;
/* Start frame number */
xvid_enc_create.start_frame_num = 0;//start_num;
/* Global encoder options */
xvid_enc_create.global = 0;
if (1/*ARG_PACKED*/)
xvid_enc_create.global |= XVID_GLOBAL_PACKED;
if (1/*ARG_CLOSED_GOP*/)
xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;
/* I use a small value here, since will not encode whole movies, but short clips */
xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
/* Retrieve the encoder instance from the structure */
x->enc_handle = xvid_enc_create.handle;
x->me_quality = 6;
free(xvid_enc_create.zones);
return (xerr);
}
static int xvid_encode_frame(
xvid_context *x, unsigned char *image, unsigned char *bitstream, int *key, int *stats_type)
{
int ret;
do {
xvid_enc_frame_t xvid_enc_frame;
xvid_enc_stats_t xvid_enc_stats;
/* Version for the frame and the stats */
memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
xvid_enc_frame.version = XVID_VERSION;
memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
xvid_enc_stats.version = XVID_VERSION;
/* Bind output buffer */
xvid_enc_frame.bitstream = bitstream;
xvid_enc_frame.length = -1;
/* Initialize input image fields */
if (image) {
xvid_enc_frame.input.plane[0] = image;
xvid_enc_frame.input.csp = XVID_CSP_I420;
xvid_enc_frame.input.stride[0] = x->xsize;
} else {
xvid_enc_frame.input.csp = XVID_CSP_NULL;
}
/* Set up core's general features */
xvid_enc_frame.vol_flags = 0;
xvid_enc_frame.par = 1;
//int div;
//div = gcd(x->xsize, x->ysize);
//xvid_enc_frame.par = XVID_PAR_EXT;
//xvid_enc_frame.par_width = x->xsize/div;
//xvid_enc_frame.par_height = x->ysize/div;
// /* Set up core's general features */
xvid_enc_frame.vop_flags = vop_presets[x->me_quality];
xvid_enc_frame.vop_flags |= XVID_VOP_HALFPEL;
xvid_enc_frame.vop_flags |= XVID_VOP_HQACPRED;
//if (ARG_TRELLIS)
xvid_enc_frame.vop_flags |= XVID_VOP_TRELLISQUANT;
/* Frame type -- taken from function call parameter */
/* Sometimes we might want to force the last frame to be a P Frame */
xvid_enc_frame.type = XVID_TYPE_AUTO;
/* Force the right quantizer -- It is internally managed by RC plugins */
xvid_enc_frame.quant = 0;
//if (ARG_CHROMAME)
xvid_enc_frame.motion |= XVID_ME_CHROMA_PVOP + XVID_ME_CHROMA_BVOP;
/* Set up motion estimation flags */
xvid_enc_frame.motion |= motion_presets[x->me_quality];
// switch (ARG_VHQMODE) /* this is the same code as for vfw */
// {
// case 1: /* VHQ_MODE_DECISION */
xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
// break;
// case 2: /* VHQ_LIMITED_SEARCH */
// xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
// break;
// case 3: /* VHQ_MEDIUM_SEARCH */
// xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
// xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
// break;
//case 4: /* VHQ_WIDE_SEARCH */
// xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
// xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
// xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
// xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
// xvid_enc_frame.motion |= XVID_ME_EXTSEARCH_RD;
// break;
//default :
// break;
//}
/* Not sure what this does */
// force keyframe spacing in 2-pass 1st pass
/* frame-based stuff */
//apply_zone_modifiers(&xvid_enc_frame, framenum);
/* Encode the frame */
ret = xvid_encore(x->enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,
&xvid_enc_stats);
*key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);
*stats_type = xvid_enc_stats.type;
} while (0);
return (ret);
}
static int xvid_encode_close(xvid_context* x)
{
int xerr;
/* Destroy the encoder instance */
xerr = xvid_encore(x->enc_handle, XVID_ENC_DESTROY, NULL, NULL);
return (xerr);
}
libxvid视频编码代码实现
最新推荐文章于 2024-05-16 08:00:00 发布