From patchwork Fri Dec 16 09:41:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunny Shukla X-Patchwork-Id: 1831 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.65.86 with SMTP id o83csp1231728vsa; Fri, 16 Dec 2016 01:42:02 -0800 (PST) X-Received: by 10.28.178.205 with SMTP id b196mr1975953wmf.8.1481881322720; Fri, 16 Dec 2016 01:42:02 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id xb8si6235984wjb.239.2016.12.16.01.42.02; Fri, 16 Dec 2016 01:42:02 -0800 (PST) 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=@eInfochipsIndia.onmicrosoft.com; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9B14E689B59; Fri, 16 Dec 2016 11:41:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from APC01-HK2-obe.outbound.protection.outlook.com (mail-hk2apc01on0068.outbound.protection.outlook.com [104.47.124.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A7DB1689B1E for ; Fri, 16 Dec 2016 11:41:46 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eInfochipsIndia.onmicrosoft.com; s=selector1-einfochips-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=d6gRaOcyoB1DgwXdPxNj+u7I/xRiEUnsBL56TJfZ0Zg=; b=Daf0WLtit7PUwVuR51pt/5w67uj9YHw3Mm0wfHIzWp7xN5xtM+laW74bOz54CuRYTwjtVJObdmFAsIXE1qMwBoCJAoMxpxtAe/VTmHEsGm1+3E43QvQ3oHLrjJucXmMKGB+6rGtt8yACY5x/Rf0S1/nHplO9TfoH3LUcIfHCl+A= Received: from SG2PR02MB1375.apcprd02.prod.outlook.com (10.169.101.137) by SG2PR02MB1374.apcprd02.prod.outlook.com (10.169.101.136) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.771.8; Fri, 16 Dec 2016 09:41:46 +0000 Received: from SG2PR02MB1375.apcprd02.prod.outlook.com ([10.169.101.137]) by SG2PR02MB1375.apcprd02.prod.outlook.com ([10.169.101.137]) with mapi id 15.01.0771.014; Fri, 16 Dec 2016 09:41:47 +0000 From: Sunny Shukla To: "ffmpeg-devel@ffmpeg.org" Thread-Topic: [FFmpeg-devel] [PATCH] NV12 Tile format conversion Thread-Index: AQHSV4CBJBoAsS4LdkGCIYN7Yz5RbQ== Date: Fri, 16 Dec 2016 09:41:46 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=sunny.shukla@einfochips.com; x-originating-ip: [25.169.49.132] x-ms-office365-filtering-correlation-id: 1fb70488-cda9-4030-ea05-08d42597c0d8 x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:SG2PR02MB1374; x-microsoft-exchange-diagnostics: 1; SG2PR02MB1374; 7:m8YyTBq2rNC7FjO8RGpRsbPnI+j9b4x7DouxmD0lyoC+vy7LGMxf8QsAFqEuKvfUbHgk2/2S+J6SqBoWhbLEMvWMqb/RDILvQinTnMZcjbsUoaIHS9rdEfK4KiNsx6MwVDUIzhhPpzOd4z53hl64VmM0HjgyrY8nqLcrKjGfG8PYNW4kqVeBf1t5ZmWNSs0zVJqgxmxIjP+BOubiDS39iBihCscmIrdzvRIYslT9TiTr9Nx53M2vA34fIEXoeNEFkSQWmtCBRDf6SEWhnrHTSCF+IwAk1uoqKlFCrJWjZq2vhkijgTgLd4qHZ7zPEQpIznM6557/nx5itHL+YgGw0ZpLvkwmJJl3dBKfo20IxX96mreeIQ3ApOP4g2V9hjJLiKP3e7EHIyXAY1xX6gKaO0h9/gJDBYEG46snS2nUGwDjKsCdtFS1to/kIg3WzastDstIkQpsij+DV1UQvAapvg== x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(166708455590820)(211936372134217)(145926492361056); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(102415395)(6040375)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6041248)(20161123560025)(20161123555025)(20161123562025)(20161123564025)(6072148); SRVR:SG2PR02MB1374; BCL:0; PCL:0; RULEID:; SRVR:SG2PR02MB1374; x-forefront-prvs: 01583E185C x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(6009001)(7916002)(39450400003)(199003)(189002)(81156014)(3660700001)(7696004)(86362001)(5890100001)(74316002)(107886002)(77096006)(38730400001)(6116002)(2501003)(189998001)(92566002)(110136003)(305945005)(3846002)(102836003)(6436002)(76576001)(6506006)(33656002)(6916009)(7736002)(575784001)(106116001)(2351001)(68736007)(2906002)(105586002)(97736004)(106356001)(8676002)(2900100001)(5660300001)(122556002)(3280700002)(8936002)(81166006)(25786008)(66066001)(9686002)(99936001)(5640700003)(450100001)(101416001)(50986999)(54356999); DIR:OUT; SFP:1101; SCL:1; SRVR:SG2PR02MB1374; H:SG2PR02MB1375.apcprd02.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; received-spf: None (protection.outlook.com: einfochips.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: einfochips.com X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Dec 2016 09:41:46.9951 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 0adb040b-ca22-4ca6-9447-ab7b049a22ff X-MS-Exchange-Transport-CrossTenantHeadersStamped: SG2PR02MB1374 Subject: [FFmpeg-devel] [PATCH] NV12 Tile format conversion X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Hi, NV12 Tile format conversion to NV12 and yuv420p support is added. NV12 Tile format conversion support is only added for input format not as output format. The algorithm used is referenced from https://github.com/ssshukla26/NV12Tile-To-NV12-Conversion. It is checked with 480p,720p, 1080p and other resolutions. Videos both in landscape and portrait mode are been able to be converted from nv12 tiled to nv12 format using this algorithm. The input file must be a yuv file in NV12Tile format, one can download such video with 480p resolution from this https://drive.google.com/open?id=0B5dp19Ic3reULWJIS0JTRFVZbjg link. See instructions file under examples folder for more details in the github link. For memory layout please refer https://www.linuxtv.org/downloads/v4l-dvb-apis-old/re36.html The need to incorporate this format conversion is to make sure that when certain hardware decoders outputs the data in nv12 tiled format can also be directly displayed in nv12 or yuv420p format using ffmpeg command line and APIs. P.S. : This patch is applied on commit id "d4c1cc2b876af1e8f1a8ca258bf092b3baa31245" of ffmpeg release 3.2 (latest release). PFA : 0001-Input-format-NV12-Tile-support-added.patch Regards, Sunny. ************************************************************************************************************************************************************* eInfochips Business Disclaimer: This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated. Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email. ************************************************************************************************************************************************************* From fea4d3574270f5e817ebe44cc326b58aa758580c Mon Sep 17 00:00:00 2001 From: Sunny Shukla Date: Thu, 15 Dec 2016 01:58:58 +0530 Subject: [PATCH] Input format NV12 Tile support added NV12 Tile format conversion to NV12 and yuv420p support is added. NV12 Tile format conversion support is only for as input format not as output format. Signed-off-by: Sunny Shukla --- Changelog | 1 + libavutil/Makefile | 4 + libavutil/imgutils.c | 14 ++- libavutil/pixdesc.c | 12 +++ libavutil/pixfmt.h | 1 + libavutil/special_format.c | 60 ++++++++++++ libavutil/special_format.h | 75 +++++++++++++++ libavutil/utils.c | 2 +- libswscale/Makefile | 2 + libswscale/nv12tiled2nv12.c | 212 ++++++++++++++++++++++++++++++++++++++++++ libswscale/nv12tiled2nv12.h | 85 +++++++++++++++++ libswscale/swscale_internal.h | 5 + libswscale/swscale_unscaled.c | 54 ++++++++++- libswscale/utils.c | 19 ++++ 14 files changed, 541 insertions(+), 5 deletions(-) create mode 100644 libavutil/special_format.c create mode 100644 libavutil/special_format.h create mode 100644 libswscale/nv12tiled2nv12.c create mode 100644 libswscale/nv12tiled2nv12.h diff --git a/Changelog b/Changelog index b36a631..23a3d87 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ version : - Support for spherical videos - configure now fails if autodetect-libraries are requested but not found - PSD Decoder +- Input format NV12 Tile support added version 3.2: - libopenmpt demuxer diff --git a/libavutil/Makefile b/libavutil/Makefile index 9841645..5d29663 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -74,6 +74,8 @@ HEADERS = adler32.h \ version.h \ xtea.h \ tea.h \ + special_format.h \ + HEADERS-$(CONFIG_LZO) += lzo.h @@ -152,6 +154,8 @@ OBJS = adler32.o \ xga_font_data.o \ xtea.o \ tea.o \ + special_format.o \ + OBJS-$(!HAVE_ATOMICS_NATIVE) += atomic.o \ diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index cc410ab..426b20c 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -30,6 +30,7 @@ #include "mathematics.h" #include "pixdesc.h" #include "rational.h" +#include "special_format.h" void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], const AVPixFmtDescriptor *pixdesc) @@ -119,9 +120,14 @@ int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int hei return AVERROR(EINVAL); data[0] = ptr; + if (linesizes[0] > (INT_MAX - 1024) / height) return AVERROR(EINVAL); - size[0] = linesizes[0] * height; + + if(pix_fmt == AV_PIX_FMT_NV12_TILED) + size[0] = avpriv_nv12tile_calc_plane_size(linesizes[0],height); + else + size[0] = linesizes[0] * height; if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { @@ -139,7 +145,11 @@ int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int hei h = (height + (1 << s) - 1) >> s; if (linesizes[i] > INT_MAX / h) return AVERROR(EINVAL); - size[i] = h * linesizes[i]; + + if(pix_fmt == AV_PIX_FMT_NV12_TILED) + size[i] = avpriv_nv12tile_calc_plane_size(linesizes[i],h); + else + size[i] = h * linesizes[i]; if (total_size > INT_MAX - size[i]) return AVERROR(EINVAL); total_size += size[i]; diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 3b9c45d..64b641a 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -448,6 +448,18 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_NV12_TILED] = { + .name = "nv12_tiled", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ + { 1, 2, 0, 0, 8, 1, 7, 1 }, /* U */ + { 1, 2, 1, 0, 8, 1, 7, 2 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, [AV_PIX_FMT_NV21] = { .name = "nv21", .nb_components = 3, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index dfb1b11..d18d463 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -88,6 +88,7 @@ enum AVPixelFormat { AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV12_TILED,///< same as NV12, but frame data is divided in microblocks/tiles having size 64*32, follows Z and flip Z pattern in logical memory layout AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... diff --git a/libavutil/special_format.c b/libavutil/special_format.c new file mode 100644 index 0000000..8b7a3f2 --- /dev/null +++ b/libavutil/special_format.c @@ -0,0 +1,60 @@ +/* + * NV12 tiled format support. + * Copyright (C) 2016 eInfochips India Pvt. Ltd. + * + * 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 "special_format.h" + +uint32_t avpriv_nv12tile_calc_wTiles(uint32_t width) +{ + return (ROUND_UP_X(width,128)/64); +} + +uint32_t avpriv_nv12tile_calc_hTiles(uint32_t height) +{ + return (ROUND_UP_X(height,32)/32); +} + +uint32_t avpriv_nv12tile_calc_boundary_padding(uint32_t width,uint32_t height) +{ + uint32_t wTiles = 0; + uint32_t hTiles = 0; + float data_size = 0; + uint32_t padding = 0; + + wTiles = avpriv_nv12tile_calc_wTiles(width); + hTiles = avpriv_nv12tile_calc_hTiles(height); + + data_size = ((float)((float)(((float)wTiles * (float)hTiles + * (float)NV12_TILE_SIZE)/(float)(4 * NV12_TILE_SIZE)))); + + data_size = data_size - (float)((uint32_t)data_size); + + padding = (uint32_t)(data_size * (float)(4 * NV12_TILE_SIZE)); + + return padding; +} + +uint32_t avpriv_nv12tile_calc_plane_size(uint32_t width,uint32_t height) +{ + if((0 == width) || (0 == height)) + return 0; + + return ((NV12_TILE_SIZE * avpriv_nv12tile_calc_wTiles(width) * avpriv_nv12tile_calc_hTiles(height)) + + avpriv_nv12tile_calc_boundary_padding(width,height)); +} diff --git a/libavutil/special_format.h b/libavutil/special_format.h new file mode 100644 index 0000000..bde8f78 --- /dev/null +++ b/libavutil/special_format.h @@ -0,0 +1,75 @@ +/* + * NV12 tiled format support. + * Copyright (C) 2016 eInfochips India Pvt. Ltd. + * + * 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_SPECIAL_FORMAT_H +#define AVUTIL_SPECIAL_FORMAT_H +#include + +//NOTE : This NV12Tile to NV12 conversion is taken from "https://github.com/ssshukla26/NV12Tile-To-NV12-Conversion" repo. + +/** + * Macro to round up a number "num" to the given number "X" + */ +#define ROUND_UP_X(num,x) (((num)+(x-1))&~(x-1)) + +/** + * Size of a single tile + */ +#define NV12_TILE_SIZE (64*32) + +/** + * This function returns no of tiles required + * for given width. + * + * @param width - width of the resolution + * @return no. of vertical tiles with respect to the width + */ +uint32_t avpriv_nv12tile_calc_wTiles(uint32_t width); + +/** + * This function returns no of tiles required + * for given height. + * + * @param height - height of the resolution + * @return no. of horizontal tiles with respect to height + */ +uint32_t avpriv_nv12tile_calc_hTiles(uint32_t height); + +/** + * This function will return padding required for + * a buffer made out of wTiles and hTiles. + * + * @param wTiles - no. of vertical tiles + * @param hTiles - no. of horizontal tiles + * @return boundary padding required with respect to horizontal and vertical tiles + */ +uint32_t avpriv_nv12tile_calc_boundary_padding(uint32_t width,uint32_t height); + +/** + * This function will returns size required + * for a plane of given width and height. + * + * @param width - width of the resolution + * @param height - height of the resolution + * @return plane size required with respect to width and height + */ +uint32_t avpriv_nv12tile_calc_plane_size(uint32_t width,uint32_t height); +#endif diff --git a/libavutil/utils.c b/libavutil/utils.c index 36e4dd5..e408eba 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -42,7 +42,7 @@ unsigned avutil_version(void) return LIBAVUTIL_VERSION_INT; #if FF_API_VDPAU - av_assert0(AV_PIX_FMT_VDA_VLD == 81); //check if the pix fmt enum has not had anything inserted or removed by mistake + av_assert0(AV_PIX_FMT_VDA_VLD == 82); //check if the pix fmt enum has not had anything inserted or removed by mistake #endif av_assert0(AV_SAMPLE_FMT_DBLP == 9); av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); diff --git a/libswscale/Makefile b/libswscale/Makefile index 0272039..ecd6dc4 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -19,6 +19,8 @@ OBJS = alphablend.o \ utils.o \ yuv2rgb.o \ vscale.o \ + nv12tiled2nv12.o \ + ../libavutil/special_format.o \ OBJS-$(CONFIG_SHARED) += log2_tab.o diff --git a/libswscale/nv12tiled2nv12.c b/libswscale/nv12tiled2nv12.c new file mode 100644 index 0000000..f949b44 --- /dev/null +++ b/libswscale/nv12tiled2nv12.c @@ -0,0 +1,212 @@ +/* + * NV12 tiled to NV12 conversion support. + * Copyright (C) 2016 eInfochips India Pvt. Ltd. + * + * 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/mem.h" +#include "libavutil/special_format.h" +#include "nv12tiled2nv12.h" + +//This functions copy a single tile from source to destination +static void nv12tile_copy_tile(uint8_t *dst,uint8_t **src,uint32_t wTiles); + +struct nv12TileParams *ff_nv12tile_params_init(uint32_t width, uint32_t height) +{ + struct nv12TileParams *params = NULL; + + if(NULL == (params = (struct nv12TileParams *) av_mallocz(sizeof(struct nv12TileParams)))) + goto error; + + params->width = width; + params->height = height; + + //Extrapolate width + width = ROUND_UP_X(width,128); + + params->wTiles = avpriv_nv12tile_calc_wTiles(width); + params->hTiles = avpriv_nv12tile_calc_hTiles(height); + params->hTiles_UV = avpriv_nv12tile_calc_hTiles(height/2); + + params->frame_size_src_Y = avpriv_nv12tile_calc_plane_size(width,height); + params->frame_size_src_UV = avpriv_nv12tile_calc_plane_size(width,height/2); + + if((params->frame_size_src_Y <= 0) || (params->frame_size_src_UV <= 0)) + goto error; + + if(NULL == (params->t_dst[0] = (uint8_t *) av_mallocz((params->frame_size_src_Y + params->frame_size_src_UV) * sizeof(uint8_t)))) + goto error; + else + params->t_dst[1] = params->t_dst[0] + (params->frame_size_src_Y * sizeof(uint8_t)); + + return params; + +error: + ff_nv12tile_params_deinit(params); + + return NULL; +} + +void ff_nv12tile_params_deinit(struct nv12TileParams *params) +{ + if(params) { + + if(params->t_dst[0]) { + + av_free(params->t_dst[0]); + params->t_dst[0] = NULL; + params->t_dst[1] = NULL; + } + + av_free(params); + } +} + +static void nv12tile_copy_tile(uint8_t *dst,uint8_t **src,uint32_t wTiles) +{ + //Loop variable + uint32_t loop = 0; + + //Run loop for all rows in a tile i.e. from row 0 to row 31 + for(loop=0;loop<32;loop++) { + + //Copy a single row from source to destination + memcpy(dst,*src,64 * sizeof(uint8_t)); + + //Move source pointer to next row + *src = *src + 64; + + //Move destination pointer to next row + dst = dst + (wTiles * 64); + } +} + +void ff_nv12tile_to_nv12(uint8_t* dst_head,uint8_t* src_head,uint32_t wTiles,uint32_t hTiles) +{ + //Loop variable + uint32_t loop = 0; + + //For Z Flip Z pattern + uint32_t Z = 0; + + //Assign source to source head pointer + uint8_t *src = src_head; + + //Assign destination to destination head pointer + uint8_t *dst = dst_head; + + //For a proper Z Flip Z pattern two consecutive row are needed to be processed + for(loop = 0; loop < (hTiles%2 == 0 ? hTiles : hTiles-1); loop=loop+2) { + + //Put src pointer at start of current row + src = src_head; + + //Copy Z and flip Z pattern to destination + for(Z = 0; Z < (wTiles/2); Z++) { + + //Put dst pointer at start of current row + dst = dst_head; + + if(Z%2 == 0) { + + //For Z pattern + + //Tile Nos: 0-8-16-... + dst = dst + (Z * 2 * 64); + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 1-9-17-... + dst = dst + 64; + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 2-10-18-... + dst = dst_head + (wTiles * NV12_TILE_SIZE); + dst = dst + (Z * 2 * 64); + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 3-11-19-... + dst = dst + 64; + nv12tile_copy_tile(dst,&src,wTiles); + } + else { + + //For Flip Z pattern + + //Tile Nos: 4-12-... + dst = dst_head + (wTiles * NV12_TILE_SIZE); + dst = dst + (Z * 2 * 64); + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 5-13... + dst = dst + 64; + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 6-14-... + dst = dst_head + (Z * 2 * 64); + nv12tile_copy_tile(dst,&src,wTiles); + + //Tile Nos: 7-15-... + dst = dst + 64; + nv12tile_copy_tile(dst,&src,wTiles); + } + } + + //Move source pointer by two chunk rows + src_head = src_head + (2 * NV12_TILE_SIZE * wTiles); + + //Move destination pointer by two chunk rows + dst_head = dst_head + (2 * wTiles * NV12_TILE_SIZE); + } + + //For linear pattern in the last remaining row + if(hTiles%2) { + + //Put src pointer at start of current row + src = src_head; + + //Loop through linear tiles + for(loop = 0; loop < wTiles ; loop++) { + + dst = dst_head + (loop * 64); + nv12tile_copy_tile(dst,&src,wTiles); + } + } +} + +void ff_nv12tile_rectify_extrapolation(uint8_t *data, int width, int height) +{ + //Check if width is not equal to extrapolated width + //then perform the conversion + if(width != ROUND_UP_X(width,128)) { + + //Index of current row + int index = 0; + + //Extrapolated width of data buffer + int extrapolated_width = ROUND_UP_X(width,128); + + //Convert extrapolated NV12 data to actual NV12 data + while(index <= height) { + + //Rectify each strides in data buffer containing extrapolated NV12 data + //such that each stride will contain actual NV12 data + memcpy(data + (index * width), data + (index * extrapolated_width), (width * sizeof(uint8_t))); + + index++; + } + } +} diff --git a/libswscale/nv12tiled2nv12.h b/libswscale/nv12tiled2nv12.h new file mode 100644 index 0000000..3f72d71 --- /dev/null +++ b/libswscale/nv12tiled2nv12.h @@ -0,0 +1,85 @@ +/* + * NV12 tiled to NV12 conversion support. + * Copyright (C) 2016 eInfochips India Pvt. Ltd. + * + * 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 SWSCALE_NV12TILED2NV12_H +#define SWSCALE_NV12TILED2NV12_H +#include +#include +#include +#include +#include + +//NOTE : This NV12Tile to NV12 conversion is taken from "https://github.com/ssshukla26/NV12Tile-To-NV12-Conversion" repo. + +/** + * Structure holding NV12 tile format specific parameters + */ +struct nv12TileParams { + uint32_t width; //Width of resolution + uint32_t height; //Height of resolution + uint32_t wTiles; //No. of vertical tiles + uint32_t hTiles; //No. of horizontal tiles for Y-Plane + uint32_t hTiles_UV; //No. of horizontal tiles for UV-Plane + uint32_t frame_size_src_Y; //Frame size of Y-Plane + uint32_t frame_size_src_UV; //Frame size of UV-Plane + uint8_t *t_dst[2]; //Pointer to Y and UV Plane +}; + +/** + * Function to calculate and fill nv12 tile format specific data. + * + * @param width - width of the resolution + * @param height - height of the resolution + * @return pointer to nv12TileParams + */ +struct nv12TileParams *ff_nv12tile_params_init(uint32_t width, uint32_t height); + +/** + * Function to free initialized parameter and data. + * + * @param params - pointer to nv12TileParams + * @return void + */ +void ff_nv12tile_params_deinit(struct nv12TileParams *params); + +/** + * This function is use to convert data from NV12tile format + * to NV12 format. + * + * @param dst_head - destination pointer to store data in NV12 format + * @param src_head - source pointer, pointing to a data in NV12tile format + * @param wTiles - No of horizontal tiles + * @param hTiles - No of vertical tiles + * @return void + */ +void ff_nv12tile_to_nv12(uint8_t* dst_head,uint8_t* src_head,uint32_t wTiles,uint32_t hTiles); + +/** + * This function is use to convert/rectify extrapolated nv12 data in a buffer + * to actual nv12 data. + * + * @param data :- Pointer pointing to a extrapolated nv12 data buffer + * @param width :- Actual width of data in data buffer + * @param height :- Height of data buffer + * @return void + */ +void ff_nv12tile_rectify_extrapolation(uint8_t *data, int width, int height); +#endif diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index af82396..81c8b8b 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -627,6 +627,11 @@ typedef struct SwsContext { SwsDither dither; SwsAlphaBlend alphablend; + + /// Pointer to hold special format specific data. As of now used to store + /// NV12 tile format specific data. + void *special_format; + } SwsContext; //FIXME check init (where 0) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index b2bfc40..9b678d6 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -34,6 +34,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" #include "libavutil/avconfig.h" +#include "nv12tiled2nv12.h" DECLARE_ALIGNED(8, static const uint8_t, dithers)[8][8][8]={ { @@ -288,6 +289,49 @@ static int planar8ToP01xleWrapper(SwsContext *c, const uint8_t *src[], #undef output_pixel +static int nv12tiledToPlanarWrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t *dstParam[], + int dstStride[]) + +{ + int ret = 0; + + if(NULL != c) { + + struct nv12TileParams *p = (struct nv12TileParams *) c->special_format; + + if(NULL != p) { + + if((NULL != p->t_dst[0]) && (NULL != p->t_dst[1])) { + + uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2; + uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2; + + ff_nv12tile_to_nv12(p->t_dst[0],(uint8_t *)src[0], p->wTiles, p->hTiles); + ff_nv12tile_rectify_extrapolation(p->t_dst[0], p->width, p->height); + + ff_nv12tile_to_nv12(p->t_dst[1],(uint8_t *)src[1], p->wTiles, p->hTiles_UV); + ff_nv12tile_rectify_extrapolation(p->t_dst[1], p->width, p->height/2); + + copyPlane(p->t_dst[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dstParam[0], dstStride[0]); + + if (c->srcFormat == AV_PIX_FMT_NV12_TILED) + deinterleaveBytes(p->t_dst[1], dst1, dst2,c->srcW / 2, srcSliceH / 2, + srcStride[1], dstStride[1], dstStride[2]); + else + deinterleaveBytes(p->t_dst[1], dst2, dst1, c->srcW / 2, srcSliceH / 2, + srcStride[1], dstStride[2], dstStride[1]); + + ret = srcSliceH; + } + } + } + + return ret; +} + static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dstParam[], int dstStride[]) @@ -1694,6 +1738,12 @@ void ff_get_unscaled_swscale(SwsContext *c) (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) { c->swscale = nv12ToPlanarWrapper; } + /* nv12tiled_to_yv12 */ + if (dstFormat == AV_PIX_FMT_YUV420P && + (srcFormat == AV_PIX_FMT_NV12_TILED)) { + c->swscale = nv12tiledToPlanarWrapper; + } + /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && @@ -1876,9 +1926,9 @@ void ff_get_unscaled_swscale(SwsContext *c) (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && c->chrDstHSubSample == c->chrSrcHSubSample && c->chrDstVSubSample == c->chrSrcVSubSample && - dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && + dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && dstFormat != AV_PIX_FMT_NV12_TILED && dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE && - srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 && + srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 && srcFormat != AV_PIX_FMT_NV12_TILED && srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE)) { if (isPacked(c->srcFormat)) diff --git a/libswscale/utils.c b/libswscale/utils.c index 60a8e55..9c97285 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -62,6 +62,7 @@ #include "rgb2rgb.h" #include "swscale.h" #include "swscale_internal.h" +#include "nv12tiled2nv12.h" #if !FF_API_SWS_VECTOR static SwsVector *sws_getIdentityVec(void); @@ -122,6 +123,7 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = { [AV_PIX_FMT_RGB4] = { 0, 1 }, [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 }, [AV_PIX_FMT_NV12] = { 1, 1 }, + [AV_PIX_FMT_NV12_TILED] = { 1, 0 }, [AV_PIX_FMT_NV21] = { 1, 1 }, [AV_PIX_FMT_ARGB] = { 1, 1 }, [AV_PIX_FMT_RGBA] = { 1, 1 }, @@ -1786,6 +1788,14 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) { ff_get_unscaled_swscale(c); + if(c->srcFormat == AV_PIX_FMT_NV12_TILED) { + if(NULL == (c->special_format = (void *) ff_nv12tile_params_init(c->srcW, c->srcH))) { + av_log(c, AV_LOG_ERROR, "Unable to initialize nv12tile parameters." + "Make sure that given resolution is supported for NV12 Tile format\n"); + goto fail; + } + } + if (c->swscale) { if (flags & SWS_PRINT_INFO) av_log(c, AV_LOG_INFO, @@ -2284,6 +2294,15 @@ void sws_freeContext(SwsContext *c) for (i = 0; i < 4; i++) av_freep(&c->dither_error[i]); + if(c->special_format) { + + if(c->srcFormat == AV_PIX_FMT_NV12_TILED) { + ff_nv12tile_params_deinit(c->special_format); + } + + c->special_format = NULL; + } + av_freep(&c->vLumFilter); av_freep(&c->vChrFilter); av_freep(&c->hLumFilter); -- 1.9.1