From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 4DD364FD6C for ; Wed, 2 Jul 2025 08:29:30 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 25CBA68CDF6; Wed, 2 Jul 2025 11:29:26 +0300 (EEST) Received: from CAN01-YQB-obe.outbound.protection.outlook.com (mail-yqbcan01on2129.outbound.protection.outlook.com [40.107.116.129]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id AC89368CD1F for ; Wed, 2 Jul 2025 11:29:18 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=R0PhLHoy8WvbBIl9xfa2IBxCnODi3xA20GCCzzmXQ8HaFMHkB9jCY1mmFyQa8TjiaKWizqCyT9I+BwyDN5kmsYBvdashytY0ibrF1DqnELwKlDPJwX6tvFvvhnwWpljr0lKrOelz2xuTqPuwXUCwZdyPt+pa4MGJ969HX7EXRnElUmZVllyoedZPow2wrq2nmMMRf5nk+gD2zGPD8ad92ELuf52bD71Dn4Sooui7TqdL8+CphkfqJl1+b4hIcUElLpbCBkoG+JIViRPWhC2StOQpfd1KB9wAGpPt3qNJmDBDu3M1i8LBW0G2GdJnre+KairX1I1ZsmtNEUIg7HZvvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=/vyQUvd5I2htDmgBc1ivFnnNxyH6mOEjZYnmZh26lj8=; b=ToOePvbYeAIT4E1QfZdu/G4eeeO1YqG8rTdiOO92SUEuNSZoQxXcf5xDvwKAsEIEJsjin0Jn8zsgCLLFfMx1DmxPACgUN8CxxNsgcenCP4m93f/BNdYH54iAU1y8pTw2zlyVCLwM3c6YI7c8+HHos8ft31Ksw1IX1eKvgbe6dIkENRVIC/TcTGhSeU8f6pSzobD03x448Cor8/DltL6jgz2F6GTtoLiRNBA7yQkioIFLBknFTYQ1Tv7LEMur21Qbekb3YhkWdjOL/OO7pYR76vSabcR/vo1//NOckCi356gC2gwPGRWEyAKIHN9joDHiWZLeHo+1ZA7MO5/tw4LlVw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=netint.ca; dmarc=pass action=none header.from=netint.ca; dkim=pass header.d=netint.ca; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netint.ca; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/vyQUvd5I2htDmgBc1ivFnnNxyH6mOEjZYnmZh26lj8=; b=T2IcEKDjyGIlkZQG/oN836VvSH+yu7zC1AJWdbzonkO3/k7ECu8vVFvCPDKETMBfCgJsZR6DvjmmHmDjFbPRcx7G9vcuB/Jh1P90ZommoeN0bPZmdz/hKxSwkWs1nmU1x9NtxwWjb+G+QNBTEfbqGhD0umkFJO1K9QJoYxFebho= Received: from YT2PR01MB4701.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:b01:3c::6) by YT2PPF3E481C4F7.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:b08::431) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8880.17; Wed, 2 Jul 2025 08:29:12 +0000 Received: from YT2PR01MB4701.CANPRD01.PROD.OUTLOOK.COM ([fe80::6697:95af:2af:a8bb]) by YT2PR01MB4701.CANPRD01.PROD.OUTLOOK.COM ([fe80::6697:95af:2af:a8bb%6]) with mapi id 15.20.8901.021; Wed, 2 Jul 2025 08:29:12 +0000 From: Steven Zhou To: FFmpeg development discussions and patches Thread-Topic: [PATCH 1/3] libavutil: add hwcontext_ni_quad Thread-Index: AdvqP9G59nzMH/49SSqE+Xeb7Qr6WgA61yeQ Date: Wed, 2 Jul 2025 08:29:12 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=netint.ca; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: YT2PR01MB4701:EE_|YT2PPF3E481C4F7:EE_ x-ms-office365-filtering-correlation-id: c51e7b9f-8f37-41e3-9634-08ddb9428620 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|366016|376014|1800799024|4022899009|7053199007|38070700018; x-microsoft-antispam-message-info: =?us-ascii?Q?Ix74KjEqvf2cNzjap6rCxHk7h3djp2HcoQHS2ZU9W+BbeGg56/AyQSojJOLC?= =?us-ascii?Q?Ty35603Xq6zF4vVKzYyI/yUtLSFC2kQSOVpnJGP8gSzeZUNF/fBXXzYFEgKR?= =?us-ascii?Q?Pf35hezA8E/9bCAdmDNUCkkqr6gcefLVal8MzweL1auTlfXJeoD9+kYTRhf+?= =?us-ascii?Q?YrdblBItENVhWwZ1RC7Qdh7TOwhD75m+5zQgeADKsDXkMfFowWKzJtP2Hypr?= =?us-ascii?Q?xi8B8ahtDrzf+g6foiqeP0QyQ013o59Rkz2u4+JjW71uic5yOsDhi9fPBo6V?= =?us-ascii?Q?cOloCn6Jy9c2CxQiJjNDhKGF2Cn7yNco0SdvGvlFYsaoAg539lgw7aF/AWtU?= =?us-ascii?Q?hT/Ihq0XSZemDqrItbaNo4nOES0aq78jg3z3e9RJG9X6LQj+PsxspAN6DTtP?= =?us-ascii?Q?igE5S3FwuMuy2sGkocRLB8593nAPF/zh7VbY3Og3NkSUkuho7BlqnheFcMk1?= =?us-ascii?Q?wB7yQnrOVyG8t5cUgxtuMVLbgQgpmZJhbZhyNPL7P4mipOrH4IWhpIb71pG9?= =?us-ascii?Q?iQASGiYug0ocVJ9QwAJLOrqj8xzhbUq4U5eX9jOZET+KiCS7Qi8aRUTRDyid?= =?us-ascii?Q?oTiYXW/kYIwuWarsaXICQGlAe0gC/c+C8LGU0KAtY6QZSpIoK7I0HnRRsOz7?= =?us-ascii?Q?jfBBuxx24hJ/m+ZE0D3JK6CqWzxHXysWl98jQOApjR2+Y91N1a5R/rOH9j9V?= =?us-ascii?Q?4gTZuABI9SxAWy9GWV+HVb4wPvka2jD2LfewCh2hC2HdTSWACue7vhY7AFlA?= =?us-ascii?Q?xYqnFoscRR/Tk4QdBrFF8gLWtQU7N7tdcxC9B1Cz56z+h1ftLeBJv+2N7obR?= =?us-ascii?Q?O8eSsW7Q8pfvmAnRFQZBSetoaBSrB/wL/UDGmGiKK5/mgg1WlzXova4Y5FAV?= =?us-ascii?Q?haZK4TmHh6g1xYYhhPEZgoEL/znCy6TX+pM/twMhZmAXVLVKfVFOcHvehoLr?= =?us-ascii?Q?d//kqKjin8tKrW+TyMDArFxkC4glRU8i3vamVzCsXCcFu5OyYn+gmAzKHg2R?= =?us-ascii?Q?w2G9HJR4G3SwzbwZSPWG9Bs/lyQhTU2XZkl9ZLEEjT8pqQdUYmjKMgL8cWbw?= =?us-ascii?Q?I4aPJL2zXH6WEOq5sJqWB/UognBiNDP+OxP900zF5KDTyAuVD9N+oRwXlIX0?= =?us-ascii?Q?7kyH90mUyQRigATh++uy52Af1jX2+wtFpoHhS1cLjMrQLPBm/ZViuaDSssar?= =?us-ascii?Q?jISjaBSQvrlU+aOkoschIPT49qCjIXvUBDIzlYqVkHgYSeYmS4I810jC4/Nc?= =?us-ascii?Q?m1zDw7PtGbGtXQtYpBDikOEzwcrsPP5+LDCHfc2AlMz+ZXh6eoWSUyFKXvfe?= =?us-ascii?Q?rWxJLz2Y0xFUZKtxD8/LnyH8HGDdnWyBPXtYOs5JPlvY4UDJeYsYrSYOuUTF?= =?us-ascii?Q?ndhGnPxFqGSALyMMmyi7RkYWfEWzJ8buF5PPaUX+CL41NuWB0Zl7Tt3agTYb?= =?us-ascii?Q?UWaAAWXd604=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:YT2PR01MB4701.CANPRD01.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(4022899009)(7053199007)(38070700018); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?ZaRNtY3vC96xkexjXP+3Whe9tOz3br7vRUCSmsJYpB38Cit26x2H5odCWqir?= =?us-ascii?Q?ce8osFeogwu0ZLHrGAvn1RcMxz+boO8UctYSPM+Zzk4ZHfmMHhhdvsLcqsFX?= =?us-ascii?Q?fDMmcziRpAwgyuVteUeD0a7KvLYIE1hiAMo7Q4xbUJ48XAYjxy28f3wapxGD?= =?us-ascii?Q?KwAtahdXbqCZZCLocjGTVWWjdOqS6MCnWHwKikdH4xYWFMNVzbCQKTPHUO6O?= =?us-ascii?Q?S46+r4yLkaJdVGLw+cjeqqtaXznrDh4VqUiY7nAmPTPRb0AK+8v8kCOMujxb?= =?us-ascii?Q?2N+OQLe6XQkl2cOphM8RqN+QmAYE4ShW+VeDJqdWAj5s/ZNziWzvB36Cyywl?= =?us-ascii?Q?DFqbxO0RncwitmZfE3+M7r2Bx20VUgasg1X/toeLlOdFWi1lEJI8JBlIPrfo?= =?us-ascii?Q?5pYyAaJlGWamLakltOzuBK7m/vRDFMVDqMS+vWT/1t/Kfq+q2rY5bhaWXTwY?= =?us-ascii?Q?P0XEdOkJqf2UNzwNhSYsKsytCpXoOfPmq2+9E9cs03AQhj4XTDtU9yLrdj6S?= =?us-ascii?Q?pEQHw2XVHpY6p9OtTK9GiT2XqFRII1kcUVUD9ko5quZd91Zul/Ju3xm6zvPN?= =?us-ascii?Q?71/JOrp9fmoyC8d7MCZ4aXo988ItbO92BvHzSbCAT9EmGBLufKj+1q9TwLif?= =?us-ascii?Q?yH+B/WcaYUELS6dpB7NV79ZMxEIKaFRY5E6RnedidARn0t1XWYK+iyUTcED6?= =?us-ascii?Q?3CZj7YDTNBKZALSW5WOf/s1gPfoqh3Uasiz+65v8flgW4Z6bcMlhIMXvhx0s?= =?us-ascii?Q?2TZ+YB0vv8RLi9qqlevDouBy3E255lQWjv2NvEmDLKYmRuQDKwOJYbZ0PJ71?= =?us-ascii?Q?CekSaTldvnrOax6/lPK3d0sQL2Tax42WhtbTmTa8Ix50PK2OP9OWgkrn+MbC?= =?us-ascii?Q?xCzPDCPkyTASFiNtnHg07rXjyj1wAaLDhMKhEtyjOo+62FGoFCKer5qfLGcX?= =?us-ascii?Q?CbaKdpS2tf8WbcVzEDlSUErQ0PnxevaVivayCZ0vUWrg29gE0HWxSnBqyma/?= =?us-ascii?Q?wxpeBb1UsD+0C+WFeBR88zCjTVffmSbFVC0jj+tQl5l7eKb6Sww3f+ejxJq/?= =?us-ascii?Q?3FdJXYhTdm9acPiY9+kbH8K5YbaekdRZV05Zr0ysVrdmhdaxUOrM/nZ3CEY0?= =?us-ascii?Q?b6VMsL4+JYx0P2gtGYcw1rcuVj6/JfokCxiqTIgYAu6J2HbQHhNiXE4jnbNK?= =?us-ascii?Q?qTAbBMdkMIvJ6B+zA6ofIuOgfenP2pb9MB+mG7MqLinYHI+Ec7UgsWZxZcaL?= =?us-ascii?Q?//HuH0eC/QHYnT7rbfme5k3+1DjCGAJBuY7fW8ic9//ub5Ih8DSFs3VVxuih?= =?us-ascii?Q?N/p4pTZ8k/pCIy3d/5f9vI9NxonAfn82mOakFoatYMWlsZ//BhxiKqM0NcZs?= =?us-ascii?Q?SrThtMe59kqPDOU2bz5DxTCa9/IJvLrQvWLT4OafSzSI5/poxzzyDJTbGDQB?= =?us-ascii?Q?4T51wRX667xmUBhEImR6+5j6psu2M5LXQFUUMeWfy4Par1LV5SXoDnHKlMDt?= =?us-ascii?Q?kQNKm1rapIRIzbkqxF5GW//lyn2mJfJrQoztTMmSpfGwhyqW+xCw9SYIzyUC?= =?us-ascii?Q?naElccge1gkLwvYvgty/Kd8l2+byJgmxGM93Zo5s?= MIME-Version: 1.0 X-OriginatorOrg: netint.ca X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: YT2PR01MB4701.CANPRD01.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-Network-Message-Id: c51e7b9f-8f37-41e3-9634-08ddb9428620 X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Jul 2025 08:29:12.5195 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 76291bb4-3d04-48ef-9eb8-3e33475af3cb X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: NbT6+PDBwgDgxqOeK5OW+Qa+b2u9AJuXBRZiPpwanDS6eie01n+KWJ3n6PqYy2Cupt4Y48z5UxkKyfeyHcUd+A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: YT2PPF3E481C4F7 Subject: Re: [FFmpeg-devel] [PATCH 1/3] libavutil: add hwcontext_ni_quad 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 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Hi everyone, this set of patches adds hwcontext, codecs, and filters support for NETINT HW video processing units. NETINT has been offering HW video transcoding products since 2017 and developing on a fork of FFmpeg since then. But this year we have partnered with Akamai to make NETINT Quadra video accelerator HW available on the Akamai Cloud: https://techdocs.akamai.com/cloud-computing/docs/accelerated-compute-instances We hope our codecs and filters can become a part of the main FFmpeg project to make accessing them easier for public cloud users. If anyone is interested in accessing some demo environments with the Quadra HW to test out this patch, please email me directly. > -----Original Message----- > From: ffmpeg-devel On Behalf Of > Steven Zhou > Sent: Wednesday, July 2, 2025 1:11 AM > To: ffmpeg-devel@ffmpeg.org > Subject: [FFmpeg-devel] [PATCH 1/3] libavutil: add hwcontext_ni_quad > > Add support for NETINT Quadra hardware video decoders, filters, and > encoders > in the libavutil hwcontext framework. This commit enables compile > configuration for linking to Quadra's driver 'Libxcoder' and HW frames > support. > > More information: > https://netint.com/products/quadra-t1a-video-processing-unit/ > https://docs.netint.com/vpu/quadra/ > > Signed-off-by: Steven Zhou > --- > configure | 13 +- > libavutil/Makefile | 3 + > libavutil/hwcontext.c | 4 + > libavutil/hwcontext.h | 1 + > libavutil/hwcontext_internal.h | 1 + > libavutil/hwcontext_ni_quad.c | 1257 > ++++++++++++++++++++++++++++++++ > libavutil/hwcontext_ni_quad.h | 99 +++ > libavutil/pixdesc.c | 15 + > libavutil/pixfmt.h | 8 + > 9 files changed, 1400 insertions(+), 1 deletion(-) > create mode 100644 libavutil/hwcontext_ni_quad.c > create mode 100644 libavutil/hwcontext_ni_quad.h > > diff --git a/configure b/configure > index 976a21b931..ca15d675d4 100755 > --- a/configure > +++ b/configure > @@ -353,6 +353,7 @@ External library support: > --enable-libvpl enable Intel oneVPL code via libvpl if libmfx is not used > [no] > --enable-libnpp enable Nvidia Performance Primitives-based code [no] > --enable-mmal enable Broadcom Multi-Media Abstraction Layer > (Raspberry Pi) via MMAL [no] > + --disable-ni_quadra disable NetInt Quadra HWaccel codecs/filters > [autodetect] > --disable-nvdec disable Nvidia video decoding acceleration (via hwaccel) > [autodetect] > --disable-nvenc disable Nvidia video encoding code [autodetect] > --enable-omx enable OpenMAX IL code [no] > @@ -2015,6 +2016,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" > d3d12va > dxva2 > ffnvcodec > + ni_quadra > libdrm > nvdec > nvenc > @@ -4105,7 +4107,7 @@ swscale_suggest="libm stdatomic" > > avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs > liblcevc_dec_extralibs lcms2_extralibs" > avfilter_extralibs="pthreads_extralibs" > -avutil_extralibs="d3d11va_extralibs d3d12va_extralibs mediacodec_extralibs > nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs > vaapi_x11_extralibs vaapi_win32_extralibs vdpau_x11_extralibs" > +avutil_extralibs="d3d11va_extralibs d3d12va_extralibs > mediacodec_extralibs nanosleep_extralibs pthreads_extralibs > vaapi_drm_extralibs vaapi_x11_extralibs vaapi_win32_extralibs > vdpau_x11_extralibs ni_quadra_extralibs" > > # programs > ffmpeg_deps="avcodec avfilter avformat threads" > @@ -6941,6 +6943,15 @@ for func in $MATH_FUNCS; do > eval check_mathfunc $func \${${func}_args:-1} $libm_extralibs > done > > +# Auto-detect ni_quadra and check libxcoder API version > +if enabled ni_quadra; then > + if ! check_pkg_config ni_quadra xcoder ni_device_api.h ni_device_open; > then > + disable_with_reason ni_quadra "libxcoder not found" > + elif ! check_cpp_condition xcoder ni_defs.h > "LIBXCODER_API_VERSION_MAJOR == 2 && > LIBXCODER_API_VERSION_MINOR >= 77"; then > + disable_with_reason ni_quadra "libxcoder API version must be >= 2.77" > + fi > +fi > + > # these are off by default, so fail if requested and not available > enabled avisynth && { require_headers "avisynth/avisynth_c.h > avisynth/avs/version.h" && > { test_cpp_condition avisynth/avs/version.h > "AVS_MAJOR_VER >= 3 && AVS_MINOR_VER >= 7 && AVS_BUGFIX_VER >= 3 > || AVS_MAJOR_VER >= 3 && AVS_MINOR_VER > 7 || AVS_MAJOR_VER > 3" > || > diff --git a/libavutil/Makefile b/libavutil/Makefile > index 9ef118016b..e5b80e245c 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -50,6 +50,7 @@ HEADERS = adler32.h \ > hwcontext_amf.h \ > hwcontext_qsv.h \ > hwcontext_mediacodec.h \ > + hwcontext_ni_quad.h \ > hwcontext_opencl.h \ > hwcontext_vaapi.h \ > hwcontext_videotoolbox.h \ > @@ -208,6 +209,7 @@ OBJS-$(CONFIG_AMF) += > hwcontext_amf.o > OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o > OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o > OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o > +OBJS-$(CONFIG_NI_QUADRA) += hwcontext_ni_quad.o > OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o > OBJS-$(CONFIG_QSV) += hwcontext_qsv.o > OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o > @@ -239,6 +241,7 @@ SKIPHEADERS-$(CONFIG_DXVA2) += > hwcontext_dxva2.h > SKIPHEADERS-$(CONFIG_AMF) += hwcontext_amf.h \ > hwcontext_amf_internal.h > SKIPHEADERS-$(CONFIG_QSV) += hwcontext_qsv.h > +SKIPHEADERS-$(CONFIG_NI_QUADRA) += hwcontext_ni_quad.h > SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h > SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h > SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h > diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c > index 3111a44651..81cbdce168 100644 > --- a/libavutil/hwcontext.c > +++ b/libavutil/hwcontext.c > @@ -54,6 +54,9 @@ static const HWContextType * const hw_table[] = { > #if CONFIG_VAAPI > &ff_hwcontext_type_vaapi, > #endif > +#if CONFIG_NI_QUADRA > + &ff_hwcontext_type_ni_quadra, > +#endif > #if CONFIG_VDPAU > &ff_hwcontext_type_vdpau, > #endif > @@ -80,6 +83,7 @@ static const char *const hw_type_names[] = { > [AV_HWDEVICE_TYPE_D3D12VA] = "d3d12va", > [AV_HWDEVICE_TYPE_OPENCL] = "opencl", > [AV_HWDEVICE_TYPE_QSV] = "qsv", > + [AV_HWDEVICE_TYPE_NI_QUADRA] = "ni_quadra", > [AV_HWDEVICE_TYPE_VAAPI] = "vaapi", > [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", > [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox", > diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h > index 96042ba197..7aa0993fe1 100644 > --- a/libavutil/hwcontext.h > +++ b/libavutil/hwcontext.h > @@ -30,6 +30,7 @@ enum AVHWDeviceType { > AV_HWDEVICE_TYPE_CUDA, > AV_HWDEVICE_TYPE_VAAPI, > AV_HWDEVICE_TYPE_DXVA2, > + AV_HWDEVICE_TYPE_NI_QUADRA, > AV_HWDEVICE_TYPE_QSV, > AV_HWDEVICE_TYPE_VIDEOTOOLBOX, > AV_HWDEVICE_TYPE_D3D11VA, > diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h > index db23579c9e..9d6825b003 100644 > --- a/libavutil/hwcontext_internal.h > +++ b/libavutil/hwcontext_internal.h > @@ -159,6 +159,7 @@ extern const HWContextType > ff_hwcontext_type_dxva2; > extern const HWContextType ff_hwcontext_type_opencl; > extern const HWContextType ff_hwcontext_type_qsv; > extern const HWContextType ff_hwcontext_type_vaapi; > +extern const HWContextType ff_hwcontext_type_ni_quadra; > extern const HWContextType ff_hwcontext_type_vdpau; > extern const HWContextType ff_hwcontext_type_videotoolbox; > extern const HWContextType ff_hwcontext_type_mediacodec; > diff --git a/libavutil/hwcontext_ni_quad.c b/libavutil/hwcontext_ni_quad.c > new file mode 100644 > index 0000000000..903ee0a253 > --- /dev/null > +++ b/libavutil/hwcontext_ni_quad.c > @@ -0,0 +1,1257 @@ > +/* > + * 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 "config.h" > + > +#include > +#include > +#if HAVE_UNISTD_H > +#include > +#endif > + > +#include "avassert.h" > +#include "buffer.h" > +#include "common.h" > +#include "hwcontext.h" > +#include "hwcontext_internal.h" > +#include "hwcontext_ni_quad.h" > +#include "libavutil/imgutils.h" > +#include "mem.h" > +#include "pixdesc.h" > +#include "pixfmt.h" > + > +static enum AVPixelFormat supported_pixel_formats[] = { > + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUYV422, AV_PIX_FMT_UYVY422, > + AV_PIX_FMT_NV12, AV_PIX_FMT_ARGB, AV_PIX_FMT_RGBA, > + AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, AV_PIX_FMT_YUV420P10LE, > + AV_PIX_FMT_NV16, AV_PIX_FMT_BGR0, AV_PIX_FMT_P010LE > +}; > + > +static inline void ni_frame_free(void *opaque, uint8_t *data) > +{ > + if (data) { > + niFrameSurface1_t* p_data3 = (niFrameSurface1_t*)data; > + if (p_data3->ui16FrameIdx != 0) { > + ni_hwframe_buffer_recycle(p_data3, p_data3->device_handle); > + } > + ni_aligned_free(p_data3); > + } > +} > + > +static int ni_device_create(AVHWDeviceContext *ctx, const char *device, > + AVDictionary *opts, int flags) > +{ > + AVNIDeviceContext *ni_hw_ctx; > + char *blk_name; > + int i, module_id = 0, ret = 0; > + ni_device_handle_t fd; > + uint32_t max_io_size = NI_INVALID_IO_SIZE; > + ni_device_t *p_ni_devices = NULL; > + > + p_ni_devices = av_calloc(1, sizeof(ni_device_t)); > + if(p_ni_devices == NULL) { > + av_log(ctx, AV_LOG_ERROR, "could not allocate memory for p_ni_devices > in %s", __func__); > + return AVERROR_UNKNOWN; > + } > + > + ni_hw_ctx = (AVNIDeviceContext *)ctx->hwctx; > + ni_hw_ctx->uploader_handle = NI_INVALID_DEVICE_HANDLE; > + ni_hw_ctx->uploader_ID = -2; // -1 is load balance by pixel rate, > + // default -2 invalid > + > + if (device) { > + /* parse device string and fail if incorrect */ > + av_log(ctx, AV_LOG_VERBOSE, "%s %s\n", __func__, device); > + ni_hw_ctx->uploader_ID = atoi(device); > + av_log(ctx, AV_LOG_DEBUG, "%s: given uploader ID %d\n", __func__, > + ni_hw_ctx->uploader_ID); > + if (ni_hw_ctx->uploader_ID < -1) { > + av_log(ctx, AV_LOG_ERROR, "%s: uploader ID %d must be >= -1.\n", > + __func__, ni_hw_ctx->uploader_ID); > + ret = AVERROR_UNKNOWN; > + LRETURN; > + } > + } > + > + for (i = 0; i < NI_MAX_DEVICE_CNT; i++) { > + ni_hw_ctx->cards[i] = NI_INVALID_DEVICE_HANDLE; > + } > + > + /* Scan all cards on the host, only look at NETINT cards */ > + if (ni_rsrc_list_all_devices(p_ni_devices) == NI_RETCODE_SUCCESS) { > + // Note: this only checks for Netint encoders > + for (i = 0; i < p_ni_devices->xcoder_cnt[NI_DEVICE_TYPE_ENCODER]; i++) > { > + blk_name = > + &(p_ni_devices- > >xcoders[NI_DEVICE_TYPE_ENCODER][i].blk_name[0]); > + // cone-to-one correspondence between card index and module_id > + module_id = p_ni_devices- > >xcoders[NI_DEVICE_TYPE_ENCODER][i].module_id; > + av_log(ctx, AV_LOG_DEBUG, "%s blk name %s\n", __func__, > blk_name); > + fd = ni_device_open(blk_name, &max_io_size); > + if (fd != NI_INVALID_DEVICE_HANDLE) { > + ni_hw_ctx->cards[module_id] = fd; > + } > + } > + } else { > + ret = AVERROR_UNKNOWN; > + } > +END: > + av_freep(&p_ni_devices); > + return ret; > +} > + > +static void ni_device_uninit(AVHWDeviceContext *ctx) > +{ > + AVNIDeviceContext *ni_hw_ctx; > + int i; > + > + ni_hw_ctx = (AVNIDeviceContext *)ctx->hwctx; > + > + av_log(ctx, AV_LOG_VERBOSE, "%s\n", __func__); > + > + if (ni_hw_ctx->uploader_handle != NI_INVALID_DEVICE_HANDLE) { > + ni_device_close(ni_hw_ctx->uploader_handle); > + ni_hw_ctx->uploader_handle = NI_INVALID_DEVICE_HANDLE; > + } > + > + for (i = 0; i < NI_MAX_DEVICE_CNT; i++) { > + ni_device_handle_t fd = ni_hw_ctx->cards[i]; > + if (fd != NI_INVALID_DEVICE_HANDLE) { > + ni_hw_ctx->cards[i] = NI_INVALID_DEVICE_HANDLE; > + ni_device_close(fd); > + } else { > + break; > + } > + } > + > + return; > +} > + > +static int ni_frames_get_constraints(AVHWDeviceContext *ctx, > + const void *hwconfig, > + AVHWFramesConstraints *constraints) > +{ > + int i; > + int num_pix_fmts_supported; > + > + num_pix_fmts_supported = FF_ARRAY_ELEMS(supported_pixel_formats); > + > + constraints->valid_sw_formats = > av_malloc_array(num_pix_fmts_supported + 1, > + sizeof(*constraints->valid_sw_formats)); > + if (!constraints->valid_sw_formats) { > + return AVERROR(ENOMEM); > + } > + > + for (i = 0; i < num_pix_fmts_supported; i++) { > + constraints->valid_sw_formats[i] = supported_pixel_formats[i]; > + } > + constraints->valid_sw_formats[num_pix_fmts_supported] = > AV_PIX_FMT_NONE; > + > + constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints- > >valid_hw_formats)); > + if (!constraints->valid_hw_formats) { > + return AVERROR(ENOMEM); > + } > + > + constraints->valid_hw_formats[0] = AV_PIX_FMT_NI_QUAD; > + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; > + > + return 0; > +} > + > +static int ni_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) > +{ > + int ret = 0; > + uint8_t *buf; > + uint32_t buf_size; > + ni_frame_t *xfme; > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + ni_session_data_io_t dst_session_io_data; > + ni_session_data_io_t * p_dst_session_data = &dst_session_io_data; > + bool isnv12frame = (ctx->sw_format == AV_PIX_FMT_NV12 || > + ctx->sw_format == AV_PIX_FMT_P010LE); > + > + av_log(ctx, AV_LOG_TRACE, "hwcontext_ni.c:ni_get_buffer()\n"); > + > + // alloc dest avframe buff > + memset(p_dst_session_data, 0, sizeof(dst_session_io_data)); > + ret = ni_frame_buffer_alloc(&p_dst_session_data->data.frame, ctx->width, > + ctx->height, 0, 1, // codec type does not matter, metadata > exists > + f_hwctx->api_ctx.bit_depth_factor, 1, !isnv12frame); > + if (ret != 0) { > + return AVERROR(ENOMEM); > + } > + > + xfme = &p_dst_session_data->data.frame; > + buf_size = xfme->data_len[0] + xfme->data_len[1] + > + xfme->data_len[2] + xfme->data_len[3]; > + buf = xfme->p_data[0]; > + memset(buf, 0, buf_size); > + frame->buf[0] = av_buffer_create(buf, buf_size, ni_frame_free, NULL, 0); > + if (!frame->buf[0]) { > + return AVERROR(ENOMEM); > + } > + frame->data[3] = xfme->p_buffer + xfme->data_len[0] + xfme->data_len[1] > + > + xfme->data_len[2]; > + frame->format = AV_PIX_FMT_NI_QUAD; > + frame->width = ctx->width; > + frame->height = ctx->height; > + > + return 0; > +} > + > +static int ni_transfer_get_formats(AVHWFramesContext *ctx, > + enum AVHWFrameTransferDirection dir, > + enum AVPixelFormat **formats) > +{ > + enum AVPixelFormat *fmts; > + > + fmts = av_malloc_array(2, sizeof(*fmts)); > + if (!fmts) { > + return AVERROR(ENOMEM); > + } > + > + fmts[0] = ctx->sw_format; > + fmts[1] = AV_PIX_FMT_NONE; > + > + *formats = fmts; > + > + return 0; > +} > + > +static void ni_frames_uninit(AVHWFramesContext *ctx) > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + int dev_dec_idx = f_hwctx->uploader_device_id; //Supplied by > init_hw_device ni=: or ni_hwupload= > + > + av_log(ctx, AV_LOG_DEBUG, "%s: only close if upload instance, > poolsize=%d " > + "devid=%d\n", > + __func__, ctx->initial_pool_size, dev_dec_idx); > + > + if (dev_dec_idx != -2 && ctx->initial_pool_size >= 0) { > + if (f_hwctx->src_session_io_data.data.frame.buffer_size > + || f_hwctx->src_session_io_data.data.frame.metadata_buffer_size > + || f_hwctx->src_session_io_data.data.frame.start_buffer_size) { > + av_log(ctx, AV_LOG_DEBUG, "%s:free upload src frame buffer\n", > + __func__); > + ni_frame_buffer_free(&f_hwctx->src_session_io_data.data.frame); > + } > + av_log(ctx, AV_LOG_VERBOSE, "SessionID = %d!\n", f_hwctx- > >api_ctx.session_id); > + if (f_hwctx->api_ctx.session_id != NI_INVALID_SESSION_ID) { > + ni_device_session_close(&f_hwctx->api_ctx, 1, > NI_DEVICE_TYPE_UPLOAD); > + } > + ni_device_session_context_clear(&f_hwctx->api_ctx); > + > + //only upload frames init allocates these ones > + av_freep(&f_hwctx->surface_ptrs); > + av_freep(&f_hwctx->surfaces_internal); > + } else { > + ni_device_session_context_clear(&f_hwctx->api_ctx); > + } > + > + if (f_hwctx->suspended_device_handle != NI_INVALID_DEVICE_HANDLE) { > + av_log(ctx, AV_LOG_DEBUG, "%s: close file handle, =%d\n", > + __func__, f_hwctx->suspended_device_handle); > + ni_device_close(f_hwctx->suspended_device_handle); > + f_hwctx->suspended_device_handle = NI_INVALID_DEVICE_HANDLE; > + } > +} > + > +static AVBufferRef *ni_pool_alloc(void *opaque, size_t size) > +{ > + AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + > + if (f_hwctx->nb_surfaces_used < f_hwctx->nb_surfaces) { > + f_hwctx->nb_surfaces_used++; > + return av_buffer_create((uint8_t*) (f_hwctx->surfaces_internal + > f_hwctx->nb_surfaces_used - 1), > + sizeof(*f_hwctx->surfaces), NULL, NULL, 0); > + } > + > + return NULL; > +} > + > +static int ni_init_surface(AVHWFramesContext *ctx, niFrameSurface1_t *surf) > +{ > + /* Fill with dummy values. This data is never used. */ > + surf->ui16FrameIdx = 0; > + surf->ui16session_ID = 0; > + surf->ui32nodeAddress = 0; > + surf->device_handle = 0; > + surf->bit_depth = 0; > + surf->encoding_type = 0; > + surf->output_idx = 0; > + surf->src_cpu = 0; > + > + return 0; > +} > + > +static int ni_init_pool(AVHWFramesContext *ctx) > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + int i, ret; > + > + av_log(ctx, AV_LOG_VERBOSE, "ctx->initial_pool_size = %d\n", ctx- > >initial_pool_size); > + > + if (ctx->initial_pool_size <= 0) { > + av_log(ctx, AV_LOG_ERROR, "NI requires a fixed frame pool size\n"); > + return AVERROR(EINVAL); > + } > + > + f_hwctx->surfaces_internal = av_calloc(ctx->initial_pool_size, > + sizeof(*f_hwctx->surfaces_internal)); > + if (!f_hwctx->surfaces_internal) { > + return AVERROR(ENOMEM); > + } > + > + for (i = 0; i < ctx->initial_pool_size; i++) { > + ret = ni_init_surface(ctx, &f_hwctx->surfaces_internal[i]); > + if (ret < 0) { > + return ret; > + } > + } > + > + ffhwframesctx(ctx)->pool_internal = > + av_buffer_pool_init2(sizeof(niFrameSurface1_t), ctx, ni_pool_alloc, > NULL); > + if (!ffhwframesctx(ctx)->pool_internal) { > + return AVERROR(ENOMEM); > + } > + > + f_hwctx->surfaces = f_hwctx->surfaces_internal; > + f_hwctx->nb_surfaces = ctx->initial_pool_size; > + > + return 0; > +} > + > +static int ni_init_internal_session(AVHWFramesContext *ctx) > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + ni_log_set_level(ff_to_ni_log_level(av_log_get_level())); > + av_log(ctx, AV_LOG_INFO, "hwcontext_ni:ni_init_internal_session()\n"); > + if (ni_device_session_context_init(&(f_hwctx->api_ctx)) < 0) { > + av_log(ctx, AV_LOG_ERROR, "ni init context failure\n"); > + return -1; > + } > + > + return 0; > +} > + > +static void init_split_rsrc(AVNIFramesContext *f_hwctx, int w, int h) > +{ > + int i; > + ni_split_context_t* p_split_ctx = &f_hwctx->split_ctx; > + memset(p_split_ctx, 0, sizeof(ni_split_context_t)); > + for (i = 0; i < 3; i++) { > + p_split_ctx->w[i] = w; > + p_split_ctx->h[i] = h; > + p_split_ctx->f[i] = -1; > + } > +} > + > +static int ni_frames_init(AVHWFramesContext *ctx) //hwupload runs this on > hwupload_config_output > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) ctx->hwctx; > + AVNIDeviceContext *device_hwctx = (AVNIDeviceContext*) ctx- > >device_ctx->hwctx; > + int linesize_aligned,height_aligned; > + int pool_size,ret; > + > + av_log(ctx, AV_LOG_INFO, "%s: Enter, supplied poolsize = %d, > devid=%d\n", > + __func__, ctx->initial_pool_size, device_hwctx->uploader_ID); > + > + f_hwctx->suspended_device_handle = NI_INVALID_DEVICE_HANDLE; > + f_hwctx->uploader_device_id = -2; // -1 is load balance by pixel rate, > + // default -2 invalid > + pool_size = ctx->initial_pool_size; > + if (device_hwctx->uploader_ID < -1) { > + if (pool_size > -1) { // ffmpeg does not specify init_hw_device for decoder > + // - so decoder device_hwctx->uploader_ID is always -1 > + av_log(ctx, AV_LOG_INFO, "%s no uploader device selected!\n", > + __func__); > + return AVERROR(EINVAL); > + } > + } > + > + ret = ni_init_internal_session(ctx); > + if (ret < 0) { > + return AVERROR(EINVAL); > + } > + > + init_split_rsrc(f_hwctx, ctx->width, ctx->height); > + if (pool_size <= -1) { // None upload init returns here > + av_log(ctx, AV_LOG_INFO, "%s: poolsize code %d, this code recquires no > host pool\n", > + __func__, pool_size); > + return ret; > + } else if (pool_size == 0) { > + pool_size = ctx->initial_pool_size = 3; > + av_log(ctx, AV_LOG_INFO, "%s: Pool_size autoset to %d\n", __func__, > pool_size); > + } > + > + /*Kept in AVNIFramesContext for future reference, the AVNIDeviceContext > data member gets overwritten*/ > + f_hwctx->uploader_device_id = device_hwctx->uploader_ID; > + > + if ((ctx->width & 0x1) || (ctx->height & 0x1)) { > + av_log(ctx, AV_LOG_ERROR, "Odd resolution %dx%d not permitted\n", > + ctx->width, ctx->height); > + return AVERROR(EINVAL); > + } > + > + linesize_aligned = NI_VPU_CEIL(ctx->width, 2); > + ctx->width = linesize_aligned; > + > + height_aligned = ctx->height; > + ctx->height = NI_VPU_CEIL(height_aligned, 2); > + > + f_hwctx->api_ctx.active_video_width = ctx->width; > + f_hwctx->api_ctx.active_video_height = ctx->height; > + > + switch (ctx->sw_format) { > + case AV_PIX_FMT_YUV420P: > + f_hwctx->api_ctx.bit_depth_factor = 1; > + f_hwctx->api_ctx.src_bit_depth = 8; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_YUV420P; > + break; > + case AV_PIX_FMT_YUV420P10LE: > + f_hwctx->api_ctx.bit_depth_factor = 2; > + f_hwctx->api_ctx.src_bit_depth = 10; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_YUV420P10LE; > + break; > + case AV_PIX_FMT_NV12: > + f_hwctx->api_ctx.bit_depth_factor = 1; > + f_hwctx->api_ctx.src_bit_depth = 8; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_NV12; > + break; > + case AV_PIX_FMT_P010LE: > + f_hwctx->api_ctx.bit_depth_factor = 2; > + f_hwctx->api_ctx.src_bit_depth = 10; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_P010LE; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + break; > + case AV_PIX_FMT_RGBA: > + f_hwctx->api_ctx.bit_depth_factor = 4; > + f_hwctx->api_ctx.src_bit_depth = 32; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_RGBA; > + break; > + case AV_PIX_FMT_BGRA: > + f_hwctx->api_ctx.bit_depth_factor = 4; > + f_hwctx->api_ctx.src_bit_depth = 32; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_BGRA; > + break; > + case AV_PIX_FMT_ABGR: > + f_hwctx->api_ctx.bit_depth_factor = 4; > + f_hwctx->api_ctx.src_bit_depth = 32; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_ABGR; > + break; > + case AV_PIX_FMT_ARGB: > + f_hwctx->api_ctx.bit_depth_factor = 4; > + f_hwctx->api_ctx.src_bit_depth = 32; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_ARGB; > + break; > + case AV_PIX_FMT_BGR0: > + f_hwctx->api_ctx.bit_depth_factor = 4; > + f_hwctx->api_ctx.src_bit_depth = 32; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_BGR0; > + break; > + case AV_PIX_FMT_YUYV422: > + f_hwctx->api_ctx.bit_depth_factor = 1; > + f_hwctx->api_ctx.src_bit_depth = 8; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_YUYV422; > + break; > + case AV_PIX_FMT_UYVY422: > + f_hwctx->api_ctx.bit_depth_factor = 1; > + f_hwctx->api_ctx.src_bit_depth = 8; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_UYVY422; > + break; > + case AV_PIX_FMT_NV16: > + f_hwctx->api_ctx.bit_depth_factor = 1; > + f_hwctx->api_ctx.src_bit_depth = 8; > + f_hwctx->api_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; > + f_hwctx->api_ctx.pixel_format = NI_PIX_FMT_NV16; > + break; > + default: > + av_log(ctx, AV_LOG_ERROR, "Pixel format not supported by > device.\n"); > + return AVERROR(EINVAL); > + } > + > + if (ctx->width > NI_MAX_RESOLUTION_WIDTH || > + ctx->height > NI_MAX_RESOLUTION_HEIGHT || > + ctx->width * ctx->height > NI_MAX_RESOLUTION_AREA) { > + av_log(ctx, AV_LOG_ERROR, "Error XCoder resolution %dx%d not > supported\n", > + ctx->width, ctx->height); > + av_log(ctx, AV_LOG_ERROR, "Max Supported Width: %d Height %d > Area %d\n", > + NI_MAX_RESOLUTION_WIDTH, NI_MAX_RESOLUTION_HEIGHT, > NI_MAX_RESOLUTION_AREA); > + return AVERROR_EXTERNAL; > + } else if (f_hwctx->uploader_device_id >= -1) { > + // leave it to ni_device_session_open to handle uploader session open > + // based on api_ctx.hw_id set to proper value > + } else { > + av_log(ctx, AV_LOG_ERROR, "Error XCoder command line options"); > + return AVERROR(EINVAL); > + } > + > + av_log(ctx, AV_LOG_VERBOSE, > + "pixel sw_format=%d width = %d height = %d outformat=%d " > + "uploader_device_id=%d\n", > + ctx->sw_format, ctx->width, ctx->height, ctx->format, > + f_hwctx->uploader_device_id); > + > + f_hwctx->api_ctx.hw_id = f_hwctx->uploader_device_id; > + f_hwctx->api_ctx.keep_alive_timeout = f_hwctx->keep_alive_timeout; > + if (0 == f_hwctx->api_ctx.keep_alive_timeout) { > + f_hwctx->api_ctx.keep_alive_timeout = > NI_DEFAULT_KEEP_ALIVE_TIMEOUT; > + } > + > + f_hwctx->api_ctx.framerate.framerate_num = f_hwctx->framerate.num; > + f_hwctx->api_ctx.framerate.framerate_denom = f_hwctx->framerate.den; > + > + ret = ni_device_session_open(&f_hwctx->api_ctx, > NI_DEVICE_TYPE_UPLOAD); > + if (ret != NI_RETCODE_SUCCESS) { > + av_log(ctx, AV_LOG_ERROR, "Error Something wrong in xcoder open\n"); > + ni_frames_uninit(ctx); > + return AVERROR_EXTERNAL; > + } else { > + av_log(ctx, AV_LOG_VERBOSE, > + "XCoder %s.%d (inst: %d) opened successfully\n", > + f_hwctx->api_ctx.dev_xcoder_name, f_hwctx->api_ctx.hw_id, > + f_hwctx->api_ctx.session_id); > +#ifndef _WIN32 > + // replace device_handle with blk_io_handle > + ni_device_close(f_hwctx->api_ctx.device_handle); > + f_hwctx->api_ctx.device_handle = f_hwctx->api_ctx.blk_io_handle; > +#endif > + // save blk_io_handle for track > + device_hwctx->uploader_handle = f_hwctx->api_ctx.blk_io_handle; > + } > + memset(&f_hwctx->src_session_io_data, 0, sizeof(ni_session_data_io_t)); > + > + ret = ni_device_session_init_framepool(&f_hwctx->api_ctx, pool_size, > NI_UPLOADER_FLAG_LM); > + if (ret < 0) { > + return ret; > + } > + > + if (!ctx->pool) { > + ret = ni_init_pool(ctx); > + if (ret < 0) { > + av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n"); > + return ret; > + } > + } > + return 0; > +} > + > +static int ni_to_avframe_copy(AVHWFramesContext *hwfc, AVFrame *dst, > + const ni_frame_t *src) > +{ > + int src_linesize[4], src_height[4]; > + int i, h, nb_planes; > + uint8_t *src_line, *dst_line; > + > + nb_planes = av_pix_fmt_count_planes(hwfc->sw_format); > + > + switch (hwfc->sw_format) { > + case AV_PIX_FMT_YUV420P: > + src_linesize[0] = FFALIGN(dst->width, 128); > + src_linesize[1] = FFALIGN(dst->width / 2, 128); > + src_linesize[2] = src_linesize[1]; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = FFALIGN(dst->height, 2) / 2; > + src_height[2] = src_height[1]; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_YUV420P10LE: > + src_linesize[0] = FFALIGN(dst->width * 2, 128); > + src_linesize[1] = FFALIGN(dst->width, 128); > + src_linesize[2] = src_linesize[1]; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = FFALIGN(dst->height, 2) / 2; > + src_height[2] = src_height[1]; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_NV12: > + src_linesize[0] = FFALIGN(dst->width, 128); > + src_linesize[1] = FFALIGN(dst->width, 128); > + src_linesize[2] = 0; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = FFALIGN(dst->height, 2) / 2; > + src_height[2] = 0; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_NV16: > + src_linesize[0] = FFALIGN(dst->width, 64); > + src_linesize[1] = FFALIGN(dst->width, 64); > + src_linesize[2] = 0; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = dst->height; > + src_height[2] = 0; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_YUYV422: > + case AV_PIX_FMT_UYVY422: > + src_linesize[0] = FFALIGN(dst->width, 16) * 2; > + src_linesize[1] = 0; > + src_linesize[2] = 0; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = 0; > + src_height[2] = 0; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_P010LE: > + src_linesize[0] = FFALIGN(dst->width * 2, 128); > + src_linesize[1] = FFALIGN(dst->width * 2, 128); > + src_linesize[2] = 0; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = FFALIGN(dst->height, 2) / 2; > + src_height[2] = 0; > + src_height[3] = 0; > + break; > + > + case AV_PIX_FMT_RGBA: > + case AV_PIX_FMT_BGRA: > + case AV_PIX_FMT_ABGR: > + case AV_PIX_FMT_ARGB: > + case AV_PIX_FMT_BGR0: > + src_linesize[0] = FFALIGN(dst->width, 16) * 4; > + src_linesize[1] = 0; > + src_linesize[2] = 0; > + src_linesize[3] = 0; > + > + src_height[0] = dst->height; > + src_height[1] = 0; > + src_height[2] = 0; > + src_height[3] = 0; > + break; > + > + default: > + av_log(hwfc, AV_LOG_ERROR, "Unsupported pixel format %s\n", > + av_get_pix_fmt_name(hwfc->sw_format)); > + return AVERROR(EINVAL); > + } > + > + for (i = 0; i < nb_planes; i++) { > + dst_line = dst->data[i]; > + src_line = src->p_data[i]; > + > + for (h = 0; h < src_height[i]; h++) { > + memcpy(dst_line, src_line, > + FFMIN(src_linesize[i], dst->linesize[i])); > + dst_line += dst->linesize[i]; > + src_line += src_linesize[i]; > + } > + } > + > + return 0; > +} > + > +static int av_to_niframe_copy(AVHWFramesContext *hwfc, const int > dst_stride[4], > + ni_frame_t *dst, const AVFrame *src) { > + int src_height[4], hpad[4], vpad[4]; > + int i, j, h, nb_planes; > + uint8_t *src_line, *dst_line, YUVsample, *sample, *dest; > + uint16_t lastidx; > + bool tenBit; > + > + nb_planes = av_pix_fmt_count_planes(hwfc->sw_format); > + > + switch (src->format) { > + case AV_PIX_FMT_YUV420P: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = FFMAX(dst_stride[1] - src->linesize[1], 0); > + hpad[2] = FFMAX(dst_stride[2] - src->linesize[2], 0); > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = FFALIGN(src->height, 2) / 2; > + src_height[2] = FFALIGN(src->height, 2) / 2; > + src_height[3] = 0; > + > + vpad[0] = FFALIGN(src_height[0], 2) - src_height[0]; > + vpad[1] = FFALIGN(src_height[1], 2) - src_height[1]; > + vpad[2] = FFALIGN(src_height[2], 2) - src_height[2]; > + vpad[3] = 0; > + > + tenBit = false; > + break; > + > + case AV_PIX_FMT_YUV420P10LE: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = FFMAX(dst_stride[1] - src->linesize[1], 0); > + hpad[2] = FFMAX(dst_stride[2] - src->linesize[2], 0); > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = FFALIGN(src->height, 2) / 2; > + src_height[2] = FFALIGN(src->height, 2) / 2; > + src_height[3] = 0; > + > + vpad[0] = FFALIGN(src_height[0], 2) - src_height[0]; > + vpad[1] = FFALIGN(src_height[1], 2) - src_height[1]; > + vpad[2] = FFALIGN(src_height[2], 2) - src_height[2]; > + vpad[3] = 0; > + > + tenBit = true; > + break; > + > + case AV_PIX_FMT_NV12: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = FFMAX(dst_stride[1] - src->linesize[1], 0); > + hpad[2] = 0; > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = FFALIGN(src->height, 2) / 2; > + src_height[2] = 0; > + src_height[3] = 0; > + > + vpad[0] = FFALIGN(src_height[0], 2) - src_height[0]; > + vpad[1] = FFALIGN(src_height[1], 2) - src_height[1]; > + vpad[2] = 0; > + vpad[3] = 0; > + > + tenBit = false; > + break; > + case AV_PIX_FMT_NV16: > + hpad[0] = 0; > + hpad[1] = 0; > + hpad[2] = 0; > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = src->height; > + src_height[2] = 0; > + src_height[3] = 0; > + > + vpad[0] = 0; > + vpad[1] = 0; > + vpad[2] = 0; > + vpad[3] = 0; > + > + tenBit = false; > + break; > + > + case AV_PIX_FMT_P010LE: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = FFMAX(dst_stride[1] - src->linesize[1], 0); > + hpad[2] = 0; > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = FFALIGN(src->height, 2) / 2; > + src_height[2] = 0; > + src_height[3] = 0; > + > + vpad[0] = FFALIGN(src_height[0], 2) - src_height[0]; > + vpad[1] = FFALIGN(src_height[1], 2) - src_height[1]; > + vpad[2] = 0; > + vpad[3] = 0; > + > + tenBit = true; > + break; > + > + case AV_PIX_FMT_RGBA: > + case AV_PIX_FMT_BGRA: > + case AV_PIX_FMT_ABGR: > + case AV_PIX_FMT_ARGB: > + case AV_PIX_FMT_BGR0: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = 0; > + hpad[2] = 0; > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = 0; > + src_height[2] = 0; > + src_height[3] = 0; > + > + vpad[0] = 0; > + vpad[1] = 0; > + vpad[2] = 0; > + vpad[3] = 0; > + > + tenBit = false; > + break; > + > + case AV_PIX_FMT_YUYV422: > + case AV_PIX_FMT_UYVY422: > + hpad[0] = FFMAX(dst_stride[0] - src->linesize[0], 0); > + hpad[1] = 0; > + hpad[2] = 0; > + hpad[3] = 0; > + > + src_height[0] = src->height; > + src_height[1] = 0; > + src_height[2] = 0; > + src_height[3] = 0; > + > + vpad[0] = 0; > + vpad[1] = 0; > + vpad[2] = 0; > + vpad[3] = 0; > + > + tenBit = false; > + break; > + > + default: > + av_log(hwfc, AV_LOG_ERROR, "Pixel format %s not supported\n", > + av_get_pix_fmt_name(src->format)); > + break; > + } > + > + for (i = 0; i < nb_planes; i++) { > + dst_line = dst->p_data[i]; > + src_line = src->data[i]; > + > + for (h = 0; h < src_height[i]; h++) { > + memcpy(dst_line, src_line, FFMIN(src->linesize[i], dst_stride[i])); > + > + if (hpad[i]) { > + lastidx = src->linesize[i]; > + > + if (tenBit) { > + sample = &src_line[lastidx - 2]; > + dest = &dst_line[lastidx]; > + > + /* two bytes per sample */ > + for (j = 0; j < hpad[i] / 2; j++) { > + memcpy(dest, sample, 2); > + dest += 2; > + } > + } else { > + YUVsample = dst_line[lastidx - 1]; > + memset(&dst_line[lastidx], YUVsample, hpad[i]); > + } > + } > + > + src_line += src->linesize[i]; > + dst_line += dst_stride[i]; > + } > + > + /* Extend the height by cloning the last line */ > + src_line = dst_line - dst_stride[i]; > + for (h = 0; h < vpad[i]; h++) { > + memcpy(dst_line, src_line, dst_stride[i]); > + dst_line += dst_stride[i]; > + } > + } > + > + return 0; > +} > + > +static int ni_hwdl_frame(AVHWFramesContext *hwfc, AVFrame *dst, > + const AVFrame *src) > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) hwfc->hwctx; > + ni_session_data_io_t session_io_data; > + ni_session_data_io_t *p_session_data = &session_io_data; > + niFrameSurface1_t *src_surf = (niFrameSurface1_t *)src->data[3]; > + int ret; > + int pixel_format; > + > + memset(&session_io_data, 0, sizeof(ni_session_data_io_t)); > + > + av_log(hwfc, AV_LOG_VERBOSE, > + "%s handle %d trace ui16FrameIdx = [%d] SID %d\n", __func__, > + src_surf->device_handle, src_surf->ui16FrameIdx, > + src_surf->ui16session_ID); > + > + av_log(hwfc, AV_LOG_DEBUG, "%s hwdl processed h/w = %d/%d\n", > __func__, > + src->height, src->width); > + > + switch (hwfc->sw_format) { > + case AV_PIX_FMT_YUV420P: > + pixel_format = NI_PIX_FMT_YUV420P; > + break; > + case AV_PIX_FMT_YUV420P10LE: > + pixel_format = NI_PIX_FMT_YUV420P10LE; > + break; > + case AV_PIX_FMT_NV12: > + pixel_format = NI_PIX_FMT_NV12; > + break; > + case AV_PIX_FMT_NV16: > + pixel_format = NI_PIX_FMT_NV16; > + break; > + case AV_PIX_FMT_YUYV422: > + pixel_format = NI_PIX_FMT_YUYV422; > + break; > + case AV_PIX_FMT_UYVY422: > + pixel_format = NI_PIX_FMT_UYVY422; > + break; > + case AV_PIX_FMT_P010LE: > + pixel_format = NI_PIX_FMT_P010LE; > + break; > + case AV_PIX_FMT_RGBA: > + pixel_format = NI_PIX_FMT_RGBA; > + break; > + case AV_PIX_FMT_BGRA: > + pixel_format = NI_PIX_FMT_BGRA; > + break; > + case AV_PIX_FMT_ABGR: > + pixel_format = NI_PIX_FMT_ABGR; > + break; > + case AV_PIX_FMT_ARGB: > + pixel_format = NI_PIX_FMT_ARGB; > + break; > + case AV_PIX_FMT_BGR0: > + pixel_format = NI_PIX_FMT_BGR0; > + break; > + default: > + av_log(hwfc, AV_LOG_ERROR, "Pixel format %s not supported\n", > + av_get_pix_fmt_name(hwfc->sw_format)); > + return AVERROR(EINVAL); > + } > + > + ret = ni_frame_buffer_alloc_dl(&(p_session_data->data.frame), src->width, > + src->height, pixel_format); > + if (ret != NI_RETCODE_SUCCESS) { > + av_log(hwfc, AV_LOG_ERROR, "%s Cannot allocate ni_frame\n", > __func__); > + return AVERROR(ENOMEM); > + } > + > + f_hwctx->api_ctx.is_auto_dl = false; > + ret = ni_device_session_hwdl(&f_hwctx->api_ctx, p_session_data, > src_surf); > + if (ret <= 0) { > + av_log(hwfc, AV_LOG_DEBUG, "%s failed to retrieve frame\n", __func__); > + ni_frame_buffer_free(&p_session_data->data.frame); > + return AVERROR_EXTERNAL; > + } > + > + ret = ni_to_avframe_copy(hwfc, dst, &p_session_data->data.frame); > + if (ret < 0) { > + av_log(hwfc, AV_LOG_ERROR, "Can't copy frame %d\n", ret); > + ni_frame_buffer_free(&p_session_data->data.frame); > + return ret; > + } > + > + dst->format = hwfc->sw_format; > + > + av_frame_copy_props(dst, src); > + ni_frame_buffer_free(&p_session_data->data.frame); > + > + return 0; > +} > + > +static int ni_hwup_frame(AVHWFramesContext *hwfc, AVFrame *dst, const > AVFrame *src) > +{ > + AVNIFramesContext *f_hwctx = (AVNIFramesContext*) hwfc->hwctx; > + ni_session_data_io_t *p_src_session_data; > + niFrameSurface1_t *dst_surf; > + int ret = 0; > + int dst_stride[4]; > + int pixel_format; > + bool isSemiPlanar; > + int need_to_copy = 1; > + size_t crop_right = 0, crop_bottom = 0; > + > + dst_surf = (niFrameSurface1_t *)dst->data[3]; > + > + if (dst_surf == NULL || dst->hw_frames_ctx == NULL) { > + av_log(hwfc, AV_LOG_ERROR, "Invalid hw frame\n"); > + return AVERROR(EINVAL); > + } > + > + p_src_session_data = &f_hwctx->src_session_io_data; > + > + switch (src->format) { > + /* 8-bit YUV420 planar */ > + case AV_PIX_FMT_YUV420P: > + dst_stride[0] = FFALIGN(src->width, 128); > + dst_stride[1] = FFALIGN((src->width / 2), 128); > + dst_stride[2] = dst_stride[1]; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_YUV420P; > + isSemiPlanar = false; > + break; > + > + /* 10-bit YUV420 planar, little-endian, least significant bits */ > + case AV_PIX_FMT_YUV420P10LE: > + dst_stride[0] = FFALIGN(src->width * 2, 128); > + dst_stride[1] = FFALIGN(src->width, 128); > + dst_stride[2] = dst_stride[1]; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_YUV420P10LE; > + isSemiPlanar = false; > + break; > + > + /* 8-bit YUV420 semi-planar */ > + case AV_PIX_FMT_NV12: > + dst_stride[0] = FFALIGN(src->width, 128); > + dst_stride[1] = dst_stride[0]; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_NV12; > + isSemiPlanar = true; > + break; > + > + /* 8-bit yuv422 semi-planar */ > + case AV_PIX_FMT_NV16: > + dst_stride[0] = FFALIGN(src->width, 64); > + dst_stride[1] = dst_stride[0]; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_NV16; > + isSemiPlanar = false; > + break; > + > + /*8-bit yuv422 planar */ > + case AV_PIX_FMT_YUYV422: > + dst_stride[0] = FFALIGN(src->width, 16) * 2; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_YUYV422; > + isSemiPlanar = false; > + break; > + > + case AV_PIX_FMT_UYVY422: > + dst_stride[0] = FFALIGN(src->width, 16) * 2; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_UYVY422; > + isSemiPlanar = false; > + break; > + > + /* 10-bit YUV420 semi-planar, little endian, most significant bits */ > + case AV_PIX_FMT_P010LE: > + dst_stride[0] = FFALIGN(src->width * 2, 128); > + dst_stride[1] = dst_stride[0]; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_P010LE; > + isSemiPlanar = true; > + break; > + > + /* 32-bit RGBA packed */ > + case AV_PIX_FMT_RGBA: > + /* RGBA for the scaler has a 16-byte width/64-byte stride alignment */ > + dst_stride[0] = FFALIGN(src->width, 16) * 4; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_RGBA; > + isSemiPlanar = false; > + break; > + > + case AV_PIX_FMT_BGRA: > + dst_stride[0] = FFALIGN(src->width, 16) * 4; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_BGRA; > + isSemiPlanar = false; > + break; > + > + case AV_PIX_FMT_ABGR: > + dst_stride[0] = FFALIGN(src->width, 16) * 4; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_ABGR; > + isSemiPlanar = false; > + break; > + > + case AV_PIX_FMT_ARGB: > + dst_stride[0] = FFALIGN(src->width, 16) * 4; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_ARGB; > + isSemiPlanar = false; > + break; > + > + case AV_PIX_FMT_BGR0: > + dst_stride[0] = FFALIGN(src->width, 16) * 4; > + dst_stride[1] = 0; > + dst_stride[2] = 0; > + dst_stride[3] = 0; > + > + pixel_format = NI_PIX_FMT_BGR0; > + isSemiPlanar = false; > + break; > + > + default: > + av_log(hwfc, AV_LOG_ERROR, "Pixel format %s not supported by > device %s\n", > + av_get_pix_fmt_name(src->format), ffhwframesctx(hwfc)->hw_type- > >name); > + return AVERROR(EINVAL); > + } > + > + // check input resolution zero copy compatible or not > + if (ni_uploader_frame_zerocopy_check(&f_hwctx->api_ctx, > + src->width, src->height, > + (const int *)src->linesize, pixel_format) == NI_RETCODE_SUCCESS) { > + need_to_copy = 0; > + p_src_session_data->data.frame.extra_data_len = > + NI_APP_ENC_FRAME_META_DATA_SIZE; > + // alloc metadata buffer etc. (if needed) > + ret = ni_encoder_frame_zerocopy_buffer_alloc( > + &p_src_session_data->data.frame, src->width, > + src->height, (const int *)src->linesize, (const uint8_t **)src->data, > + (int)p_src_session_data->data.frame.extra_data_len); > + if (ret != NI_RETCODE_SUCCESS) { > + return AVERROR(ENOMEM); > + } > + } else { > + // allocate only once per upload Session when we have frame info > + p_src_session_data->data.frame.extra_data_len = > + NI_APP_ENC_FRAME_META_DATA_SIZE; > + > + ret = ni_frame_buffer_alloc_pixfmt(&p_src_session_data->data.frame, > + pixel_format, src->width, > + src->height, dst_stride, > + 1, // force to av_codec_id_h264 for max compat > + (int)p_src_session_data->data.frame.extra_data_len); > + if (ret < 0) { > + av_log(hwfc, AV_LOG_ERROR, "Cannot allocate ni_frame %d\n", ret); > + return ret; > + } > + } > + > + if (need_to_copy) { > + ret = av_to_niframe_copy(hwfc, dst_stride, &p_src_session_data- > >data.frame, src); > + if (ret < 0) { > + av_log(hwfc, AV_LOG_ERROR, "%s can't copy frame\n", __func__); > + return AVERROR(EINVAL); > + } > + } > + > + ret = ni_device_session_hwup(&f_hwctx->api_ctx, p_src_session_data, > dst_surf); > + if (ret < 0) { > + av_log(hwfc, AV_LOG_ERROR, "%s failed to upload frame %d\n", > + __func__, ret); > + return AVERROR_EXTERNAL; > + } > + > + dst_surf->ui16width = f_hwctx->split_ctx.w[0] = src->width; > + dst_surf->ui16height = f_hwctx->split_ctx.h[0] = src->height; > + dst_surf->ui32nodeAddress = 0; // always 0 offset for upload > + dst_surf->encoding_type = isSemiPlanar ? > NI_PIXEL_PLANAR_FORMAT_SEMIPLANAR > + : NI_PIXEL_PLANAR_FORMAT_PLANAR; > + > + av_log(hwfc, AV_LOG_VERBOSE, "%s trace ui16FrameIdx = [%u] hdl %d > SID%d\n", > + __func__, dst_surf->ui16FrameIdx, dst_surf->device_handle, > + dst_surf->ui16session_ID); > + > + // Update frames context > + f_hwctx->split_ctx.f[0] = (int)dst_surf->encoding_type; > + > + /* Set the hw_id/card number in AVNIFramesContext */ > + ((AVNIFramesContext*)((AVHWFramesContext*)dst->hw_frames_ctx- > >data)->hwctx)->hw_id = f_hwctx->api_ctx.hw_id; > + > + crop_right = dst->crop_right; > + crop_bottom = dst->crop_bottom; > + > + av_frame_copy_props(dst, src); // should get the metadata right > + av_log(hwfc, AV_LOG_DEBUG, "%s Upload frame w/h %d/%d crop > r/b %lu/%lu\n", > + __func__, dst->width, dst->height, crop_right, crop_bottom); > + > + return ret; > +} > + > +static int ni_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, > + const AVFrame *src) > +{ > + int err; > + niFrameSurface1_t *dst_surf; > + > + if (src->width > hwfc->width || src->height > hwfc->height) { > + return AVERROR(EINVAL); > + } > + > + /* should check against MAX frame size */ > + err = ni_hwup_frame(hwfc, dst, src); > + if (err) { > + return err; > + } > + > + dst_surf = (niFrameSurface1_t *)(dst->data[3]); > + > + av_log(hwfc, AV_LOG_VERBOSE, > + "hwcontext.c:ni_hwup_frame() dst_surf FID %d %d\n", > + dst_surf->ui16FrameIdx, dst_surf->ui16session_ID); > + > + return 0; > +} > + > +static int ni_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, > + const AVFrame *src) > +{ > + if (dst->width > hwfc->width || dst->height > hwfc->height) { > + av_log(hwfc, AV_LOG_ERROR, "Invalid frame dimensions\n"); > + return AVERROR(EINVAL); > + } > + > + return ni_hwdl_frame(hwfc, dst, src); > +} > + > +const HWContextType ff_hwcontext_type_ni_quadra = { > + // QUADRA > + .type = AV_HWDEVICE_TYPE_NI_QUADRA, > + .name = "NI_QUADRA", > + > + .device_hwctx_size = sizeof(AVNIDeviceContext), > + .frames_hwctx_size = sizeof(AVNIFramesContext), > + > + .device_create = ni_device_create, > + .device_uninit = ni_device_uninit, > + > + .frames_get_constraints = ni_frames_get_constraints, > + > + .frames_init = ni_frames_init, > + .frames_uninit = ni_frames_uninit, > + > + .frames_get_buffer = ni_get_buffer, > + > + .transfer_get_formats = ni_transfer_get_formats, > + .transfer_data_to = ni_transfer_data_to, > + .transfer_data_from = ni_transfer_data_from, > + > + .pix_fmts = > + (const enum AVPixelFormat[]){AV_PIX_FMT_NI_QUAD, > AV_PIX_FMT_NONE}, > +}; > diff --git a/libavutil/hwcontext_ni_quad.h b/libavutil/hwcontext_ni_quad.h > new file mode 100644 > index 0000000000..a8795398d7 > --- /dev/null > +++ b/libavutil/hwcontext_ni_quad.h > @@ -0,0 +1,99 @@ > +/* > + * 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 AVUTIL_HWCONTEXT_NI_QUAD_H > +#define AVUTIL_HWCONTEXT_NI_QUAD_H > + > +#include "hwcontext.h" > +#include > +#include > +#include > + > +enum > +{ > + NI_MEMTYPE_VIDEO_MEMORY_NONE, > + NI_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET, > + NI_MEMTYPE_VIDEO_MEMORY_HWUPLOAD_TARGET, > +}; > + > +typedef enum _ni_filter_poolsize_code { > + NI_DECODER_ID = -1, > + NI_SCALE_ID = -2, > + NI_PAD_ID = -3, > + NI_CROP_ID = -4, > + NI_OVERLAY_ID = -5, > + NI_ROI_ID = -6, > + NI_BG_ID = -7, > + NI_STACK_ID = -8, > + NI_ROTATE_ID = -9, > + NI_DRAWBOX_ID = -10, > + NI_BGR_ID = -11, > + NI_DRAWTEXT_ID = -12, > + NI_AI_PREPROCESS_ID = -13, > + NI_DELOGO_ID = -14, > + NI_MERGE_ID = -15, > + NI_FLIP_ID = -16, > + NI_HVSPLUS_ID = -17, > +} ni_filter_poolsize_code; > + > +/** > +* This struct is allocated as AVHWDeviceContext.hwctx > +*/ > +typedef struct AVNIDeviceContext { > + int uploader_ID; > + ni_device_handle_t uploader_handle; > + > + ni_device_handle_t cards[NI_MAX_DEVICE_CNT]; > +} AVNIDeviceContext; > + > +/** > +* This struct is allocated as AVHWFramesContext.hwctx > +*/ > +typedef struct AVNIFramesContext { > + niFrameSurface1_t *surfaces; > + int nb_surfaces; > + int keep_alive_timeout; > + int frame_type; > + AVRational framerate; /* used for modelling hwupload */ > + int hw_id; > + ni_session_context_t api_ctx; // for down/uploading frames > + ni_split_context_t split_ctx; > + ni_device_handle_t suspended_device_handle; > + int uploader_device_id; // same one passed to libxcoder session > open > + > + // Accessed only by hwcontext_ni_quad.c > + niFrameSurface1_t *surfaces_internal; > + int nb_surfaces_used; > + niFrameSurface1_t **surface_ptrs; > + ni_session_data_io_t src_session_io_data; // for upload frame to be sent > up > +} AVNIFramesContext; > + > +static inline int ni_get_cardno(const AVFrame *frame) { > + AVNIFramesContext* ni_hwf_ctx; > + ni_hwf_ctx = (AVNIFramesContext*)((AVHWFramesContext*)frame- > >hw_frames_ctx->data)->hwctx; > + return ni_hwf_ctx->hw_id; > +} > + > +// copy hwctx specific data from one AVHWFramesContext to another > +static inline void ni_cpy_hwframe_ctx(AVHWFramesContext *in_frames_ctx, > + AVHWFramesContext *out_frames_ctx) > +{ > + memcpy(out_frames_ctx->hwctx, in_frames_ctx->hwctx, > sizeof(AVNIFramesContext)); > +} > + > +#endif /* AVUTIL_HWCONTEXT_NI_H */ > diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c > index 53adde5aba..ad001cec93 100644 > --- a/libavutil/pixdesc.c > +++ b/libavutil/pixdesc.c > @@ -2170,6 +2170,21 @@ static const AVPixFmtDescriptor > av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { > .name = "qsv", > .flags = AV_PIX_FMT_FLAG_HWACCEL, > }, > + // NETINT: AV_PIX_FMT_NI_QUAD pixel format for Quadra HW frame > + [AV_PIX_FMT_NI_QUAD] = { > + .name = "ni_quadra", > + .flags = AV_PIX_FMT_FLAG_HWACCEL, > + }, > + // NETINT: AV_PIX_FMT_NI_QUAD_8_TILE_4X4 pixel format for Quadra > internally compressed frame > + [AV_PIX_FMT_NI_QUAD_8_TILE_4X4] = { > + .name = "ni_quadra_8_tile4x4", > + .flags = AV_PIX_FMT_FLAG_HWACCEL, > + }, > + // NETINT: AV_PIX_FMT_NI_QUAD_10_TILE_4X4 pixel format for Quadra > internally compressed frame > + [AV_PIX_FMT_NI_QUAD_10_TILE_4X4] = { > + .name = "ni_quadra_10_tile4x4", > + .flags = AV_PIX_FMT_FLAG_HWACCEL, > + }, > [AV_PIX_FMT_MEDIACODEC] = { > .name = "mediacodec", > .flags = AV_PIX_FMT_FLAG_HWACCEL, > diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h > index bf1b8ed008..a7ee2b6b1c 100644 > --- a/libavutil/pixfmt.h > +++ b/libavutil/pixfmt.h > @@ -488,6 +488,14 @@ enum AVPixelFormat { > AV_PIX_FMT_GBRAP32BE, ///< planar GBRA 4:4:4:4 128bpp, big-endian > AV_PIX_FMT_GBRAP32LE, ///< planar GBRA 4:4:4:4 128bpp, little-endian > > + /** > + * HW acceleration through NI, data[3] contains a pointer to the > + * niFrameSurface1_t structure, for Netint Quadra. > + */ > + AV_PIX_FMT_NI_QUAD, > + AV_PIX_FMT_NI_QUAD_8_TILE_4X4, /// 8-bit tiled 4x4 compression > format within QUADRA > + AV_PIX_FMT_NI_QUAD_10_TILE_4X4, /// 10-bit tiled 4x4 compression > format within QUADRA > + > AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you > want to link with shared libav* because the number of formats might differ > between versions > }; > > -- > 2.25.1 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".