theonlineoasis

VideoCodec/Modules/Transform/DCT.cpp

#include "DCT.h" // For reference DCT: #define DCT_PI 3.14159265358979323846 #define DCT_RECIPROCAL_SQRT_2 0.70710678118654752438 namespace VideoCodec {    DCT::DCT() : Module(DCT_MODULE_ID)    {       this->isInitialized = false;    }        DCT::~DCT()    {       if (this->isInitialized)       {          delete[] this->dctCosineProductLookupTable;          delete[] this->idctCosineProductLookupTable;       }    }        ConfigurationStatus DCT::Configure(ConfigurationElement* configuration)    {       return MODULE_CONFIGURATION_OK;    }        void DCT::ExecuteIDCT(PictureInfo* picture)    {       if (!this->isInitialized)          this->initialize();              int blockRows = picture->GetBlockRows();       int blockColumns = picture->GetBlockColumns();              if (picture->GetPixelLayout() != PIXEL_LAYOUT_MB_FOUR_TWO_ZERO)          Logger::LogMessage("Warning: The reference IDCT requires a 4:2:0 MB pixel layout.");       SignedShort* transformedBlocks = picture->GetSignedShortData();       UnsignedByte* result = new UnsignedByte[8 * 8 * 6 * (blockRows * blockColumns)];              for (int y = 0; y < blockRows; y++)          for (int x = 0; x < blockColumns; x++)          {             for (int block = 0; block < 6; block++)             {                //this->debugOutputMB(transformedBlocks + 8 * 8 * 6 * (x + (y * blockColumns)), "Source blocks\n");                                this->referenceIDCT(transformedBlocks + 8 * 8 * 6 * (x + y * blockColumns) + (block << 6), result + 8 * 8 * 6 * (x + y * blockColumns) + (block << 6));                                /*char* debugLabel = new char[255];                sprintf(debugLabel, "IDCTed block at (%d, %d)\n", x, y);                this->debugOutputMB(result + 8 * 8 * 6 * (x + (y * blockColumns)), debugLabel);                delete debugLabel;*/             }          }              // Store the result of the IDCT.       picture->SetUnsignedByteData(result, blockRows * blockColumns * 6 * 64);    }        void DCT::ExecuteDCT(PictureInfo* picture)    {       if (!this->isInitialized)          this->initialize();              int blockRows = picture->GetBlockRows();       int blockColumns = picture->GetBlockColumns();              if (picture->GetPixelLayout() != PIXEL_LAYOUT_MB_FOUR_TWO_ZERO)          Logger::LogMessage("Warning: The reference DCT requires a 4:2:0 MB pixel layout.");              // Get the block data.       UnsignedByte* mbData = picture->GetUnsignedByteData();       SignedShort* result = new SignedShort[8 * 8 * 6 * (blockRows * blockColumns)];              for (int index = 0; index < blockRows * blockColumns * 6 * 64; index += 64)          this->referenceDCT(mbData + index, result + index);              // Store the result in the picture.       picture->SetSignedShortData(result, blockRows * blockColumns * 6 * 64);    }        void DCT::initialize()    {       Logger::LogMessage("Initializing simple DCT/IDCT");       this->dctCosineProductLookupTable = new double[1 << 12];       this->idctCosineProductLookupTable = new double[1 << 12];              this->reciprocalRootTwo = 1.0 / sqrt(2.0);              for (int index = 0, v = 0; v < 8; v++)       {          for (int u = 0; u < 8; u++)          {             for (int y = 0; y < 8; y++)             {                for (int x = 0; x < 8; x++, index++)                {                   this->dctCosineProductLookupTable[index] =                      cos(((2.0 * (double)x + 1.0) * (double)u * DCT_PI) / 16.0) *                      cos(((2.0 * (double)y + 1.0) * (double)v * DCT_PI) / 16.0);                }             }          }       }              for (int index = 0, y = 0; y < 8; y++)          for (int x = 0; x < 8; x++)             for (int v = 0; v < 8; v++)                for (int u = 0; u < 8; u++, index++)                   this->idctCosineProductLookupTable[index] =                      cos(((2.0 * (double)x + 1.0) * (double)u * DCT_PI) / 16.0) *                      cos(((2.0 * (double)y + 1.0) * (double)v * DCT_PI) / 16.0) *                      (v == 0 ? this->reciprocalRootTwo : 1.0) *                      (u == 0 ? this->reciprocalRootTwo : 1.0);              this->isInitialized = true;              Logger::LogMessage("Initialization complete.");    }        void DCT::debugOutputMB(short int* mb, const char* label)    {       Logger::BeginIncrementalLogMessage(label);              for (int y = 0; y < 8; y++)       {          for (int x = 0; x < 8; x++)          {             Logger::IncrementalLogMessage((int)mb[y * 8 + x]);             Logger::IncrementalLogMessage(" ");          }          Logger::IncrementalLogMessage("\n");       }              Logger::EndIncrementalLogMessage(label);    }        void DCT::debugOutputMB(unsigned char* mb, const char* label)    {       Logger::BeginIncrementalLogMessage(label);              for (int y = 0; y < 8; y++)       {          for (int x = 0; x < 8; x++)          {             Logger::IncrementalLogMessage((int)mb[y * 8 + x]);             Logger::IncrementalLogMessage(" ");          }          Logger::IncrementalLogMessage("\n");       }              Logger::EndIncrementalLogMessage(label);    }        // Slow reference IDCT.    void DCT::referenceIDCT(SignedShort* data, UnsignedByte* result)    {       double temp;       int index = 0;       for (int outerIndex = 0; outerIndex < 64; outerIndex++)       {          temp = 0;          for (int i = 0; i < 64; i++, index++)             temp += (double)data[i] * this->idctCosineProductLookupTable[index];          temp *= 0.25;          short int value = lrintf(temp);          result[outerIndex] = (value < 0 ? 0 : value > 255 ? 255 : value);       }    }        // Slow reference DCT.    void DCT::referenceDCT(unsigned char* data, short int* result)    {       double temp;       int index = 0;       for (int outerIndex = 0; outerIndex < 64; outerIndex++)       {          temp = 0.0;          for (int i = 0; i < 64; i++, index++)          {             temp += ((double)data[i] * this->dctCosineProductLookupTable[index]);          }          temp *= 0.25 *             (outerIndex < 8 ? this->reciprocalRootTwo : 1.0) *             ((outerIndex % 8) == 0 ? this->reciprocalRootTwo : 1.0);          result[outerIndex] = lrintf(temp);       }    } }