From patchwork Wed Apr 29 03:02:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Reid X-Patchwork-Id: 19359 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 337C2449B30 for ; Wed, 29 Apr 2020 06:25:14 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EB89868BDFE; Wed, 29 Apr 2020 06:25:13 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f194.google.com (mail-pf1-f194.google.com [209.85.210.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4974368B00A for ; Wed, 29 Apr 2020 06:25:07 +0300 (EEST) Received: by mail-pf1-f194.google.com with SMTP id 145so410209pfw.13 for ; Tue, 28 Apr 2020 20:25:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GmdcLIOG5DeK3xekSOSZvEPppX5CfEnkQVhSU03qs48=; b=Ub5Wy9IGgC7ebck9MqdkP39qzDSByADa33iFGPLwZL37jsyNMOUEx5XGgvPE8mI+cv LByISkq+oGS9N63QoCh2DGz9POrzLdBMaFS3mjQ8rXTl1o6I9LTyMkpRNdTWRT0AwyYf MPSHG+kX4/5byrhkyjOFLbLylaO14G/fEKyNGt1QrSoxS5LYjhYLAgtax7FacUEEd1dP ZQXrpfQVuLFadumsWbgjvQMpTxkWHjt7k5C/iGqhmOjG2a6DOB6yzw2NedRJSmdcPL/s 7vBcEG+fE+6e4X5gtMeOOD/inF7lAuX13hNu2mXPj7MX5YiMQcoONDl/mcQpAzUs7G/T YkLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GmdcLIOG5DeK3xekSOSZvEPppX5CfEnkQVhSU03qs48=; b=X6+6zxQ92MKWf3nfh0FU4nxs3dmbIWQlJrtQDB5eOfJzgdb//e7JW8zLQXC7baRUcK 9hQJ7ONREP5h4nkbOAHW7ibmIFhtmHbmL/mJYBfjZje59zrw2cBa13Wff/H/HVGN2iX1 CoXBcd6V/aLvgZwp3c3BN6E1tPfRWtJWc7cRYkjlcvNrnM7JsvWYljmi5liSaoq7Stu6 AVq+YzFe5K8y9tU2ghGCYHsRYHugL0BbMiJ9+qIznH/ESnHyXH5VqDIFIOigaIiJJO/4 QeHWs+/RKOjwZaj8LB+GZYrDuIJXI6e0Iqf9DLhzCkJjGl/TsBGXgw7qL6olzw87tWmI 1UKQ== X-Gm-Message-State: AGi0PuZjnZ/c56TJzcurix+AbFXiqNf+CAu24Y7aCkhFnB4BwE2bgPkg Dwn1X2Wlx9kRnzQ8OjpsxK/p8OII X-Google-Smtp-Source: APiQypLm6plfkCyUAWagofmNDo9fhc/0GgbAnS+0cospj5p8lq7TczgthelLENk3I3C2qHsgY68g3g== X-Received: by 2002:a62:cf81:: with SMTP id b123mr31932725pfg.84.1588129365675; Tue, 28 Apr 2020 20:02:45 -0700 (PDT) Received: from localhost.localdomain (S01069050ca607903.vc.shawcable.net. [174.7.236.190]) by smtp.gmail.com with ESMTPSA id i9sm16335401pfk.199.2020.04.28.20.02.45 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Apr 2020 20:02:45 -0700 (PDT) From: mindmark@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 28 Apr 2020 20:02:35 -0700 Message-Id: <20200429030235.37074-4-mindmark@gmail.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200429030235.37074-1-mindmark@gmail.com> References: <20200429030235.37074-1-mindmark@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] avcodec/exr: add option to output pixels in float 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 Cc: Mark Reid Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Mark Reid --- libavcodec/exr.c | 103 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 73419eadb1..f86e97a433 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -161,6 +161,7 @@ typedef struct EXRContext { enum AVColorTransferCharacteristic apply_trc_type; float gamma; uint16_t gamma_table[65536]; + int output_float; } EXRContext; /* -15 stored using a single precision bias of 127 */ @@ -1035,14 +1036,14 @@ static int decode_block(AVCodecContext *avctx, void *tdata, const uint8_t *channel_buffer[4] = { 0 }; const uint8_t *buf = s->buf; uint64_t line_offset, uncompressed_size; - uint16_t *ptr_x; uint8_t *ptr; uint32_t data_size; uint64_t line, col = 0; uint64_t tile_x, tile_y, tile_level_x, tile_level_y; const uint8_t *src; - int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; /* nb pixel to add at the right of the datawindow */ - int bxmin = s->xmin * 2 * s->desc->nb_components; /* nb pixel to add at the left of the datawindow */ + int step = s->desc->flags & AV_PIX_FMT_FLAG_FLOAT ? 4 : 2 * s->desc->nb_components; + int axmax = (avctx->width - (s->xmax + 1)) * step; /* nb pixel to add at the right of the datawindow */ + int bxmin = s->xmin * step; /* nb pixel to add at the left of the datawindow */ int i, x, buf_size = s->buf_size; int c, rgb_channel_count; float one_gamma = 1.0f / s->gamma; @@ -1175,6 +1176,58 @@ static int decode_block(AVCodecContext *avctx, void *tdata, if (s->channel_offsets[3] >= 0) channel_buffer[3] = src + td->xsize * s->channel_offsets[3]; + if (s->desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + + /* todo: change this when a floating point pixel format with luma with alpha is implemented */ + int channel_count = s->channel_offsets[3] >= 0 ? 4 : rgb_channel_count; + if (s->is_luma) { + channel_buffer[1] = channel_buffer[0]; + channel_buffer[2] = channel_buffer[0]; + } + + for (c = 0; c < channel_count; c++) { + int plane = s->desc->comp[c].plane; + ptr = p->data[plane] + line * p->linesize[plane] + (col * 4); + + for (i = 0; i < td->ysize; i++, ptr += p->linesize[plane]) { + const uint8_t *src; + union av_intfloat32 *ptr_x; + + src = channel_buffer[c]; + ptr_x = (union av_intfloat32 *)ptr; + + // Zero out the start if xmin is not 0 + memset(ptr_x, 0, bxmin); + ptr_x += s->xmin; + + if (s->pixel_type == EXR_FLOAT) { + // 32-bit + for (x = 0; x < td->xsize; x++) { + ptr_x->i = bytestream_get_le32(&src); + ptr_x++; + } + } else if (s->pixel_type == EXR_HALF) { + // 16-bit + for (x = 0; x < td->xsize; x++) { + *ptr_x++ = exr_half2float(bytestream_get_le16(&src)); + } + } else if (s->pixel_type == EXR_UINT) { + const float float_mult = 1.0f / (float)UINT32_MAX; + for (x = 0; x < td->xsize; x++) { + ptr_x->f = float_mult * (float)bytestream_get_le32(&src); + ptr_x++; + } + } + + // Zero out the end if xmax+1 is not w + memset(ptr_x, 0, axmax); + channel_buffer[c] += td->channel_line_size; + } + } + + return 0; + } + ptr = p->data[0] + line * p->linesize[0] + (col * s->desc->nb_components * 2); for (i = 0; @@ -1182,6 +1235,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, const uint8_t * a; const uint8_t *rgb[3]; + uint16_t *ptr_x; for (c = 0; c < rgb_channel_count; c++) { rgb[c] = channel_buffer[c]; @@ -1676,7 +1730,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, AVFrame *picture = data; uint8_t *ptr; - int y, ret; + int i, y, ret; + int planes; int out_line_size; int nb_blocks; /* nb scanline or nb tile */ uint64_t start_offset_table; @@ -1694,15 +1749,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, case EXR_UINT: if (s->channel_offsets[3] >= 0) { if (!s->is_luma) { - avctx->pix_fmt = AV_PIX_FMT_RGBA64; + avctx->pix_fmt = s->output_float ? AV_PIX_FMT_GBRAPF32 : AV_PIX_FMT_RGBA64; } else { - avctx->pix_fmt = AV_PIX_FMT_YA16; + /* todo: change this when a floating point pixel format with luma with alpha is implemented */ + avctx->pix_fmt = s->output_float ? AV_PIX_FMT_GBRAPF32 : AV_PIX_FMT_YA16; } } else { if (!s->is_luma) { - avctx->pix_fmt = AV_PIX_FMT_RGB48; + avctx->pix_fmt = s->output_float ? AV_PIX_FMT_GBRPF32 : AV_PIX_FMT_RGB48; } else { - avctx->pix_fmt = AV_PIX_FMT_GRAY16; + avctx->pix_fmt = s->output_float ? AV_PIX_FMT_GRAYF32 : AV_PIX_FMT_GRAY16; } } break; @@ -1751,7 +1807,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, s->desc = av_pix_fmt_desc_get(avctx->pix_fmt); if (!s->desc) return AVERROR_INVALIDDATA; - out_line_size = avctx->width * 2 * s->desc->nb_components; + + if (s->desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + planes = s->desc->nb_components; + out_line_size = avctx->width * 4; + } else { + planes = 1; + out_line_size = avctx->width * 2 * s->desc->nb_components; + } if (s->is_tile) { nb_blocks = ((s->xdelta + s->tile_attr.xSize - 1) / s->tile_attr.xSize) * @@ -1789,12 +1852,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, // save pointer we are going to use in decode_block s->buf = avpkt->data; s->buf_size = avpkt->size; - ptr = picture->data[0]; // Zero out the start if ymin is not 0 - for (y = 0; y < s->ymin; y++) { - memset(ptr, 0, out_line_size); - ptr += picture->linesize[0]; + for (i = 0; i < planes; i++) { + ptr = picture->data[i]; + for (y = 0; y < s->ymin; y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[i]; + } } s->picture = picture; @@ -1802,10 +1867,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, avctx->execute2(avctx, decode_block, s->thread_data, NULL, nb_blocks); // Zero out the end if ymax+1 is not h - ptr = picture->data[0] + ((s->ymax+1) * picture->linesize[0]); - for (y = s->ymax + 1; y < avctx->height; y++) { - memset(ptr, 0, out_line_size); - ptr += picture->linesize[0]; + for (i = 0; i < planes; i++) { + ptr = picture->data[i] + ((s->ymax+1) * picture->linesize[i]); + for (y = s->ymax + 1; y < avctx->height; y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[i]; + } } picture->pict_type = AV_PICTURE_TYPE_I; @@ -1888,6 +1955,8 @@ static const AVOption options[] = { AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, { "gamma", "Set the float gamma value when decoding", OFFSET(gamma), AV_OPT_TYPE_FLOAT, { .dbl = 1.0f }, 0.001, FLT_MAX, VD }, + { "float", "Output frame in floating point pixel format, apply_trc does not get applied", OFFSET(output_float), + AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD}, // XXX: Note the abuse of the enum using AVCOL_TRC_UNSPECIFIED to subsume the existing gamma option { "apply_trc", "color transfer characteristics to apply to EXR linear input", OFFSET(apply_trc_type),