VideoCodec/Modules/Prediction/FrameDifference.cpp
#include "FrameDifference.h"
namespace VideoCodec
{
FrameDifference::FrameDifference() : Module(FRAME_DIFFERENCE_MODULE_ID)
{
}
FrameDifference::~FrameDifference()
{
}
ConfigurationStatus FrameDifference::Configure(ConfigurationElement* configuration)
{
return MODULE_CONFIGURATION_OK;
}
void FrameDifference::SubtractFrame(PictureInfo* current, PictureInfo* previous)
{
if (current->GetPixelLayout() != previous->GetPixelLayout() || current->GetPixelLayout() != PIXEL_LAYOUT_SCAN ||
current->GetBlockRows() != previous->GetBlockRows() ||
current->GetBlockColumns() != previous->GetBlockColumns())
Logger::LogMessage("Warning: Mismatched frames for frame difference.");
// Get information from the supplied frames.
PixelCount pixelsX = current->GetPixelsX();
PixelCount pixelsY = current->GetPixelsY();
UnsignedByte* currentData = current->GetUnsignedByteData();
UnsignedByte* previousData = previous->GetUnsignedByteData();
// The result has a new range of -256 to 255, so needs to be stored in a signed integer.
SignedShort* result = new SignedShort[pixelsX * pixelsY * 3];
for (int index = 0; index < pixelsX * pixelsY * 3; index++)
result[index] = currentData[index] - previousData[index];
// Store the result of the subtraction.
current->SetSignedShortData(result, pixelsX * pixelsY * 3);
}
void FrameDifference::AddFrame(PictureInfo* reference, PictureInfo* residual)
{
// Add the residual to the reference picture.
if (reference->GetPixelLayout() != residual->GetPixelLayout() || reference->GetPixelLayout() != PIXEL_LAYOUT_SCAN ||
reference->GetBlockRows() != residual->GetBlockRows() ||
reference->GetBlockColumns() != residual->GetBlockColumns())
Logger::LogMessage("Warning: Mismatched frames for frame difference.");
// Get information for the supplied frames.
PixelCount pixelsX = reference->GetPixelsX();
PixelCount pixelsY = reference->GetPixelsY();
UnsignedByte* referenceData = reference->GetUnsignedByteData();
SignedShort* residualData = residual->GetSignedShortData();
// Create an array to store the result.
UnsignedByte* result = new UnsignedByte[pixelsX * pixelsY * 3];
// The resulting values will be clipped into the range 0 to 255.
for (int index = 0; index < pixelsX * pixelsY * 3; index++)
{
SignedShort newValue = referenceData[index] + residualData[index];
// Clip the value.
if (newValue > 255)
newValue = 255;
else if (newValue < 0)
newValue = 0;
result[index] = (UnsignedByte)newValue;
}
reference->SetUnsignedByteData(result, pixelsX * pixelsY * 3);
}
void FrameDifference::DiagnosticResidual(PictureInfo* residual)
{
// Add the residual to a flat picture.
PixelCount pixelsX = residual->GetPixelsX();
PixelCount pixelsY = residual->GetPixelsY();
SignedShort* residualData = residual->GetSignedShortData();
// Create an array to store the result.
UnsignedByte* result = new UnsignedByte[pixelsX * pixelsY * 3];
// The resulting values will be clipped into the range 0 to 255.
for (int index = 0; index < pixelsX * pixelsY * 3; index++)
{
SignedShort newValue = 128 + (residualData[index] >> 1);
// Clip the value.
if (newValue > 255)
newValue = 255;
else if (newValue < 0)
newValue = 0;
result[index] = (UnsignedByte)newValue;
}
residual->SetUnsignedByteData(result, pixelsX * pixelsY * 3);
}
}