Hello, in attach patch to fix decoding B44 exr, when there is several pixel_type.
Theses patch need to be apply after the 3 patch of mail : libavcodec/exr : fix tile and pxr24 when all channels doesn't have the same type 004 : Move channel_line_size to thread data, in order to be use by b44_uncompress 005 : Add a test by channel, to know if we need to only copy data, or uncompress it before (only half data are compress en B44, float and uint32 are store uncompress 006 : indentation of the previous patch. Sample can be found here : https://we.tl/DRb2rXg0a7 Comments welcome Martin Vignali Jokyo Images
From a72c1ba27b9beed792cf9abe25dc597ed1825ea7 Mon Sep 17 00:00:00 2001 From: Martin Vignali <martin.vign...@gmail.com> Date: Sat, 4 Jun 2016 15:47:53 +0200 Subject: [PATCH 6/6] libavodec/exr : (cosmetic) indent in b44 uncompress func --- libavcodec/exr.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 3f58750..8cfb9a0 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -945,37 +945,37 @@ static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size for (iY = 0; iY < nbB44BlockH; iY++) { for (iX = 0; iX < nbB44BlockW; iX++) {/* For each B44 block */ if (s->channels[c].pixel_type == EXR_HALF) {/* B44 only compress half float data */ - if (stayToUncompress < 3) { - av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stayToUncompress); - return AVERROR_INVALIDDATA; - } - - if (src[compressed_size - stayToUncompress + 2] == 0xfc) { /* B44A block */ - unpack_3(sr, tmpBuffer); - sr += 3; - stayToUncompress -= 3; - } else {/* B44 Block */ - if (stayToUncompress < 14) { - av_log(s, AV_LOG_ERROR, "Not enough data for B44 block: %d", stayToUncompress); + if (stayToUncompress < 3) { + av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stayToUncompress); return AVERROR_INVALIDDATA; } - unpack_14(sr, tmpBuffer); - sr += 14; - stayToUncompress -= 14; - } - /* copy data to uncompress buffer (B44 block can exceed target resolution)*/ - indexHgX = iX * 4; - indexHgY = iY * 4; + if (src[compressed_size - stayToUncompress + 2] == 0xfc) { /* B44A block */ + unpack_3(sr, tmpBuffer); + sr += 3; + stayToUncompress -= 3; + } else {/* B44 Block */ + if (stayToUncompress < 14) { + av_log(s, AV_LOG_ERROR, "Not enough data for B44 block: %d", stayToUncompress); + return AVERROR_INVALIDDATA; + } + unpack_14(sr, tmpBuffer); + sr += 14; + stayToUncompress -= 14; + } + + /* copy data to uncompress buffer (B44 block can exceed target resolution)*/ + indexHgX = iX * 4; + indexHgY = iY * 4; - for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) { - for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) { - indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x; - indexTmp = (y-indexHgY) * 4 + (x-indexHgX); - td->uncompressed_data[indexOut] = tmpBuffer[indexTmp] & 0xff; - td->uncompressed_data[indexOut + 1] = tmpBuffer[indexTmp] >> 8; + for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) { + for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) { + indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x; + indexTmp = (y-indexHgY) * 4 + (x-indexHgX); + td->uncompressed_data[indexOut] = tmpBuffer[indexTmp] & 0xff; + td->uncompressed_data[indexOut + 1] = tmpBuffer[indexTmp] >> 8; + } } - } } else{/* Float or UINT 32 channel */ for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) { for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) { -- 1.9.3 (Apple Git-50)
From 33fb13c0f9bae1206af48ef08e1017ec343b0675 Mon Sep 17 00:00:00 2001 From: Martin Vignali <martin.vign...@gmail.com> Date: Sat, 4 Jun 2016 15:38:59 +0200 Subject: [PATCH 4/6] libavodec/exr : move channel_line_size to thread data. In order to be used by b44 uncompress --- libavcodec/exr.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index d4dda03..07de3ed 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -105,6 +105,8 @@ typedef struct EXRThreadData { uint16_t *lut; int ysize, xsize; + + int channel_line_size; } EXRThreadData; typedef struct EXRContext { @@ -992,7 +994,6 @@ static int decode_block(AVCodecContext *avctx, void *tdata, uint8_t *ptr; uint32_t data_size, line, col = 0; uint32_t tileX, tileY, tileLevelX, tileLevelY; - int channel_line_size; 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 */ @@ -1036,8 +1037,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, 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 */ - channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ - uncompressed_size = channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */ + 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 */ } else { if (line_offset > buf_size - 8) return AVERROR_INVALIDDATA; @@ -1055,8 +1056,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, td->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */ td->xsize = s->xdelta; - channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ - uncompressed_size = channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */ + 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 */ if ((s->compression == EXR_RAW && (data_size != uncompressed_size || line_offset > buf_size - uncompressed_size)) || @@ -1185,11 +1186,11 @@ static int decode_block(AVCodecContext *avctx, void *tdata, // Zero out the end if xmax+1 is not w memset(ptr_x, 0, axmax); - channel_buffer[0] += channel_line_size; - channel_buffer[1] += channel_line_size; - channel_buffer[2] += 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] += channel_line_size; + channel_buffer[3] += td->channel_line_size; } return 0; -- 1.9.3 (Apple Git-50)
From 6010ca99d7a90ceebd8aad6f52ff7505c26a7c71 Mon Sep 17 00:00:00 2001 From: Martin Vignali <martin.vign...@gmail.com> Date: Sat, 4 Jun 2016 15:43:48 +0200 Subject: [PATCH 5/6] libavcodec/exr : fix decoding of B44 exr when all channel doesnt have the same pixel type --- libavcodec/exr.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 07de3ed..3f58750 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -930,6 +930,7 @@ static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size int indexHgX, indexHgY, indexOut, indexTmp; uint16_t tmpBuffer[16]; /* B44 use 4x4 half float pixel */ int c, iY, iX, y, x; + int target_channel_offset = 0; /* calc B44 block count */ nbB44BlockW = td->xsize / 4; @@ -943,6 +944,7 @@ static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size for (c = 0; c < s->nb_channels; c++) { for (iY = 0; iY < nbB44BlockH; iY++) { for (iX = 0; iX < nbB44BlockW; iX++) {/* For each B44 block */ + if (s->channels[c].pixel_type == EXR_HALF) {/* B44 only compress half float data */ if (stayToUncompress < 3) { av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stayToUncompress); return AVERROR_INVALIDDATA; @@ -968,14 +970,28 @@ static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) { for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) { - indexOut = (c * td->xsize + y * td->xsize * s->nb_channels + x) * 2; + indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x; indexTmp = (y-indexHgY) * 4 + (x-indexHgX); td->uncompressed_data[indexOut] = tmpBuffer[indexTmp] & 0xff; td->uncompressed_data[indexOut + 1] = tmpBuffer[indexTmp] >> 8; } } + } else{/* Float or UINT 32 channel */ + for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) { + for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) { + indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 4 * x; + memcpy(&td->uncompressed_data[indexOut], sr, 4); + sr += 4; + } + } + } } } + if (s->channels[c].pixel_type == EXR_HALF) { + target_channel_offset += 2; + } else { + target_channel_offset += 4; + } } return 0; -- 1.9.3 (Apple Git-50)
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel