* For more information on the OpenEXR format, visit:
* http://openexr.com/
*
- * exr_flt2uint() and exr_halflt2uint() is credited to Reimar Döffinger.
* exr_half2float() is credited to Aaftab Munshi, Dan Ginsburg, Dave Shreiner.
*/
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/intfloat.h"
+#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "libavutil/color_utils.h"
const AVPixFmtDescriptor *desc;
int w, h;
- uint32_t xmax, xmin;
- uint32_t ymax, ymin;
+ int32_t xmax, xmin;
+ int32_t ymax, ymin;
uint32_t xdelta, ydelta;
int scan_lines_per_block;
enum AVColorTransferCharacteristic apply_trc_type;
float gamma;
- uint16_t gamma_table[65536];
+ union av_intfloat32 gamma_table[65536];
} EXRContext;
/* -15 stored using a single precision bias of 127 */
// half-float NaNs will be converted to a single precision NaN
// half-float Infs will be converted to a single precision Inf
exp = FLOAT_MAX_BIASED_EXP;
- if (mantissa)
- mantissa = (1 << 23) - 1; // set all bits to indicate a NaN
+ mantissa <<= 13; // preserve half-float NaN bits if set
} else if (exp == 0x0) {
// convert half-float zero/denorm to single precision value
if (mantissa) {
mantissa <<= 1;
exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
// check for leading 1 in denorm mantissa
- while ((mantissa & (1 << 10))) {
+ while (!(mantissa & (1 << 10))) {
// for every leading 0, decrement single precision exponent by 1
// and shift half-float mantissa value to the left
mantissa <<= 1;
return f;
}
-
-/**
- * Convert from 32-bit float as uint32_t to uint16_t.
- *
- * @param v 32-bit float
- *
- * @return normalized 16-bit unsigned int
- */
-static inline uint16_t exr_flt2uint(int32_t v)
-{
- int32_t exp = v >> 23;
- // "HACK": negative values result in exp< 0, so clipping them to 0
- // is also handled by this condition, avoids explicit check for sign bit.
- if (exp <= 127 + 7 - 24) // we would shift out all bits anyway
- return 0;
- if (exp >= 127)
- return 0xffff;
- v &= 0x007fffff;
- return (v + (1 << 23)) >> (127 + 7 - exp);
-}
-
-/**
- * Convert from 16-bit float as uint16_t to uint16_t.
- *
- * @param v 16-bit float
- *
- * @return normalized 16-bit unsigned int
- */
-static inline uint16_t exr_halflt2uint(uint16_t v)
-{
- unsigned exp = 14 - (v >> 10);
- if (exp >= 14) {
- if (exp == 14)
- return (v >> 9) & 1;
- else
- return (v & 0x8000) ? 0 : 0xffff;
- }
- v <<= 6;
- return (v + (1 << 16)) >> (exp + 1);
-}
-
static int zip_uncompress(EXRContext *s, const uint8_t *src, int compressed_size,
int uncompressed_size, EXRThreadData *td)
{
in = ptr[3] + s->xdelta;
for (j = 0; j < s->xdelta; ++j) {
- uint32_t diff = (*(ptr[0]++) << 24) |
+ uint32_t diff = ((uint32_t)*(ptr[0]++) << 24) |
(*(ptr[1]++) << 16) |
(*(ptr[2]++) << 8 ) |
(*(ptr[3]++));
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;
+ int 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 bxmin = 0, axmax = 0, window_xoffset = 0;
+ int window_xmin, window_xmax, window_ymin, window_ymax;
+ int data_xoffset, data_yoffset, data_window_offset, xsize, ysize;
int i, x, buf_size = s->buf_size;
int c, rgb_channel_count;
float one_gamma = 1.0f / s->gamma;
return AVERROR_PATCHWELCOME;
}
- if (s->xmin || s->ymin) {
- avpriv_report_missing_feature(s->avctx, "Tiles with xmin/ymin");
- return AVERROR_PATCHWELCOME;
- }
-
- line = s->tile_attr.ySize * tile_y;
+ line = s->ymin + s->tile_attr.ySize * tile_y;
col = s->tile_attr.xSize * tile_x;
if (line < s->ymin || line > s->ymax ||
- col < s->xmin || col > s->xmax)
+ s->xmin + col < s->xmin || s->xmin + col > s->xmax)
return AVERROR_INVALIDDATA;
td->ysize = FFMIN(s->tile_attr.ySize, s->ydelta - tile_y * s->tile_attr.ySize);
td->xsize = FFMIN(s->tile_attr.xSize, s->xdelta - tile_x * s->tile_attr.xSize);
- if (col) { /* not the first tile of the line */
- bxmin = 0; /* doesn't add pixel at the left of the datawindow */
- }
-
- if ((col + td->xsize) != s->xdelta)/* not the last tile of the line */
- axmax = 0; /* doesn't add pixel at the right of the datawindow */
+ if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX)
+ return AVERROR_INVALIDDATA;
td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */
uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */
td->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */
td->xsize = s->xdelta;
+ if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX)
+ return AVERROR_INVALIDDATA;
+
td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */
uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */
}
}
+ window_xmin = FFMIN(avctx->width, FFMAX(0, s->xmin + col));
+ window_xmax = FFMIN(avctx->width, FFMAX(0, s->xmin + col + td->xsize));
+ window_ymin = FFMIN(avctx->height, FFMAX(0, line ));
+ window_ymax = FFMIN(avctx->height, FFMAX(0, line + td->ysize));
+ xsize = window_xmax - window_xmin;
+ ysize = window_ymax - window_ymin;
+
+ /* tile or scanline not visible skip decoding */
+ if (xsize <= 0 || ysize <= 0)
+ return 0;
+
+ /* is the first tile or is a scanline */
+ if(col == 0) {
+ window_xmin = 0;
+ /* pixels to add at the left of the display window */
+ window_xoffset = FFMAX(0, s->xmin);
+ /* bytes to add at the left of the display window */
+ bxmin = window_xoffset * step;
+ }
+
+ /* is the last tile or is a scanline */
+ if(col + td->xsize == s->xdelta) {
+ window_xmax = avctx->width;
+ /* bytes to add at the right of the display window */
+ axmax = FFMAX(0, (avctx->width - (s->xmax + 1))) * step;
+ }
+
if (data_size < uncompressed_size || s->is_tile) { /* td->tmp is use for tile reorganization */
av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size);
if (!td->tmp)
src = td->uncompressed_data;
}
+ /* offsets to crop data outside display window */
+ data_xoffset = FFABS(FFMIN(0, s->xmin + col)) * (s->pixel_type == EXR_HALF ? 2 : 4);
+ data_yoffset = FFABS(FFMIN(0, line));
+ data_window_offset = (data_yoffset * td->channel_line_size) + data_xoffset;
+
if (!s->is_luma) {
- channel_buffer[0] = src + td->xsize * s->channel_offsets[0];
- channel_buffer[1] = src + td->xsize * s->channel_offsets[1];
- channel_buffer[2] = src + td->xsize * s->channel_offsets[2];
+ channel_buffer[0] = src + (td->xsize * s->channel_offsets[0]) + data_window_offset;
+ channel_buffer[1] = src + (td->xsize * s->channel_offsets[1]) + data_window_offset;
+ channel_buffer[2] = src + (td->xsize * s->channel_offsets[2]) + data_window_offset;
rgb_channel_count = 3;
} else { /* put y data in the first channel_buffer */
- channel_buffer[0] = src + td->xsize * s->channel_offsets[1];
+ channel_buffer[0] = src + (td->xsize * s->channel_offsets[1]) + data_window_offset;
rgb_channel_count = 1;
}
- if (s->channel_offsets[3] >= 0)
- channel_buffer[3] = src + td->xsize * s->channel_offsets[3];
-
- ptr = p->data[0] + line * p->linesize[0] + (col * s->desc->nb_components * 2);
-
- for (i = 0;
- i < td->ysize; i++, ptr += p->linesize[0]) {
+ if (s->channel_offsets[3] >= 0)
+ channel_buffer[3] = src + (td->xsize * s->channel_offsets[3]) + data_window_offset;
- const uint8_t * a;
- const uint8_t *rgb[3];
+ if (s->desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
- for (c = 0; c < rgb_channel_count; c++){
- rgb[c] = channel_buffer[c];
+ /* 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];
}
- if (channel_buffer[3])
- a = channel_buffer[3];
+ for (c = 0; c < channel_count; c++) {
+ int plane = s->desc->comp[c].plane;
+ ptr = p->data[plane] + window_ymin * p->linesize[plane] + (window_xmin * 4);
- ptr_x = (uint16_t *) ptr;
+ for (i = 0; i < ysize; i++, ptr += p->linesize[plane]) {
+ const uint8_t *src;
+ union av_intfloat32 *ptr_x;
- // Zero out the start if xmin is not 0
- memset(ptr_x, 0, bxmin);
- ptr_x += s->xmin * s->desc->nb_components;
+ src = channel_buffer[c];
+ ptr_x = (union av_intfloat32 *)ptr;
- if (s->pixel_type == EXR_FLOAT) {
- // 32-bit
- if (trc_func) {
- for (x = 0; x < td->xsize; x++) {
- union av_intfloat32 t;
+ // Zero out the start if xmin is not 0
+ memset(ptr_x, 0, bxmin);
+ ptr_x += window_xoffset;
- for (c = 0; c < rgb_channel_count; c++) {
- t.i = bytestream_get_le32(&rgb[c]);
- t.f = trc_func(t.f);
- *ptr_x++ = exr_flt2uint(t.i);
- }
- if (channel_buffer[3])
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
- }
- } else {
- for (x = 0; x < td->xsize; x++) {
+ if (s->pixel_type == EXR_FLOAT) {
+ // 32-bit
union av_intfloat32 t;
- int c;
-
- for (c = 0; c < rgb_channel_count; c++) {
- t.i = bytestream_get_le32(&rgb[c]);
- if (t.f > 0.0f) /* avoid negative values */
- t.f = powf(t.f, one_gamma);
- *ptr_x++ = exr_flt2uint(t.i);
+ if (trc_func && c < 3) {
+ for (x = 0; x < xsize; x++) {
+ t.i = bytestream_get_le32(&src);
+ t.f = trc_func(t.f);
+ *ptr_x++ = t;
+ }
+ } else {
+ for (x = 0; x < xsize; x++) {
+ t.i = bytestream_get_le32(&src);
+ if (t.f > 0.0f && c < 3) /* avoid negative values */
+ t.f = powf(t.f, one_gamma);
+ *ptr_x++ = t;
+ }
+ }
+ } else if (s->pixel_type == EXR_HALF) {
+ // 16-bit
+ if (c < 3 || !trc_func) {
+ for (x = 0; x < xsize; x++) {
+ *ptr_x++ = s->gamma_table[bytestream_get_le16(&src)];
+ }
+ } else {
+ for (x = 0; x < xsize; x++) {
+ *ptr_x++ = exr_half2float(bytestream_get_le16(&src));;
+ }
}
-
- if (channel_buffer[3])
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
}
+
+ // Zero out the end if xmax+1 is not w
+ memset(ptr_x, 0, axmax);
+ channel_buffer[c] += td->channel_line_size;
}
- } else if (s->pixel_type == EXR_HALF) {
- // 16-bit
- for (x = 0; x < td->xsize; x++) {
- int c;
- for (c = 0; c < rgb_channel_count; c++) {
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&rgb[c])];
- }
+ }
+ } else {
- if (channel_buffer[3])
- *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a));
+ av_assert1(s->pixel_type == EXR_UINT);
+ ptr = p->data[0] + window_ymin * p->linesize[0] + (window_xmin * s->desc->nb_components * 2);
+
+ for (i = 0; i < ysize; i++, ptr += p->linesize[0]) {
+
+ 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];
}
- } else if (s->pixel_type == EXR_UINT) {
- for (x = 0; x < td->xsize; x++) {
+
+ if (channel_buffer[3])
+ a = channel_buffer[3];
+
+ ptr_x = (uint16_t *) ptr;
+
+ // Zero out the start if xmin is not 0
+ memset(ptr_x, 0, bxmin);
+ ptr_x += window_xoffset * s->desc->nb_components;
+
+ for (x = 0; x < xsize; x++) {
for (c = 0; c < rgb_channel_count; c++) {
*ptr_x++ = bytestream_get_le32(&rgb[c]) >> 16;
}
if (channel_buffer[3])
*ptr_x++ = bytestream_get_le32(&a) >> 16;
}
- }
- // Zero out the end if xmax+1 is not w
- memset(ptr_x, 0, axmax);
+ // Zero out the end if xmax+1 is not w
+ memset(ptr_x, 0, axmax);
- channel_buffer[0] += td->channel_line_size;
- channel_buffer[1] += td->channel_line_size;
- channel_buffer[2] += td->channel_line_size;
- if (channel_buffer[3])
- channel_buffer[3] += td->channel_line_size;
+ channel_buffer[0] += td->channel_line_size;
+ channel_buffer[1] += td->channel_line_size;
+ channel_buffer[2] += td->channel_line_size;
+ if (channel_buffer[3])
+ channel_buffer[3] += td->channel_line_size;
+ }
}
return 0;
int magic_number, version, i, flags, sar = 0;
int layer_match = 0;
int ret;
+ int dup_channels = 0;
s->current_channel_offset = 0;
s->xmin = ~0;
}
if (layer_match) { /* only search channel if the layer match is valid */
- if (!strcmp(ch_gb.buffer, "R") ||
- !strcmp(ch_gb.buffer, "X") ||
- !strcmp(ch_gb.buffer, "U")) {
+ if (!av_strcasecmp(ch_gb.buffer, "R") ||
+ !av_strcasecmp(ch_gb.buffer, "X") ||
+ !av_strcasecmp(ch_gb.buffer, "U")) {
channel_index = 0;
s->is_luma = 0;
- } else if (!strcmp(ch_gb.buffer, "G") ||
- !strcmp(ch_gb.buffer, "V")) {
+ } else if (!av_strcasecmp(ch_gb.buffer, "G") ||
+ !av_strcasecmp(ch_gb.buffer, "V")) {
channel_index = 1;
s->is_luma = 0;
- } else if (!strcmp(ch_gb.buffer, "Y")) {
+ } else if (!av_strcasecmp(ch_gb.buffer, "Y")) {
channel_index = 1;
s->is_luma = 1;
- } else if (!strcmp(ch_gb.buffer, "B") ||
- !strcmp(ch_gb.buffer, "Z") ||
- !strcmp(ch_gb.buffer, "W")){
- channel_index = 2;
+ } else if (!av_strcasecmp(ch_gb.buffer, "B") ||
+ !av_strcasecmp(ch_gb.buffer, "Z") ||
+ !av_strcasecmp(ch_gb.buffer, "W")) {
+ channel_index = 2;
s->is_luma = 0;
- } else if (!strcmp(ch_gb.buffer, "A")) {
+ } else if (!av_strcasecmp(ch_gb.buffer, "A")) {
channel_index = 3;
} else {
av_log(s->avctx, AV_LOG_WARNING,
s->pixel_type = current_pixel_type;
s->channel_offsets[channel_index] = s->current_channel_offset;
} else if (channel_index >= 0) {
- av_log(s->avctx, AV_LOG_ERROR,
+ av_log(s->avctx, AV_LOG_WARNING,
"Multiple channels with index %d.\n", channel_index);
- ret = AVERROR_INVALIDDATA;
- goto fail;
+ if (++dup_channels > 10) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
}
s->channels = av_realloc(s->channels,
/* Check if all channels are set with an offset or if the channels
* are causing an overflow */
- if (!s->is_luma){/* if we expected to have at least 3 channels */
+ if (!s->is_luma) {/* if we expected to have at least 3 channels */
if (FFMIN3(s->channel_offsets[0],
s->channel_offsets[1],
s->channel_offsets[2]) < 0) {
continue;
} else if ((var_size = check_header_variable(s, "dataWindow", "box2i",
31)) >= 0) {
+ int xmin, ymin, xmax, ymax;
if (!var_size) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
- s->xmin = bytestream2_get_le32(&s->gb);
- s->ymin = bytestream2_get_le32(&s->gb);
- s->xmax = bytestream2_get_le32(&s->gb);
- s->ymax = bytestream2_get_le32(&s->gb);
+ xmin = bytestream2_get_le32(&s->gb);
+ ymin = bytestream2_get_le32(&s->gb);
+ xmax = bytestream2_get_le32(&s->gb);
+ ymax = bytestream2_get_le32(&s->gb);
+
+ if (xmin > xmax || ymin > ymax ||
+ (unsigned)xmax - xmin >= INT_MAX ||
+ (unsigned)ymax - ymin >= INT_MAX) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ s->xmin = xmin;
+ s->xmax = xmax;
+ s->ymin = ymin;
+ s->ymax = ymax;
s->xdelta = (s->xmax - s->xmin) + 1;
s->ydelta = (s->ymax - s->ymin) + 1;
s->tile_attr.level_mode = tileLevel & 0x0f;
s->tile_attr.level_round = (tileLevel >> 4) & 0x0f;
- if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN){
+ if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN) {
avpriv_report_missing_feature(s->avctx, "Tile level mode %d",
s->tile_attr.level_mode);
ret = AVERROR_PATCHWELCOME;
AVFrame *picture = data;
uint8_t *ptr;
- int y, ret;
+ int i, y, ret, ymax;
+ int planes;
int out_line_size;
int nb_blocks; /* nb scanline or nb tile */
uint64_t start_offset_table;
switch (s->pixel_type) {
case EXR_FLOAT:
case EXR_HALF:
+ if (s->channel_offsets[3] >= 0) {
+ if (!s->is_luma) {
+ avctx->pix_fmt = AV_PIX_FMT_GBRAPF32;
+ } else {
+ /* todo: change this when a floating point pixel format with luma with alpha is implemented */
+ avctx->pix_fmt = AV_PIX_FMT_GBRAPF32;
+ }
+ } else {
+ if (!s->is_luma) {
+ avctx->pix_fmt = AV_PIX_FMT_GBRPF32;
+ } else {
+ avctx->pix_fmt = AV_PIX_FMT_GRAYF32;
+ }
+ }
+ break;
case EXR_UINT:
if (s->channel_offsets[3] >= 0) {
if (!s->is_luma) {
return AVERROR_PATCHWELCOME;
}
- /* Verify the xmin, xmax, ymin, ymax and xdelta before setting
- * the actual image size. */
- if (s->xmin > s->xmax ||
- s->ymin > s->ymax ||
- s->xdelta != s->xmax - s->xmin + 1 ||
- s->xmax >= s->w ||
- s->ymax >= s->h) {
+ /* Verify the xmin, xmax, ymin and ymax before setting the actual image size.
+ * It's possible for the data window can larger or outside the display window */
+ if (s->xmin > s->xmax || s->ymin > s->ymax ||
+ s->ydelta == 0xFFFFFFFF || s->xdelta == 0xFFFFFFFF) {
av_log(avctx, AV_LOG_ERROR, "Wrong or missing size information.\n");
return AVERROR_INVALIDDATA;
}
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) *
if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
return ret;
- if (bytestream2_get_bytes_left(&s->gb) < nb_blocks * 8)
+ if (bytestream2_get_bytes_left(&s->gb)/8 < nb_blocks)
return AVERROR_INVALIDDATA;
// check offset table and recreate it if need
// 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 < FFMIN(s->ymin, s->h); y++) {
+ memset(ptr, 0, out_line_size);
+ ptr += picture->linesize[i];
+ }
}
s->picture = picture;
avctx->execute2(avctx, decode_block, s->thread_data, NULL, nb_blocks);
+ ymax = FFMAX(0, s->ymax + 1);
// 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];
- }
+ if (ymax < avctx->height)
+ for (i = 0; i < planes; i++) {
+ ptr = picture->data[i] + (ymax * picture->linesize[i]);
+ for (y = ymax; y < avctx->height; y++) {
+ memset(ptr, 0, out_line_size);
+ ptr += picture->linesize[i];
+ }
+ }
picture->pict_type = AV_PICTURE_TYPE_I;
*got_frame = 1;
for (i = 0; i < 65536; ++i) {
t = exr_half2float(i);
t.f = trc_func(t.f);
- s->gamma_table[i] = exr_flt2uint(t.i);
+ s->gamma_table[i] = t;
}
} else {
if (one_gamma > 0.9999f && one_gamma < 1.0001f) {
- for (i = 0; i < 65536; ++i)
- s->gamma_table[i] = exr_halflt2uint(i);
+ for (i = 0; i < 65536; ++i) {
+ s->gamma_table[i] = exr_half2float(i);
+ }
} else {
for (i = 0; i < 65536; ++i) {
t = exr_half2float(i);
/* If negative value we reuse half value */
if (t.f <= 0.0f) {
- s->gamma_table[i] = exr_halflt2uint(i);
+ s->gamma_table[i] = t;
} else {
t.f = powf(t.f, one_gamma);
- s->gamma_table[i] = exr_flt2uint(t.i);
+ s->gamma_table[i] = t;
}
}
}
return 0;
}
-#if HAVE_THREADS
-static int decode_init_thread_copy(AVCodecContext *avctx)
-{ EXRContext *s = avctx->priv_data;
-
- // allocate thread data, used for non EXR_RAW compression types
- s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData));
- if (!s->thread_data)
- return AVERROR_INVALIDDATA;
-
- return 0;
-}
-#endif
-
static av_cold int decode_end(AVCodecContext *avctx)
{
EXRContext *s = avctx->priv_data;
.id = AV_CODEC_ID_EXR,
.priv_data_size = sizeof(EXRContext),
.init = decode_init,
- .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.close = decode_end,
.decode = decode_frame,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |