void PictureBuffer::PushPicture( const PictureParams& pp ) {// Put a new picture onto the top of the stack // if picture is present - return if (IsPictureAvail(pp.PictureNum())) return; // if ( pp.PicSort().IsRef() ) // m_ref_count++; Picture* pptr = new Picture(pp); // add the picture to the buffer m_pic_data.push_back(pptr); // put the picture number into the index table std::pair<unsigned int,unsigned int> temp_pair(pp.PictureNum() , m_pic_data.size()-1 ); m_pnum_map.insert(temp_pair); }
void SequenceCompressor::UpdateIntraPicCBRModel( const PictureParams& pparams, const bool is_a_cut ){ // For intra pictures we want to update before coding // especially if they're inserted if ( pparams.PicSort().IsIntra() && m_current_display_pnum > 0 && m_encparams.NumL1() != 0){ // Calculate the new QF for encoding the following I picture if ( is_a_cut ) m_ratecontrol->SetCutPictureQualFactor(); else m_ratecontrol->CalcNextIntraQualFactor(); } }
void CoeffArray::SetBandWeights (const EncoderParams& encparams, const PictureParams& pparams, const CompSort csort) { const WltFilter wltfilter = encparams.TransformFilter(); const bool field_coding = encparams.FieldCoding(); const ChromaFormat cformat = pparams.CFormat(); const float cpd = encparams.CPD(); const PictureSort psort = pparams.PicSort(); int xlen, ylen, xl, yl, xp, yp; float xfreq, yfreq; float temp(0.0); // Compensate for chroma subsampling float chroma_xfac(1.0); float chroma_yfac(1.0); if( csort != Y_COMP) { if( cformat == format422) { chroma_xfac = 2.0; chroma_yfac = 1.0; } else if( cformat == format420 ) { chroma_xfac = 2.0; chroma_yfac = 2.0; } } xlen = 2 * m_band_list(1).Xl(); ylen = 2 * m_band_list(1).Yl(); if (cpd != 0.0) { for( int i = 1; i<=m_band_list.Length() ; i++ ) { xp = m_band_list(i).Xp(); yp = m_band_list(i).Yp(); xl = m_band_list(i).Xl(); yl = m_band_list(i).Yl(); xfreq = cpd * ( float(xp) + (float(xl)/2.0) ) / float(xlen); yfreq = cpd * ( float(yp) + (float(yl)/2.0) ) / float(ylen); if ( psort.IsInter() ) { xfreq /= 8.0; yfreq /= 8.0; } if(field_coding) yfreq/=2.0; temp = PerceptualWeight( xfreq/chroma_xfac , yfreq/chroma_yfac , csort ); m_band_list(i).SetWt(temp); }// i // Make sure dc is always the lowest weight float min_weight=m_band_list(m_band_list.Length()).Wt(); for( int b=1 ; b<=m_band_list.Length()-1 ; b++ ) min_weight = ((min_weight>m_band_list(b).Wt()) ? m_band_list(b).Wt() : min_weight); m_band_list( m_band_list.Length() ).SetWt( min_weight ); // Now normalize weights so that white noise is always weighted the same // Overall factor to ensure that white noise ends up with the same RMS, whatever the weight double overall_factor=0.0; //fraction of the total number of samples belonging to each subband double subband_fraction; for( int i=1 ; i<=m_band_list.Length() ; i++ ) { subband_fraction = 1.0/((double) m_band_list(i).Scale() * m_band_list(i).Scale()); overall_factor += subband_fraction/( m_band_list(i).Wt() * m_band_list(i).Wt() ); } overall_factor = std::sqrt( overall_factor ); //go through and normalise for( int i=m_band_list.Length() ; i>0 ; i-- ) m_band_list(i).SetWt( m_band_list(i).Wt() * overall_factor ); } else {//cpd=0 so set all weights to 1 for( int i=1 ; i<=m_band_list.Length() ; i++ ) m_band_list(i).SetWt( 1.0 ); } //Finally, adjust to compensate for the absence of scaling in the transform //Factor used to compensate: double lfac; double hfac; int filt_shift; switch (wltfilter){ case DD9_7 : lfac = 1.218660804;; hfac = 0.780720058; filt_shift = 1; break; case LEGALL5_3 : lfac = 1.179535649; hfac = 0.81649658; filt_shift = 1; break; case DD13_7 : lfac = 1.235705971; hfac = 0.780719354; filt_shift = 1; break; case HAAR0 : lfac = 1.414213562; hfac = 0.707106781; filt_shift = 0; break; case HAAR1 : lfac = 1.414213562; hfac = 0.707106781; filt_shift = 1; break; case DAUB9_7 : lfac = 1.149604398; hfac = 0.869864452; filt_shift = 1; break; default: lfac = 1.0; hfac = 1.0; filt_shift = 0; } int idx; int shift; int depth = (m_band_list.Length()-1)/3; // Do the DC subband idx = m_band_list.Length(); double cf = (1<<(depth*filt_shift)) / std::pow(lfac,2*depth ) ; m_band_list(idx).SetWt( m_band_list(idx).Wt()*cf); // Do the non-DC subbands for (int level=1; level<=depth; level++) { shift = (depth-level+1)*filt_shift; for ( int orient=3;orient>=1; --orient ) { idx = 3*(depth-level)+orient; // index into the subband list idx = 3*(depth-level)+orient; // Divide through by the weight for the LF subband that was decomposed // to create this level cf = 1.0/ std::pow(lfac,2*(depth-level) ); if ( m_band_list(idx).Xp() != 0 && m_band_list(idx).Yp() != 0) // HH subband cf /= (hfac * hfac); else // LH or HL subband cf /= (lfac * hfac); cf *= double(1<<shift); m_band_list(idx).SetWt( m_band_list(idx).Wt()*cf ); }// orient }//level }
void FieldSequenceCompressor::SetPicTypeAndRefs( PictureParams& pparams ) { // FIXME: won't work with adaptive GOP properly // Set the temporal prediction parameters for field coding const int pnum = pparams.PictureNum(); const int rel_pnum = pparams.PictureNum()-m_gop_start_num; const int gop_len = m_encparams.GOPLength(); const int num_L1 = m_encparams.NumL1(); pparams.SetRetiredPictureNum( -1 ); pparams.Refs().clear(); if ( num_L1>0 ){ if ( (rel_pnum/2) % gop_len == 0){ // Field 1 is Intra Field if (gop_len > 1){ pparams.SetPicSort( PictureSort::IntraRefPictureSort()); // I picture expires after we've coded the next L1 picture pparams.SetExpiryTime( gop_len * 2); pparams.SetExpiryTime( 2*m_L1_sep ); if ( pnum%2){ pparams.SetPicSort( PictureSort::InterRefPictureSort()); // Ref the previous I field pparams.Refs().push_back( pnum-1 ); } } else{ // I-picture only coding pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); pparams.SetExpiryTime( gop_len ); } } else if ((rel_pnum/2) % m_L1_sep == 0){ pparams.SetPicSort( PictureSort::InterRefPictureSort()); if (pnum%2){ // Field 2 // Ref the first field of same picture pparams.Refs().push_back( pnum - 1); // Ref the previous field 2 of I or L1 picture pparams.Refs().push_back( pnum - m_L1_sep*2 ); } else{ // Field 1 // Ref the field 1 of previous I or L1 picture pparams.Refs().push_back( pnum - m_L1_sep*2 ); // Ref the field 2 of previous I or L1 picture pparams.Refs().push_back( pnum - m_L1_sep*2 + 1 ); } // Expires after the next L1 or I picture pparams.SetExpiryTime( (m_L1_sep+1)*2-1 ); if ((rel_pnum/2) % m_encparams.L1Sep() == 0 ) pparams.SetExpiryTime((2*m_encparams.L1Sep())+1*2-1); } else if ((rel_pnum/2+1) % m_L1_sep == 0){ // Bi-directional non-reference fields. if (pnum%2) pparams.SetPicSort( PictureSort::InterNonRefPictureSort()); else pparams.SetPicSort( PictureSort::InterRefPictureSort()); pparams.Refs().push_back(pnum-1); if (m_enc_pbuffer.IsPictureAvail(pnum+2)) pparams.Refs().push_back(pnum+2); pparams.SetExpiryTime( 1 ); } else{ // Bi-directional reference fields. pparams.SetPicSort( PictureSort::InterRefPictureSort()); pparams.Refs().push_back(pnum-1); int next_ref = (((pnum/2)/m_L1_sep+1)*m_L1_sep)*2+(pnum%2); if (m_enc_pbuffer.IsPictureAvail(next_ref)) pparams.Refs().push_back(next_ref); pparams.SetExpiryTime( 4 ); } } else{ pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); pparams.SetExpiryTime( 2 ); } }
void FrameSequenceCompressor::SetPicTypeAndRefs( PictureParams& pparams ) { // Set the temporal prediction parameters for frame coding const int pnum = pparams.PictureNum(); const int rel_pnum = pnum - m_gop_start_num; const int gop_len = m_encparams.GOPLength(); const int num_L1 = m_encparams.NumL1(); pparams.SetRetiredPictureNum( -1 ); pparams.Refs().clear(); if ( num_L1>0 ){ if ( rel_pnum % gop_len == 0){ if (gop_len > 1) pparams.SetPicSort( PictureSort::IntraRefPictureSort()); else // I-picture only coding pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); // I picture expires after we've coded the next I picture pparams.SetExpiryTime( 2*m_L1_sep ); } else if (rel_pnum % m_L1_sep == 0){ pparams.SetPicSort( PictureSort::InterRefPictureSort()); // Ref the previous I or L1 picture pparams.Refs().push_back( pnum - m_L1_sep ); // if we don't have the first L1 picture ... if ( ((rel_pnum-m_L1_sep) % gop_len>0) && m_L1_sep>1) // ... other ref is the prior I/L1 picture but one pparams.Refs().push_back( pnum - 2*m_L1_sep ); // Expires after the next L1 or I picture pparams.SetExpiryTime( 2*m_L1_sep ); if (rel_pnum % m_encparams.L1Sep() == 0 ) pparams.SetExpiryTime(2*m_encparams.L1Sep()); } else if ((rel_pnum+1) % m_L1_sep == 0){ pparams.SetPicSort( PictureSort::InterNonRefPictureSort()); // .. and the previous picture pparams.Refs().push_back(pnum-1); // Refs are the next I or L1 picture ... if (m_enc_pbuffer.IsPictureAvail(pnum+1)) pparams.Refs().push_back(pnum+1); pparams.SetExpiryTime( 1 ); } else{ pparams.SetPicSort( PictureSort::InterRefPictureSort()); // .. and the previous picture pparams.Refs().push_back(pnum-1); // Refs are the next I or L1 picture ... int next_ref = ((pnum/m_L1_sep)+1)*m_L1_sep; if (m_enc_pbuffer.IsPictureAvail(next_ref)) pparams.Refs().push_back(next_ref); pparams.SetExpiryTime( 2 ); } } else{ pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); pparams.SetExpiryTime( 1 ); } }
//Constructor CompDecompressor::CompDecompressor( DecoderParams& decp, const PictureParams& pp) : m_decparams(decp), m_pparams(pp), m_psort( pp.PicSort() ) {}