[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