[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