VideoCodec/Modules/Input/FrameInputModule.cpp
#include <Magick++.h>
#include "FrameInputModule.h"
using namespace Magick;
namespace VideoCodec
{
FrameInputModule::FrameInputModule() : Module(FRAME_INPUT_MODULE_ID)
{
}
FrameInputModule::~FrameInputModule()
{
}
ConfigurationStatus FrameInputModule::Configure(ConfigurationElement* configuration)
{
if (configuration != NULL && configuration->GetType() == CONFIGURATION_PAIRS)
{
configurationList* value = configuration->GetValue(std::string("files"))->GetList();
this->inputFrameFileNames = vector<std::string>();
this->unprocessedFrameFileNames = vector<std::string>();
this->processedFrameFileNames = vector<std::string>();
// Get file names into a vector.
for (unsigned int i = 0; i < value->size(); i++)
this->inputFrameFileNames.insert(this->inputFrameFileNames.end(), *(*value)[i]->GetString());
// Initially all frames are unprocessed.
for (unsigned int i = 0; i < value->size(); i++)
this->unprocessedFrameFileNames.insert(this->unprocessedFrameFileNames.end(), this->inputFrameFileNames[i]);
// Deal with preloading all frames.
if (configuration->GetValue(std::string("preload")) != NULL && configuration->GetValue(std::string("preload"))->GetType() == CONFIGURATION_STRING && *(configuration->GetValue(std::string("preload"))->GetString()) == std::string("true"))
this->PreloadInputFrames();
else
this->preload = false;
return MODULE_CONFIGURATION_OK;
}
else
{
return MODULE_CONFIGURATION_ERROR;
}
}
FrameCount FrameInputModule::GetTotalFrameCount()
{
return this->processedFrameFileNames.size() + this->unprocessedFrameFileNames.size();
}
void FrameInputModule::CleanUpPreloaded()
{
// Delete frame data.
for (unsigned int i = 0; i < this->preloadedFrames.size(); i++)
delete this->preloadedFrames.at(i);
this->preload = false;
}
void FrameInputModule::PreloadInputFrames()
{
if (this->preload == true)
this->CleanUpPreloaded();
this->preload = true;
this->preloadedFrames = vector<PictureInfo*>();
for (unsigned int i = 0; i < this->inputFrameFileNames.size(); i++)
this->preloadedFrames.insert(this->preloadedFrames.end(), this->preloadFrame(this->inputFrameFileNames[i]));
}
PictureInfo* FrameInputModule::preloadFrame(std::string fileName)
{
Image image;
try
{
image.read(fileName.c_str());
}
catch (Exception& error)
{
Logger::LogMessage("Unable to preload all frames.");
return NULL;
}
int imageWidth = image.size().width();
int imageHeight = image.size().height();
const PixelPacket* pixels = image.getConstPixels(0, 0, imageWidth, imageHeight);
// Put all the component values into an unsigned byte array.
PictureInfo* picture = new PictureInfo();
UnsignedByte* components = new UnsignedByte[imageWidth * imageHeight * 3];
for (int y = 0, index = 0, componentIndex = 0; y < imageHeight; y++)
for (int x = 0; x < imageWidth; x++, index++, componentIndex += 3)
{
components[componentIndex] = pixels[index].red;
components[componentIndex + 1] = pixels[index].green;
components[componentIndex + 2] = pixels[index].blue;
}
// Initial frame data is in RGB format.
picture->SetPixelLayout(PIXEL_LAYOUT_SCAN);
picture->SetUnsignedByteData(components, 3 * imageWidth * imageHeight);
picture->SetPixelsX(imageWidth);
picture->SetPixelsY(imageHeight);
picture->SetColourFormat(COLOUR_FORMAT_RGB);
return picture;
}
PictureInfo* FrameInputModule::FetchNextFrame()
{
std::string fileName = (this->unprocessedFrameFileNames)[0];
this->processedFrameFileNames.insert(this->processedFrameFileNames.begin(), fileName);
this->unprocessedFrameFileNames.erase(this->unprocessedFrameFileNames.begin());
if (this->preload)
{
PictureInfo* thisFrame = NULL;
while (thisFrame == NULL)
{
thisFrame = (this->preloadedFrames)[0];
this->preloadedFrames.erase(this->preloadedFrames.begin());
}
return thisFrame;
}
Image image;
PictureInfo* picture = new PictureInfo();
try
{
image.read(fileName.c_str());
}
catch (Exception& error)
{
// Mark this frame invalid and skip to the next one.
Logger::LogMessage(("Could not open file " + fileName + ".").c_str());
return NULL;
}
int imageWidth = image.size().width();
int imageHeight = image.size().height();
// Do not deallocate pixels. (Magick++ documentation)
const PixelPacket* pixels = image.getConstPixels(0, 0, imageWidth, imageHeight);
// Put all the component values into an unsigned byte array.
UnsignedByte* components = new UnsignedByte[imageWidth * imageHeight * 3];
for (int y = 0, index = 0, componentIndex = 0; y < imageHeight; y++)
for (int x = 0; x < imageWidth; x++, index++, componentIndex += 3)
{
components[componentIndex] = pixels[index].red;
components[componentIndex + 1] = pixels[index].green;
components[componentIndex + 2] = pixels[index].blue;
}
// Initial frame data is in RGB format.
picture->SetPixelLayout(PIXEL_LAYOUT_SCAN);
picture->SetUnsignedByteData(components, 3 * imageWidth * imageHeight);
picture->SetPixelsX(imageWidth);
picture->SetPixelsY(imageHeight);
picture->SetColourFormat(COLOUR_FORMAT_RGB);
return picture;
}
bool FrameInputModule::HasFrames()
{
return (this->unprocessedFrameFileNames.size() > 0);
}
}