[FFmpeg-devel,1/2] avcodec/tiff: add initial bayer support

Submitted by Paul B Mahol on Oct. 31, 2018, 2:25 p.m.

Details

Message ID 20181031142528.25850-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol Oct. 31, 2018, 2:25 p.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavcodec/tiff.c | 58 +++++++++++++++++++++++++++++++++++++++--------
 libavcodec/tiff.h |  1 +
 2 files changed, 49 insertions(+), 10 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index b537ec06a5..d42550b4cf 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -46,6 +46,7 @@ 
 #include "tiff.h"
 #include "tiff_data.h"
 #include "thread.h"
+#include "get_bits.h"
 
 typedef struct TiffContext {
     AVCodecContext *avctx;
@@ -65,6 +66,9 @@  typedef struct TiffContext {
     int fill_order;
     uint32_t res[4];
 
+    int is_bayer;
+    uint8_t pattern[4];
+
     int strips, rps, sstype;
     int sot;
     int stripsizesoff, stripsize, stripoff, strippos;
@@ -236,7 +240,8 @@  static int add_metadata(int count, int type,
     };
 }
 
-static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst,
+static void av_always_inline horizontal_fill(TiffContext *s,
+                                             unsigned int bpp, uint8_t* dst,
                                              int usePtr, const uint8_t *src,
                                              uint8_t c, int width, int offset)
 {
@@ -267,6 +272,15 @@  static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst,
             dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4;
         }
         break;
+    case 12: {
+                 uint16_t *dst16 = (uint16_t *)dst;
+                 GetBitContext gb;
+                 init_get_bits8(&gb, src, width);
+                 for (int i = 0; i < s->width; i++) {
+                     dst16[i] = get_bits(&gb, 12) << 4;;
+                 }
+             }
+        break;
     default:
         if (usePtr) {
             memcpy(dst + offset, src, width);
@@ -368,7 +382,7 @@  static int tiff_unpack_zlib(TiffContext *s, AVFrame *p, uint8_t *dst, int stride
     src = zbuf;
     for (line = 0; line < lines; line++) {
         if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-            horizontal_fill(s->bpp, dst, 1, src, 0, width, 0);
+            horizontal_fill(s, s->bpp, dst, 1, src, 0, width, 0);
         } else {
             memcpy(dst, src, width);
         }
@@ -433,7 +447,7 @@  static int tiff_unpack_lzma(TiffContext *s, AVFrame *p, uint8_t *dst, int stride
     src = buf;
     for (line = 0; line < lines; line++) {
         if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-            horizontal_fill(s->bpp, dst, 1, src, 0, width, 0);
+            horizontal_fill(s, s->bpp, dst, 1, src, 0, width, 0);
         } else {
             memcpy(dst, src, width);
         }
@@ -476,7 +490,7 @@  static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride,
                           s->compr, s->fax_opts);
     if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
         for (line = 0; line < lines; line++) {
-            horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
+            horizontal_fill(s, s->bpp, dst, 1, dst, 0, width, 0);
             dst += stride;
         }
     return ret;
@@ -516,6 +530,9 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
         av_assert0(width <= bytes_per_row);
         av_assert0(s->bpp == 24);
     }
+    if (s->is_bayer) {
+        width = (s->bpp * s->width + 7) >> 3;
+    }
 
     if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) {
 #if CONFIG_ZLIB
@@ -559,7 +576,7 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
                 return AVERROR_INVALIDDATA;
             }
             if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
-                horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
+                horizontal_fill(s, s->bpp, dst, 1, dst, 0, width, 0);
             if (is_yuv) {
                 unpack_yuv(s, p, dst, strip_start + line);
                 line += s->subsampling[1] - 1;
@@ -595,7 +612,7 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
                 return AVERROR_INVALIDDATA;
 
             if (!s->fill_order) {
-                horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
+                horizontal_fill(s, s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 || s->is_bayer),
                                 dst, 1, src, 0, width, 0);
             } else {
                 int i;
@@ -619,7 +636,7 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
                                "Copy went out of bounds\n");
                         return AVERROR_INVALIDDATA;
                     }
-                    horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
+                    horizontal_fill(s, s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
                                     dst, 1, src, 0, code, pixels);
                     src    += code;
                     pixels += code;
@@ -631,7 +648,7 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
                         return AVERROR_INVALIDDATA;
                     }
                     c = *src++;
-                    horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
+                    horizontal_fill(s, s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
                                     dst, 0, NULL, c, code, pixels);
                     pixels += code;
                 }
@@ -665,7 +682,7 @@  static int init_image(TiffContext *s, ThreadFrame *frame)
         return AVERROR_INVALIDDATA;
     }
 
-    switch (s->planar * 1000 + s->bpp * 10 + s->bppcount) {
+    switch (s->planar * 1000 + s->bpp * 10 + s->bppcount + s->is_bayer * 10000) {
     case 11:
         if (!s->palette_is_set) {
             s->avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
@@ -681,6 +698,20 @@  static int init_image(TiffContext *s, ThreadFrame *frame)
     case 81:
         s->avctx->pix_fmt = s->palette_is_set ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8;
         break;
+    case 10121:
+        switch (s->pattern[0] | s->pattern[1] << 8 | s->pattern[2] << 16 | s->pattern[3] << 24) {
+        case 0x02010100:
+            s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE;
+            break;
+        case 0x00010102:
+            s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_BGGR16LE : AV_PIX_FMT_BAYER_BGGR16BE;
+            break;
+        default:
+            av_log(s->avctx, AV_LOG_ERROR, "Unsupported Bayer pattern: 0x%X\n",
+                   s->pattern[0] | s->pattern[1] << 8 | s->pattern[2] << 16 | s->pattern[3] << 24);
+            return AVERROR_PATCHWELCOME;
+        }
+        break;
     case 243:
         if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) {
             if (s->subsampling[0] == 1 && s->subsampling[1] == 1) {
@@ -961,6 +992,13 @@  static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
     case TIFF_PREDICTOR:
         s->predictor = value;
         break;
+    case TIFF_CFA_PATTERN:
+        s->is_bayer = 1;
+        s->pattern[0] = ff_tget(&s->gb, type, s->le);
+        s->pattern[1] = ff_tget(&s->gb, type, s->le);
+        s->pattern[2] = ff_tget(&s->gb, type, s->le);
+        s->pattern[3] = ff_tget(&s->gb, type, s->le);
+        break;
     case TIFF_PHOTOMETRIC:
         switch (value) {
         case TIFF_PHOTOMETRIC_WHITE_IS_ZERO:
@@ -968,6 +1006,7 @@  static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
         case TIFF_PHOTOMETRIC_RGB:
         case TIFF_PHOTOMETRIC_PALETTE:
         case TIFF_PHOTOMETRIC_YCBCR:
+        case TIFF_PHOTOMETRIC_CFA:
             s->photometric = value;
             break;
         case TIFF_PHOTOMETRIC_ALPHA_MASK:
@@ -975,7 +1014,6 @@  static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
         case TIFF_PHOTOMETRIC_CIE_LAB:
         case TIFF_PHOTOMETRIC_ICC_LAB:
         case TIFF_PHOTOMETRIC_ITU_LAB:
-        case TIFF_PHOTOMETRIC_CFA:
         case TIFF_PHOTOMETRIC_LOG_L:
         case TIFF_PHOTOMETRIC_LOG_LUV:
         case TIFF_PHOTOMETRIC_LINEAR_RAW:
diff --git a/libavcodec/tiff.h b/libavcodec/tiff.h
index 3f692afa00..ae6622cb0c 100644
--- a/libavcodec/tiff.h
+++ b/libavcodec/tiff.h
@@ -75,6 +75,7 @@  enum TiffTags {
     TIFF_YCBCR_SUBSAMPLING  = 0x212,
     TIFF_YCBCR_POSITIONING  = 0x213,
     TIFF_REFERENCE_BW       = 0x214,
+    TIFF_CFA_PATTERN        = 0x828E,
     TIFF_COPYRIGHT          = 0x8298,
     TIFF_MODEL_TIEPOINT     = 0x8482,
     TIFF_MODEL_PIXEL_SCALE  = 0x830E,