[FFmpeg-devel] [PATCH 2/2] avcodec/exr: use planar pixel format for output
Paul B Mahol
onemda at gmail.com
Mon Oct 14 19:42:42 CEST 2013
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
libavcodec/exr.c | 106 ++++++++++++++++++++++++-------------------------------
1 file changed, 46 insertions(+), 60 deletions(-)
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 021d5a4..3733384 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -338,7 +338,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
EXRContext *s = avctx->priv_data;
AVFrame *const p = s->picture;
EXRThreadData *td = &s->thread_data[threadnr];
- const uint8_t *channel_buffer[4] = { 0 };
+ const uint8_t *channel_buffer;
const uint8_t *buf = s->buf;
uint64_t line_offset, uncompressed_size;
uint32_t xdelta = s->xdelta;
@@ -346,9 +346,9 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
uint8_t *ptr;
int32_t data_size, line;
const uint8_t *src;
- int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components;
- int bxmin = s->xmin * 2 * s->desc->nb_components;
- int i, x, buf_size = s->buf_size;
+ int axmax = (avctx->width - (s->xmax + 1)) * 2;
+ int bxmin = s->xmin * 2;
+ int i, x, c, buf_size = s->buf_size;
int av_unused ret;
line_offset = AV_RL64(s->table + jobnr * 8);
@@ -395,55 +395,35 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
src = td->uncompressed_data;
}
- channel_buffer[0] = src + xdelta * s->channel_offsets[0];
- channel_buffer[1] = src + xdelta * s->channel_offsets[1];
- channel_buffer[2] = src + xdelta * s->channel_offsets[2];
- if (s->channel_offsets[3] >= 0)
- channel_buffer[3] = src + xdelta * s->channel_offsets[3];
-
- ptr = p->data[0] + line * p->linesize[0];
- for (i = 0; i < s->scan_lines_per_block && line + i <= s->ymax; i++, ptr += p->linesize[0]) {
- const uint8_t *r, *g, *b, *a;
-
- r = channel_buffer[0];
- g = channel_buffer[1];
- b = channel_buffer[2];
- 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 += s->xmin * s->desc->nb_components;
- if (s->pixel_type == EXR_FLOAT) {
- // 32-bit
- for (x = 0; x < xdelta; x++) {
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&r));
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&g));
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&b));
- if (channel_buffer[3])
- *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
- }
- } else {
- // 16-bit
- for (x = 0; x < xdelta; x++) {
- *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&r));
- *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&g));
- *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&b));
- if (channel_buffer[3])
- *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a));
- }
- }
- // Zero out the end if xmax+1 is not w
- memset(ptr_x, 0, axmax);
+ for (c = 0; p->data[c]; c++) {
+ int plane = s->desc->comp[c].plane;
+ channel_buffer = src + xdelta * s->channel_offsets[c];
+ ptr = p->data[plane] + line * p->linesize[plane];
+
+ for (i = 0; i < s->scan_lines_per_block && line + i <= s->ymax; i++, ptr += p->linesize[plane]) {
+ const uint8_t *g;
+
+ ptr_x = (uint16_t *)ptr;
+ g = channel_buffer;
+
+ // 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 < xdelta; x++)
+ *ptr_x++ = exr_flt2uint(bytestream_get_le32(&g));
+ } else {
+ // 16-bit
+ for (x = 0; x < xdelta; x++)
+ *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&g));
+ }
- channel_buffer[0] += s->scan_line_size;
- channel_buffer[1] += s->scan_line_size;
- channel_buffer[2] += s->scan_line_size;
- if (channel_buffer[3])
- channel_buffer[3] += s->scan_line_size;
+ // Zero out the end if xmax+1 is not width
+ memset(ptr_x, 0, axmax);
+ channel_buffer += s->scan_line_size;
+ }
}
return 0;
@@ -692,9 +672,9 @@ static int decode_frame(AVCodecContext *avctx,
case EXR_FLOAT:
case EXR_HALF:
if (s->channel_offsets[3] >= 0)
- avctx->pix_fmt = AV_PIX_FMT_RGBA64;
+ avctx->pix_fmt = AV_PIX_FMT_GBRAP16;
else
- avctx->pix_fmt = AV_PIX_FMT_RGB48;
+ avctx->pix_fmt = AV_PIX_FMT_GBRP16;
break;
case EXR_UINT:
avpriv_request_sample(avctx, "32-bit unsigned int");
@@ -736,7 +716,7 @@ static int decode_frame(AVCodecContext *avctx,
}
s->desc = av_pix_fmt_desc_get(avctx->pix_fmt);
- out_line_size = avctx->width * 2 * s->desc->nb_components;
+ out_line_size = avctx->width * 2;
s->scan_line_size = s->xdelta * current_channel_offset;
scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) / s->scan_lines_per_block;
@@ -764,18 +744,24 @@ static int decode_frame(AVCodecContext *avctx,
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; picture->data[i]; 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;
avctx->execute2(avctx, decode_block, s->thread_data, NULL, scan_line_blocks);
// Zero out the end if ymax+1 is not h
- for (y = s->ymax + 1; y < avctx->height; y++) {
- memset(ptr, 0, out_line_size);
- ptr += picture->linesize[0];
+ for (i = 0; picture->data[i]; i++) {
+ ptr = picture->data[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;
--
1.7.11.2
More information about the ffmpeg-devel
mailing list