On 08/02/2018 11:28, Jerome Martinez wrote:
Currently RGB and RGBA 12-bit are supported by DPX decoder only if component values are padded (packing "Filled to 32-bit words, method A"). This patch adds decoding of RGB and RGBA 12-bit with no padding (packing "Packed into 32-bit words").


As I have no file with line boundaries not aligned on 32-bit, I can not have good tests about the stride computing (so code about non aligned boundaries is theory) so I preferred to limit risks by decoding only if line boundaries are aligned on 32-bit words: - 8 pixels for RGB (8 pixels x 3 components x 12 bits = 288 bits = 9 x 32-bit words) - 2 pixels for RGBA (2 pixels x 4 components x 12 bits = 3 x 32-bit words)

I think Little Endian parsing is fine thanks to the generic code about Big vs Little endian but I have no Little Endian test file so I also limited the decoding to Big Endian files.

Would be happy to check with cases I was not able to check if someone provides files.

I kept "Packing to 16bit required\n" message but interested in any suggestion about a better wording due to exceptions.

My test files:
https://github.com/MediaArea/RAWcooked-RegressionTestingFiles/tree/master/Formats/DPX/Flavors/RGB_12_Packed_BE

Regression tests done on 12-bit content "Filled to 32-bit words, method A" in:
https://samples.ffmpeg.org/image-samples/dpx_samples.zip

Looks like the previous version of the patch is not included due to the debate about RGBA. Please consider to include this modified patch, which has the RGBA part commented (I could remove the commented lines if you prefer).
From 28316686fed140279494d8c94e4f6bb5707e9ac0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= <jer...@mediaarea.net>
Date: Thu, 8 Feb 2018 09:22:08 +0100
Subject: [PATCH] avcodec/dpx: Support for RGB 12-bit packed decoding

Limited to widths multiple of 8 (RGB) due to lack of test files for such corner 
case

This partially fixes ticket #5639
---
 libavcodec/dpx.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c
index 1aa2cbd1c8..7e2a6fb779 100644
--- a/libavcodec/dpx.c
+++ b/libavcodec/dpx.c
@@ -65,6 +65,38 @@ static uint16_t read10in32(const uint8_t **ptr, uint32_t * 
lbuf,
     return *lbuf & 0x3FF;
 }
 
+static uint16_t read12in32(const uint8_t **ptr, uint32_t * lbuf,
+                                  int * n_datum, int is_big)
+{
+    if (*n_datum)
+        (*n_datum)--;
+    else {
+        *lbuf = read32(ptr, is_big);
+        *n_datum = 7;
+    }
+
+    switch (*n_datum){
+    case 7: return *lbuf & 0xFFF;
+    case 6: return (*lbuf >> 12) & 0xFFF;
+    case 5: {
+            uint32_t c = *lbuf >> 24;
+            *lbuf = read32(ptr, is_big);
+            c |= *lbuf << 8;
+            return c & 0xFFF;
+            }
+    case 4: return (*lbuf >> 4) & 0xFFF;
+    case 3: return (*lbuf >> 16) & 0xFFF;
+    case 2: {
+            uint32_t c = *lbuf >> 28;
+            *lbuf = read32(ptr, is_big);
+            c |= *lbuf << 4;
+            return c & 0xFFF;
+            }
+    case 1: return (*lbuf >> 8) & 0xFFF;
+    default: return *lbuf >> 20;
+    }
+}
+
 static int decode_frame(AVCodecContext *avctx,
                         void *data,
                         int *got_frame,
@@ -201,10 +233,29 @@ static int decode_frame(AVCodecContext *avctx,
         break;
     case 12:
         if (!packing) {
-            av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
-            return -1;
+            int tested = 0;
+            if (endian && descriptor == 50 && (avctx->width%8) == 0) // Little 
endian and widths not a multiple of 8 need tests
+                tested = 1;
+            //if (endian && descriptor == 51 && (avctx->width%2) == 0) // 
Little endian and widths not a multiple of 2 need tests
+            //    tested = 1;
+            if (!tested) {
+                av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n");
+                return -1;
+            }
+        }
+        stride = avctx->width * elements;
+        if (packing)
+            stride *= 2;
+        else {
+            stride *= 3; // 12 bits are 1.5 byte so multiplied by 3 then 
divided by 2
+            if (stride % 8) {
+                // Align to 32-bit boundaries (not tested)
+                stride /= 8;
+                stride++;
+                stride *= 8;
+            }
+            stride /= 2;
         }
-        stride = 2 * avctx->width * elements;
         break;
     case 16:
         stride = 2 * avctx->width * elements;
@@ -349,6 +400,7 @@ static int decode_frame(AVCodecContext *avctx,
                                 (uint16_t*)ptr[2],
                                 (uint16_t*)ptr[3]};
             for (y = 0; y < avctx->width; y++) {
+                if (packing) {
                 if (elements >= 3)
                     *dst[2]++ = read16(&buf, endian) >> 4;
                 *dst[0] = read16(&buf, endian) >> 4;
@@ -357,6 +409,17 @@ static int decode_frame(AVCodecContext *avctx,
                     *dst[1]++ = read16(&buf, endian) >> 4;
                 if (elements == 4)
                     *dst[3]++ = read16(&buf, endian) >> 4;
+                } else {
+                    *dst[2]++ = read12in32(&buf, &rgbBuffer,
+                                           &n_datum, endian);
+                    *dst[0]++ = read12in32(&buf, &rgbBuffer,
+                                           &n_datum, endian);
+                    *dst[1]++ = read12in32(&buf, &rgbBuffer,
+                                           &n_datum, endian);
+                    if (elements == 4)
+                        *dst[3]++ = read12in32(&buf, &rgbBuffer,
+                                               &n_datum, endian);
+                }
             }
             for (i = 0; i < elements; i++)
                 ptr[i] += p->linesize[i];
-- 
2.13.3.windows.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to