Использование delete в буфере изображений std :: deque (плагин OFX)

Я пытаюсь запрограммировать видеобуфер в std :: deque в моем видео-плагине OFX. Я хотел бы получить доступ к ранее обработанным изображениям для обработки текущего изображения. Моя идея состоит в том, чтобы поместить обработанные изображения в начало деке и вытолкнуть их сзади, если буфер превышает максимальный размер.
Плагин аварийно завершает работу, когда я пытаюсь освободить память изображения, используя delete перед удалением его из буфера. Я обнаружил, что могу без проблем добавить одно или несколько изображений в буфер, а затем сразу же удалить и удалить их. Однако, если я пытаюсь удалить изображение, которое было добавлено в более раннем цикле, оно вылетает.
Плагин состоит из основного класса OFXPlugin и класса процессора myplugin. Экземпляр OFXPlugin остается со временем, но для каждого обрабатываемого изображения он создает экземпляр myplugin и уничтожает его после обработки этого кадра.

Я не уверен, что я делаю что-то не так в том, как я использую deque, если мне не разрешено освобождать память, выделенную другим экземпляром myplugin, или я делаю что-то нелегальное, связанное с OFX API.

Код ниже показывает выдержки из плагина, связанные с проблемой. Он основан на примерах поддержки OFX. Он падает на delete videoBuffer_.back().img; в функции OFXPlugin::addToVBuff(OFX::Image *img, double t), Я не могу поймать исключение, по-видимому, оно обрабатывается (игнорируется) в OFX API.

Большое спасибо за вашу помощь!

myplugin.h

#include "ofxsImageEffect.h"#include "ofxsMultiThread.h"#include "../Support/Plugins/include/ofxsProcessing.H"
#include <deque>

// Video Buffer Element
typedef struct vBuffEl
{
OFX::Image* img;
double  time;
} vBuffEl;

inline
bool operator==(const vBuffEl &a, const double b)
{
return a.time == b;
}class myplugin : public OFX::ImageProcessor {
protected :
OFX::Image *_srcImg;
double   _time;
OFXPlugin *_opInstance;

public :
// ctor
myplugin(OFX::ImageEffect &instance)
: OFX::ImageProcessor(instance)
, _srcImg(0)
, _time(0)
{}

void multiThreadProcessImages(OfxRectI procWindow);

void setOFXPlugin(OFXPlugin* opInstance) {_opInstance = opInstance;}

OFXPlugin* getOFXPlugin() {return _opInstance;}

void setTime(double argsTime) {_time = argsTime;}

double getTime() {return _time;}

void setSrcImg(OFX::Image *v) {_srcImg = v;}

OFX::Image* getSrcImg() {return _srcImg;}

};class OFXPlugin : public OFX::ImageEffect {
protected :
OFX::Clip *dstClip_;
OFX::Clip *srcClip_;

double time_;
std::deque<vBuffEl> videoBuffer_;

public :

/** @brief ctor */
OFXPlugin(OfxImageEffectHandle handle);

/** @brief dtor */
~OFXPlugin();

/* Override the render */
virtual void render(const OFX::RenderArguments &args);

/* get the source Clip */
OFX::Clip* getSrcClip();

/* get the current time */
double getTime();

/* set up and run a processor */
void setupAndProcess(myplugin &, const OFX::RenderArguments &args);

/* add to video buffer */
void addToVBuff(OFX::Image *img, double t);

/* fetch a dst image from buffer */
void fetchDstImageBuff(double t, OFX::Image* &img, bool &buff);
};

myplugin.cpp

#include "myplugin.h"#include <algorithm>void myplugin::multiThreadProcessImages(OfxRectI procWindow)
{
// Do some filtering of the source image and store result in destination image
myfiltering(_dstImg, _srcImg, procWindow);

// add to buffer
_opInstance->addToVBuff(_dstImg, _time);

}/* set up and run a processor */
void
OFXPlugin::setupAndProcess(myplugin &processor, const OFX::RenderArguments &args)
{
// get a dst image
std::auto_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
OFX::BitDepthEnum dstBitDepth       = dst->getPixelDepth();
OFX::PixelComponentEnum dstComponents  = dst->getPixelComponents();

// fetch main input image
std::auto_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));

// set the images
processor.setDstImg(dst.get());
processor.setSrcImg(src.get());

// set the render window
processor.setRenderWindow(args.renderWindow);

// set time
processor.setTime(args.time);
time_ = args.time;

// set OFXPlugin instance
processor.setOFXPlugin(this);

// Call the base class process member, this will call the derived templated process code
processor.process();
}OFX::Clip* OFXPlugin::getSrcClip()
{
return srcClip_;
}

/* get the current time */
double
OFXPlugin::getTime()
{
return time_;
}

// the overridden render function
void
OFXPlugin::render(const OFX::RenderArguments &args)
{
try {
myplugin fred(*this);
setupAndProcess(fred, args);
} catch (...) {
outputMessage("ERROR: An unknown error happened!");
}
}

/* add to video buffer */
void
OFXPlugin::addToVBuff(OFX::Image *img, double t)
{
try {
// if frame already exists in buffer, remove
std::deque<vBuffEl>::iterator it;
it = find(videoBuffer_.begin(), videoBuffer_.end(), t);
if(it != videoBuffer_.end())
{
delete it->img;
videoBuffer_.erase(it);
}

// add new frame to the front
vBuffEl e;
e.time = t;
e.img = new OFX::Image(img->getPropertySet().propSetHandle());
memcpy(e.img, img, sizeof(img));
videoBuffer_.push_front(e);

// remove elements at the end, if the buffer exceeds the max size
int LASTIMG_ARRAY_SIZE = 10;
while(videoBuffer_.size() > LASTIMG_ARRAY_SIZE)
{
delete videoBuffer_.back().img;
videoBuffer_.erase(--(videoBuffer_.end()));
}
} catch (...) {
outputMessage("ERROR: An unknown error happened!");
}
}

/* fetch a dst image from buffer */
void
OFXPlugin::fetchDstImageBuff(double t, OFX::Image* &img, bool &buff)
{
try {
std::deque<vBuffEl>::iterator it;
it = find(videoBuffer_.begin(), videoBuffer_.end(), t);
if(it != videoBuffer_.end())
{
img = it->img;      // return buffered dst image
buff = true;
}
else
{
img = getSrcClip()->fetchImage(t);  // fetch and return src image
buff = false;
}
} catch (...) {
outputMessage("ERROR: An unknown error happened!");
}
}

0

Решение

Заявление

memcpy(e.img, img, sizeof(img));

не делает то, что вы ожидаете.

sizeof операция указателя возвращает размер указателя, не то, на что это указывает. Это означает, что в этом случае вы копируете только 4 или 8 байтов (в зависимости от того, используете ли вы 32- или 64-битную платформу).

Однако есть еще один хуже проблема скрыта в этом memcpy вызов. Если OFX::Image содержит указатели членов данных, копирование данных будет копировать указатели, а не данные. Это мелкая копия, а не глубокая. По этой причине C ++ имеет конструкторы копирования и операторы копирования.

То, что вы должны сделать, это простое задание, и надеюсь, что OFX::Image следует правило трех:

*e.img = *img;
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]