Dynamic Output Quality Patch, Take 2
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@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). --- 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"); --- 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){
participants (1)
-
Timothy B. Terriberry