Mercurial > mplayer.hg
changeset 13610:b79ee5bf2c9e
Sync with GomGom's patch-12 version.
updated copyright
bvhq options added (xvid 1.1+ api4.1)
psnr handling moved in separate functions
proper free() on uninit
printf -> mp_msg
capability to flush delayed frames
Changes by me (iive)
support for flushing delayed frames at the end
suppressed cosmetics and new aspect code changes
author | iive |
---|---|
date | Mon, 11 Oct 2004 15:48:18 +0000 |
parents | 529aad3fc0a4 |
children | e0720270e0e1 |
files | libmpcodecs/ve_xvid4.c |
diffstat | 1 files changed, 227 insertions(+), 101 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpcodecs/ve_xvid4.c Mon Oct 11 12:16:00 2004 +0000 +++ b/libmpcodecs/ve_xvid4.c Mon Oct 11 15:48:18 2004 +0000 @@ -1,9 +1,9 @@ /***************************************************************************** * - * - XviD 1.0 export module for mplayer/mencoder - + * - XviD 1.x export module for mplayer/mencoder - * - * Copyright(C) 2003 Marco Belli <elcabesa@inwind.it> - * 2003 Edouard Gomez <ed.gomez@free.fr> + * Copyright(C) 2003 Marco Belli <elcabesa@inwind.it> + * 2003-2004 Edouard Gomez <ed.gomez@free.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 @@ -63,7 +63,7 @@ // Code taken from Libavcodec and ve_lavc.c to handle Aspect Ratio calculation -typedef struct XVIDRational{ +typedef struct xvid_rational_s{ int num; int den; } XVIDRational; @@ -160,6 +160,7 @@ static int xvidenc_chromame = 0; static int xvidenc_chroma_opt = 0; static int xvidenc_vhq = 0; +static int xvidenc_bvhq = 0; static int xvidenc_motion = 6; static int xvidenc_turbo = 0; static int xvidenc_stats = 0; @@ -213,6 +214,7 @@ {"chroma_me", &xvidenc_chromame, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"chroma_opt", &xvidenc_chroma_opt, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"vhq", &xvidenc_vhq, CONF_TYPE_INT, CONF_RANGE, 0, 4, NULL}, + {"bvhq", &xvidenc_bvhq, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL}, {"max_bframes", &xvidenc_max_bframes, CONF_TYPE_INT, CONF_RANGE, 0, 20, NULL}, {"bquant_ratio", &xvidenc_bquant_ratio, CONF_TYPE_INT, CONF_RANGE, 0, 200, NULL}, {"bquant_offset", &xvidenc_bquant_offset, CONF_TYPE_INT, CONF_RANGE, 0, 200, NULL}, @@ -310,12 +312,20 @@ int max_framenum; int pixels; - int d_width, d_height; + + /* DAR/PAR and all that thingies */ + int d_width; + int d_height; + FILE *fvstats; } xvid_mplayer_module_t; static void dispatch_settings(xvid_mplayer_module_t *mod); static int set_create_struct(xvid_mplayer_module_t *mod); static int set_frame_struct(xvid_mplayer_module_t *mod, mp_image_t *mpi); +static void update_stats(xvid_mplayer_module_t *mod, xvid_enc_stats_t *stats); +static void print_stats(xvid_mplayer_module_t *mod); +static void flush_internal_buffers(xvid_mplayer_module_t *mod); +static const char *par_string(int parcode); static const char *errorstring(int err); /***************************************************************************** @@ -338,7 +348,7 @@ mod->mux->bih->biWidth = width; mod->mux->bih->biHeight = height; mod->mux->bih->biSizeImage = - mod->mux->bih->biWidth * mod->mux->bih->biHeight * 3; + mod->mux->bih->biWidth * mod->mux->bih->biHeight * 3 / 2; mod->mux->aspect = (float)d_width/d_height; /* Message the FourCC type */ @@ -347,6 +357,9 @@ width, height, mod->mux->bih->biCompression, (char *)&mod->mux->bih->biCompression); + /* Total number of pixels per frame required for PSNR */ + mod->pixels = mod->mux->bih->biWidth*mod->mux->bih->biHeight; + /*-------------------------------------------------------------------- * Dispatch all module settings to XviD structures *------------------------------------------------------------------*/ @@ -394,39 +407,27 @@ /* Destroy xvid instance */ xvid_encore(mod->instance, XVID_ENC_DESTROY, NULL, NULL); - /* Display stats */ - if(mod->frames) { - mod->sse_y /= mod->frames; - mod->sse_u /= mod->frames; - mod->sse_v /= mod->frames; + /* Display stats (if any) */ + print_stats(mod); -#define SSE2PSNR(sse, nbpixels) \ -((!(sse)) ? 99.99f : 48.131f - 10*(double)log10((double)(sse)/(double)((nbpixels)))) - mp_msg(MSGT_MENCODER, MSGL_INFO, - "The value 99.99dB is a special value and represents " - "the upper range limit\n"); - mp_msg(MSGT_MENCODER, MSGL_INFO, - "xvid: Min PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, in frame %d\n", - SSE2PSNR(mod->max_sse_y, mod->pixels), - SSE2PSNR(mod->max_sse_u, mod->pixels/4), - SSE2PSNR(mod->max_sse_v, mod->pixels/4), - mod->max_framenum); - mp_msg(MSGT_MENCODER, MSGL_INFO, - "xvid: Average PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, for %d frames\n", - SSE2PSNR(mod->sse_y, mod->pixels), - SSE2PSNR(mod->sse_u, mod->pixels/4), - SSE2PSNR(mod->sse_v, mod->pixels/4), - mod->frames); - mp_msg(MSGT_MENCODER, MSGL_INFO, - "xvid: Max PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, in frame %d\n", - SSE2PSNR(mod->min_sse_y, mod->pixels), - SSE2PSNR(mod->min_sse_u, mod->pixels/4), - SSE2PSNR(mod->min_sse_v, mod->pixels/4), - mod->min_framenum); + /* Close PSNR file if ever opened */ + if (mod->fvstats) { + fclose(mod->fvstats); + mod->fvstats = NULL; } - /* ToDo: free matrices, and some string settings (quant method, matrix - * filenames...) */ + /* Free allocated memory */ + if(mod->frame.quant_intra_matrix) + free(mod->frame.quant_intra_matrix); + + if(mod->frame.quant_inter_matrix) + free(mod->frame.quant_inter_matrix); + + if(mod->mux->bih) + free(mod->mux->bih); + + free(vf->priv); + vf->priv=NULL; return; } @@ -438,6 +439,14 @@ static int control(struct vf_instance_s* vf, int request, void* data) { +xvid_mplayer_module_t *mod = (xvid_mplayer_module_t *)vf->priv; + + switch(request){ + case VFCTRL_FLUSH_FRAMES: + if(mod)/*paranoid*/ + flush_internal_buffers(mod); + break; + } return(CONTROL_UNKNOWN); } @@ -500,56 +509,9 @@ /* If size is == 0, we're done with that frame */ if(size == 0) return(FINE); - /* Did xvidcore returned stats about an encoded frame ? (asynchronous) */ - if(xvidenc_stats && stats.type > 0) { - mod->sse_y += stats.sse_y; - mod->sse_u += stats.sse_u; - mod->sse_v += stats.sse_v; - - if(mod->min_sse_y > stats.sse_y) { - mod->min_sse_y = stats.sse_y; - mod->min_sse_u = stats.sse_u; - mod->min_sse_v = stats.sse_v; - mod->min_framenum = mod->frames; - } - - if(mod->max_sse_y < stats.sse_y) { - mod->max_sse_y = stats.sse_y; - mod->max_sse_u = stats.sse_u; - mod->max_sse_v = stats.sse_v; - mod->max_framenum = mod->frames; - } - if (xvidenc_psnr) { - static FILE *fvstats = NULL; - char filename[20]; - - if (!fvstats) { - time_t today2; - struct tm *today; - today2 = time (NULL); - today = localtime (&today2); - sprintf (filename, "psnr_%02d%02d%02d.log", today->tm_hour, today->tm_min, today->tm_sec); - fvstats = fopen (filename,"w"); - if (!fvstats) { - perror ("fopen"); - xvidenc_psnr = 0; // disable block - } - } - fprintf (fvstats, "%6d, %2d, %6d, %2.2f, %2.2f, %2.2f, %2.2f %c\n", - mod->frames, - stats.quant, - stats.length, - SSE2PSNR (stats.sse_y, mod->pixels), - SSE2PSNR (stats.sse_u, mod->pixels / 4), - SSE2PSNR (stats.sse_v, mod->pixels / 4), - SSE2PSNR (stats.sse_y + stats.sse_u + stats.sse_v,(double)mod->pixels * 1.5), - stats.type==1?'I':stats.type==2?'P':stats.type==3?'B':stats.type?'S':'?' - ); - } - mod->frames++; - - } -#undef SSE2PSNR + /* xvidcore returns stats about encoded frame in an asynchronous way + * accumulate these stats */ + update_stats(mod, &stats); /* xvidcore outputed bitstream -- mux it */ muxer_write_chunk(mod->mux, @@ -608,7 +570,7 @@ mod->mux->bih->biWidth = 0; mod->mux->bih->biHeight = 0; mod->mux->bih->biPlanes = 1; - mod->mux->bih->biBitCount = 24; + mod->mux->bih->biBitCount = 12; mod->mux->bih->biCompression = mmioFOURCC('X','V','I','D'); /* Retrieve information about the host XviD library */ @@ -616,7 +578,7 @@ xvid_gbl_info.version = XVID_VERSION; if (xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL) < 0) { - mp_msg(MSGT_MENCODER,MSGL_INFO, "xvid: could not get information about the library\n"); + mp_msg(MSGT_MENCODER,MSGL_WARN, "xvid: could not get information about the library\n"); } else { mp_msg(MSGT_MENCODER,MSGL_INFO, "xvid: using library version %d.%d.%d (build %s)\n", XVID_VERSION_MAJOR(xvid_gbl_info.actual_version), @@ -755,7 +717,7 @@ if(xvidenc_intra_matrix_file != NULL) { frame->quant_intra_matrix = (unsigned char*)read_matrix(xvidenc_intra_matrix_file); if(frame->quant_intra_matrix != NULL) { - fprintf(stderr, "xvid: Loaded Intra matrix (switching to mpeg quantization type)\n"); + mp_msg(MSGT_MENCODER, MSGL_INFO, "xvid: Loaded Intra matrix (switching to mpeg quantization type)\n"); if(xvidenc_quant_method) free(xvidenc_quant_method); xvidenc_quant_method = strdup("mpeg"); } @@ -763,7 +725,7 @@ if(xvidenc_inter_matrix_file != NULL) { frame->quant_inter_matrix = read_matrix(xvidenc_inter_matrix_file); if(frame->quant_inter_matrix) { - fprintf(stderr, "\nxvid: Loaded Inter matrix (switching to mpeg quantization type)\n"); + mp_msg(MSGT_MENCODER, MSGL_INFO, "\nxvid: Loaded Inter matrix (switching to mpeg quantization type)\n"); if(xvidenc_quant_method) free(xvidenc_quant_method); xvidenc_quant_method = strdup("mpeg"); } @@ -814,6 +776,11 @@ if(xvidenc_vhq >= 4) { frame->motion |= XVID_ME_EXTSEARCH_RD; } + if(xvidenc_bvhq >= 1) { +#if XVID_API >= XVID_MAKE_API(4,1) + frame->vop_flags |= XVID_VOP_RD_BVOP; +#endif + } if(xvidenc_turbo) { frame->motion |= XVID_ME_FASTREFINE16; frame->motion |= XVID_ME_FASTREFINE8; @@ -857,9 +824,6 @@ frame->par_height= ar.den; } - mp_msg(MSGT_MENCODER, MSGL_INFO, "XVID4_DAR: %d/%d code %d, Display frame: (%d, %d), original frame: (%d, %d)\n", - ar.num, ar.den, frame->par, - mod->d_width, mod->d_height, mod->mux->bih->biWidth, mod->mux->bih->biHeight); } else if(xvidenc_par != NULL) { if(strcasecmp(xvidenc_par, "pal43") == 0) frame->par = XVID_PAR_43_PAL; @@ -884,6 +848,11 @@ frame->par_height = 1; } } + + /* Display par information */ + mp_msg(MSGT_MENCODER, MSGL_INFO, "xvid: par=%d/%d (%s), displayed=%dx%d, sampled=%dx%d\n", + ar.num, ar.den, par_string(frame->par), + mod->d_width, mod->d_height, mod->mux->bih->biWidth, mod->mux->bih->biHeight); return; } @@ -900,9 +869,6 @@ create->width = mod->mux->bih->biWidth; create->height = mod->mux->bih->biHeight; - /* Pixels are needed for PSNR calculations */ - mod->pixels = create->width * create->height; - /* FPS */ create->fincr = mod->mux->h.dwScale; create->fbase = mod->mux->h.dwRate; @@ -930,7 +896,7 @@ } if(xvidenc_bitrate != 0 && xvidenc_pass == 1) { - mp_msg(MSGT_MENCODER, MSGL_ERR, + mp_msg(MSGT_MENCODER, MSGL_WARN, "xvid: bitrate setting is ignored during first pass\n"); } @@ -1107,6 +1073,135 @@ return(FINE); } +static void +flush_internal_buffers(xvid_mplayer_module_t *mod) +{ + int size; + xvid_enc_frame_t *frame = &mod->frame; + + if (mod->instance == NULL) + return;/*encoder not inited*/ + + /* Init a fake frame to force flushing */ + frame->version = XVID_VERSION; + frame->bitstream = mod->mux->buffer; + frame->length = -1; + frame->input.csp = XVID_CSP_NULL; + frame->input.plane[0] = NULL; + frame->input.plane[1] = NULL; + frame->input.plane[2] = NULL; + frame->input.stride[0] = 0; + frame->input.stride[1] = 0; + frame->input.stride[2] = 0; + frame->quant = 0; + + /* Flush encoder buffers caused by bframes usage */ + do { + xvid_enc_stats_t stats; + memset(&stats, 0, sizeof(xvid_enc_stats_t)); + stats.version = XVID_VERSION; + + /* Encode internal buffer */ + size = xvid_encore(mod->instance, XVID_ENC_ENCODE, &mod->frame, &stats); + + if (size>0) { + /* Update stats */ + update_stats(mod, &stats); + + /* xvidcore outputed bitstream -- mux it */ + muxer_write_chunk(mod->mux, size, + (mod->frame.out_flags & XVID_KEYFRAME)?0x10:0); + } + } while (size>0); +} + +#define SSE2PSNR(sse, nbpixels) \ + ((!(sse)) ? 99.99f : 48.131f - 10*(double)log10((double)(sse)/(double)((nbpixels)))) +static void +update_stats(xvid_mplayer_module_t *mod, xvid_enc_stats_t *stats) +{ + if(xvidenc_stats && stats->type > 0) { + mod->sse_y += stats->sse_y; + mod->sse_u += stats->sse_u; + mod->sse_v += stats->sse_v; + + if(mod->min_sse_y > stats->sse_y) { + mod->min_sse_y = stats->sse_y; + mod->min_sse_u = stats->sse_u; + mod->min_sse_v = stats->sse_v; + mod->min_framenum = mod->frames; + } + + if(mod->max_sse_y < stats->sse_y) { + mod->max_sse_y = stats->sse_y; + mod->max_sse_u = stats->sse_u; + mod->max_sse_v = stats->sse_v; + mod->max_framenum = mod->frames; + } + + if (xvidenc_psnr) { + if (!mod->fvstats) { + char filename[20]; + time_t today2; + struct tm *today; + today2 = time (NULL); + today = localtime (&today2); + sprintf (filename, "psnr_%02d%02d%02d.log", today->tm_hour, today->tm_min, today->tm_sec); + mod->fvstats = fopen (filename,"w"); + if (!mod->fvstats) { + perror ("fopen"); + /* Disable PSNR file output so we don't get here again */ + xvidenc_psnr = 0; + } + } + fprintf (mod->fvstats, "%6d, %2d, %6d, %2.2f, %2.2f, %2.2f, %2.2f %c\n", + mod->frames, + stats->quant, + stats->length, + SSE2PSNR (stats->sse_y, mod->pixels), + SSE2PSNR (stats->sse_u, mod->pixels / 4), + SSE2PSNR (stats->sse_v, mod->pixels / 4), + SSE2PSNR (stats->sse_y + stats->sse_u + stats->sse_v,(double)mod->pixels * 1.5), + stats->type==1?'I':stats->type==2?'P':stats->type==3?'B':stats->type?'S':'?' + ); + } + mod->frames++; + } +} + +static void +print_stats(xvid_mplayer_module_t *mod) +{ + if (mod->frames) { + mod->sse_y /= mod->frames; + mod->sse_u /= mod->frames; + mod->sse_v /= mod->frames; + + mp_msg(MSGT_MENCODER, MSGL_INFO, + "The value 99.99dB is a special value and represents " + "the upper range limit\n"); + mp_msg(MSGT_MENCODER, MSGL_INFO, + "xvid: Min PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, in frame %d\n", + SSE2PSNR(mod->max_sse_y, mod->pixels), + SSE2PSNR(mod->max_sse_u, mod->pixels/4), + SSE2PSNR(mod->max_sse_v, mod->pixels/4), + mod->max_framenum); + mp_msg(MSGT_MENCODER, MSGL_INFO, + "xvid: Average PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, for %d frames\n", + SSE2PSNR(mod->sse_y, mod->pixels), + SSE2PSNR(mod->sse_u, mod->pixels/4), + SSE2PSNR(mod->sse_v, mod->pixels/4), + mod->frames); + mp_msg(MSGT_MENCODER, MSGL_INFO, + "xvid: Max PSNR y : %.2f dB, u : %.2f dB, v : %.2f dB, in frame %d\n", + SSE2PSNR(mod->min_sse_y, mod->pixels), + SSE2PSNR(mod->min_sse_u, mod->pixels/4), + SSE2PSNR(mod->min_sse_v, mod->pixels/4), + mod->min_framenum); + } +} +#undef SSE2PSNR + static void *read_matrix(unsigned char *filename) { int i; @@ -1119,7 +1214,7 @@ /* Open the matrix file */ if((input = fopen(filename, "rb")) == NULL) { - fprintf(stderr, + mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: Error opening the matrix file %s\n", filename); free(matrix); @@ -1133,7 +1228,7 @@ /* If fscanf fails then get out of the loop */ if(fscanf(input, "%d", &value) != 1) { - fprintf(stderr, + mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: Error reading the matrix file %s\n", filename); free(matrix); @@ -1157,9 +1252,40 @@ } + +static const char * +par_string(int parcode) +{ + const char *par_string; + switch (parcode) { + case XVID_PAR_11_VGA: + par_string = "vga11"; + break; + case XVID_PAR_43_PAL: + par_string = "pal43"; + break; + case XVID_PAR_43_NTSC: + par_string = "ntsc43"; + break; + case XVID_PAR_169_PAL: + par_string = "pal169"; + break; + case XVID_PAR_169_NTSC: + par_string = "ntsc69"; + break; + case XVID_PAR_EXT: + par_string = "ext"; + break; + default: + par_string = "unknown"; + break; + } + return (par_string); +} + static const char *errorstring(int err) { - char *error; + const char *error; switch(err) { case XVID_ERR_FAIL: error = "General fault"; @@ -1180,7 +1306,7 @@ error = "Unknown"; } - return((const char *)error); + return(error); } /*****************************************************************************