[Ffmpeg-devel] [PATCH] TIFF encoder (Google SoC qualification task)

Kamil Nowosad k.nowosad
Thu Apr 5 18:37:16 CEST 2007


Hi

I'd like to add YUV support to tiff encoder. The specification says,
that planar pixel formats are extension only. For example in libtiff
they are unsupported. For this reason my solution is to add some
tiff-compatible packed formats [none of existing is compatible]. I have
now added only one format [YYUV422], but I'll add some more (this seems
to be fully analogous).

I've attached the patch, because I'm not completely sure if I don't do
anything wrong and reviewing this on the early stage can avoid a lot
of work later.

-- 
Best regards,
Kamil Nowosad
-------------- next part --------------
Index: libavutil/avutil.h
===================================================================
--- libavutil/avutil.h	(wersja 8629)
+++ libavutil/avutil.h	(kopia robocza)
@@ -70,6 +70,7 @@
     PIX_FMT_NONE= -1,
     PIX_FMT_YUV420P,   ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
     PIX_FMT_YUYV422,   ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+    PIX_FMT_YYUV422,   ///< Packed YUV 4:2:2, 16bpp, Y0 Y1 Cb Cr
     PIX_FMT_RGB24,     ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
     PIX_FMT_BGR24,     ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
     PIX_FMT_YUV422P,   ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Index: libavcodec/utils.c
===================================================================
--- libavcodec/utils.c	(wersja 8629)
+++ libavcodec/utils.c	(kopia robocza)
@@ -160,6 +160,7 @@
     switch(s->pix_fmt){
     case PIX_FMT_YUV420P:
     case PIX_FMT_YUYV422:
+    case PIX_FMT_YYUV422:
     case PIX_FMT_UYVY422:
     case PIX_FMT_YUV422P:
     case PIX_FMT_YUV444P:
Index: libavcodec/imgconvert.c
===================================================================
--- libavcodec/imgconvert.c	(wersja 8629)
+++ libavcodec/imgconvert.c	(kopia robocza)
@@ -99,6 +99,14 @@
         .depth = 8,
         .x_chroma_shift = 1, .y_chroma_shift = 0,
     },
+    [PIX_FMT_YYUV422] = {
+        .name = "yyuv422",
+        .nb_channels = 1,
+        .color_type = FF_COLOR_YUV,
+        .pixel_type = FF_PIXEL_PACKED,
+        .depth = 8,
+        .x_chroma_shift = 1, .y_chroma_shift = 0,
+    },
     [PIX_FMT_UYVY422] = {
         .name = "uyvy422",
         .nb_channels = 1,
@@ -447,6 +455,7 @@
     case PIX_FMT_RGB555:
     case PIX_FMT_RGB565:
     case PIX_FMT_YUYV422:
+    case PIX_FMT_YYUV422:
         picture->data[0] = ptr;
         picture->data[1] = NULL;
         picture->data[2] = NULL;
@@ -519,6 +528,7 @@
 
     if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) {
         if (pix_fmt == PIX_FMT_YUYV422 ||
+            pix_fmt == PIX_FMT_YYUV422 ||
             pix_fmt == PIX_FMT_UYVY422 ||
             pix_fmt == PIX_FMT_BGR565 ||
             pix_fmt == PIX_FMT_BGR555 ||
@@ -630,6 +640,7 @@
     case FF_PIXEL_PACKED:
         switch(pix_fmt) {
         case PIX_FMT_YUYV422:
+        case PIX_FMT_YYUV422:
         case PIX_FMT_UYVY422:
         case PIX_FMT_RGB565:
         case PIX_FMT_RGB555:
@@ -744,6 +755,7 @@
     case FF_PIXEL_PACKED:
         switch(pix_fmt) {
         case PIX_FMT_YUYV422:
+        case PIX_FMT_YYUV422:
         case PIX_FMT_UYVY422:
         case PIX_FMT_RGB565:
         case PIX_FMT_RGB555:
@@ -1006,6 +1018,39 @@
     }
 }
 
+static void yuv422p_to_yyuv422(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    uint8_t *p, *p1;
+    const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
+    int w;
+
+    p1 = dst->data[0];
+    lum1 = src->data[0];
+    cb1 = src->data[1];
+    cr1 = src->data[2];
+    for(;height > 0; height--) {
+        p = p1;
+        lum = lum1;
+        cb = cb1;
+        cr = cr1;
+        for(w = width; w >= 2; w -= 2) {
+            p[0] = lum[0];
+            p[1] = lum[1];
+            p[2] = cb[0];
+            p[3] = cr[0];
+            p += 4;
+            lum += 2;
+            cb++;
+            cr++;
+        }
+        p1 += dst->linesize[0];
+        lum1 += src->linesize[0];
+        cb1 += src->linesize[1];
+        cr1 += src->linesize[2];
+    }
+}
+
 static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
                               int width, int height)
 {
@@ -1108,6 +1153,39 @@
     }
 }
 
+static void yuv420p_to_yyuv422(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    int w, h;
+    uint8_t *line1, *line2, *linesrc = dst->data[0];
+    uint8_t *lum1, *lum2, *lumsrc = src->data[0];
+    uint8_t *cb1, *cb2 = src->data[1];
+    uint8_t *cr1, *cr2 = src->data[2];
+
+    for(h = height / 2; h--;) {
+        line1 = linesrc;
+        line2 = linesrc + dst->linesize[0];
+
+        lum1 = lumsrc;
+        lum2 = lumsrc + src->linesize[0];
+
+        cb1 = cb2;
+        cr1 = cr2;
+
+        for(w = width / 2; w--;) {
+                *line1++ = *lum1++; *line2++ = *lum2++;
+                *line1++ = *lum1++; *line2++ = *lum2++;
+                *line1++ =          *line2++ = *cb1++;
+                *line1++ =          *line2++ = *cr1++;
+        }
+
+        linesrc += dst->linesize[0] * 2;
+        lumsrc += src->linesize[0] * 2;
+        cb2 += src->linesize[1];
+        cr2 += src->linesize[2];
+    }
+}
+
 static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src,
                               int width, int height)
 {
@@ -1935,6 +2013,9 @@
         [PIX_FMT_YUYV422] = {
             .convert = yuv420p_to_yuyv422,
         },
+        [PIX_FMT_YYUV422] = {
+            .convert = yuv420p_to_yyuv422,
+        },
         [PIX_FMT_RGB555] = {
             .convert = yuv420p_to_rgb555
         },
@@ -1958,6 +2039,9 @@
         [PIX_FMT_YUYV422] = {
             .convert = yuv422p_to_yuyv422,
         },
+        [PIX_FMT_YYUV422] = {
+            .convert = yuv422p_to_yyuv422,
+        },
         [PIX_FMT_UYVY422] = {
             .convert = yuv422p_to_uyvy422,
         },
@@ -2508,6 +2592,10 @@
         dst_pix_fmt == PIX_FMT_YUYV422) {
         /* specific case: convert to YUV422P first */
         int_pix_fmt = PIX_FMT_YUV422P;
+    } else if (src_pix_fmt == PIX_FMT_YYUV422 ||
+        dst_pix_fmt == PIX_FMT_YYUV422) {
+        /* specific case: convert to YUV422P first */
+        int_pix_fmt = PIX_FMT_YUV422P;
     } else if (src_pix_fmt == PIX_FMT_UYVY422 ||
         dst_pix_fmt == PIX_FMT_UYVY422) {
         /* specific case: convert to YUV422P first */
Index: libavcodec/tiffenc.c
===================================================================
--- libavcodec/tiffenc.c	(wersja 8629)
+++ libavcodec/tiffenc.c	(kopia robocza)
@@ -190,6 +190,8 @@
     uint32_t res[2] = { 72, 1 };        // image resolution (72/1)
     static const uint16_t bpp_tab[] = { 8, 8, 8, 8 };
     int ret = -1;
+    int isYUV = 0;
+    uint16_t yuv_subsampling[2] = {1, 1};
 
     s->buf_start = buf;
     s->buf = &ptr;
@@ -200,7 +202,8 @@
     p->key_frame = 1;
 
     s->compr = TIFF_PACKBITS;
-    if (avctx->compression_level == 0) {
+    if (avctx->pix_fmt == PIX_FMT_YYUV422
+        || avctx->compression_level == 0) {
         s->compr = TIFF_RAW;
 #ifdef CONFIG_ZLIB
     } else if ((avctx->compression_level > 2)) {
@@ -232,13 +235,23 @@
         s->bpp = 1;
         s->invert = 0;
         break;
+    case PIX_FMT_YYUV422:
+        s->bpp = 16;
+        s->invert = 6;
+        yuv_subsampling[0] = 2;
+        isYUV = 1;
+        break;
     default:
         av_log(s->avctx, AV_LOG_ERROR,
                "This colors format is not supported\n");
         return -1;
     }
-    s->bpp_tab_size = (s->bpp >> 3);
 
+    if (isYUV)
+        s->bpp_tab_size = 3;
+    else
+        s->bpp_tab_size = (s->bpp >> 3);
+
     if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE)
         //best choose for DEFLATE
         s->rps = s->height;
@@ -336,6 +349,13 @@
         }
         add_entry(s, TIFF_PAL, TIFF_SHORT, 256 * 3, pal);
     }
+    if (isYUV){
+        /** according to CCIR Recommendation 601.1 */
+        uint32_t refbw[12] = {15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1};
+        add_entry(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT,    2, yuv_subsampling);
+        add_entry(s, TIFF_REFERENCE_BW,      TIFF_RATIONAL, 6, refbw);
+    }
+
     bytestream_put_le32(&offset, ptr - buf);    // write offset to dir
 
     if (check_size(s, 6 + s->num_entries * 12))
@@ -366,6 +386,7 @@
     .pix_fmts =
         (enum PixelFormat[]) {PIX_FMT_RGB24, PIX_FMT_PAL8, PIX_FMT_GRAY8,
                               PIX_FMT_MONOBLACK, PIX_FMT_MONOWHITE,
+                              PIX_FMT_YYUV422,
                               -1}
 
 };



More information about the ffmpeg-devel mailing list