Giter Site home page Giter Site logo

pymagewell's Introduction

pymagewell

pymagewell is a Python library for interfacing with Magewell ProCapture frame grabbers.

It is based on (and includes) Magewell's Windows SDK and is therefore Windows only. However, it provides a mock class that for testing and development that does not depend on the SDK's Windows .dll files, so pymagwell can also be installed on macOS and Linux.

Installation

From PyPI:

pip install pymagewell

From conda-forge (Windows and macOS only):

conda install -c conda-forge pymagewell

Example of use

A full working example is provided in example_script.py.

First, create a ProCaptureSettings dataclass:

from pymagewell import (
    ProCaptureSettings, ImageSizeInPixels, TransferMode, ColourFormat
)

device_settings = ProCaptureSettings(
    dimensions=ImageSizeInPixels(1920, 1080),
    color_format=ColourFormat.BGR24,  # Color format of captured video frames
    transfer_mode=TransferMode.LOW_LATENCY,
    num_lines_per_chunk=64  # has effect only in low latency mode
)

Then create a ProCaptureDevice (or MockProCaptureDevice for testing on a system without a grabber) configured with your chosen settings:

from pymagewell import ProCaptureDevice

device = ProCaptureDevice(settings=device_settings)

Then create a ProCaptureDeviceController to transfer frames from the device to your PC:

from pymagewell import ProCaptureController

controller = ProCaptureController(device)

Then you can grab frames in a loop using the transfer_when_ready() method, which will wait until a frame has been acquired by the device, transfer it from the device to the PC, and return it as a VideoFrame object. This is a blocking call.

while True:
    frame = controller.transfer_when_ready()

VideoFrame provides access to the pixels as a Numpy array with its as_array method. It also provides access to timestamps (datetime.datetime) describing the frame acquisition process:

t1 = frame.timestamps.buffering_started  # time at which frame started being written to the hardware buffer
buffer
t2 = frame.timestamps.buffering_complete  # time at which frame was completely written to the hardware buffer
t3 = frame.timestamps.transfer_started  # time at which the software started transferring the frame to PC memory
t4 = frame.timestamps.transfer_complete  # time by which the whole frame had arrived in PC memory

In TIMER and NORMAL transfer modes, transfer starts after the full frame has been written to hardware buffer. In LOW_LATENCY transfer mode, transfer starts while the frame is still being written to hardware memory. This will be reflected in the timestamps.

pymagewell's People

Contributors

crnbaker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pymagewell's Issues

linux support - any specific reason or just "no linux"?

magewell SDK provides dynamic library also for Linux, so I would assume it would have similar to .dll API?

I've not done of "loading dynamic libraries from Python" recently so not sure what to do about following but I would expect it to be possible to load the .so as well:

In [1]: from ctypes import cdll

In [2]: l = cdll.LoadLibrary('./Capture/Lib/x64/libMWCapture.so')
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Input In [2], in <cell line: 1>()
----> 1 l = cdll.LoadLibrary('./Capture/Lib/x64/libMWCapture.so')

File /usr/lib/python3.10/ctypes/__init__.py:452, in LibraryLoader.LoadLibrary(self, name)
    451 def LoadLibrary(self, name):
--> 452     return self._dlltype(name)

File /usr/lib/python3.10/ctypes/__init__.py:374, in CDLL.__init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    371 self._FuncPtr = _FuncPtr
    373 if handle is None:
--> 374     self._handle = _dlopen(self._name, mode)
    375 else:
    376     self._handle = handle

OSError: ./Capture/Lib/x64/libMWCapture.so: undefined symbol: snd_mixer_first_elem

where that symbol is provided by /usr/lib/x86_64-linux-gnu/libasound.so, but libMWCapture.so didn't link against it... googled myself into a solution

In [3]: from ctypes import CDLL, RTLD_GLOBAL

In [4]: CDLL('libasound.so', mode = RTLD_GLOBAL)
Out[4]: <CDLL 'libasound.so', handle 5618b3565990 at 0x7f86b8247eb0>

In [5]: CDLL('libudev.so', mode = RTLD_GLOBAL)
Out[5]: <CDLL 'libudev.so', handle 5618b3568d20 at 0x7f86b3548190>

In [6]: CDLL('libv4l2.so', mode = RTLD_GLOBAL)
Out[6]: <CDLL 'libv4l2.so', handle 5618b3552d70 at 0x7f86b8158d60>

In [7]: l = CDLL('./Capture/Lib/x64/libMWCapture.so', mode = RTLD_GLOBAL)

In [11]: l
Out[11]: <CDLL './Capture/Lib/x64/libMWCapture.so', handle 5618b32912c0 at 0x7f86b83a4490>

so I guess could be loaded fine under Linux ;-)

Multi device support

Dear Christian,

I'm testing the Magewell dual DVI device with your repository for a research implementation.
As far as I now understand in your current release it is not possible to easily switch between devices or input channels.
I've tried to run your example script, which works fine for input 0. For input 1 though it cannot read the time from the device after changing the 0 to a 1 on line 266 of pro_capture_device.py in the function capturer.mw_get_device_path(0, t_path).
It then throws an exception in: _get_device_time_in_ticks line 197.
Though it does not break anymore due to no video signal detected.

Would there be an easy implementation of making it possible to start 2 capture instances to grab frames with the same timestamp?

Best,
Enzo

Python 3.11 support

Condaforge bots unable to build on 3.11 because of mutable dataclass field with a default argument (see here.

Offending class: ProCaptureSettings
Offending field: dimensions

Enable low latency mode

Low latency mode allows:

  • chunks of a frame to be transferred to PC memory before the whole frame has been acquired by the card
  • the software application to be notifies each time a chunk is copied, so that the chunks can be processed by the application before the whole frame has been received

This is described in [this Magewell document(https://www.magewell.com/files/LowLatency%20&PartialNotification.pdf). This Magewell documentation page explains how to achieve this using the SDK.

In summary, instead of using a Timer to control the acquisition of frames, you register MWCAP_NOTIFY_VIDEO_FRAME_BUFFERING as an event, and when the event occurs, copy the last received chunk out of memory. The size of the chunks (number of lines) can be set using the cyParitalNotify input to the frame grabbing function (must be a power of 2, minimum 64).

For some reason, MWCAP_NOTIFY_VIDEO_FRAME_BUFFERING is not included as a constant in the Python wrapper for the SDK. From looking around in the C++ examples, I found that it should be:
#define MWCAP_NOTIFY_VIDEO_FRAME_BUFFERING 0x0100ULL

NB: Currently we use a timer to decide when to grab the frames. to use the source frame rate (without low latency mode) requires #define MWCAP_NOTIFY_VIDEO_FRAME_BUFFERED 0x0400ULL which is also not provided in the Python wrapper for some reason.

Support for USB devices?

Hi!
The Magewell SDK also supports their line of USB devices (like the USB Capture). Due to obvious hardware restrictions, some special functionality like low-latency mode is not available, but if you stay within the capabilities of the actual hardware their SDK is said to works just the same for the USB variants.

Is there any reason to assume your Python library will not work with USB devices, or have you just never tried?
Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.