mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
282 lines
6.8 KiB
C++
Executable File
282 lines
6.8 KiB
C++
Executable File
#include "VideoCaptureWrap.h"
|
|
#include "Matrix.h"
|
|
#include "OpenCV.h"
|
|
|
|
#include <iostream>
|
|
|
|
Nan::Persistent<FunctionTemplate> VideoCaptureWrap::constructor;
|
|
|
|
struct videocapture_baton {
|
|
|
|
Nan::Persistent<Function> cb;
|
|
VideoCaptureWrap *vc;
|
|
Matrix *im;
|
|
|
|
uv_work_t request;
|
|
};
|
|
|
|
void VideoCaptureWrap::Init(Local<Object> target) {
|
|
Nan::HandleScope scope;
|
|
|
|
//Class
|
|
Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(VideoCaptureWrap::New);
|
|
constructor.Reset(ctor);
|
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
|
ctor->SetClassName(Nan::New("VideoCapture").ToLocalChecked());
|
|
|
|
// Prototype
|
|
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
|
|
|
Nan::SetPrototypeMethod(ctor, "read", Read);
|
|
Nan::SetPrototypeMethod(ctor, "setWidth", SetWidth);
|
|
Nan::SetPrototypeMethod(ctor, "setHeight", SetHeight);
|
|
Nan::SetPrototypeMethod(ctor, "setPosition", SetPosition);
|
|
Nan::SetPrototypeMethod(ctor, "getFrameAt", GetFrameAt);
|
|
Nan::SetPrototypeMethod(ctor, "getFrameCount", GetFrameCount);
|
|
Nan::SetPrototypeMethod(ctor, "release", Release);
|
|
Nan::SetPrototypeMethod(ctor, "ReadSync", ReadSync);
|
|
Nan::SetPrototypeMethod(ctor, "grab", Grab);
|
|
Nan::SetPrototypeMethod(ctor, "retrieve", Retrieve);
|
|
|
|
target->Set(Nan::New("VideoCapture").ToLocalChecked(), ctor->GetFunction());
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::New) {
|
|
Nan::HandleScope scope;
|
|
|
|
if (info.This()->InternalFieldCount() == 0)
|
|
return Nan::ThrowTypeError("Cannot Instantiate without new");
|
|
|
|
VideoCaptureWrap *v;
|
|
|
|
if (info[0]->IsNumber()) {
|
|
v = new VideoCaptureWrap(info[0]->NumberValue());
|
|
} else {
|
|
//TODO - assumes that we have string, verify
|
|
v = new VideoCaptureWrap(std::string(*Nan::Utf8String(info[0]->ToString())));
|
|
}
|
|
|
|
v->Wrap(info.This());
|
|
|
|
info.GetReturnValue().Set(info.This());
|
|
}
|
|
|
|
VideoCaptureWrap::VideoCaptureWrap(int device) {
|
|
Nan::HandleScope scope;
|
|
cap.open(device);
|
|
|
|
if(!cap.isOpened()) {
|
|
Nan::ThrowError("Camera could not be opened");
|
|
}
|
|
}
|
|
|
|
VideoCaptureWrap::VideoCaptureWrap(const std::string& filename) {
|
|
Nan::HandleScope scope;
|
|
cap.open(filename);
|
|
// TODO! At the moment this only takes a full path - do relative too.
|
|
if(!cap.isOpened()) {
|
|
Nan::ThrowError("Video file could not be opened (opencv reqs. non relative paths)");
|
|
}
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::SetWidth) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
if(info.Length() != 1)
|
|
return;
|
|
|
|
int w = info[0]->IntegerValue();
|
|
|
|
if(v->cap.isOpened())
|
|
v->cap.set(CV_CAP_PROP_FRAME_WIDTH, w);
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::GetFrameCount) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
int cnt = int(v->cap.get(CV_CAP_PROP_FRAME_COUNT));
|
|
|
|
info.GetReturnValue().Set(Nan::New<Number>(cnt));
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::SetHeight) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
if(info.Length() != 1)
|
|
return;
|
|
|
|
int h = info[0]->IntegerValue();
|
|
|
|
v->cap.set(CV_CAP_PROP_FRAME_HEIGHT, h);
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::SetPosition) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
if(info.Length() != 1)
|
|
return;
|
|
|
|
int pos = info[0]->IntegerValue();
|
|
|
|
v->cap.set(CV_CAP_PROP_POS_FRAMES, pos);
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::GetFrameAt) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
if(info.Length() != 1)
|
|
return;
|
|
|
|
int pos = info[0]->IntegerValue();
|
|
|
|
v->cap.set(CV_CAP_PROP_POS_MSEC, pos);
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::Release) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
v->cap.release();
|
|
|
|
return;
|
|
}
|
|
|
|
class AsyncVCWorker: public Nan::AsyncWorker {
|
|
public:
|
|
AsyncVCWorker(Nan::Callback *callback, VideoCaptureWrap* vc,
|
|
bool retrieve = false, int channel = 0) :
|
|
Nan::AsyncWorker(callback),
|
|
vc(vc),
|
|
retrieve(retrieve),
|
|
channel(channel) {
|
|
}
|
|
|
|
~AsyncVCWorker() {
|
|
}
|
|
|
|
// Executed inside the worker-thread.
|
|
// It is not safe to access V8, or V8 data structures
|
|
// here, so everything we need for input and output
|
|
// should go on `this`.
|
|
void Execute() {
|
|
if (retrieve) {
|
|
if (!this->vc->cap.retrieve(mat, channel)) {
|
|
SetErrorMessage("retrieve failed");
|
|
}
|
|
return;
|
|
}
|
|
this->vc->cap.read(mat);
|
|
}
|
|
|
|
// Executed when the async work is complete
|
|
// this function will be run inside the main event loop
|
|
// so it is safe to use V8 again
|
|
void HandleOKCallback() {
|
|
Nan::HandleScope scope;
|
|
|
|
Local<Object> im_to_return= Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
|
|
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im_to_return);
|
|
img->mat = mat;
|
|
|
|
Local<Value> argv[] = {
|
|
Nan::Null()
|
|
, im_to_return
|
|
};
|
|
|
|
Nan::TryCatch try_catch;
|
|
callback->Call(2, argv);
|
|
if (try_catch.HasCaught()) {
|
|
Nan::FatalException(try_catch);
|
|
}
|
|
}
|
|
|
|
private:
|
|
VideoCaptureWrap *vc;
|
|
cv::Mat mat;
|
|
bool retrieve;
|
|
int channel;
|
|
};
|
|
|
|
NAN_METHOD(VideoCaptureWrap::Read) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
REQ_FUN_ARG(0, cb);
|
|
|
|
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
|
Nan::AsyncQueueWorker(new AsyncVCWorker(callback, v));
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::ReadSync) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
Local<Object> im_to_return= Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
|
|
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im_to_return);
|
|
|
|
v->cap.read(img->mat);
|
|
|
|
info.GetReturnValue().Set(im_to_return);
|
|
}
|
|
|
|
class AsyncGrabWorker: public Nan::AsyncWorker {
|
|
public:
|
|
AsyncGrabWorker(Nan::Callback *callback, VideoCaptureWrap* vc) :
|
|
Nan::AsyncWorker(callback),
|
|
vc(vc) {
|
|
}
|
|
|
|
~AsyncGrabWorker() {
|
|
}
|
|
|
|
void Execute() {
|
|
if (!this->vc->cap.grab()) {
|
|
SetErrorMessage("grab failed");
|
|
}
|
|
}
|
|
|
|
private:
|
|
VideoCaptureWrap *vc;
|
|
};
|
|
|
|
NAN_METHOD(VideoCaptureWrap::Grab) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
REQ_FUN_ARG(0, cb);
|
|
|
|
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
|
Nan::AsyncQueueWorker(new AsyncGrabWorker(callback, v));
|
|
|
|
return;
|
|
}
|
|
|
|
NAN_METHOD(VideoCaptureWrap::Retrieve) {
|
|
Nan::HandleScope scope;
|
|
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
|
|
|
|
int channel = 0;
|
|
REQ_FUN_ARG(0, cb);
|
|
INT_FROM_ARGS(channel, 1);
|
|
|
|
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
|
Nan::AsyncQueueWorker(new AsyncVCWorker(callback, v, true, channel));
|
|
|
|
return;
|
|
}
|