Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] OpenCV-free BGRA capture using Epiphan DVI2PCIe Duo #70

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4edc384
Issue #9: Epiphan SDK video source now supports BGRA captures
dzhoshkun Oct 29, 2018
8d1378f
Issue #9: VideoSourceFactory uses Epiphan SDK video source for BGRA c…
dzhoshkun Oct 29, 2018
ba99c16
Issue #9: using malloc instead of realloc
dzhoshkun Oct 29, 2018
ccebfed
Issue #9: explicitly resetting Epiphan SDK frame buffer
dzhoshkun Oct 29, 2018
de4cd90
Issue #9: added an app for profiling ARGB => BGRA conversions
dzhoshkun Oct 30, 2018
3f0e011
Issue #9: activated newly added profiling app in CMake
dzhoshkun Oct 30, 2018
2b770cc
Issue #9: revised concepts in profiler app
dzhoshkun Oct 30, 2018
530a1a6
Issue #46: added an ArgbToBgraConverter class stub
dzhoshkun Oct 30, 2018
f890e27
Issue #46: added the ArgbToBgraConverter class to CMake config
dzhoshkun Oct 30, 2018
ff7f63e
Issue #46: added basic constructor and method stubs to ArgbToBgraConv…
dzhoshkun Oct 30, 2018
ddd4487
Issue #46: added width and height properties to ArgbToBgraConverter
dzhoshkun Oct 30, 2018
34b24eb
Issue #46: implemented naive conversion in ArgbToBgraConverter
dzhoshkun Oct 30, 2018
0edc677
Issue #46: added FFmpeg-related members to ArgbToBgraConverter
dzhoshkun Oct 30, 2018
b299611
Issue #46: implemented FFmpeg-supported ARGB-to-BGRA conversion in Ar…
dzhoshkun Oct 30, 2018
ab54065
Issue #46: set_frame_dimensions is now no-op if dims do not change
dzhoshkun Oct 30, 2018
aa1ed44
Issue #46: EpiphanSDK video source now uses ArgbToBgraConverter to ab…
dzhoshkun Oct 30, 2018
25a3510
Issue #46: protecting frame capture with a mutex in Epiphan SDK video…
dzhoshkun Oct 30, 2018
aa2ac5e
Issue #46: using BGRA-specific frame rate in Epiphan SDK video source
dzhoshkun Oct 30, 2018
a7886f8
Issue #46: fixed image stride definitions
dzhoshkun Oct 30, 2018
4b025b7
Issue #46: conversion profiler now supports reading an image and also…
dzhoshkun Oct 30, 2018
88681c5
Issue #46: renamed all functor => function for clarity
dzhoshkun Oct 30, 2018
a167db6
Issue #46: profiler app writes looped conversion image as well
dzhoshkun Oct 30, 2018
b80276d
Issue #46: fixed FFmpeg strides in profiler app
dzhoshkun Oct 30, 2018
4965396
Issue #46: stride is now width not packed pixel size
dzhoshkun Oct 31, 2018
2c91da4
Issue #46: fixed memcpy src-dst order in profiler app
dzhoshkun Oct 31, 2018
5b62e59
Issue #46: writing original BGR out, and composing ARGB from BGR data…
dzhoshkun Oct 31, 2018
4117583
Issue #46: using copy_strided as last one in profiler app
dzhoshkun Oct 31, 2018
cb00184
Issue #46: outputting bgra_function result as well in profiler app
dzhoshkun Oct 31, 2018
8f8f26b
Issue #46: fixed pointer freeing order in profiler app
dzhoshkun Oct 31, 2018
32f576d
Revert "Issue #46: stride is now width not packed pixel size"
dzhoshkun Oct 31, 2018
62246d2
Issue #46: added a static cast from size_t to int to make FFmpeg func…
dzhoshkun Oct 31, 2018
e738da5
Issue #46: ArgbToBgraConverter now uses 4*width as stride
dzhoshkun Oct 31, 2018
3774ec9
Issue #46: using buttom-up flag with for ARGB captures
dzhoshkun Nov 1, 2018
f0ba32d
Issue #46: EpiphanSDK video source uses RGB to capture with BGRA format
dzhoshkun Nov 2, 2018
27dc596
Issue #46: converted ARGB-to-BGRA profiler to RGB-to-BGRA profiler
dzhoshkun Nov 2, 2018
5185540
Issue #46: fixed BGRA buffer allocation
dzhoshkun Nov 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,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 @@ -63,11 +63,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 @@ -115,11 +116,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
73 changes: 60 additions & 13 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 @@ -21,7 +23,7 @@ VideoSourceEpiphanSDK::VideoSourceEpiphanSDK(
return;
}

if (colour_space != V2U_GRABFRAME_FORMAT_I420 and colour_space != V2U_GRABFRAME_FORMAT_BGR24)
if (colour_space != V2U_GRABFRAME_FORMAT_I420 and colour_space != V2U_GRABFRAME_FORMAT_RGB24)
{
// TODO - exception GiftGrab#42
std::cerr << "Colour space " << colour_space << " not supported" << std::endl;
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 (not 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) and \
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 @@ -3,6 +3,7 @@
#include "ivideosource.h"
#include "macros.h"
#include "broadcastdaemon.h"
#include "rgb_to_bgra_converter.h"

namespace gg
{
Expand Down Expand Up @@ -37,11 +38,28 @@ class 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 @@ -50,7 +68,7 @@ class 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 and _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
}

}
77 changes: 77 additions & 0 deletions src/epiphansdk/rgb_to_bgra_converter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#pragma once

#include <cstdlib>
#ifdef USE_FFMPEG
extern "C" {
#include <libswscale/swscale.h>
}
#endif

namespace gg
{

//!
//! \brief Epiphan SDK seems to support RGB but not BGRA.
//! This class abstracts the conversion of captured RGB
//! data to BGRA.
//! \sa VideoSourceEpiphanSDK
//!
class RgbToBgraConverter
{
protected:
//!
//! \brief Width of frames passed for conversion
//!
size_t _width;

//!
//! \brief Height of frames passed for conversion
//!
size_t _height;

#ifdef USE_FFMPEG
unsigned char *_sws_srcSlice[1];
int _sws_srcStride[1];
unsigned char *_sws_dst[1];
int _sws_dstStride[1];
AVPixelFormat _sws_srcFormat = AV_PIX_FMT_RGB24;
AVPixelFormat _sws_dstFormat = AV_PIX_FMT_BGRA;
SwsContext *_sws_context;
#endif

public:
//!
//! \brief Create a converter, which should be
//! initialised by informing it of the frame
//! dimensions
//! \sa set_frame_dimensions
//!
RgbToBgraConverter();

//!
//! \brief Free all allocated resources
//!
~RgbToBgraConverter();

public:
//!
//! \brief Convert RGB data in passed buffer to BGRA
//! data, saving it into the passed output buffer.
//! \param rgb should be in line with the frame
//! dimensions set before
//! \param bgra should be at least as large as the
//! input buffer
//! \sa set_frame_dimensions
//!
void convert(unsigned char *rgb, unsigned char *bgra);

//!
//! \brief Allocate all resources needed for RGB to
//! BGRA conversion based on passed frame dimensions
//! \param width
//! \param height
//!
void set_frame_dimensions(size_t width, size_t height);
};

}
3 changes: 3 additions & 0 deletions src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,6 @@ endif(USE_FILES)

# VideoSourceFactory leak checker
ADD_SUBDIRECTORY(videosourcefactory)

# Simple colour space conversion profiling
ADD_SUBDIRECTORY(rgbswap)
14 changes: 14 additions & 0 deletions src/tests/rgbswap/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
SET(RGB_TO_BGRA_PROFILER rgb_to_bgra_profiler)
ADD_EXECUTABLE(
${RGB_TO_BGRA_PROFILER}
${CMAKE_SOURCE_DIR}/tests/rgbswap/profile_rgb_to_bgra.cpp
)
if(USE_FFMPEG)
LIST(APPEND RGB_TO_BGRA_PROFILER_LIBS ${FFmpeg_LIBS})
endif(USE_FFMPEG)
if(USE_OPENCV)
LIST(APPEND RGB_TO_BGRA_PROFILER_LIBS ${OpenCV_LIBS})
endif(USE_OPENCV)
TARGET_LINK_LIBRARIES(
${RGB_TO_BGRA_PROFILER} ${RGB_TO_BGRA_PROFILER_LIBS}
)
Loading