From patchwork Fri Jul 7 14:05:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nuo Mi X-Patchwork-Id: 42504 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:3b1e:b0:12b:9ae3:586d with SMTP id c30csp7318013pzh; Fri, 7 Jul 2023 07:06:17 -0700 (PDT) X-Google-Smtp-Source: APBJJlFXT9lKHSGuQ1MhGDFQorn5gGH+vA1dRIsIky907ngKcoG7rnwLdH68QgjcdE1X2dWA277L X-Received: by 2002:a17:906:72c9:b0:993:d7c4:79c6 with SMTP id m9-20020a17090672c900b00993d7c479c6mr1030701ejl.18.1688738777228; Fri, 07 Jul 2023 07:06:17 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id oz25-20020a170906cd1900b0099316721726si2241105ejb.957.2023.07.07.07.06.16; Fri, 07 Jul 2023 07:06:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@outlook.com header.s=selector1 header.b=TetYor0g; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3413868C7BE; Fri, 7 Jul 2023 17:06:08 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from APC01-TYZ-obe.outbound.protection.outlook.com (mail-tyzapc01olkn2103.outbound.protection.outlook.com [40.92.107.103]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5F13068C7A9 for ; Fri, 7 Jul 2023 17:06:01 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=PiJtxEhJ6i8l87pkK/Rgxx9fusNQeBubw4EUQATFezBL7TifI/LU/ZKkV3mL/Tb6k15ZpssASsts7QKHqVujFnSYfsdddB8JuCXHW2DIiFo/v60HWx9gHJKrmCsdlFBf99YCvRd2tKGcbxQ1o8mnt5LbltA32PIdxun/8KPdcCqMN28BAbzZaBNsRUVM3g6ny+JwsbYbrL5YDqQba2Zf8hOnL/6xxSIxIvFmLgIjJUkWeOV0E0qyrcrRXuTeCIET/bhSdOY1rjBQeezygwvfkrbSKKmSxfvKdkaGURfSv82B+Zl6/nv+ZyOr2Ie0I+ysTc1t06x7i6dsF1Zum0VMlA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=65L2YkZEPaQe3GXNSlBtto7tJS9jJIJBM3ApgdXpQaE=; b=YAIlaiXnxa+OtfXFq4nnnWIOR0ovVypaoqfidi0vOd4r48rwUTgQx7TBorktLOjEnjwXRRn8SNqQ5tm3CYdGTs+OI2cxBzQ/MhKaY0gxc3N57EuXYEFGNhlhsErUfU1YuePcGbajawsDcCWPYr+Y1xxFCg/lOsxI06Y79I+WtqryeWYNU3p0Pg/DK/405VbCbdMm85m8GGOCXonFcvPCWg8H4jCMZTwIsXGa2nRQ02AN8bgzwoICErqk6D6DIcmflEindi8ezRKlDDAd96gAhjqdNg0hRzvhPuYVGVypHPgs1DqsU47DOcxleLujrqXCVU1pPAPIsDzT1MpGRhtarw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=65L2YkZEPaQe3GXNSlBtto7tJS9jJIJBM3ApgdXpQaE=; b=TetYor0gUyH8+LEYCJW/Ea01B0YaeeJi4G7x7t2O55WUXwjYPFtYBvn/F9qEIDa59HtG/Lp5JW+bmCLqwamRRkbGX1fYvMm7NDRIOvs6Jt/oWHX90theCKa6e6hS5HpPKSqmoUtiWHNM2R3XT/HcSgNonP8n8LMT3bJDGOnkbQn05D2/STvAJRsRvPaTufsjVL53LL31LRjgp84WXkqIJVu4lqHOkAOV57wpW76Rpp8GtnblNzTlvGSvfCkTxyGRj/2nxUyCaZc5X8UsyeM8T4ZmCvSox/+HgLYR/U1vHO+/gXwN4p9VOQIygV6SMhRMPtyRfKk71u/59UPcQvVzSw== Received: from TYSPR06MB6433.apcprd06.prod.outlook.com (2603:1096:400:47a::6) by KL1PR0601MB5445.apcprd06.prod.outlook.com (2603:1096:820:c0::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6565.25; Fri, 7 Jul 2023 14:05:51 +0000 Received: from TYSPR06MB6433.apcprd06.prod.outlook.com ([fe80::7d80:1294:fd54:a7f]) by TYSPR06MB6433.apcprd06.prod.outlook.com ([fe80::7d80:1294:fd54:a7f%7]) with mapi id 15.20.6565.016; Fri, 7 Jul 2023 14:05:50 +0000 From: Nuo Mi To: ffmpeg-devel@ffmpeg.org Date: Fri, 7 Jul 2023 22:05:27 +0800 Message-ID: X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230707140540.10279-1-nuomi2021@gmail.com> References: <20230707140540.10279-1-nuomi2021@gmail.com> X-TMN: [QSEGwOZm7HRHzkZIKvZXmm2eDal5PZC+] X-ClientProxiedBy: TYCP286CA0251.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:456::20) To TYSPR06MB6433.apcprd06.prod.outlook.com (2603:1096:400:47a::6) X-Microsoft-Original-Message-ID: <20230707140540.10279-2-nuomi2021@gmail.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 2 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: TYSPR06MB6433:EE_|KL1PR0601MB5445:EE_ X-MS-Office365-Filtering-Correlation-Id: c9e0c414-f1b9-47c0-5e4a-08db7ef34537 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: tXgfq7BE+Hs4ZpmDEZEIve/FcdBlN+HOYzHRtHXAbC0mt/v2LJqVsgCF9Ey8mrgpuFSp9+exmSIYeHLP97y18NPWXd7LKwu3IMG3BzCc9IzrFnmgf2WMBJ4EiIEphjL387zTvPnOtIhFOCi4r9MoSi6I6InWFlrDCDo5R89gg/wsu7VL61lUeFYujOUkEEUh5etWfr0pHo8K6wWYZxIV29BTyB+B/r+PR1Cp2zVW/v7WfA3VALOxFl0PXCt48lJAFAf+5fbPeKd85cu4K/IbezY1wcMIZhcPyqwJZhlVq9d7jkLucnqsj+tB1AgOdP8BZJH8L2X+0AAwcKlxSlGJ2A69OAgP7kVwGXV4YLHyqk3NGgVeFVg/SiyY5iCikhLiKowNoAcUlGi+c2dRMyG+tnXGWeA2ESeG5Tlwi79IGpwwMAnXhpKxwbiZVoq+CTebpSSXX/wVdAxnySbiipAKTIb3CSHW+mGqqQsVCeC4QYz4A07oSSt66/mL6F9YQZQGGlvElwkbNNQmnEfZ+zdcSGTcOpzdt4cckcn15u4fzdDax/11Xld9xWVYIGrRay/gL3Lu94q6ctaohLegfJOBmzyYJQcrR0+q3MNRDrapLVzXYjexu+nbqD3I2TsmyemhkGeVXnO8MEqYnkIQDVwB9Q== X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 1hqoqlRMy6TNXb2NUHEXM8hSIHQg5vxVmjVsaEuc9MY1p+tkyamGTn6/MUE4z97CU49NqyQHixQE7WFTxg+lXU603tagR4Y0RQ2x6WeS9lIMFjSNhWyhDStImXn+G/H4qyKB/zqa8fdV2oRUOOv9KKoktJ0U+xdH4B/8I2e2gj9EWyQhh9+VqkwsErQ+9bjoHjcDTyuo4DiopnR4x6lQc71EfNI1nXJQd0BFWCuilgXhuBwkK3Q500kr6GAhjUsDhAZEAnt8VdcYhvXzK26UhWpchqq4vRlQY0mDdjTswNhdG1S0tCME1SaO8Lys/YS/t1F4DrkGE5L7pswUnv9ipVcgUgPF2cWZqJ1UBBOoD1AcOl1FNAA/Nvr8bHEC6qenUAng1rrXWRgDWaCzsC0JYreLAWsD50q3PeWaT15r6+YFCt5f8HJipM2Td2cE4WG1sz9GcxQYFcbQOv/7BAfMrov+k/y6p80+Ce3oIay/GeUztmZkYsYBzIbiJrJvhAmtPfvvsqa03YY+x4UfhgteI9Xukk4sj0sDs2Ud4YXECrkvNxxRiWf8za4REqIJY0VOaHZh6Zrvbc2Yqco67CyLaJg6PRVHx1+Na82pM6/f3BSWLTAWDMX3WLlflwU4jEqZoFLCN0icA6Veu8cpyymqLab+Xpy5dZ2qgaB/l3AFfXLF6Azqhfsp5WOY0Mhp7r00khXCWyZWLYLtSOT7ftbIo/8OjNTI4PSFGxUaEVhqFmwOl5A3/fZzhN28za8rV9t+UrC7m5RbojvahMB/27sVqmWIejmX+vL3SVfFbGiTT7fXriBZIuOcs66wMBHigRgtvDWyDuOzwZzJjtf4y/qiLElrwtrsPuuUgC4jJP97V5WbJbSFaINLI3FzILCJtvOXRTaioU9jSKbZXtt3EpOTzyVHxuGD+EbOFnxFyQzF/CfLzl3YKVng+iela0xcElGFLyqms9k5471DNOZ+ij1YSW9ECEZ0fC4UzHEesozYZnqZ24c2jsdSgex+1Gv3sz/qlZR4GekrMUDHHGwcUQl3VbrR/3Kk7/xSoxYcqXnZytulU88hUFBjlUXaGB/UseB4c1HhfwsIgpM8RyQ3A7beT8yA3Xf0zRnsduasTXUD8e/HbxlMOkn0PZPdt0IMmVrrv5d3p0MPloQLCVKvUOBCkje26j1rsAtZfIB+bXrai/Hmu1AE1Oj1xICcVD58A9m11qMv+qCmsm8uuQpX2kNxHyhwBZd+NxVU4CBnBXZbhNT0mme71C//yYRQ/d4suZIB X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: c9e0c414-f1b9-47c0-5e4a-08db7ef34537 X-MS-Exchange-CrossTenant-AuthSource: TYSPR06MB6433.apcprd06.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jul 2023 14:05:50.9259 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR0601MB5445 Subject: [FFmpeg-devel] [PATCH v2 01/14] vvcdec: add thread executor X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Nuo Mi Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8wXyP3KmGAHh The executor design pattern was inroduced by java it also adapted by python Compared to handcrafted thread pool management, it greatly simplifies the thread code. --- libavcodec/Makefile | 1 + libavcodec/executor.c | 182 ++++++++++++++++++++++++++++++++++++++++ libavcodec/executor.h | 67 +++++++++++++++ libavcodec/vvc/Makefile | 4 + 4 files changed, 254 insertions(+) create mode 100644 libavcodec/executor.c create mode 100644 libavcodec/executor.h create mode 100644 libavcodec/vvc/Makefile diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 1b0226c089..4a3c7a7a1f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -62,6 +62,7 @@ OBJS = ac3_parser.o \ xiph.o \ # subsystems +include $(SRC_PATH)/libavcodec/vvc/Makefile OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o diff --git a/libavcodec/executor.c b/libavcodec/executor.c new file mode 100644 index 0000000000..c5094f608a --- /dev/null +++ b/libavcodec/executor.c @@ -0,0 +1,182 @@ +/* + * VVC video Decoder + * + * Copyright (C) 2022 Nuo Mi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libavutil/avutil.h" +#include "libavutil/thread.h" + +#include "executor.h" + +typedef struct ThreadInfo { + Executor *e; + pthread_t thread; +} ThreadInfo; + +struct Executor { + TaskletCallbacks cb; + ThreadInfo *threads; + uint8_t *local_contexts; + int thread_count; + + pthread_mutex_t lock; + pthread_cond_t cond; + int die; + Tasklet *tasks; +}; + +static void remove_task(Tasklet **prev, Tasklet *t) +{ + *prev = t->next; + t->next = NULL; +} + +static void add_task(Tasklet **prev, Tasklet *t) +{ + t->next = *prev; + *prev = t; +} + +static void *executor_worker_task(void *data) +{ + ThreadInfo *ti = (ThreadInfo*)data; + Executor *e = ti->e; + void *lc = e->local_contexts + (ti - e->threads) * e->cb.local_context_size; + Tasklet **prev; + TaskletCallbacks *cb = &e->cb; + + pthread_mutex_lock(&e->lock); + while (1) { + Tasklet* t = NULL; + if (e->die) break; + + for (prev = &e->tasks; *prev; prev = &(*prev)->next) { + if (cb->ready(*prev, cb->user_data)) { + t = *prev; + break; + } + } + if (t) { + //found one task + remove_task(prev, t); + pthread_mutex_unlock(&e->lock); + cb->run(t, lc, cb->user_data); + pthread_mutex_lock(&e->lock); + } else { + //no task in one loop + pthread_cond_wait(&e->cond, &e->lock); + } + } + pthread_mutex_unlock(&e->lock); + return NULL; +} + +Executor* ff_executor_alloc(const TaskletCallbacks *cb, int thread_count) +{ + Executor *e; + int i, j, ret; + if (!cb || !cb->user_data || !cb->ready || !cb->run || !cb->priority_higher) + return NULL; + e = av_calloc(1, sizeof(*e)); + if (!e) + return NULL; + e->cb = *cb; + + e->local_contexts = av_calloc(thread_count, e->cb.local_context_size); + if (!e->local_contexts) + goto free_executor; + + e->threads = av_calloc(thread_count, sizeof(*e->threads)); + if (!e->threads) + goto free_contexts; + ret = pthread_mutex_init(&e->lock, NULL); + if (ret) + goto free_threads; + + ret = pthread_cond_init(&e->cond, NULL); + if (ret) + goto destroy_lock; + + for (i = 0; i < thread_count; i++) { + ThreadInfo *ti = e->threads + i; + ti->e = e; + ret = pthread_create(&ti->thread, NULL, executor_worker_task, ti); + if (ret) + goto join_threads; + } + e->thread_count = thread_count; + return e; + +join_threads: + pthread_mutex_lock(&e->lock); + e->die = 1; + pthread_cond_broadcast(&e->cond); + pthread_mutex_unlock(&e->lock); + for (j = 0; j < i; j++) + pthread_join(e->threads[j].thread, NULL); + pthread_cond_destroy(&e->cond); +destroy_lock: + pthread_mutex_destroy(&e->lock); +free_threads: + av_free(e->threads); +free_contexts: + av_free(e->local_contexts); +free_executor: + free(e); + return NULL; +} + +void ff_executor_free(Executor **executor) +{ + Executor *e; + if (!executor || !*executor) + return; + e = *executor; + + //singal die + pthread_mutex_lock(&e->lock); + e->die = 1; + pthread_cond_broadcast(&e->cond); + pthread_mutex_unlock(&e->lock); + + for (int i = 0; i < e->thread_count; i++) + pthread_join(e->threads[i].thread, NULL); + pthread_cond_destroy(&e->cond); + pthread_mutex_destroy(&e->lock); + + av_free(e->threads); + av_free(e->local_contexts); + + av_freep(executor); +} + +void ff_executor_execute(Executor *e, Tasklet *t) +{ + TaskletCallbacks *cb = &e->cb; + Tasklet **prev; + + pthread_mutex_lock(&e->lock); + if (t) { + for (prev = &e->tasks; *prev && cb->priority_higher(*prev, t); prev = &(*prev)->next) + /* nothing */; + add_task(prev, t); + } + pthread_cond_signal(&e->cond); + pthread_mutex_unlock(&e->lock); +} \ No newline at end of file diff --git a/libavcodec/executor.h b/libavcodec/executor.h new file mode 100644 index 0000000000..4b641acce6 --- /dev/null +++ b/libavcodec/executor.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 Nuo Mi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_EXECUTOR_H +#define AVCODEC_EXECUTOR_H + +typedef struct Executor Executor; +typedef struct Tasklet Tasklet; + +struct Tasklet { + Tasklet *next; +}; + +typedef struct TaskletCallbacks { + void *user_data; + + int local_context_size; + + // return 1 if a's priority > b's priority + int (*priority_higher)(const Tasklet *a, const Tasklet *b); + + // task is ready for run + int (*ready)(const Tasklet *t, void *user_data); + + // run the task + int (*run)(Tasklet *t, void *local_context, void *user_data); +} TaskletCallbacks; + +/** + * Alloc executor + * @param callbacks callback strucutre for executor + * @param thread_count worker thread number + * @return return the executor + */ +Executor* ff_executor_alloc(const TaskletCallbacks *callbacks, int thread_count); + +/** + * Free executor + * @param e pointer to executor + */ +void ff_executor_free(Executor **e); + +/** + * Add task to executor + * @param e pointer to executor + * @param t pointer to task. If NULL, it will wakeup one work thread + */ +void ff_executor_execute(Executor *e, Tasklet *t); + +#endif //AVCODEC_EXECUTOR_H diff --git a/libavcodec/vvc/Makefile b/libavcodec/vvc/Makefile new file mode 100644 index 0000000000..16cdd04307 --- /dev/null +++ b/libavcodec/vvc/Makefile @@ -0,0 +1,4 @@ +clean:: + $(RM) $(CLEANSUFFIXES:%=libavcodec/vvc/%) + +OBJS-$(CONFIG_VVC_DECODER) += executor.o