00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <libdirac_encoder/quality_monitor.h>
00039 #include <libdirac_common/wavelet_utils.h>
00040 using namespace dirac;
00041
00042 using std::log10;
00043
00044 QualityMonitor::QualityMonitor(EncoderParams& encp,
00045 const SeqParams& sparams)
00046 :
00047 m_encparams(encp),
00048 m_cformat( sparams.CFormat() ),
00049 m_true_xl( sparams.Xl() ),
00050 m_true_yl( sparams.Yl() ),
00051 m_target_quality(3),
00052 m_last_quality(3),
00053 m_slope(3),
00054 m_offset(3),
00055 m_last_lambda(3)
00056 {
00057 ResetAll();
00058 }
00059
00060 void QualityMonitor::ResetAll()
00061 {
00062
00063 m_target_quality[I_frame] = 0.28 * m_encparams.Qf()* m_encparams.Qf() + 20.0 ;
00064 m_target_quality[L1_frame] = m_target_quality[I_frame] - 1.0;
00065 m_target_quality[L2_frame] = m_target_quality[I_frame] - 2.0;
00066
00067
00068 m_last_quality = m_target_quality;
00069
00070
00071 m_slope[I_frame] = -4.0;
00072 m_slope[L1_frame] = -4.0;
00073 m_slope[L2_frame] = -4.0;
00074 m_offset[I_frame] = 38.5,
00075 m_offset[L1_frame] = 43.3;
00076 m_offset[L2_frame] = 43.3;
00077
00078 for (size_t fsort=0; fsort<3; ++fsort)
00079 {
00080 m_last_lambda[fsort] = std::pow( 10.0, (m_target_quality[fsort] - m_offset[fsort])/m_slope[fsort] );
00081 }
00082
00083
00084
00085
00086
00087 m_me_ratio = 0.1;
00088
00089
00090 for (size_t fsort=0; fsort<3; ++fsort)
00091 {
00092 m_encparams.SetLambda( FrameSort(fsort), m_last_lambda[fsort] );
00093 }
00094
00095 m_encparams.SetL1MELambda( std::sqrt(m_encparams.L1Lambda())*m_me_ratio );
00096 m_encparams.SetL2MELambda( std::sqrt(m_encparams.L2Lambda())*m_me_ratio );
00097
00098 }
00099
00100 bool QualityMonitor::UpdateModel(const Frame& ld_frame, const Frame& orig_frame , const int count)
00101 {
00102
00103 bool recode = false;
00104
00105 const FrameSort& fsort = ld_frame.GetFparams().FSort();
00106 double target_quality;
00107
00108
00109 double last_lambda;
00110 double last_quality;
00111
00112
00113 double current_lambda;
00114 double current_quality;
00115
00116
00117
00118 current_lambda = m_encparams.Lambda(fsort);
00119 last_lambda = m_last_lambda[fsort];
00120 last_quality = m_last_quality[fsort];
00121 target_quality = m_target_quality[fsort];
00122
00123
00124 current_quality = QualityVal( ld_frame.Ydata() , orig_frame.Ydata() , 0.0 , fsort );
00125
00126
00127 m_last_lambda[fsort] = m_encparams.Lambda(fsort);
00128 m_last_quality[fsort] = current_quality;
00129
00130
00131
00132
00133 if ( std::abs(current_quality - last_quality)> 0.2 &&
00134 std::abs(log10(current_lambda) - log10(last_lambda)) > 0.1 )
00135 {
00136
00137 double slope, offset;
00138
00139
00140 slope = (current_quality - last_quality)/( log10(current_lambda) - log10(last_lambda) );
00141
00142
00143 slope = std::min( std::max( -10.0 , slope ), -0.1);
00144
00145
00146 offset = current_quality - ( log10(current_lambda) * slope );
00147
00148 if ( count != 1 )
00149 {
00150
00151 m_slope[fsort] = (3.0*m_slope[fsort] + slope)/4.0;
00152 m_offset[fsort] = (3.0*m_offset[fsort] + offset)/4.0;
00153 }
00154 else
00155 {
00156
00157 m_slope[fsort] = (m_slope[fsort] + slope)/2.0;
00158 m_offset[fsort] = (m_offset[fsort] + offset)/2.0;
00159 }
00160 m_slope[fsort] = std::min( std::max( -10.0 , m_slope[fsort] ), -1.5);
00161 }
00162
00163
00164 if ( std::abs(current_quality - target_quality)> 0.2 )
00165 {
00166
00167 float quality_diff = m_target_quality[fsort] - current_quality;
00168
00169 CalcNewLambdas(fsort , std::min( m_slope[fsort] , -1.0 ), quality_diff );
00170 }
00171
00172
00173 if ( std::abs( current_quality - target_quality )>1.5 )
00174 recode = true;
00175
00176 return recode;
00177 }
00178
00179 void QualityMonitor::CalcNewLambdas(const FrameSort fsort, const double slope, const double quality_diff )
00180 {
00181 const double clipped_quality_ratio = std::min( 2.0 , std::max( quality_diff/slope , -2.0 ) );
00182
00183 if ( m_encparams.Lambda(fsort) > 100001.0 && clipped_quality_ratio > 0.0 )
00184 m_encparams.SetLambda(fsort, 100000.0);
00185 else
00186 m_encparams.SetLambda(fsort, m_encparams.Lambda(fsort) *
00187 std::pow( (double)10.0, clipped_quality_ratio ) );
00188
00189 if (fsort == L1_frame)
00190 m_encparams.SetL1MELambda( std::sqrt(m_encparams.L1Lambda()) * m_me_ratio );
00191 else if (fsort == L2_frame)
00192 m_encparams.SetL2MELambda( std::sqrt(m_encparams.L2Lambda()) * m_me_ratio );
00193
00194 }
00195
00196 double QualityMonitor::QualityVal(const PicArray& coded_data, const PicArray& orig_data , double cpd , const FrameSort fsort)
00197 {
00198
00199
00200 int xregions( 4 );
00201 int yregions( 3 );
00202
00203 if ( fsort == I_frame )
00204 {
00205 xregions = 1;
00206 yregions = 1;
00207 }
00208
00209 TwoDArray<long double> diff_array( yregions , xregions);
00210 long double diff;
00211
00212 OneDArray<int> xstart( diff_array.LengthX() );
00213 OneDArray<int> xend( diff_array.LengthX() );
00214 OneDArray<int> ystart( diff_array.LengthY() );
00215 OneDArray<int> yend( diff_array.LengthX() );
00216
00217 for ( int i=0 ; i<xstart.Length() ; ++i)
00218 {
00219 xstart[i] =( i * m_true_xl )/xstart.Length();
00220 xend[i] = ( (i+1) * m_true_xl )/xstart.Length();
00221 }
00222
00223 for ( int i=0 ; i<ystart.Length() ; ++i)
00224 {
00225 ystart[i] =( i * m_true_yl )/ystart.Length();
00226 yend[i] = ( (i+1) * m_true_yl )/ystart.Length();
00227 }
00228
00229 for ( int q=0 ; q<diff_array.LengthY() ; ++q )
00230 {
00231 for ( int p=0 ; p<diff_array.LengthX() ; ++p )
00232 {
00233 diff_array[q][p] = 0.0;
00234
00235 for (int j=ystart[q]; j<yend[q]; ++j)
00236 {
00237 for (int i=xstart[p]; i<xend[p]; ++i)
00238 {
00239 diff = static_cast<long double> ( coded_data[j][i] - orig_data[j][i] );
00240
00241 diff *= diff;
00242 diff *= diff;
00243
00244 diff_array[q][p] += diff;
00245 }
00246 }
00247
00248 diff_array[q][p] /= ( xend[p]-xstart[p] ) * ( yend[q]-ystart[q] );
00249 diff_array[q][p] = std::sqrt( diff_array[q][p] );
00250
00251
00252 diff_array[q][p] /= 16.0;
00253
00254 }
00255 }
00256
00257
00258 long double worst_diff = diff_array[0][0];
00259 for ( int q=0 ; q<diff_array.LengthY() ; ++q )
00260 {
00261 for ( int p=0 ; p<diff_array.LengthX() ; ++p )
00262 {
00263 if ( diff_array[q][p] > worst_diff )
00264 worst_diff = diff_array[q][p];
00265 }
00266 }
00267
00268 return static_cast<double> ( 10.0 * std::log10( 255.0*255.0 / worst_diff ) );
00269 }