mirror of
https://github.com/ruby-opencv/ruby-opencv
synced 2023-03-27 23:22:12 -04:00
fix issue #22
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:
parent
20ba28b3bf
commit
21adfe1035
3 changed files with 67 additions and 61 deletions
|
@ -187,21 +187,25 @@ VALUE
|
||||||
rb_retrieve(VALUE self)
|
rb_retrieve(VALUE self)
|
||||||
{
|
{
|
||||||
VALUE image = Qnil;
|
VALUE image = Qnil;
|
||||||
|
IplImage *frame = NULL;
|
||||||
try {
|
try {
|
||||||
IplImage *frame = cvRetrieveFrame(CVCAPTURE(self));
|
if (!(frame = cvRetrieveFrame(CVCAPTURE(self)))) {
|
||||||
if (!frame)
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
image = cIplImage::new_object(cvSize(frame->width, frame->height),
|
}
|
||||||
CV_MAKETYPE(CV_8U, frame->nChannels));
|
image = cIplImage::new_object(frame->width, frame->height,
|
||||||
if (frame->origin == IPL_ORIGIN_TL)
|
CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels));
|
||||||
|
if (frame->origin == IPL_ORIGIN_TL) {
|
||||||
cvCopy(frame, CVARR(image));
|
cvCopy(frame, CVARR(image));
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
cvFlip(frame, CVARR(image));
|
cvFlip(frame, CVARR(image));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (cv::Exception& e) {
|
catch (cv::Exception& e) {
|
||||||
raise_cverror(e);
|
raise_cverror(e);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -214,16 +218,19 @@ VALUE
|
||||||
rb_query(VALUE self)
|
rb_query(VALUE self)
|
||||||
{
|
{
|
||||||
VALUE image = Qnil;
|
VALUE image = Qnil;
|
||||||
|
IplImage *frame = NULL;
|
||||||
try {
|
try {
|
||||||
IplImage *frame = cvQueryFrame(CVCAPTURE(self));
|
if (!(frame = cvQueryFrame(CVCAPTURE(self)))) {
|
||||||
if (!frame)
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
image = cIplImage::new_object(cvSize(frame->width, frame->height),
|
}
|
||||||
CV_MAKETYPE(CV_8U, frame->nChannels));
|
image = cIplImage::new_object(frame->width, frame->height,
|
||||||
if (frame->origin == IPL_ORIGIN_TL)
|
CV_MAKETYPE(IPL2CV_DEPTH(frame->depth), frame->nChannels));
|
||||||
|
if (frame->origin == IPL_ORIGIN_TL) {
|
||||||
cvCopy(frame, CVARR(image));
|
cvCopy(frame, CVARR(image));
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
cvFlip(frame, CVARR(image));
|
cvFlip(frame, CVARR(image));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (cv::Exception& e) {
|
catch (cv::Exception& e) {
|
||||||
raise_cverror(e);
|
raise_cverror(e);
|
||||||
|
|
|
@ -35,6 +35,22 @@ raise_compatible_typeerror(VALUE object, const char* expected_class_name)
|
||||||
rb_obj_classname(object), 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
|
* Allocates a memory buffer
|
||||||
* When memory allocation is failed, run GC and retry it
|
* 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*
|
void*
|
||||||
rb_cvAlloc(size_t size)
|
rb_cvAlloc(size_t size)
|
||||||
{
|
{
|
||||||
void* ptr = NULL;
|
return rbFastMalloc(size);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,28 +66,31 @@ rb_cvAlloc(size_t size)
|
||||||
* When memory allocation is failed, run GC and retry it
|
* When memory allocation is failed, run GC and retry it
|
||||||
*/
|
*/
|
||||||
CvMat*
|
CvMat*
|
||||||
rb_cvCreateMat(int height, int width, int type)
|
rb_cvCreateMat(int rows, int cols, int type)
|
||||||
{
|
{
|
||||||
CvMat* ptr = NULL;
|
CvMat* mat = NULL;
|
||||||
try {
|
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) {
|
catch(cv::Exception& e) {
|
||||||
if (e.code != CV_StsNoMem)
|
if (mat) {
|
||||||
rb_raise(rb_eRuntimeError, "%s", e.what());
|
cvReleaseMat(&mat);
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
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;
|
IplImage* ptr = NULL;
|
||||||
try {
|
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) {
|
catch(cv::Exception& e) {
|
||||||
if (e.code != CV_StsNoMem)
|
if (ptr) {
|
||||||
rb_raise(rb_eRuntimeError, "%s", e.what());
|
cvReleaseImage(&ptr);
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
rb_raise(rb_eRuntimeError, "%s", e.what());
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
#include "opencv2/core/core_c.h"
|
#include "opencv2/core/core_c.h"
|
||||||
#include "opencv2/core/core.hpp"
|
#include "opencv2/core/core.hpp"
|
||||||
|
#include "opencv2/core/internal.hpp"
|
||||||
#include "opencv2/imgproc/imgproc_c.h"
|
#include "opencv2/imgproc/imgproc_c.h"
|
||||||
#include "opencv2/imgproc/imgproc.hpp"
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue