From 412f9eb214c63b5f149c03b61e0f8c354c001ba8 Mon Sep 17 00:00:00 2001 From: Sigoden Huang Date: Tue, 12 Jun 2018 11:11:12 +0800 Subject: [PATCH 1/8] =?UTF-8?q?[fix]=20field=20=E2=80=98timestamp=E2=80=99?= =?UTF-8?q?=20has=20incomplete=20type,=20closes=20#44?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- capture.h | 1 + 1 file changed, 1 insertion(+) diff --git a/capture.h b/capture.h index 31188bb..02afa80 100644 --- a/capture.h +++ b/capture.h @@ -1,6 +1,7 @@ #ifndef CAMERA_H #define CAMERA_H +#include #include #include #include From db1f20671b53cb1f3e1bca3a636b1ca863003fbb Mon Sep 17 00:00:00 2001 From: Sigoden Huang Date: Tue, 12 Jun 2018 11:13:51 +0800 Subject: [PATCH 2/8] [fix] check failed: receiver->IsJSFunction(), closes #34 --- v4l2camera.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v4l2camera.cc b/v4l2camera.cc index 6beb6dd..208faba 100644 --- a/v4l2camera.cc +++ b/v4l2camera.cc @@ -306,6 +306,9 @@ namespace { Nan::ThrowError(cameraError(camera)); return; } + if (info.Length() < 1) { + return; + } Watch(info, StopCB); } From 1a81c3a4b2022b236aceaedb03cc4ebb4de678db Mon Sep 17 00:00:00 2001 From: Sigoden Huang Date: Tue, 12 Jun 2018 11:17:52 +0800 Subject: [PATCH 3/8] [update] add android supports --- binding.gyp | 14 ++++++++++---- package.json | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/binding.gyp b/binding.gyp index 4fc3358..fe535d3 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,14 +4,20 @@ "target_name": "v4l2camera", "sources": ["capture.c", "v4l2camera.cc"], "include_dirs" : [ - "=2.3.0" From 714b9287a4052c1fd0b998d4b9ee1a01d3f44c27 Mon Sep 17 00:00:00 2001 From: sebakerckhof Date: Fri, 22 Jun 2018 13:40:56 +0200 Subject: [PATCH 4/8] Temporarily disable optional code that contains removed info.Callee() call --- package.json | 5 +++-- v4l2camera.cc | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index ce055fe..9438ee8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { - "name": "v4l2camera", - "version": "1.0.4", + "name": "@barco/v4l2camera", + "version": "1.0.8", + "publishConfig": { "registry": "https://bin.barco.com/artifactory/api/npm/npm-local"}, "description": "Capturing images from USB(UVC) webcam on linux machines", "keywords": [ "linux", diff --git a/v4l2camera.cc b/v4l2camera.cc index 208faba..92991e2 100644 --- a/v4l2camera.cc +++ b/v4l2camera.cc @@ -246,16 +246,16 @@ namespace { } return formats; } - + NAN_METHOD(Camera::New) { - if (!info.IsConstructCall()) { - // [NOTE] generic recursive call with `new` - std::vector> args(info.Length()); - for (auto i = std::size_t{0}; i < args.size(); ++i) args[i] = info[i]; - auto inst = Nan::NewInstance(info.Callee(), args.size(), args.data()); - if (!inst.IsEmpty()) info.GetReturnValue().Set(inst.ToLocalChecked()); - return; - } + // if (!info.IsConstructCall()) { + // // [NOTE] generic recursive call with `new` + // std::vector> args(info.Length()); + // for (auto i = std::size_t{0}; i < args.size(); ++i) args[i] = info[i]; + // auto inst = Nan::NewInstance(info.Callee(), args.size(), args.data()); + // if (!inst.IsEmpty()) info.GetReturnValue().Set(inst.ToLocalChecked()); + // return; + // } if (info.Length() < 1) { Nan::ThrowTypeError("argument required: device"); From c9de456a8d6699168fe903d9fbf3e517db270007 Mon Sep 17 00:00:00 2001 From: seke Date: Wed, 26 Jun 2019 16:20:11 +0200 Subject: [PATCH 5/8] Add v4l device capabilities --- capture.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++--- capture.h | 4 +++ v4l2camera.cc | 21 +++++++++++-- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/capture.c b/capture.c index d80be75..6309328 100644 --- a/capture.c +++ b/capture.c @@ -57,6 +57,8 @@ camera_t* camera_open(const char * device) camera->initialized = false; camera->width = 0; camera->height = 0; + camera->capabilities = 0; + camera->device_capabilities = 0; camera->buffer_count = 0; camera->buffers = NULL; camera->head.length = 0; @@ -77,12 +79,12 @@ static void free_buffers(camera_t* camera, size_t count) } static bool camera_init(camera_t* camera) { - struct v4l2_capability cap; - if (xioctl(camera->fd, VIDIOC_QUERYCAP, &cap) == -1) - return error(camera, "VIDIOC_QUERYCAP"); - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + if (camera->initialized) + return true; + + if (!(camera->capabilities & V4L2_CAP_VIDEO_CAPTURE)) return failure(camera, "no capture"); - if (!(cap.capabilities & V4L2_CAP_STREAMING)) + if (!(camera->capabilities & V4L2_CAP_STREAMING)) return failure(camera, "no streaming"); struct v4l2_cropcap cropcap; @@ -100,6 +102,70 @@ static bool camera_init(camera_t* camera) { return true; } +char** cap2s(unsigned cap) +{ + char **caps = calloc (sizeof(char*), 128); + int i = 0; + + if (cap & V4L2_CAP_VIDEO_CAPTURE) + caps[i++] = "Video Capture"; + if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + caps[i++] = "Video Capture Multiplanar"; + if (cap & V4L2_CAP_VIDEO_OUTPUT) + caps[i++] = "Video Output"; + if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE) + caps[i++] = "Video Output Multiplanar"; + if (cap & V4L2_CAP_VIDEO_M2M) + caps[i++] = "Video Memory-to-Memory"; + if (cap & V4L2_CAP_VIDEO_M2M_MPLANE) + caps[i++] = "Video Memory-to-Memory Multiplanar"; + if (cap & V4L2_CAP_VIDEO_OVERLAY) + caps[i++] = "Video Overlay"; + if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) + caps[i++] = "Video Output Overlay"; + if (cap & V4L2_CAP_VBI_CAPTURE) + caps[i++] = "VBI Capture"; + if (cap & V4L2_CAP_VBI_OUTPUT) + caps[i++] = "VBI Output"; + if (cap & V4L2_CAP_SLICED_VBI_CAPTURE) + caps[i++] = "Sliced VBI Capture"; + if (cap & V4L2_CAP_SLICED_VBI_OUTPUT) + caps[i++] = "Sliced VBI Output"; + if (cap & V4L2_CAP_RDS_CAPTURE) + caps[i++] = "RDS Capture"; + if (cap & V4L2_CAP_RDS_OUTPUT) + caps[i++] = "RDS Output"; + if (cap & V4L2_CAP_SDR_CAPTURE) + caps[i++] = "SDR Capture"; + if (cap & V4L2_CAP_SDR_OUTPUT) + caps[i++] = "SDR Output"; + if (cap & V4L2_CAP_META_CAPTURE) + caps[i++] = "Metadata Capture"; + if (cap & V4L2_CAP_TUNER) + caps[i++] = "Tuner"; + if (cap & V4L2_CAP_TOUCH) + caps[i++] = "Touch Device"; + if (cap & V4L2_CAP_HW_FREQ_SEEK) + caps[i++] = "HW Frequency Seek"; + if (cap & V4L2_CAP_MODULATOR) + caps[i++] = "Modulator"; + if (cap & V4L2_CAP_AUDIO) + caps[i++] = "Audio"; + if (cap & V4L2_CAP_RADIO) + caps[i++] = "Radio"; + if (cap & V4L2_CAP_READWRITE) + caps[i++] = "Read/Write"; + if (cap & V4L2_CAP_ASYNCIO) + caps[i++] = "Async I/O"; + if (cap & V4L2_CAP_STREAMING) + caps[i++] = "Streaming"; + if (cap & V4L2_CAP_EXT_PIX_FORMAT) + caps[i++] = "Extended Pix Format"; + if (cap & V4L2_CAP_DEVICE_CAPS) + caps[i++] = "Device Capabilities"; + return caps; +} + static bool camera_buffer_prepare(camera_t* camera) { struct v4l2_requestbuffers req; @@ -355,6 +421,17 @@ bool camera_config_set(camera_t* camera, const camera_format_t* format) return camera_buffer_prepare(camera); } +void camera_capabilities(camera_t* camera) { + struct v4l2_capability cap; + if (xioctl(camera->fd, VIDIOC_QUERYCAP, &cap) == -1) + return error(camera, "VIDIOC_QUERYCAP"); + + camera->capabilities = cap.capabilities; + + if (cap.capabilities & V4L2_CAP_DEVICE_CAPS) + camera->device_capabilities = cap.device_caps; +} + camera_formats_t* camera_formats_new(const camera_t* camera) { camera_formats_t* ret = malloc(sizeof (camera_formats_t)); diff --git a/capture.h b/capture.h index 02afa80..3582945 100644 --- a/capture.h +++ b/capture.h @@ -38,6 +38,8 @@ typedef struct { uint32_t width; uint32_t height; size_t buffer_count; + uint32_t capabilities; + uint32_t device_capabilities; camera_buffer_t* buffers; camera_buffer_t head; camera_context_t context; @@ -76,6 +78,8 @@ void camera_formats_delete(camera_formats_t* formats); bool camera_config_get(camera_t* camera, camera_format_t* format); bool camera_config_set(camera_t* camera, const camera_format_t* format); +char** cap2s(unsigned caps); +void camera_capabilities(camera_t* camera); typedef enum { CAMERA_CTRL_INTEGER = 1, diff --git a/v4l2camera.cc b/v4l2camera.cc index 92991e2..b7a3be4 100644 --- a/v4l2camera.cc +++ b/v4l2camera.cc @@ -83,7 +83,7 @@ namespace { getUint(const v8::Local& self, const char* name) { return Nan::To(getValue(self, name)).FromJust(); } - + static inline void setValue(const v8::Local& self, const char* name, const v8::Local& value) { @@ -247,6 +247,18 @@ namespace { return formats; } + static v8::Local convertCapabilities(unsigned flags) { + char** ccaps = cap2s(flags); + size_t len; + for (len = 0; ccaps[len] != NULL; len++); + auto caps = Nan::New(len); + for (auto i = std::size_t{0}; i < len; ++i) { + Nan::Set(caps, i, Nan::New(ccaps[i]).ToLocalChecked()); + } + free(ccaps); + return caps; + } + NAN_METHOD(Camera::New) { // if (!info.IsConstructCall()) { // // [NOTE] generic recursive call with `new` @@ -274,9 +286,15 @@ namespace { auto self = new Camera; self->camera = camera; self->Wrap(thisObj); + camera_capabilities(camera); + setValue(thisObj, "device", info[0]); setValue(thisObj, "formats", cameraFormats(camera)); setValue(thisObj, "controls", cameraControls(camera)); + setUint(thisObj, "rawCapabilities", camera->capabilities); + setUint(thisObj, "rawDeviceCapabilities", camera->device_capabilities); + setValue(thisObj, "capabilities", convertCapabilities(camera->capabilities)); + setValue(thisObj, "deviceCapabilities", convertCapabilities(camera->device_capabilities)); } NAN_METHOD(Camera::Start) { @@ -291,7 +309,6 @@ namespace { info.GetReturnValue().Set(thisObj); } - void Camera::StopCB(uv_poll_t* handle, int /*status*/, int /*events*/) { auto callCallback = [](CallbackData* data) -> void { Nan::HandleScope scope; From 8cc7730fd230ac949030a312a628fa23f8902130 Mon Sep 17 00:00:00 2001 From: seke Date: Wed, 26 Jun 2019 16:26:13 +0200 Subject: [PATCH 6/8] Bump version --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9438ee8..11fbeca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,10 @@ { "name": "@barco/v4l2camera", - "version": "1.0.8", - "publishConfig": { "registry": "https://bin.barco.com/artifactory/api/npm/npm-local"}, + "version": "1.1.0", + "upstreamVersion": "1.0.4", + "publishConfig": { + "registry": "https://bin.barco.com/artifactory/api/npm/npm-local" + }, "description": "Capturing images from USB(UVC) webcam on linux machines", "keywords": [ "linux", From fbad5abb3035c97c8d2bafa2e034ad7f2a55c112 Mon Sep 17 00:00:00 2001 From: seke Date: Wed, 4 Sep 2019 14:46:19 +0200 Subject: [PATCH 7/8] Update for node 12 --- package.json | 8 ++++---- test.js | 11 +++++++++++ v4l2camera.cc | 11 ++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 11fbeca..6e6fb18 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@barco/v4l2camera", - "version": "1.1.0", - "upstreamVersion": "1.0.4", + "version": "1.2.0", + "upstreamVersion": "1.0.4", "publishConfig": { "registry": "https://bin.barco.com/artifactory/api/npm/npm-local" }, @@ -32,7 +32,7 @@ "jpeg-js": "*" }, "engines": { - "node": ">=4.0.0" + "node": ">=10.0.0" }, "scripts": { "test": "node test.js", @@ -43,7 +43,7 @@ "android" ], "dependencies": { - "nan": ">=2.3.0" + "nan": "^2.14.0" }, "contributors": [ "Tim Cameron Ryan (https://github.com/tcr)", diff --git a/test.js b/test.js index b622dba..3988733 100644 --- a/test.js +++ b/test.js @@ -1,2 +1,13 @@ // this script for travis-ci, but its linux kernel is old 2.6 var v4l2camera = require("./"); + +try { + const camera = v4l2camera.Camera('/dev/video0'); + camera.configSet(camera.formats[6]); + console.log(camera.controlGet(9963778)); +camera.controlSet(9963778, 50) + console.log(camera.controlGet(9963778)); + debugger; +} catch (error) { +debugger; +} diff --git a/v4l2camera.cc b/v4l2camera.cc index b7a3be4..16cc78b 100644 --- a/v4l2camera.cc +++ b/v4l2camera.cc @@ -212,7 +212,7 @@ namespace { auto denominator = std::uint32_t{0}; const auto finterval = getValue(format, "interval"); if (finterval->IsObject()) { - const auto interval = finterval->ToObject(); + const auto interval = finterval->ToObject(Nan::GetCurrentContext()).ToLocalChecked(); numerator = getUint(interval, "numerator"); denominator = getUint(interval, "denominator"); } @@ -259,6 +259,7 @@ namespace { return caps; } + NAN_METHOD(Camera::New) { // if (!info.IsConstructCall()) { // // [NOTE] generic recursive call with `new` @@ -384,7 +385,7 @@ namespace { Nan::ThrowTypeError("argument required: config"); return; } - const auto cformat = convertCFormat(info[0]->ToObject()); + const auto cformat = convertCFormat(info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked()); auto thisObj = info.Holder(); auto camera = Nan::ObjectWrap::Unwrap(thisObj)->camera; if (!camera_config_set(camera, &cformat)) { @@ -401,7 +402,7 @@ namespace { Nan::ThrowTypeError("an argument required: id"); return; } - const auto id = info[0]->Uint32Value(); + const auto id = Nan::To(info[0]).FromJust(); auto camera = Nan::ObjectWrap::Unwrap(info.Holder())->camera; auto value = std::int32_t{0}; auto success = bool{camera_control_get(camera, id, &value)}; @@ -417,8 +418,8 @@ namespace { Nan::ThrowTypeError("arguments required: id, value"); return; } - const auto id = info[0]->Uint32Value(); - const auto value = info[1]->Int32Value(); + const auto id = Nan::To(info[0]).FromJust(); + const auto value = Nan::To(info[1]).FromJust(); auto thisObj = info.Holder(); auto camera = Nan::ObjectWrap::Unwrap(thisObj)->camera; auto success = bool{camera_control_set(camera, id, value)}; From 4481dfadf7a33280512d1a486f61d48ecf6595f0 Mon Sep 17 00:00:00 2001 From: seke Date: Wed, 4 Sep 2019 14:47:37 +0200 Subject: [PATCH 8/8] Make public --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 6e6fb18..28489ce 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { - "name": "@barco/v4l2camera", + "name": "v4l2camera", "version": "1.2.0", - "upstreamVersion": "1.0.4", "publishConfig": { "registry": "https://bin.barco.com/artifactory/api/npm/npm-local" },