1
0
Fork 0
mirror of https://github.com/ruby-opencv/ruby-opencv synced 2023-03-27 23:22:12 -04:00
Use Ruby's memory allocation function xmalloc() instead of OpenCV's cvAlloc()
to run GC when running out of memory
This commit is contained in:
ser1zw 2013-04-30 09:10:05 +09:00
parent 20ba28b3bf
commit 21adfe1035
3 changed files with 67 additions and 61 deletions

View file

@ -187,21 +187,25 @@ VALUE
rb_retrieve(VALUE self)
{
VALUE image = Qnil;
IplImage *frame = NULL;
try {
IplImage *frame = cvRetrieveFrame(CVCAPTURE(self));
if (!frame)
if (!(frame = cvRetrieveFrame(CVCAPTURE(self)))) {
return Qnil;
image = cIplImage::new_object(cvSize(frame->width, frame->height),
CV_MAKETYPE(CV_8U, frame->nChannels));
if (frame->origin == IPL_ORIGIN_TL)
}
image = cIplImage::new_object(frame->width, frame->height,
CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels));
if (frame->origin == IPL_ORIGIN_TL) {
cvCopy(frame, CVARR(image));
else
}
else {
cvFlip(frame, CVARR(image));
}
}
catch (cv::Exception& e) {
raise_cverror(e);
}
return image;
}
/*
@ -214,16 +218,19 @@ VALUE
rb_query(VALUE self)
{
VALUE image = Qnil;
IplImage *frame = NULL;
try {
IplImage *frame = cvQueryFrame(CVCAPTURE(self));
if (!frame)
if (!(frame = cvQueryFrame(CVCAPTURE(self)))) {
return Qnil;
image = cIplImage::new_object(cvSize(frame->width, frame->height),
CV_MAKETYPE(CV_8U, frame->nChannels));
if (frame->origin == IPL_ORIGIN_TL)
}
image = cIplImage::new_object(frame->width, frame->height,
CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels));
if (frame->origin == IPL_ORIGIN_TL) {
cvCopy(frame, CVARR(image));
else
}
else {
cvFlip(frame, CVARR(image));
}
}
catch (cv::Exception& e) {
raise_cverror(e);

View file

@ -35,6 +35,22 @@ raise_compatible_typeerror(VALUE object, const char* expected_class_name)
rb_obj_classname(object), expected_class_name);
}
/*
* Allocates a memory buffer
* see cv::fastMalloc()
*/
void*
rbFastMalloc(size_t size)
{
uchar* udata = (uchar*)xmalloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
if(!udata) {
rb_raise(rb_eNoMemError, "Failed to allocate memory");
}
uchar** adata = cv::alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);
adata[-1] = udata;
return adata;
}
/*
* Allocates a memory buffer
* When memory allocation is failed, run GC and retry it
@ -42,26 +58,7 @@ raise_compatible_typeerror(VALUE object, const char* expected_class_name)
void*
rb_cvAlloc(size_t size)
{
void* ptr = NULL;
try {
ptr = cvAlloc(size);
}
catch(cv::Exception& e) {
if (e.code != CV_StsNoMem)
rb_raise(rb_eRuntimeError, "%s", e.what());
rb_gc_start();
try {
ptr = cvAlloc(size);
}
catch (cv::Exception& e) {
if (e.code == CV_StsNoMem)
rb_raise(rb_eNoMemError, "%s", e.what());
else
rb_raise(rb_eRuntimeError, "%s", e.what());
}
}
return ptr;
return rbFastMalloc(size);
}
/*
@ -69,28 +66,31 @@ rb_cvAlloc(size_t size)
* When memory allocation is failed, run GC and retry it
*/
CvMat*
rb_cvCreateMat(int height, int width, int type)
rb_cvCreateMat(int rows, int cols, int type)
{
CvMat* ptr = NULL;
CvMat* mat = NULL;
try {
ptr = cvCreateMat(height, width, type);
mat = cvCreateMatHeader(rows, cols, type);
if (mat) {
// see OpenCV's cvCreateData()
size_t step = mat->step;
size_t total_size = step * mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
mat->refcount = (int*)rbFastMalloc(total_size);
mat->data.ptr = (uchar*)cvAlignPtr(mat->refcount + 1, CV_MALLOC_ALIGN);
*mat->refcount = 1;
}
else {
rb_raise(rb_eRuntimeError, "Failed to create mat header");
}
}
catch(cv::Exception& e) {
if (e.code != CV_StsNoMem)
rb_raise(rb_eRuntimeError, "%s", e.what());
rb_gc_start();
try {
ptr = cvCreateMat(height, width, type);
}
catch (cv::Exception& e) {
if (e.code == CV_StsNoMem)
rb_raise(rb_eNoMemError, "%s", e.what());
else
rb_raise(rb_eRuntimeError, "%s", e.what());
if (mat) {
cvReleaseMat(&mat);
}
rb_raise(rb_eRuntimeError, "%s", e.what());
}
return ptr;
return mat;
}
/*
@ -102,22 +102,20 @@ rb_cvCreateImage(CvSize size, int depth, int channels)
{
IplImage* ptr = NULL;
try {
ptr = cvCreateImage(size, depth, channels);
ptr = cvCreateImageHeader(size, depth, channels);
if (ptr) {
// see OpenCV's cvCreateData()
ptr->imageData = ptr->imageDataOrigin = (char*)rbFastMalloc((size_t)ptr->imageSize);
}
else {
rb_raise(rb_eRuntimeError, "Failed to create image header");
}
}
catch(cv::Exception& e) {
if (e.code != CV_StsNoMem)
rb_raise(rb_eRuntimeError, "%s", e.what());
rb_gc_start();
try {
ptr = cvCreateImage(size, depth, channels);
}
catch (cv::Exception& e) {
if (e.code == CV_StsNoMem)
rb_raise(rb_eNoMemError, "%s", e.what());
else
rb_raise(rb_eRuntimeError, "%s", e.what());
if (ptr) {
cvReleaseImage(&ptr);
}
rb_raise(rb_eRuntimeError, "%s", e.what());
}
return ptr;
}

View file

@ -11,6 +11,7 @@
#include <ruby.h>
#include "opencv2/core/core_c.h"
#include "opencv2/core/core.hpp"
#include "opencv2/core/internal.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"