mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-22 07:40:24 +00:00
NDI disp.: use async API
According to the documentation, this may improve performance.
This commit is contained in:
@@ -40,9 +40,6 @@
|
||||
* Although the NDI SDK provides a C interface, there are constructors for the
|
||||
* NDI structs when invoked from C++. So it is needed at least to zero-initialize
|
||||
* the structs and check the original constructors.
|
||||
*
|
||||
* There is also async NDI API - it may improve the throughput if needed
|
||||
* (NDIlib_send_send_video_async_v2).
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -66,14 +63,20 @@
|
||||
#define DEFAULT_AUDIO_LEVEL 0
|
||||
#define MOD_NAME "[NDI disp.] "
|
||||
|
||||
typedef void ndi_disp_convert_t(const struct video_frame *f, char *out);
|
||||
static void ndi_disp_convert_Y216_to_P216(const struct video_frame *f, char *out);
|
||||
|
||||
struct display_ndi {
|
||||
LIB_HANDLE lib;
|
||||
const NDIlib_t *NDIlib;
|
||||
int audio_level; ///< audio reference level - usually 0 or 20
|
||||
NDIlib_send_instance_t pNDI_send;
|
||||
NDIlib_video_frame_v2_t NDI_video_frame;
|
||||
struct video_desc desc;
|
||||
struct audio_desc audio_desc;
|
||||
struct video_frame *send_frame; ///< frame that is just being asynchronously sent
|
||||
|
||||
ndi_disp_convert_t *convert;
|
||||
char *convert_buffer; ///< for codecs that need conversion (eg. Y216->P216)
|
||||
};
|
||||
|
||||
@@ -93,6 +96,17 @@ static void display_ndi_run(void *arg)
|
||||
UNUSED(arg);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
codec_t ug_codec;
|
||||
NDIlib_FourCC_video_type_e ndi_fourcc;
|
||||
ndi_disp_convert_t *convert;
|
||||
} codec_mapping[] = {
|
||||
{ RGBA, NDIlib_FourCC_type_RGBA, NULL },
|
||||
{ UYVY, NDIlib_FourCC_type_UYVY, NULL },
|
||||
{ I420, NDIlib_FourCC_video_type_I420, NULL },
|
||||
{ Y216, NDIlib_FourCC_type_P216, ndi_disp_convert_Y216_to_P216 },
|
||||
};
|
||||
|
||||
static int display_ndi_reconfigure(void *state, struct video_desc desc)
|
||||
{
|
||||
struct display_ndi *s = (struct display_ndi *) state;
|
||||
@@ -101,6 +115,20 @@ static int display_ndi_reconfigure(void *state, struct video_desc desc)
|
||||
free(s->convert_buffer);
|
||||
s->convert_buffer = malloc(MAX_BPS * desc.width * desc.height + MAX_PADDING);
|
||||
|
||||
s->NDI_video_frame.xres = s->desc.width;
|
||||
s->NDI_video_frame.yres = s->desc.height;
|
||||
for (size_t i = 0; i < sizeof codec_mapping / sizeof codec_mapping[0]; ++i) {
|
||||
if (codec_mapping[i].ug_codec == desc.color_spec) {
|
||||
s->NDI_video_frame.FourCC = codec_mapping[i].ndi_fourcc;
|
||||
s->convert = codec_mapping[i].convert;
|
||||
}
|
||||
}
|
||||
assert(s->NDI_video_frame.FourCC != 0);
|
||||
s->NDI_video_frame.frame_rate_N = get_framerate_n(desc.fps);
|
||||
s->NDI_video_frame.frame_rate_D = get_framerate_d(desc.fps);
|
||||
s->NDI_video_frame.frame_format_type = desc.interlacing == PROGRESSIVE ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
|
||||
s->NDI_video_frame.timecode = NDIlib_send_timecode_synthesize;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -211,6 +239,7 @@ static void display_ndi_done(void *state)
|
||||
free(s->convert_buffer);
|
||||
s->NDIlib->destroy();
|
||||
close_ndi_library(s->lib);
|
||||
vf_free(s->send_frame);
|
||||
free(s);
|
||||
}
|
||||
|
||||
@@ -221,8 +250,6 @@ static struct video_frame *display_ndi_getf(void *state)
|
||||
return vf_alloc_desc_data(s->desc);
|
||||
}
|
||||
|
||||
typedef void ndi_disp_convert_t(const struct video_frame *f, char *out);
|
||||
|
||||
static void ndi_disp_convert_Y216_to_P216(const struct video_frame *f, char *out)
|
||||
{
|
||||
assert((uintptr_t) out % 2 == 0);
|
||||
@@ -241,17 +268,6 @@ static void ndi_disp_convert_Y216_to_P216(const struct video_frame *f, char *out
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
codec_t ug_codec;
|
||||
NDIlib_FourCC_video_type_e ndi_fourcc;
|
||||
ndi_disp_convert_t *convert;
|
||||
} codec_mapping[] = {
|
||||
{ RGBA, NDIlib_FourCC_type_RGBA, NULL },
|
||||
{ UYVY, NDIlib_FourCC_type_UYVY, NULL },
|
||||
{ I420, NDIlib_FourCC_video_type_I420, NULL },
|
||||
{ Y216, NDIlib_FourCC_type_P216, ndi_disp_convert_Y216_to_P216 },
|
||||
};
|
||||
|
||||
/**
|
||||
* flag = PUTF_NONBLOCK is not implemented
|
||||
*/
|
||||
@@ -268,32 +284,20 @@ static int display_ndi_putf(void *state, struct video_frame *frame, int flag)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ndi_disp_convert_t *convert = NULL;
|
||||
s->NDIlib->send_send_video_v2(s->pNDI_send, NULL); // wait for the async frame to be processed
|
||||
vf_free(s->send_frame);
|
||||
s->send_frame = NULL;
|
||||
|
||||
NDIlib_video_frame_v2_t NDI_video_frame = { 0 };
|
||||
NDI_video_frame.xres = s->desc.width;
|
||||
NDI_video_frame.yres = s->desc.height;
|
||||
for (size_t i = 0; i < sizeof codec_mapping / sizeof codec_mapping[0]; ++i) {
|
||||
if (codec_mapping[i].ug_codec == frame->color_spec) {
|
||||
NDI_video_frame.FourCC = codec_mapping[i].ndi_fourcc;
|
||||
convert = codec_mapping[i].convert;
|
||||
}
|
||||
}
|
||||
assert(NDI_video_frame.FourCC != 0);
|
||||
NDI_video_frame.frame_rate_N = get_framerate_n(frame->fps);
|
||||
NDI_video_frame.frame_rate_D = get_framerate_d(frame->fps);
|
||||
NDI_video_frame.frame_format_type = frame->interlacing == PROGRESSIVE ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
|
||||
NDI_video_frame.timecode = NDIlib_send_timecode_synthesize;
|
||||
|
||||
if (convert != NULL) {
|
||||
convert(frame, s->convert_buffer);
|
||||
NDI_video_frame.p_data = (uint8_t *) s->convert_buffer;
|
||||
if (s->convert != NULL) {
|
||||
s->convert(frame, s->convert_buffer);
|
||||
s->NDI_video_frame.p_data = (uint8_t *) s->convert_buffer;
|
||||
vf_free(frame);
|
||||
} else {
|
||||
NDI_video_frame.p_data = (uint8_t *) frame->tiles[0].data;
|
||||
s->NDI_video_frame.p_data = (uint8_t *) frame->tiles[0].data;
|
||||
s->send_frame = frame;
|
||||
}
|
||||
|
||||
s->NDIlib->send_send_video_v2(s->pNDI_send, &NDI_video_frame);
|
||||
vf_free(frame);
|
||||
s->NDIlib->send_send_video_async_v2(s->pNDI_send, &s->NDI_video_frame);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user