|
|
|
@ -143,6 +143,8 @@ typedef struct EXRContext { |
|
|
|
|
|
|
|
|
|
EXRTileAttribute tile_attr; /* header data attribute of tile */ |
|
|
|
|
int is_tile; /* 0 if scanline, 1 if tile */ |
|
|
|
|
int is_multipart; |
|
|
|
|
int current_part; |
|
|
|
|
|
|
|
|
|
int is_luma;/* 1 if there is an Y plane */ |
|
|
|
|
|
|
|
|
@ -153,10 +155,12 @@ typedef struct EXRContext { |
|
|
|
|
EXRChannel *channels; |
|
|
|
|
int nb_channels; |
|
|
|
|
int current_channel_offset; |
|
|
|
|
uint32_t chunk_count; |
|
|
|
|
|
|
|
|
|
EXRThreadData *thread_data; |
|
|
|
|
|
|
|
|
|
const char *layer; |
|
|
|
|
int selected_part; |
|
|
|
|
|
|
|
|
|
enum AVColorTransferCharacteristic apply_trc_type; |
|
|
|
|
float gamma; |
|
|
|
@ -1015,6 +1019,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
|
src = buf + line_offset + 20; |
|
|
|
|
if (s->is_multipart) |
|
|
|
|
src += 4; |
|
|
|
|
|
|
|
|
|
tile_x = AV_RL32(src - 20); |
|
|
|
|
tile_y = AV_RL32(src - 16); |
|
|
|
@ -1050,6 +1056,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
|
src = buf + line_offset + 8; |
|
|
|
|
if (s->is_multipart) |
|
|
|
|
src += 4; |
|
|
|
|
line = AV_RL32(src - 8); |
|
|
|
|
|
|
|
|
|
if (line < s->ymin || line > s->ymax) |
|
|
|
@ -1266,6 +1274,21 @@ static int decode_block(AVCodecContext *avctx, void *tdata, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void skip_header_chunk(EXRContext *s) |
|
|
|
|
{ |
|
|
|
|
while (bytestream2_get_bytes_left(&s->gb) > 0) { |
|
|
|
|
if (!bytestream2_peek_byte(&s->gb)) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
// Process unknown variables
|
|
|
|
|
for (int i = 0; i < 2; i++) // value_name and value_type
|
|
|
|
|
while (bytestream2_get_byte(&s->gb) != 0); |
|
|
|
|
|
|
|
|
|
// Skip variable length
|
|
|
|
|
bytestream2_skip(&s->gb, bytestream2_get_le32(&s->gb)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if the variable name corresponds to its data type. |
|
|
|
|
* |
|
|
|
@ -1334,7 +1357,9 @@ static int decode_header(EXRContext *s, AVFrame *frame) |
|
|
|
|
s->tile_attr.xSize = -1; |
|
|
|
|
s->tile_attr.ySize = -1; |
|
|
|
|
s->is_tile = 0; |
|
|
|
|
s->is_multipart = 0; |
|
|
|
|
s->is_luma = 0; |
|
|
|
|
s->current_part = 0; |
|
|
|
|
|
|
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 10) { |
|
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n"); |
|
|
|
@ -1359,18 +1384,50 @@ static int decode_header(EXRContext *s, AVFrame *frame) |
|
|
|
|
|
|
|
|
|
if (flags & 0x02) |
|
|
|
|
s->is_tile = 1; |
|
|
|
|
if (flags & 0x10) |
|
|
|
|
s->is_multipart = 1; |
|
|
|
|
if (flags & 0x08) { |
|
|
|
|
avpriv_report_missing_feature(s->avctx, "deep data"); |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
} |
|
|
|
|
if (flags & 0x10) { |
|
|
|
|
avpriv_report_missing_feature(s->avctx, "multipart"); |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Parse the header
|
|
|
|
|
while (bytestream2_get_bytes_left(&s->gb) > 0 && *s->gb.buffer) { |
|
|
|
|
while (bytestream2_get_bytes_left(&s->gb) > 0) { |
|
|
|
|
int var_size; |
|
|
|
|
|
|
|
|
|
while (s->is_multipart && s->current_part < s->selected_part && |
|
|
|
|
bytestream2_get_bytes_left(&s->gb) > 0) { |
|
|
|
|
if (bytestream2_peek_byte(&s->gb)) { |
|
|
|
|
skip_header_chunk(s); |
|
|
|
|
} else { |
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
if (!bytestream2_peek_byte(&s->gb)) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
s->current_part++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!bytestream2_peek_byte(&s->gb)) { |
|
|
|
|
if (!s->is_multipart) |
|
|
|
|
break; |
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
if (s->current_part == s->selected_part) { |
|
|
|
|
while (bytestream2_get_bytes_left(&s->gb) > 0) { |
|
|
|
|
if (bytestream2_peek_byte(&s->gb)) { |
|
|
|
|
skip_header_chunk(s); |
|
|
|
|
} else { |
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
if (!bytestream2_peek_byte(&s->gb)) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!bytestream2_peek_byte(&s->gb)) |
|
|
|
|
break; |
|
|
|
|
s->current_part++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((var_size = check_header_variable(s, "channels", |
|
|
|
|
"chlist", 38)) >= 0) { |
|
|
|
|
GetByteContext ch_gb; |
|
|
|
@ -1593,9 +1650,11 @@ static int decode_header(EXRContext *s, AVFrame *frame) |
|
|
|
|
|
|
|
|
|
if (s->compression == EXR_UNKN) |
|
|
|
|
s->compression = bytestream2_get_byte(&s->gb); |
|
|
|
|
else |
|
|
|
|
else { |
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
av_log(s->avctx, AV_LOG_WARNING, |
|
|
|
|
"Found more than one compression attribute.\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} else if ((var_size = check_header_variable(s, "tiles", |
|
|
|
@ -1646,6 +1705,22 @@ static int decode_header(EXRContext *s, AVFrame *frame) |
|
|
|
|
s->avctx->framerate.num = bytestream2_get_le32(&s->gb); |
|
|
|
|
s->avctx->framerate.den = bytestream2_get_le32(&s->gb); |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} else if ((var_size = check_header_variable(s, "chunkCount", |
|
|
|
|
"int", 23)) >= 0) { |
|
|
|
|
|
|
|
|
|
s->chunk_count = bytestream2_get_le32(&s->gb); |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} else if ((var_size = check_header_variable(s, "type", |
|
|
|
|
"string", 16)) >= 0) { |
|
|
|
|
uint8_t key[256] = { 0 }; |
|
|
|
|
|
|
|
|
|
bytestream2_get_buffer(&s->gb, key, FFMIN(sizeof(key) - 1, var_size)); |
|
|
|
|
if (strncmp("scanlineimage", key, var_size) && |
|
|
|
|
strncmp("tiledimage", key, var_size)) |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1941,6 +2016,8 @@ static av_cold int decode_end(AVCodecContext *avctx) |
|
|
|
|
static const AVOption options[] = { |
|
|
|
|
{ "layer", "Set the decoding layer", OFFSET(layer), |
|
|
|
|
AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, |
|
|
|
|
{ "part", "Set the decoding part", OFFSET(selected_part), |
|
|
|
|
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, |
|
|
|
|
{ "gamma", "Set the float gamma value when decoding", OFFSET(gamma), |
|
|
|
|
AV_OPT_TYPE_FLOAT, { .dbl = 1.0f }, 0.001, FLT_MAX, VD }, |
|
|
|
|
|
|
|
|
|