#include #include #include #include #include /*This utility generates the extrapolation matrices used to pad incomplete blocks when given frame sizes that are not a multiple of two. Although the technique used here is generalizable to non-rectangular shapes, the storage needed for the matrices becomes larger (exactly 13.75K, if we discount the superfluous mask, na, pi, and ci members of the oc_coeffcient_info structure and use a 256-byte mask-padding lookup table instead).*/ /*The matrix representation of the Theora's actual iDCT. This is computed using the 16-bit approximations of the sines and cosines that Theora uses, but using floating point values and assuming that no truncation occurs after division (i.e., pretending that the transform is linear like the real DCT).*/ static const double OC_IDCT_MATRIX[8][8]={ { +0.7071075439453125,+0.9807891845703125, +0.9238739013671875,+0.8314666748046875, +0.7071075439453125,+0.555572509765625, +0.3826904296875, +0.1950836181640625 }, { +0.7071075439453125,+0.8314685295335948, +0.3826904296875, -0.1950868454296142, -0.7071075439453125,-0.9807858711574227, -0.9238739013671875,-0.5555783333256841 }, { +0.7071075439453125,+0.5555783333256841, -0.3826904296875, -0.9807858711574227, -0.7071075439453125,+0.1950868454296142, 0.9238739013671875,+0.8314685295335948 }, { +0.7071075439453125,+0.1950836181640625, -0.9238739013671875,-0.555572509765625, +0.7071075439453125,+0.8314666748046875, -0.3826904296875, -0.9807891845703125 }, { +0.7071075439453125,-0.1950836181640625, -0.9238739013671875,+0.555572509765625, +0.7071075439453125,-0.8314666748046875, -0.3826904296875, +0.9807891845703125 }, { +0.7071075439453125,-0.5555783333256841, -0.3826904296875, 0.9807858711574227, -0.7071075439453125,-0.1950868454296142, +0.9238739013671875,-0.8314685295335948 }, { +0.7071075439453125,-0.8314685295335948, +0.3826904296875, +0.1950868454296142, -0.7071075439453125,+0.9807858711574227, -0.9238739013671875,+0.5555783333256841 }, { +0.7071075439453125,-0.9807891845703125, +0.9238739013671875,-0.8314666748046875, +0.7071075439453125,-0.555572509765625, +0.3826904296875, -0.1950836181640625 } }; /*A table of the non-zero coefficients to keep for each possible shape. Our basis selection is chosen to optimize the coding gain. This gives us marginally better performance than other optimization criteria for the border extension case (and significantly better performance in the general case).*/ static const unsigned char OC_PAD_MASK_GAIN[256]={ 0x00,0x01,0x01,0x11,0x01,0x11,0x05,0x49, 0x01,0x05,0x11,0x15,0x11,0x15,0xA1,0x55, 0x01,0x05,0x11,0x15,0x11,0x29,0x51,0x55, 0x03,0x85,0x19,0xA5,0x61,0x35,0xB1,0xAD, 0x01,0x11,0x05,0x23,0x03,0x85,0x0D,0x2B, 0x11,0x15,0x61,0x55,0x13,0x1B,0xA3,0x5B, 0x11,0x83,0x83,0x55,0x13,0x93,0xC3,0xCB, 0x61,0xC3,0x33,0x3B,0x99,0xCB,0xB3,0xDB, 0x01,0x11,0x03,0x0B,0x05,0x0B,0x07,0x4B, 0x11,0x07,0x07,0x1B,0x83,0x8B,0x87,0x57, 0x11,0x23,0x07,0x33,0x61,0x2B,0x0F,0x57, 0x19,0x87,0x1B,0x2F,0x33,0x8F,0x8F,0xB7, 0x05,0x83,0x07,0x63,0x0D,0x87,0x87,0x6B, 0x51,0x47,0x0F,0x67,0xC3,0xCB,0xE3,0xD7, 0xA1,0xA3,0x87,0x73,0xA3,0x6B,0xE3,0xCF, 0xB1,0x8F,0x8F,0xE7,0xB3,0xCF,0xE7,0xF7, 0x01,0x03,0x11,0x43,0x11,0x31,0x83,0x93, 0x05,0x07,0x23,0x27,0x83,0x87,0xA3,0x57, 0x05,0x07,0x07,0xC3,0x15,0x0F,0x47,0x4F, 0x85,0x87,0x87,0xA7,0xC3,0x8F,0x8F,0xAF, 0x11,0x31,0x0B,0x1B,0x85,0x1B,0x87,0x2F, 0x29,0x0F,0x2B,0x1F,0x93,0x1F,0x6B,0x5F, 0x15,0x87,0x8B,0x57,0x1B,0x1F,0xCB,0x5F, 0x35,0x8F,0x8F,0x3F,0xCB,0x9F,0xCF,0xDF, 0x11,0x43,0x0B,0x33,0x23,0x1B,0x63,0x9B, 0x15,0xC3,0x33,0x37,0x55,0x57,0x73,0x77, 0x15,0x27,0x1B,0x37,0x55,0x1F,0x67,0x3F, 0xA5,0xA7,0x2F,0xB7,0x3B,0x3F,0xE7,0xBF, 0x49,0x93,0x4B,0x9B,0x2B,0x2F,0x6B,0x7B, 0x55,0x4F,0x57,0x3F,0xCB,0x5F,0xCF,0x7F, 0x55,0x57,0x57,0x77,0x5B,0x5F,0xD7,0x7F, 0xAD,0xAF,0xB7,0xBF,0xDB,0xDF,0xF7,0xFF }; /*Computes the Cholesky factorization L L^T of the matrix G^T G, where G is the currently selected bass functions restricted to the region of spatial support. The reciprocal of the diagonal element is stored instead of the diagonal itself, so that the division only needs to be done once. _l: The L matrix to compute. _ac: The set of basis functions used for each row. _ap: The set of pixels that are not padding. _na: The number of active pixels/coefficients.*/ static void oc_cholesky8(double _l[8][8],int _ac[8],int _ap[8],int _na){ int aci; int acj; int ack; int api; int ci; int cj; int pi; for(aci=0;aci<_na;aci++){ /*Step 1: Add the next row/column of G^T G.*/ ci=_ac[aci]; for(acj=0;acj<=aci;acj++){ cj=_ac[acj]; _l[aci][acj]=0; for(api=0;api<_na;api++){ pi=_ap[api]; _l[aci][acj]+=OC_IDCT_MATRIX[pi][cj]*OC_IDCT_MATRIX[pi][ci]; } } /*Step 2: Convert the newly added row to the corresponding row of the Cholesky factorization.*/ for(acj=0;acj0;){ for(acj=aci+1;acjbest_cre){ if(cj-ci=cj||crend[cri]<=cj);cri++); if(cri>=ncr){ /*No conflicting ranges were found, so we can insert the necessary coefficients.*/ best_ci=ci; best_cre=cj-ci; } } else{ /*Otherwise, we have a complete match, so we can stop searching.*/ best_ci=ci; best_cre=cj-ci; break; } } } if(best_cre=best_ci+best_cre){ crstart[cri]+=na[mi]-best_cre; crend[cri]+=na[mi]-best_cre; } } } /*Actually add the coefficients.*/ for(cj=best_cre;cjbest_ore){ if(oj-oi=oj||orend[ori]<=oj);ori++); if(ori>=nor){ /*No conflicting ranges were found, so we can insert the necessary coefficients.*/ best_oi=oi; best_ore=oj-oi; } } else{ /*Otherwise, we have a complete match, so we can stop searching.*/ best_oi=oi; best_ore=oj-oi; break; } } } if(best_ore=best_oi+best_ore){ orstart[ori]+=nz-best_ore; orend[ori]+=nz-best_ore; } } } /*Actually add the offsets.*/ for(oj=best_ore;oj