[Mplayer-dev-eng] Re: Dynamic Output Quality Patch, Take 2
Timothy B. Terriberry
tterribe at vt.edu
Thu Aug 2 03:54:17 CEST 2001
Okay, those requests are reasonable. The new switch is -autoq as
suggested, and stores it's setting in the variable auto_quality. The
default behavior is to use autoq with the maximum supported value. -pp
will override -autoq if specified.
This is done by giving divx_quality a negative initial value, and only
using auto_quality if it still has a negative value after the
configuration information has been parsed.
I also made sure that DS_SetAttr_DivX() is always called when the codec
is initialized.
-------------- next part --------------
--- ../MPlayer-20010731/mplayer.c Sun Jul 29 22:00:54 2001
+++ mplayer.c Wed Aug 1 20:37:50 2001
@@ -225,7 +225,9 @@
// options:
int osd_level=2;
-int divx_quality=0;
+int divx_quality=-1;
+int auto_quality=-1;
+int output_quality;
char *seek_to_sec=NULL;
int seek_to_byte=0;
int has_audio=1;
@@ -385,6 +387,8 @@
extern void skip_audio_frame(sh_audio_t *sh_audio);
// dec_video.c:
+extern int get_video_quality_max(sh_video_t *sh_video);
+extern void set_video_quality(sh_video_t *sh_video,int quality);
extern int init_video(sh_video_t *sh_video);
#ifdef USE_LIBVO2
extern int decode_video(vo2_handle_t *video_out,sh_video_t *sh_video,unsigned char *start,int in_size,int drop_frame);
@@ -876,6 +880,13 @@
GUI_MSG( mplUnknowError )
exit(1);
}
+/*Set the initial video quality on codecs that support it.*/
+if(divx_quality<0){
+ output_quality=get_video_quality_max(sh_video);
+ if(auto_quality<0||auto_quality>output_quality)auto_quality=output_quality;
+ else output_quality=auto_quality;
+ set_video_quality(sh_video,output_quality);}
+
// ================== Init output files for encoding ===============
if(encode_name){
@@ -994,7 +1005,7 @@
//================== MAIN: ==========================
{
-//float frame_correction=0; // average of A-V timestamp differences
+float frame_correction=0; // average of A-V timestamp differences
//int frame_corr_num=0; //
//float v_frame=0; // Video
float time_frame=0; // Timer
@@ -1005,6 +1016,9 @@
char osd_text_buffer[64];
int drop_frame=0;
int drop_frame_cnt=0;
+double cvideo_base_vtime;
+double cvideo_base_vframe;
+double vdecode_time;
#ifdef HAVE_LIRC
#ifdef HAVE_GUI
@@ -1187,6 +1201,8 @@
#endif
/*========================== PLAY VIDEO ============================*/
+cvideo_base_vframe=sh_video->timer;
+cvideo_base_vtime=video_time_usage;
if(1)
while(1){
@@ -1244,7 +1260,9 @@
fclose(f);
}
+ vdecode_time=video_time_usage;
blit_frame=decode_video(video_out,sh_video,videobuffer,videobuf_len,drop_frame);
+ vdecode_time=video_time_usage-vdecode_time;
// get mpeg fps:
newfps=frameratecode2framerate[picture->frame_rate_code]*0.0001f;
@@ -1264,7 +1282,9 @@
int in_size=ds_get_packet(d_video,&start);
if(in_size<0){ eof=5;break;}
if(in_size>max_framesize) max_framesize=in_size;
+ vdecode_time=video_time_usage;
blit_frame=decode_video(video_out,sh_video,start,in_size,drop_frame);
+ vdecode_time=video_time_usage-vdecode_time;
}
//------------------------ frame decoded. --------------------
@@ -1286,7 +1306,7 @@
}
sh_video->timer+=frame_time;
time_frame+=frame_time; // for nosound
-
+
if(file_format==DEMUXER_TYPE_MPEG_PS) d_video->pts+=frame_time;
if(verbose>1) printf("*** ftime=%5.3f ***\n",frame_time);
@@ -1365,6 +1385,7 @@
#if 1
/*================ A-V TIMESTAMP CORRECTION: =========================*/
+ frame_correction=0;
if(sh_audio){
float a_pts=0;
float v_pts=0;
@@ -1401,7 +1422,7 @@
if(verbose>1)printf("### A:%8.3f (%8.3f) V:%8.3f A-V:%7.4f \n",a_pts,a_pts-audio_delay-delay,v_pts,(a_pts-delay-audio_delay)-v_pts);
if(delay_corrected){
- float x=(a_pts-delay-audio_delay)-v_pts;
+ float x=frame_correction=(a_pts-delay-audio_delay)-v_pts;
// printf("A:%6.1f V:%6.1f A-V:%7.3f",a_pts-audio_delay-delay,v_pts,x);
printf("A:%6.1f (%6.1f) V:%6.1f A-V:%7.3f",a_pts,a_pts-audio_delay-delay,v_pts,x);
x*=0.1f;
@@ -1436,6 +1457,26 @@
}
#endif
+
+ /*Output quality adjustments:*/
+ if(divx_quality<0){
+ /*If we took a long time decoding this frame, downgrade the quality.*/
+ if(output_quality>0&&
+ (video_time_usage-cvideo_base_vtime)*sh_video->timer>=
+ (0.95*sh_video->timer-(vout_time_usage+audio_time_usage))*
+ (sh_video->timer-cvideo_base_vframe-frame_correction)){
+ output_quality>>=1;
+ /*printf("Downgrading quality to %i.\n",output_quality);*/
+ set_video_quality(sh_video,output_quality);}
+ /*If we had plenty of extra time, upgrade the quality.*/
+ if(output_quality<auto_quality&&
+ vdecode_time<0.5*frame_time&&
+ (video_time_usage-cvideo_base_vtime)*sh_video->timer<
+ (0.67*sh_video->timer-(vout_time_usage+audio_time_usage))*
+ (sh_video->timer-cvideo_base_vframe-frame_correction)){
+ output_quality++;
+ /*printf("Upgrading quality to %i.\n",output_quality);*/
+ set_video_quality(sh_video,output_quality);} }
#ifdef USE_OSD
if(osd_visible){
-------------- next part --------------
--- ../MPlayer-20010731/dec_video.c Sun Jul 29 22:00:54 2001
+++ dec_video.c Wed Aug 1 19:57:32 2001
@@ -84,6 +84,40 @@
}
#endif
+int get_video_quality_max(sh_video_t *sh_video){
+ switch(sh_video->codec->driver){
+#ifdef ARCH_X86
+#ifdef USE_DIRECTSHOW
+ case VFM_DSHOW:return 4;
+#endif
+#endif
+#ifdef MPEG12_POSTPROC
+ case VFM_MPEG :
+#endif
+ case VFM_DIVX4:
+ case VFM_ODIVX:return 6;
+ default :return 0;} }
+
+void set_video_quality(sh_video_t *sh_video,int quality){
+ switch(sh_video->codec->driver){
+#ifdef ARCH_X86
+#ifdef USE_DIRECTSHOW
+ case VFM_DSHOW:{
+ if(quality<0||quality>4)quality=4;
+ DS_SetValue_DivX("Quality",quality);}break;
+#endif
+#endif
+#ifdef MPEG12_POSTPROC
+ case VFM_MPEG :{
+ if(quality<0||quality>6)quality=6;
+ picture->pp_options=(1<<quality)-1;}break;
+#endif
+ case VFM_DIVX4:
+ case VFM_ODIVX:{
+ DEC_SET dec_set;
+ if(quality<0||quality>6)quality=6;
+ dec_set.postproc_level=(1<<quality)-1;
+ decore(0x123,DEC_OPT_SETPP,&dec_set,NULL);}break;} }
int init_video(sh_video_t *sh_video){
unsigned int out_fmt=sh_video->codec->outfmt[sh_video->outfmtidx];
@@ -148,7 +182,7 @@
DS_VideoDecoder_Start();
- DS_SetAttr_DivX("Quality",divx_quality);
+ DS_SetAttr_DivX("Quality",divx_quality>=0?divx_quality:0);
// printf("DivX setting result = %d\n", DS_SetAttr_DivX("Quality",divx_quality) );
// printf("DivX setting result = %d\n", DS_SetValue_DivX("Brightness",60) );
@@ -166,7 +200,6 @@
case VFM_ODIVX: { // OpenDivX
if(verbose) printf("OpenDivX video codec\n");
{ DEC_PARAM dec_param;
- DEC_SET dec_set;
memset(&dec_param,0,sizeof(dec_param));
#ifdef NEW_DECORE
dec_param.output_format=DEC_USER;
@@ -176,8 +209,11 @@
dec_param.x_dim = sh_video->bih->biWidth;
dec_param.y_dim = sh_video->bih->biHeight;
decore(0x123, DEC_OPT_INIT, &dec_param, NULL);
- dec_set.postproc_level = divx_quality;
- decore(0x123, DEC_OPT_SETPP, &dec_set, NULL);
+ if(divx_quality>=0){
+ DEC_SET dec_set;
+ dec_set.postproc_level = divx_quality;
+ decore(0x123, DEC_OPT_SETPP, &dec_set, NULL);
+ }
}
if(verbose) printf("INFO: OpenDivX video codec init OK!\n");
break;
@@ -189,7 +225,6 @@
#else
if(verbose) printf("DivX4Linux video codec\n");
{ DEC_PARAM dec_param;
- DEC_SET dec_set;
int bits=16;
memset(&dec_param,0,sizeof(dec_param));
switch(out_fmt){
@@ -208,8 +243,11 @@
dec_param.x_dim = sh_video->bih->biWidth;
dec_param.y_dim = sh_video->bih->biHeight;
decore(0x123, DEC_OPT_INIT, &dec_param, NULL);
- dec_set.postproc_level = divx_quality;
- decore(0x123, DEC_OPT_SETPP, &dec_set, NULL);
+ if(divx_quality>=0){
+ DEC_SET dec_set;
+ dec_set.postproc_level = divx_quality;
+ decore(0x123, DEC_OPT_SETPP, &dec_set, NULL);
+ }
sh_video->our_out_buffer = shmem_alloc(((bits*dec_param.x_dim+7)/8)*dec_param.y_dim);
// sh_video->our_out_buffer = shmem_alloc(dec_param.x_dim*dec_param.y_dim*5);
}
@@ -248,9 +286,9 @@
case VFM_MPEG: {
// init libmpeg2:
#ifdef MPEG12_POSTPROC
- picture->pp_options=divx_quality;
+ picture->pp_options=divx_quality>=0?divx_quality:0;
#else
- if(divx_quality){
+ if(divx_quality>0){
printf("WARNING! You requested image postprocessing for an MPEG 1/2 video,\n");
printf(" but compiled MPlayer without MPEG 1/2 postprocessing support!\n");
printf(" #define MPEG12_POSTPROC in config.h, and recompile libmpeg2!\n");
-------------- next part --------------
--- ../../MPlayer-20010731/DOCS/mplayer.1 Wed Jul 25 13:28:16 2001
+++ mplayer.1 Wed Aug 1 20:46:16 2001
@@ -25,6 +25,7 @@
.RB [ \-y\ y ]
.RB [ \-xy\ factor ]
.RB [ \-pp\ quality ]
+.RB [ \-autoq\ quality ]
.RB [ \-include\ configfile ]
.RB [ \-lircconf\ configfile ]
.RB [ \-ffactor\ number ]
@@ -119,7 +120,7 @@
use software scaling, where available (use with -nofs)
.TP
.B \-x\ x
-scale image to x width [if driver suppports!]
+scale image to x width [if driver supports!]
.TP
.B \-y\ y
scale image to y height
@@ -141,6 +142,23 @@
.I NOTE
You can use this with OpenDivX encoding too! See ALPHA/BETA CODE section.
+.TP
+.B \-autoq\ quality
+automatically apply postprocess filter on decoded image.
+This is enabled by default, and can be disabled by specifying the -pp option.
+.I quality
+is the maximum quality to use.
+The actual quality is lowered if CPU usage becomes too high, and raised again
+when CPU usage drops.
+The valid ranges for
+.I quality
+are:
+
+ MPEG 1/2 0 to 6
+ OpenDivX 0 to 6
+ DivX 0 to 4
+
+The default is to use the maximum value supported by the current codec.
.TP
.B \-ffactor\ number
resample alphamap of the font. Can be:
-------------- next part --------------
--- ../MPlayer-20010731/cfg-mplayer.h Sun Jul 29 22:00:54 2001
+++ cfg-mplayer.h Wed Aug 1 19:49:44 2001
@@ -156,6 +156,7 @@
{"divxq", "Option -divxq has been renamed to -pp (postprocessing), use -pp !\n",
CONF_TYPE_PRINT, 0, 0, 0},
{"pp", &divx_quality, CONF_TYPE_INT, CONF_RANGE, 0, 63},
+ {"autoq", &auto_quality, CONF_TYPE_INT, 0, 0, 0},
{"br", &encode_bitrate, CONF_TYPE_INT, CONF_RANGE, 10000, 10000000},
#ifdef HAVE_PNG
{"z", &z_compression, CONF_TYPE_INT, CONF_RANGE, 0, 9},
More information about the MPlayer-dev-eng
mailing list