[FFmpeg-devel] [PATCH] avcodec/dpx: Support for RGB 12-bit packed decoding

Jerome Martinez jerome at mediaarea.net
Wed Feb 14 14:46:59 EET 2018


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).
-------------- next part --------------
From 28316686fed140279494d8c94e4f6bb5707e9ac0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= <jerome at 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



More information about the ffmpeg-devel mailing list