From 0b668e9a0528001534bfce95e4718dfa37bc2bdf Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 9 Aug 2021 14:07:19 +0200 Subject: [PATCH] Lavc: run the UG conversions in parallel + create helper for that + macro for default color shifts --- Makefile.in | 1 + src/utils/parallel_conv.c | 96 +++++++++++++++++++++++++++++++ src/utils/parallel_conv.h | 54 +++++++++++++++++ src/video_codec.h | 3 + src/video_compress/libavcodec.cpp | 10 +--- 5 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 src/utils/parallel_conv.c create mode 100644 src/utils/parallel_conv.h diff --git a/Makefile.in b/Makefile.in index 721c49678..9ee04e3de 100644 --- a/Makefile.in +++ b/Makefile.in @@ -141,6 +141,7 @@ COMMON_OBJS = \ src/utils/nat.o \ src/utils/net.o \ src/utils/packet_counter.o \ + src/utils/parallel_conv.o \ src/utils/resource_manager.o \ src/utils/ring_buffer.o \ src/utils/sdp.o \ diff --git a/src/utils/parallel_conv.c b/src/utils/parallel_conv.c new file mode 100644 index 000000000..fdc02f94b --- /dev/null +++ b/src/utils/parallel_conv.c @@ -0,0 +1,96 @@ +/** + * @file utils/parallel_conv.c + * @author Martin Pulec + */ +/* + * Copyright (c) 2021 CESNET, z. s. p. o. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif + +#include "utils/parallel_conv.h" +#include "utils/worker.h" + +struct parallel_pix_conv_data { + decoder_t decode; + int height; + unsigned char *out_data; + int out_linesize; + const unsigned char *in_data; + int in_linesize; +}; + +static void *parallel_pix_conv_task(void *arg) { + struct parallel_pix_conv_data *data = arg; + for (int y = 0; y < data->height; ++y) { + data->decode(data->out_data, data->in_data, data->out_linesize, DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT); + data->out_data += data->out_linesize; + data->in_data += data->in_linesize; + } + return NULL; +} + +void parallel_pix_conv(int height, char *out, int out_linesize, const char *in, int in_linesize, decoder_t decode, int threads) +{ + struct parallel_pix_conv_data data[threads]; + + for (int i = 0; i < threads; ++i) { + data[i].decode = decode; + data[i].height = height / threads; + data[i].out_data = (unsigned char *) out + i * data[i].height * out_linesize; + data[i].out_linesize = out_linesize; + data[i].in_data = (const unsigned char *) in + i * data[i].height * in_linesize; + data[i].in_linesize = in_linesize; + if (i == threads - 1) { + data[i].height = height - (threads - 1) * (height / threads); + } + } + + if (threads == 1) { + parallel_pix_conv_task((void *) &data[0]); + } else { + task_result_handle_t handle[threads]; + + for (int i = 0; i < threads; ++i) { + handle[i] = task_run_async(parallel_pix_conv_task, (void *) &data[i]); + } + + for (int i = 0; i < threads; ++i) { + wait_task(handle[i]); + } + } +} + diff --git a/src/utils/parallel_conv.h b/src/utils/parallel_conv.h new file mode 100644 index 000000000..e02c72f8e --- /dev/null +++ b/src/utils/parallel_conv.h @@ -0,0 +1,54 @@ +/** + * @file utils/parallel_conv.h + * @author Martin Pulec + */ +/* + * Copyright (c) 2021 CESNET z.s.p.o. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTILS_PARALLEL_CONV_H_8871B46B_0006_4854_9578_5B72B691C500 +#define UTILS_PARALLEL_CONV_H_8871B46B_0006_4854_9578_5B72B691C500 + +#include "video_codec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void parallel_pix_conv(int height, char *out, int out_linesize, const char *in, int in_linesize, decoder_t decode, int threads); + +#ifdef __cplusplus +} +#endif + +#endif // defined UTILS_PARALLEL_CONV_H_8871B46B_0006_4854_9578_5B72B691C500 + diff --git a/src/video_codec.h b/src/video_codec.h index 546098d0d..f3f5b876e 100644 --- a/src/video_codec.h +++ b/src/video_codec.h @@ -53,6 +53,9 @@ extern "C" { #endif +#define DEFAULT_R_SHIFT 0 +#define DEFAULT_G_SHIFT 8 +#define DEFAULT_B_SHIFT 16 #define MAX_BPS 6 /* for RG48 */ ///< maximal (average) number of pixels per know pixel formats (up-round if needed) #define MAX_PADDING 36 /* R12L */ ///< maximal padding that may be needed to align to pixfmt block size diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index 35029a9ea..32831e7c3 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -65,6 +65,7 @@ #include "module.h" #include "rang.hpp" #include "utils/misc.h" +#include "utils/parallel_conv.h" #include "utils/resource_manager.h" #include "utils/worker.h" #include "video.h" @@ -1433,16 +1434,9 @@ static shared_ptr libavcodec_compress_tile(struct module *mod, shar s->in_frame->pts = frame_seq++; if (s->decoder != vc_memcpy) { - unsigned char *line1 = (unsigned char *) tx->tiles[0].data; - unsigned char *line2 = (unsigned char *) s->decoded; int src_linesize = vc_get_linesize(tx->tiles[0].width, tx->color_spec); int dst_linesize = vc_get_linesize(tx->tiles[0].width, s->decoded_codec); - for (int i = 0; i < (int) tx->tiles[0].height; ++i) { - s->decoder(line2, line1, dst_linesize, - 0, 8, 16); - line1 += src_linesize; - line2 += dst_linesize; - } + parallel_pix_conv(tx->tiles[0].height, reinterpret_cast(s->decoded), dst_linesize, tx->tiles[0].data, src_linesize, s->decoder, s->params.conv_thread_count); decoded = s->decoded; } else { decoded = (unsigned char *) tx->tiles[0].data;