📄 sadct.cpp
字号:
/*************************************************************************This software module was originally developed by Stefan Rauthenberg (rauthenberg@HHI.DE), HHI (date: January, 1998)in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). This software module is an implementation of a part of one or more MPEG-4 Video tools as specified by the MPEG-4 Video. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. The original developer of this software module and his/her company, the subsequent editors and their companies, and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. Copyright is not released for non MPEG-4 Video conforming products. Microsoft retains full right to use the code for his/her own purpose, assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. This copyright notice must be included in all copies or derivative works. Copyright (c) 1998.Module Name: sadct.cppAbstract: SADCT and inverse SADCTRevision History: *************************************************************************/#include "typeapi.h"#include "dct.hpp"#include <math.h>#if defined(__DEBUG_SADCT_) && !defined(NDEBUG)#include <iostream.h>#endif#ifdef __MFC_#ifdef _DEBUG#undef THIS_FILEstatic char BASED_CODE THIS_FILE[] = __FILE__;#endif#define new DEBUG_NEW #endif // __MFC_CSADCT::CSADCT(): m_N(8), m_mat_tmp1(0), m_row_buf(0), m_ly(0), m_lx(0), m_mask(0){ allocMatrix(&m_mat_tmp1, m_N, m_N); m_row_buf = new Float[m_N]; m_ly = new Int[m_N]; m_lx = new Int[m_N]; allocMatrix(&m_mask, m_N, m_N); allocMatrix(&m_in, m_N, m_N); allocMatrix(&m_out, m_N, m_N); // Schueuer HHI: added for fast_sadct#ifdef _FAST_SADCT_ c_buf = new Float[m_N]; allocMatrix(&tmp_out, m_N, m_N); f0_2 = 0.707107; f0_3 = 0.577350; f1_3 = 0.707107; f2_3 = 0.408248; f3_3 = 0.816497; f0_4 = 0.500000; f1_4 = 0.653281; f2_4 = 0.270598; f0_5 = 0.447214; f1_5 = 0.601501; f2_5 = 0.371748; f3_5 = 0.511667; f4_5 = 0.195440; f5_5 = 0.632456; f0_6 = 0.408248; f1_6 = 0.557678; f2_6 = 0.500000; f3_6 = 0.288675; f4_6 = 0.149429; f5_6 = 0.577350; f0_7 = 0.377964; f1_7 = 0.521121; f2_7 = 0.481588; f3_7 = 0.417907; f4_7 = 0.333269; f5_7 = 0.231921; f6_7 = 0.118942; f7_7 = 0.534522; f0_8 = 0.7071068; f1_8 = 0.4903926; f2_8 = 0.4619398; f3_8 = 0.4157348; f4_8 = 0.3535534; f5_8 = 0.2777851; f6_8 = 0.1913417; f7_8 = 0.0975452; sq[0] = 0.00000000000; sq[1] = 1.00000000000; sq[2] = 1.41421356237; sq[3] = 1.73205080757; sq[4] = 2.00000000000; sq[5] = 2.23606797750; sq[6] = 2.44948974278; sq[7] = 2.64575131106; sq[8] = 2.82842712475;#endif}CSADCT::~CSADCT(){ freeMatrix(m_mat_tmp1, m_N); delete [] m_row_buf; delete [] m_ly; delete [] m_lx; freeMatrix(m_mask, m_N); freeMatrix(m_in, m_N); freeMatrix(m_out, m_N);// Schueuer HHI #ifdef _FAST_SADCT_ delete [] c_buf; freeMatrix(tmp_out, m_N);#endif}Void CSADCT::allocMatrix(Float ***mat, Int nr, Int nc) { Float **m = new Float* [nr]; m[0] = new Float[nr*nc]; for (Int i=1; i<nr; i++) { m[i] = m[i-1] + nc; } *mat = m;}Void CSADCT::allocMatrix(PixelC ***mat, Int nr, Int nc) { PixelC **m = new PixelC* [nr]; m[0] = new PixelC[nr*nc]; for (Int i=1; i<nr; i++) { m[i] = m[i-1] + nc; } *mat = m;}Float ***CSADCT::allocDctTable(Int n) { Float ***tbl = new Float** [n+1]; tbl[0] = 0; // transformation length of zero is impossible for (Int i=1; i<=n; i++) { allocMatrix(&tbl[i], n, n); } return (tbl);}Float ***CInvSADCT::allocReorderTable(Int n){ Float ***tbl = new Float** [n]; for (Int i=0; i<n; i++) { tbl[i] = new Float* [n]; // to play it safe and get an exception if trying to access // an uninitialized poInter. memset(tbl[i], 0, sizeof(Float*)*n); } return tbl;}Void CInvSADCT::freeReorderTable(Float ***tbl, Int n){ if (tbl) { for (Int i=0; i<n; i++) delete [] tbl[i]; delete [] tbl; }}// parameter nr not used yet because the data elements are allocated in contiguous memory and // in separate rows.Void CSADCT::freeMatrix(Float **mat, Int nr) { if (mat) { delete [] mat[0]; delete [] mat; }}Void CSADCT::freeMatrix(PixelC **mat, Int nr) { if (mat) { delete [] mat[0]; delete [] mat; }}Void CSADCT::freeDctTable(Float ***tbl, Int n) { if (tbl) { for (Int i=1; i<=n; i++) { freeMatrix(tbl[i], n); } delete [] tbl; }}Void CSADCT::getRowLength(Int *lx, const PixelC* ppxlcMask, Int iStride){ prepareMask(ppxlcMask, iStride); getRowLengthInternal(lx, m_mask, m_N, m_N);}/* * returns in `lx' the number of active pels per line after shifting * the pels towards the upper left corner. This function may be * called by a decoder in order to find out how the pels of a partial * block are arranged for transmission. */Void CSADCT::getRowLengthInternal(Int *lx, PixelC **mask, Int bky, Int bkx){ Int iy_out = 0; Int iy, ix, l; for (ix=0; ix<bkx; ix++) { l = 0; for (iy=0; iy<bky; iy++) { if ( mask[iy][ix] ) l++; } if ( l ) m_ly[iy_out++] = l; } for (ix=iy_out; ix<bkx; ix++) m_ly[ix] = 0; for (iy=0; iy<bky; iy++) { l = 0; for (ix=0; ix<bkx; ix++) { if ( m_ly[ix] > iy ) l++; } lx[iy] = l; } }Void CSADCT::prepareMask(const PixelC* rgchMask, Int stride){ for (Int iy=0; iy<m_N; iy++) { PixelC* dstPtr = m_mask[iy]; const PixelC* srcPtr = rgchMask; for (Int ix=0; ix<m_N; ix++) *dstPtr++ = (*srcPtr++ != transpValue) ? 1 : 0; rgchMask += stride; }}Void CSADCT::prepareInputBlock(Float **matDst, const Int *rgiSrc, Int stride){ Float *rowDstPtr; const Int *rowSrcPtr; for (Int iy=0; iy<m_N; iy++) { rowDstPtr = matDst[iy]; rowSrcPtr = rgiSrc + iy*stride; for (Int ix=0; ix<m_N; ix++) { *rowDstPtr++ = *rowSrcPtr++; } }}Void CSADCT::prepareInputBlock(Float **matDst, const PixelC *rgiSrc, Int stride){ Float *rowDstPtr; const PixelC *rowSrcPtr; for (Int iy=0; iy<m_N; iy++) { rowDstPtr = matDst[iy]; rowSrcPtr = rgiSrc + iy*stride; for (Int ix=0; ix<m_N; ix++) { *rowDstPtr++ = *rowSrcPtr++; } }}CFwdSADCT::CFwdSADCT(UInt nBits) : CFwdBlockDCT(nBits){ m_dct_matrix = allocDctTable(m_N); initTrfTables();}CFwdSADCT::~CFwdSADCT(){ freeDctTable(m_dct_matrix, m_N);}Void CFwdSADCT::initTrfTables(Float scale){ Float **mat, a, factcos; Int u, x; Int n; for (n=1; n<=m_N; n++) { mat = m_dct_matrix[n]; factcos = M_PI/(2*n); a = scale * sqrt(2.0 / n); for (u=0; u<n; u++) { for (x=0; x<n; x++) { mat[u][x] = a * cos(factcos*u*(2*x+1)); if ( u == 0 ) mat[u][x] /= M_SQRT2; } } }}// shape adaptive dct for inter coded blocks.Void CFwdSADCT::apply(const Int* rgiSrc, Int nColSrc, Int* rgiDst, Int nColDst, const PixelC* rgchMask, Int nColMask, Int *lx){ if (rgchMask) { prepareMask(rgchMask, nColMask); prepareInputBlock(m_in, rgiSrc, nColSrc);// Schueuer HHI: added for fast_sadct#ifdef _FAST_SADCT_ fast_transform(m_out, lx, m_in, m_mask, m_N, m_N);#else transform(m_out, lx, m_in, m_mask, m_N, m_N);#endif copyBack(rgiDst, nColDst, m_out, lx); } else CBlockDCT::apply(rgiSrc, nColSrc, rgiDst, nColDst, NULL, 0, NULL);}// inverse shape adaptive dct for intra coded blocks.Void CFwdSADCT::apply (const PixelC* rgchSrc, Int nColSrc, Int* rgiDst, Int nColDst, const PixelC* rgchMask, Int nColMask, Int *lx){ if (rgchMask) { prepareMask(rgchMask, nColMask); prepareInputBlock(m_in, rgchSrc, nColSrc);// HHI Schueuer: inserted for fastsadct#ifdef _FAST_SADCT_ fast_deltaDCTransform(m_out, lx, m_in, m_mask, m_N, m_N); #else deltaDCTransform(m_out, lx, m_in, m_mask, m_N, m_N);#endif // dirty hack for the AC/DC prediction: The transparent pixels of the // first row and columns must be cleared acc. to the sadct proposal. memset(rgiDst, 0, m_N*sizeof(PixelI)); PixelI* rgiDstPtr = rgiDst+nColDst; for (int i = 1; i < m_N; i++ ) { *rgiDstPtr = 0; rgiDstPtr += nColDst; } copyBack(rgiDst, nColDst, m_out, lx); } else CBlockDCT::apply(rgchSrc, nColSrc, rgiDst, nColDst, NULL, 0, NULL);}Void CFwdSADCT::copyBack(PixelI *rgiDst, Int nColDst, Float **in, Int *lx){ Float *rowSrcPtr; PixelI *rowDstPtr; int i, j; for (i=0; i<m_N && lx[i]; i++) { rowSrcPtr = in[i]; rowDstPtr = rgiDst; for (j = 0; j < lx[i]; j++) { *rowDstPtr = (*rowSrcPtr < 0) ? (PixelI)(*rowSrcPtr - .5) : (PixelI)(*rowSrcPtr + .5); rowDstPtr++; rowSrcPtr++; } rgiDst += nColDst; }}Void CFwdSADCT::deltaDCTransform(Float **out, Int *lx, Float **in, PixelC **mask, Int bky, Int bkx){ Int i, j; Float mean_value; Int active_pels; out[0][0] = 0.0; /* compute meanvalue */ mean_value = 0.0; active_pels = 0; for (i = 0; i < bky; i++) { for (j = 0; j < bkx; j++) { active_pels+= mask[i][j]; mean_value += in[i][j] * mask[i][j]; } } if (active_pels) mean_value = mean_value / (Float)active_pels; mean_value = mean_value + 0.5; mean_value = (int)mean_value; for (i = 0; i < bky; i++) { for (j = 0; j < bkx; j++) { in[i][j] -= mean_value; } } transform(out, lx, in, mask, bky, bkx); /* copy meanvalue to DC-coefficient */ out[0][0] = mean_value * 8.0; }// HHI Schueuer: inserted for fast sadct#ifdef _FAST_SADCT_Void CFwdSADCT::fast_deltaDCTransform(Float **out, Int *lx, Float **in, PixelC **mask, Int bky, Int bkx){ Int i, j, jmax, k; Float mean_value; Float *row, *row_coeff; Int active_pels; out[0][0] = 0.0; /* compute meanvalue */ // mean_value = 0.0; // active_pels = 0; fastshiftupTranspose(m_mat_tmp1, m_ly, in, mask, &mean_value, &active_pels, bky, bkx); if (active_pels) { mean_value /= (Float) active_pels; if (mean_value > 0) mean_value = (Int) (mean_value + 0.5); else mean_value = (Int) (mean_value - 0.5); } memset(lx, 0, sizeof(Int)*bky); for (i=0; i<bkx && m_ly[i]; i++) { jmax = m_ly[i]; row = m_mat_tmp1[i]; for (j = 0; j < jmax; j++) row[j] -= mean_value; switch (jmax) { case 1: c_buf[0] = row[0]; break; case 2: dct_vec2 (row, c_buf); break; case 3: dct_vec3 (row, c_buf); break; case 4: dct_vec4 (row, c_buf); break; case 5: dct_vec5 (row, c_buf); break; case 6: dct_vec6 (row, c_buf); break; case 7: dct_vec7 (row, c_buf); break; case 8: dct_vec8 (row, c_buf); break; } for (k=0; k<jmax; k++) { tmp_out[k][lx[k]] = c_buf[k]; lx[k]++; } } /* and finally the horizontal transformation */ for (i=0; i<bky && lx[i]; i++) { jmax = lx[i]; row = out[i]; row_coeff = tmp_out[i]; switch (jmax) { case 1: *row = row_coeff[0]; break; case 2: dct_vec2 (row_coeff, row); break; case 3: dct_vec3 (row_coeff, row); break; case 4: dct_vec4 (row_coeff, row); break; case 5: dct_vec5 (row_coeff, row); break; case 6: dct_vec6 (row_coeff, row); break; case 7: dct_vec7 (row_coeff, row); break; case 8: dct_vec8 (row_coeff, row); break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -