Skip to content

Commit

Permalink
Merge pull request #99 from gift-surg/78-opencv-free-epiphan-dvi2pcie…
Browse files Browse the repository at this point in the history
…-duo-on-windows-for-91

OpenCV-free Epiphan DVI2PCIe Duo support on Windows for #91
  • Loading branch information
dzhoshkun authored Apr 16, 2019
2 parents bd6ec39 + c4124bc commit 524b7dd
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ windows:
script:
- mkdir build
- cd build
- cmake -A x64 -D CMAKE_BUILD_TYPE=Release -D PYTHON_INCLUDE_DIRS="%python_include_dirs%" -D PYTHON_LIBRARY="%python_library%" -D BOOST_INCLUDEDIR="%boost_includedir%" -D BOOST_LIBRARYDIR="%boost_librarydir%" -D ZLIB_ROOT="%zlib_root%" -D BUILD_PYTHON=ON -D USE_NUMPY=ON -D USE_EPIPHAN_DVI2PCIE_DUO=ON -D ENABLE_NONFREE=ON -D USE_EPIPHANSDK=ON -D USE_BGRA=OFF ../src
- cmake -A x64 -D CMAKE_BUILD_TYPE=Release -D PYTHON_INCLUDE_DIRS="%python_include_dirs%" -D PYTHON_LIBRARY="%python_library%" -D BOOST_INCLUDEDIR="%boost_includedir%" -D BOOST_LIBRARYDIR="%boost_librarydir%" -D ZLIB_ROOT="%zlib_root%" -D BUILD_PYTHON=ON -D USE_NUMPY=ON -D USE_EPIPHAN_DVI2PCIE_DUO=ON -D ENABLE_NONFREE=ON -D USE_EPIPHANSDK=ON ../src
- cmake --build . --config Release
- ls
- cd Release
Expand Down
11 changes: 5 additions & 6 deletions doc/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,15 @@ In addition, also the following two **BSD-3-incompatible** options are available

## Epiphan DVI2PCIe Duo

`-D USE_EPIPHAN_DVI2PCIE_DUO=ON` (requires [OpenCV](tips.md#opencv) and [libVLC](tips.md#libvlc))
`-D USE_EPIPHAN_DVI2PCIE_DUO=ON` (requires [libVLC](tips.md#libvlc), supports only [I420][i420] colour space captures)

OpenCV and libVLC are needed for capturing in the BGRA and [I420][i420] colour spaces respectively.
Both options are active by default.
Append `-D USE_BGRA=OFF` or `-D USE_I420=OFF` to deactivate the respective option.

Also Epiphan Video Grabber SDK can be used instead of libVLC:
To enable BGRA colour space captures, please use Epiphan Video Grabber SDK instead of libVLC:
`-D USE_EPIPHAN_DVI2PCIE_DUO=ON -D ENABLE_NONFREE=ON -D USE_EPIPHANSDK=ON` (requires zlib, pthreads and [Epiphan Video Grabber SDK](tips.md#epiphan-video-grabbing-sdk)).
This option **makes GIFT-Grab undistributable**.

Both colour spaces are active by default.
Append `-D USE_BGRA=OFF` or `-D USE_I420=OFF` to deactivate the respective option.

[i420]: https://wiki.videolan.org/YUV/#I420


Expand Down
4 changes: 3 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ if(USE_BLACKMAGIC_DECKLINK_4K_EXTREME_12G)
endif(USE_BLACKMAGIC_DECKLINK_4K_EXTREME_12G)

# Determine whether OpenCV needed
if(((USE_EPIPHAN_DVI2PCIE_DUO OR USE_NETWORK_SOURCES) AND USE_BGRA) OR
if((USE_NETWORK_SOURCES AND USE_BGRA) OR
USE_XVID)
SET(USE_OPENCV ON CACHE BOOL "OFF ON" FORCE)
endif()
Expand Down Expand Up @@ -270,7 +270,9 @@ if(USE_EPIPHANSDK)

INCLUDE_DIRECTORIES(epiphansdk)
LIST(APPEND HEADERS epiphansdk/epiphansdk_video_source.h)
LIST(APPEND HEADERS epiphansdk/rgb_to_bgra_converter.h)
LIST(APPEND SOURCES epiphansdk/epiphansdk_video_source.cpp)
LIST(APPEND SOURCES epiphansdk/rgb_to_bgra_converter.cpp)
endif(USE_EPIPHANSDK)

# Blackmagic SDK video source
Expand Down
14 changes: 8 additions & 6 deletions src/api/videosourcefactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ IVideoSource * VideoSourceFactory::get_device(Device device,

// BGRA ========================================
case BGRA:
#ifdef USE_OPENCV
src = new VideoSourceOpenCV(0);
#ifdef USE_EPIPHANSDK
src = new VideoSourceEpiphanSDK(Epiphan_DVI2PCIeDuo_DVI,
V2U_GRABFRAME_FORMAT_RGB24);
#else
throw VideoSourceError(
"BGRA colour space on Epiphan DVI2PCIe Duo supported only with OpenCV");
"BGRA colour space on Epiphan DVI2PCIe Duo supported only with Epiphan SDK");
#endif
break;

Expand Down Expand Up @@ -116,11 +117,12 @@ IVideoSource * VideoSourceFactory::get_device(Device device,

// BGRA ========================================
case BGRA:
#ifdef USE_OPENCV
src = new VideoSourceOpenCV(1);
#ifdef USE_EPIPHANSDK
src = new VideoSourceEpiphanSDK(Epiphan_DVI2PCIeDuo_SDI,
V2U_GRABFRAME_FORMAT_RGB24);
#else
throw VideoSourceError(
"BGRA colour space on Epiphan DVI2PCIe Duo supported only with OpenCV");
"BGRA colour space on Epiphan DVI2PCIe Duo supported only with Epiphan SDK");
#endif
break;

Expand Down
71 changes: 59 additions & 12 deletions src/epiphansdk/epiphansdk_video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ VideoSourceEpiphanSDK::VideoSourceEpiphanSDK(
, _frame_grabber(nullptr)
, _flags(0)
, _daemon(nullptr)
, _bgra_data(nullptr)
, _buffer(nullptr)
{
FrmGrab_Init();

Expand All @@ -30,7 +32,10 @@ VideoSourceEpiphanSDK::VideoSourceEpiphanSDK(
else if (colour_space == V2U_GRABFRAME_FORMAT_I420)
_colour = I420;
else
{
_colour = BGRA;
_flags |= V2U_GRABFRAME_BOTTOM_UP_FLAG; // for some reason without this the image is flipped
}
_flags |= colour_space;

VideoFrame frame(_colour);
Expand All @@ -42,6 +47,12 @@ VideoSourceEpiphanSDK::VideoSourceEpiphanSDK(
*/
_full.width = 1920;
_full.height = 1080;
if (_colour == BGRA)
{
_bgra_data = reinterpret_cast<unsigned char*>(malloc(
4 * _full.width * _full.height * sizeof(unsigned char)
));
}
get_full_frame();
// TODO - exception GiftGrab#42
if (!get_frame(frame)) return;
Expand All @@ -55,6 +66,11 @@ VideoSourceEpiphanSDK::~VideoSourceEpiphanSDK()
delete _daemon;
if (_frame_grabber) FrmGrab_Close(_frame_grabber);
FrmGrab_Deinit();
if (_colour == BGRA && _bgra_data != nullptr)
{
free(_bgra_data);
_bgra_data = nullptr;
}
}

bool VideoSourceEpiphanSDK::get_frame_dimensions(int & width, int & height)
Expand All @@ -70,21 +86,42 @@ bool VideoSourceEpiphanSDK::get_frame(VideoFrame & frame)
// TODO - exception GiftGrab#42
return false;

std::lock_guard<std::mutex> buffer_lock_guard(_buffer_lock);

_buffer = FrmGrab_Frame(_frame_grabber, _flags, &_roi);
if (_buffer)
{
unsigned char *data = static_cast<unsigned char*>(_buffer->pixbuf);
size_t frame_data_length = _buffer->imagelen;
/* TODO #54 specified _roi not always
* respected by FrmGrab_Frame, hence
* constructing with _buffer->crop
* instead of _roi to avoid alignment
* problems when saving to video files
*/
size_t frame_width = _buffer->crop.width,
frame_height = _buffer->crop.height;
unsigned char *frame_data = nullptr;
switch(_colour)
{
case I420:
frame_data = data;
break;
case BGRA:
_rgb_to_bgra.set_frame_dimensions(frame_width, frame_height);
_rgb_to_bgra.convert(data, _bgra_data);
frame_data = _bgra_data;
break;
default:
// TODO
break;
}
frame.init_from_specs(
static_cast<unsigned char*>(_buffer->pixbuf),
_buffer->imagelen,
/* TODO #54 specified _roi not always
* respected by FrmGrab_Frame, hence
* constructing with _buffer->crop
* instead of _roi to avoid alignment
* problems when saving to video files
*/
_buffer->crop.width, _buffer->crop.height
);
frame_data, frame_data_length,
frame_width, frame_height
);
FrmGrab_Release(_frame_grabber, _buffer);
_buffer = nullptr;
return true;
}
else
Expand All @@ -93,6 +130,7 @@ bool VideoSourceEpiphanSDK::get_frame(VideoFrame & frame)

double VideoSourceEpiphanSDK::get_frame_rate()
{
double frame_rate = -1;
if (_frame_grabber)
{
#if defined(Epiphan_DVI2PCIeDuo_DVI) && \
Expand All @@ -101,9 +139,18 @@ double VideoSourceEpiphanSDK::get_frame_rate()
defined(Epiphan_DVI2PCIeDuo_SDI_MAX_FRAME_RATE)
std::string port_id = FrmGrab_GetId(_frame_grabber);
if (port_id == Epiphan_DVI2PCIeDuo_DVI)
return Epiphan_DVI2PCIeDuo_DVI_MAX_FRAME_RATE;
frame_rate = Epiphan_DVI2PCIeDuo_DVI_MAX_FRAME_RATE;
else if (port_id == Epiphan_DVI2PCIeDuo_SDI)
return Epiphan_DVI2PCIeDuo_SDI_MAX_FRAME_RATE;
frame_rate = Epiphan_DVI2PCIeDuo_SDI_MAX_FRAME_RATE;
if (frame_rate > 0)
{
/* The above max frame rates are defined for I420,
* and are halved for BGRA, due to hardware bandwidth
*/
if (_colour == BGRA)
frame_rate /= 2.0;
return frame_rate;
}
#endif
}

Expand Down
20 changes: 19 additions & 1 deletion src/epiphansdk/epiphansdk_video_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "ivideosource.h"
#include "macros.h"
#include "broadcastdaemon.h"
#include "rgb_to_bgra_converter.h"

namespace gg
{
Expand Down Expand Up @@ -38,11 +39,28 @@ class GG_EXPORTS VideoSourceEpiphanSDK : public IVideoSource
//!
V2U_GrabFrame2 * _buffer;

//!
//! \brief This mutex to be locked when
//! accessing the buffer
//! \sa _buffer
//!
std::mutex _buffer_lock;

//!
//! \brief
//!
gg::BroadcastDaemon * _daemon;

//!
//! \brief Buffer for converting from RGB to BGRA
//!
unsigned char *_bgra_data;

//!
//! \brief RGB to BGRA converter
//!
RgbToBgraConverter _rgb_to_bgra;

public:
//!
//! \brief Connects to specified port of an Epiphan
Expand All @@ -51,7 +69,7 @@ class GG_EXPORTS VideoSourceEpiphanSDK : public IVideoSource
//! as \c \#define'd in Epiphan device properties
//! header
//! \param colour_space \c V2U_GRABFRAME_FORMAT_I420
//! or \c V2U_GRABFRAME_FORMAT_BGR24
//! or \c V2U_GRABFRAME_FORMAT_RGB24
//! \throw VideoSourceError if connection attempt
//! fails, with a detailed error message
//!
Expand Down
68 changes: 68 additions & 0 deletions src/epiphansdk/rgb_to_bgra_converter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "rgb_to_bgra_converter.h"
#include <assert.h>

namespace gg
{

RgbToBgraConverter::RgbToBgraConverter()
: _width(0)
, _height(0)
#ifdef USE_FFMPEG
, _sws_context(nullptr)
#endif
{

}

RgbToBgraConverter::~RgbToBgraConverter()
{
#ifdef USE_FFMPEG
sws_freeContext(_sws_context);
_sws_context = nullptr;
#endif
}

void RgbToBgraConverter::convert(unsigned char *rgb,
unsigned char *bgra)
{
#ifdef USE_FFMPEG
_sws_srcSlice[0] = rgb;
_sws_srcStride[0] = 3 * _width;
_sws_dst[0] = bgra;
_sws_dstStride[0] = 4 * _width;
sws_scale(_sws_context,
_sws_srcSlice, _sws_srcStride, 0, _height,
_sws_dst, _sws_dstStride);
#else
size_t length = 4 * _width * _height;
for (size_t i = 0, j = 0; i < length; i += 4, j += 3)
{
bgra[i] = rgb[j+2];
bgra[i+1] = rgb[j+1];
bgra[i+2] = rgb[j];
bgra[i+3] = 255;
}
#endif
}

void RgbToBgraConverter::set_frame_dimensions(size_t width,
size_t height)
{
assert(width > 0);
assert(height > 0);
if (_width == width && _height == height)
return;

_width = width;
_height = height;
#ifdef USE_FFMPEG
_sws_context = sws_getCachedContext(
_sws_context,
_width, _height, _sws_srcFormat,
_width, _height, _sws_dstFormat,
0, nullptr, nullptr, nullptr // advanced
);
#endif
}

}
Loading

0 comments on commit 524b7dd

Please sign in to comment.