[Mplayer-dev-eng] Dynamic Output Quality Patch, Take 2

Timothy B. Terriberry tterribe at vt.edu
Tue Jul 31 09:06:30 CEST 2001


Okay, I recently upgraded to the 7/31 CVS snapshot (the 0.18pre5 deb
package was broken), and noticed my previous patch had not been
included. I checked the mailing list history to see why, and saw your
comments on diff format and timing changes. I am not currently
subscribed to this list, so please cc replies to this attempt to my
e-mail address (mailto:tterribe at vt.edu) if you want me to see them.

The patch introduces two new functions into dec_video.c:
get_video_quality_max(): returns the maximum allowed video quality for
the current codec (0 is the minimum)
set_video_quality(): sets the video quality

The new variable output_quality contains the current video quality. The
variable divx_quality represents the maximum allowed quality. If the
user specifies a negative amount, or too large an amount, the maximum
allowed quality for the current codec is used. The default was changed
to -1 (to always use the maximum allowed).

The scale from the OpenDivX postprocessing filters was changed from 0-63
to 0-6. Yes, I know, you can't select exactly which filters are used,
but it probably makes more sense from a user's perspective. Easy enough
to undo if you don't agree.

A few other variables were introduced to keep track of how much CPU time
is being spent on decoding each frame, and adjusting the quality
accordingly (cvideo_base_vtime, cvideo_base_vframe, vdecode_time,
frame_correction).
-------------- next part --------------
--- dec_video.c	Sun Jul 29 22:00:54 2001
+++ dec_video.c~	Tue Jul 31 02:54:23 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);
 //   printf("DivX setting result = %d\n", DS_SetAttr_DivX("Quality",divx_quality) );
 //   printf("DivX setting result = %d\n", DS_SetValue_DivX("Brightness",60) );
    
@@ -176,8 +210,8 @@
 	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);
+//	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;
@@ -208,8 +242,8 @@
 	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);
+//	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);
    }
@@ -247,10 +281,8 @@
 
  case VFM_MPEG: {
    // init libmpeg2:
-#ifdef MPEG12_POSTPROC
-   picture->pp_options=divx_quality;
-#else
-   if(divx_quality){
+#ifndef MPEG12_POSTPROC
+   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.c	Sun Jul 29 22:00:54 2001
+++ mplayer.c~	Tue Jul 31 02:54:14 2001
@@ -225,7 +225,8 @@
 
 // options:
 int osd_level=2;
-int divx_quality=0;
+int divx_quality=-1;
+int output_quality;
 char *seek_to_sec=NULL;
 int seek_to_byte=0;
 int has_audio=1;
@@ -385,6 +386,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 +879,12 @@
      GUI_MSG( mplUnknowError )
      exit(1);
 }
+/*Set the initial video quality on codecs that support it.*/
+output_quality=get_video_quality_max(sh_video);
+if(divx_quality<0||divx_quality>output_quality)divx_quality=output_quality;
+else output_quality=divx_quality;
+set_video_quality(sh_video,output_quality);
+
 
 // ================== Init output files for encoding ===============
    if(encode_name){
@@ -994,7 +1003,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 +1014,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 +1199,8 @@
 #endif
 
 /*========================== PLAY VIDEO ============================*/
+cvideo_base_vframe=sh_video->timer;
+cvideo_base_vtime=video_time_usage;
 
 if(1)
   while(1){
@@ -1244,7 +1258,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;
 
     // get mpeg fps:
     newfps=frameratecode2framerate[picture->frame_rate_code]*0.0001f;
@@ -1286,7 +1302,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 +1381,7 @@
 
 #if 1
 /*================ A-V TIMESTAMP CORRECTION: =========================*/
+  frame_correction=0;
   if(sh_audio){
     float a_pts=0;
     float v_pts=0;
@@ -1401,7 +1418,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 +1453,25 @@
 
   }
 #endif
+
+    /*Output quality adjustments:*/
+    /*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<divx_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){


More information about the MPlayer-dev-eng mailing list