]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/imgconvert.c
zero copy packet handling for DV1394 by Max Krasnyansky
[ffmpeg] / libavcodec / imgconvert.c
index 9ab0bdbdf0980dc11d857acc2487b985f1aa94e7..401963193286b34f7a885565f0bf6a8094501775 100644 (file)
@@ -133,18 +133,27 @@ const char *avcodec_get_pix_fmt_name(int pix_fmt)
 int avpicture_fill(AVPicture *picture, UINT8 *ptr,
                    int pix_fmt, int width, int height)
 {
-    int size;
-
+    int size, w2, h2, size2;
+    PixFmtInfo *pinfo;
+    
+    pinfo = &pix_fmt_info[pix_fmt];
     size = width * height;
     switch(pix_fmt) {
     case PIX_FMT_YUV420P:
+    case PIX_FMT_YUV422P:
+    case PIX_FMT_YUV444P:
+    case PIX_FMT_YUV410P:
+    case PIX_FMT_YUV411P:
+        w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
+        h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
+        size2 = w2 * h2;
         picture->data[0] = ptr;
         picture->data[1] = picture->data[0] + size;
-        picture->data[2] = picture->data[1] + size / 4;
+        picture->data[2] = picture->data[1] + size2;
         picture->linesize[0] = width;
-        picture->linesize[1] = width / 2;
-        picture->linesize[2] = width / 2;
-        return (size * 3) / 2;
+        picture->linesize[1] = w2;
+        picture->linesize[2] = w2;
+        return size + 2 * size2;
     case PIX_FMT_RGB24:
     case PIX_FMT_BGR24:
         picture->data[0] = ptr;
@@ -152,44 +161,12 @@ int avpicture_fill(AVPicture *picture, UINT8 *ptr,
         picture->data[2] = NULL;
         picture->linesize[0] = width * 3;
         return size * 3;
-    case PIX_FMT_YUV422P:
-        picture->data[0] = ptr;
-        picture->data[1] = picture->data[0] + size;
-        picture->data[2] = picture->data[1] + size / 2;
-        picture->linesize[0] = width;
-        picture->linesize[1] = width / 2;
-        picture->linesize[2] = width / 2;
-        return (size * 2);
-    case PIX_FMT_YUV444P:
-        picture->data[0] = ptr;
-        picture->data[1] = picture->data[0] + size;
-        picture->data[2] = picture->data[1] + size;
-        picture->linesize[0] = width;
-        picture->linesize[1] = width;
-        picture->linesize[2] = width;
-        return size * 3;
     case PIX_FMT_RGBA32:
         picture->data[0] = ptr;
         picture->data[1] = NULL;
         picture->data[2] = NULL;
         picture->linesize[0] = width * 4;
         return size * 4;
-    case PIX_FMT_YUV410P:
-        picture->data[0] = ptr;
-        picture->data[1] = picture->data[0] + size;
-        picture->data[2] = picture->data[1] + size / 16;
-        picture->linesize[0] = width;
-        picture->linesize[1] = width / 4;
-        picture->linesize[2] = width / 4;
-        return size + (size / 8);
-    case PIX_FMT_YUV411P:
-        picture->data[0] = ptr;
-        picture->data[1] = picture->data[0] + size;
-        picture->data[2] = picture->data[1] + size / 4;
-        picture->linesize[0] = width;
-        picture->linesize[1] = width / 4;
-        picture->linesize[2] = width / 4;
-        return size + (size / 2);
     case PIX_FMT_RGB555:
     case PIX_FMT_RGB565:
     case PIX_FMT_YUV422:
@@ -424,12 +401,12 @@ static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
     y1_ptr = src->data[0];                                              \
     cb_ptr = src->data[1];                                              \
     cr_ptr = src->data[2];                                              \
-    width2 = width >> 1;                                                \
-    for(;height > 0; height -= 2) {                                     \
+    width2 = (width + 1) >> 1;                                          \
+    for(;height >= 2; height -= 2) {                                    \
         d1 = d;                                                         \
         d2 = d + dst->linesize[0];                                      \
         y2_ptr = y1_ptr + src->linesize[0];                             \
-        for(w = width2; w > 0; w --) {                                  \
+        for(w = width; w >= 2; w -= 2) {                                \
             cb = cb_ptr[0] - 128;                                       \
             cr = cr_ptr[0] - 128;                                       \
             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
@@ -457,11 +434,72 @@ static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
             cb_ptr++;                                                   \
             cr_ptr++;                                                   \
         }                                                               \
+        /* handle odd width */                                          \
+        if (w) {                                                        \
+            cb = cb_ptr[0] - 128;                                       \
+            cr = cr_ptr[0] - 128;                                       \
+            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
+            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
+            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
+                                                                        \
+            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
+            RGB_OUT(d1, r, g, b);                                       \
+                                                                        \
+            YUV_TO_RGB2(r, g, b, y2_ptr[0]);                            \
+            RGB_OUT(d2, r, g, b);                                       \
+            d1 += BPP;                                                  \
+            d2 += BPP;                                                  \
+            y1_ptr++;                                                   \
+            y2_ptr++;                                                   \
+            cb_ptr++;                                                   \
+            cr_ptr++;                                                   \
+        }                                                               \
         d += 2 * dst->linesize[0];                                      \
         y1_ptr += 2 * src->linesize[0] - width;                         \
         cb_ptr += src->linesize[1] - width2;                            \
         cr_ptr += src->linesize[2] - width2;                            \
     }                                                                   \
+    /* handle odd height */                                             \
+    if (height) {                                                       \
+        d1 = d;                                                         \
+        for(w = width; w >= 2; w -= 2) {                                \
+            cb = cb_ptr[0] - 128;                                       \
+            cr = cr_ptr[0] - 128;                                       \
+            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
+            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
+            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
+                                                                        \
+            /* output 2 pixels */                                       \
+            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
+            RGB_OUT(d1, r, g, b);                                       \
+                                                                        \
+            YUV_TO_RGB2(r, g, b, y1_ptr[1]);                            \
+            RGB_OUT(d1 + BPP, r, g, b);                                 \
+                                                                        \
+            d1 += 2 * BPP;                                              \
+                                                                        \
+            y1_ptr += 2;                                                \
+            cb_ptr++;                                                   \
+            cr_ptr++;                                                   \
+        }                                                               \
+        /* handle width */                                              \
+        if (w) {                                                        \
+            cb = cb_ptr[0] - 128;                                       \
+            cr = cr_ptr[0] - 128;                                       \
+            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
+            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
+            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
+                                                                        \
+            /* output 2 pixels */                                       \
+            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
+            RGB_OUT(d1, r, g, b);                                       \
+            d1 += BPP;                                                  \
+                                                                        \
+            y1_ptr++;                                                   \
+            cb_ptr++;                                                   \
+            cr_ptr++;                                                   \
+        }                                                               \
+    }                                                                   \
 }                                                                       \
                                                                         \
 /* XXX: no chroma interpolating is done */                              \
@@ -477,10 +515,10 @@ static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
     y1_ptr = src->data[0];                                              \
     cb_ptr = src->data[1];                                              \
     cr_ptr = src->data[2];                                              \
-    width2 = width >> 1;                                                \
+    width2 = (width + 1) >> 1;                                          \
     for(;height > 0; height --) {                                       \
         d1 = d;                                                         \
-        for(w = width2; w > 0; w --) {                                  \
+        for(w = width; w >= 2; w -= 2) {                                \
             cb = cb_ptr[0] - 128;                                       \
             cr = cr_ptr[0] - 128;                                       \
             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
@@ -489,17 +527,34 @@ static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src,    \
                                                                         \
             /* output 2 pixels */                                       \
             YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
-            RGB_OUT(d, r, g, b);                                        \
+            RGB_OUT(d1, r, g, b);                                       \
                                                                         \
             YUV_TO_RGB2(r, g, b, y1_ptr[1]);                            \
-            RGB_OUT(d + BPP, r, g, b);                                  \
+            RGB_OUT(d1 + BPP, r, g, b);                                 \
                                                                         \
-            d += 2 * BPP;                                               \
+            d1 += 2 * BPP;                                              \
                                                                         \
             y1_ptr += 2;                                                \
             cb_ptr++;                                                   \
             cr_ptr++;                                                   \
         }                                                               \
+        /* handle width */                                              \
+        if (w) {                                                        \
+            cb = cb_ptr[0] - 128;                                       \
+            cr = cr_ptr[0] - 128;                                       \
+            r_add = C_RV * cr + (1 << (SCALE_BITS - 1));                \
+            g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));  \
+            b_add = C_BU * cb + (1 << (SCALE_BITS - 1));                \
+                                                                        \
+            /* output 2 pixels */                                       \
+            YUV_TO_RGB2(r, g, b, y1_ptr[0]);                            \
+            RGB_OUT(d1, r, g, b);                                       \
+            d1 += BPP;                                                  \
+                                                                        \
+            y1_ptr++;                                                   \
+            cb_ptr++;                                                   \
+            cr_ptr++;                                                   \
+        }                                                               \
         d += dst->linesize[0];                                          \
         y1_ptr += src->linesize[0] - width;                             \
         cb_ptr += src->linesize[1] - width2;                            \
@@ -520,7 +575,7 @@ static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src,     \
     cr = dst->data[2];                                                  \
                                                                         \
     wrap = width;                                                       \
-    wrap3 = width * 3;                                                  \
+    wrap3 = width * BPP;                                                \
     p = src->data[0];                                                   \
     for(y=0;y<height;y+=2) {                                            \
         for(x=0;x<width;x+=2) {                                         \
@@ -562,12 +617,65 @@ static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src,     \
                                                                         \
             cb++;                                                       \
             cr++;                                                       \
-            p += -wrap3 + 2 * 3;                                        \
+            p += -wrap3 + 2 * BPP;                                      \
             lum += -wrap + 2;                                           \
         }                                                               \
         p += wrap3;                                                     \
         lum += wrap;                                                    \
     }                                                                   \
+}                                                                       \
+                                                                        \
+static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src,        \
+                                 int width, int height)                 \
+{                                                                       \
+    const unsigned char *p;                                             \
+    unsigned char *q;                                                   \
+    int r, g, b, dst_wrap, src_wrap;                                    \
+    int x, y;                                                           \
+                                                                        \
+    p = src->data[0];                                                   \
+    src_wrap = src->linesize[0] - BPP * width;                          \
+                                                                        \
+    q = dst->data[0];                                                   \
+    dst_wrap = dst->linesize[0] - width;                                \
+                                                                        \
+    for(y=0;y<height;y++) {                                             \
+        for(x=0;x<width;x++) {                                          \
+            RGB_IN(r, g, b, p);                                         \
+            q[0] = (FIX(0.29900) * r + FIX(0.58700) * g +               \
+                    FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;          \
+            q++;                                                        \
+            p += BPP;                                                   \
+        }                                                               \
+        p += src_wrap;                                                  \
+        q += dst_wrap;                                                  \
+    }                                                                   \
+}                                                                       \
+                                                                        \
+static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src,        \
+                                 int width, int height)                 \
+{                                                                       \
+    const unsigned char *p;                                             \
+    unsigned char *q;                                                   \
+    int r, dst_wrap, src_wrap;                                          \
+    int x, y;                                                           \
+                                                                        \
+    p = src->data[0];                                                   \
+    src_wrap = src->linesize[0] - width;                                \
+                                                                        \
+    q = dst->data[0];                                                   \
+    dst_wrap = dst->linesize[0] - BPP * width;                          \
+                                                                        \
+    for(y=0;y<height;y++) {                                             \
+        for(x=0;x<width;x++) {                                          \
+            r = p[0];                                                   \
+            RGB_OUT(q, r, r, r);                                        \
+            q += BPP;                                                   \
+            p ++;                                                       \
+        }                                                               \
+        p += src_wrap;                                                  \
+        q += dst_wrap;                                                  \
+    }                                                                   \
 }
 
 /* copy bit n to bits 0 ... n - 1 */
@@ -757,66 +865,6 @@ static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
     }
 }
 
-static void rgb24_to_gray(AVPicture *dst, AVPicture *src,
-                          int width, int height)
-{
-    const unsigned char *p;
-    unsigned char *q;
-    int r, g, b, dst_wrap, src_wrap;
-    int x, y;
-
-    p = src->data[0];
-    src_wrap = src->linesize[0] - 3 * width;
-
-    q = dst->data[0];
-    dst_wrap = dst->linesize[0] - width;
-
-    for(y=0;y<height;y++) {
-        for(x=0;x<width;x++) {
-            r = p[0];
-            g = p[1];
-            b = p[2];
-
-            q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
-                    FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
-            q++;
-            p += 3;
-        }
-        p += src_wrap;
-        q += dst_wrap;
-    }
-}
-
-static void gray_to_rgb24(AVPicture *dst, AVPicture *src,
-                          int width, int height)
-{
-    const unsigned char *p;
-    unsigned char *q;
-    int r, dst_wrap, src_wrap;
-    int x, y;
-
-    p = src->data[0];
-    src_wrap = src->linesize[0] - width;
-
-    q = dst->data[0];
-    dst_wrap = dst->linesize[0] - 3 * width;
-
-    for(y=0;y<height;y++) {
-        for(x=0;x<width;x++) {
-            r = p[0];
-
-            q[0] = r;
-            q[1] = r;
-            q[2] = r;
-            
-            q += 3;
-            p ++;
-        }
-        p += src_wrap;
-        q += dst_wrap;
-    }
-}
-
 static void mono_to_gray(AVPicture *dst, AVPicture *src,
                          int width, int height, int xor_mask)
 {
@@ -994,26 +1042,50 @@ static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
         [PIX_FMT_YUV420P] = { 
             .convert = rgba32_to_yuv420p
         },
+        [PIX_FMT_GRAY8] = { 
+            .convert = rgba32_to_gray
+        },
     },
     [PIX_FMT_BGR24] = {
         [PIX_FMT_YUV420P] = { 
             .convert = bgr24_to_yuv420p
         },
+        [PIX_FMT_GRAY8] = { 
+            .convert = bgr24_to_gray
+        },
     },
     [PIX_FMT_RGB555] = {
         [PIX_FMT_YUV420P] = { 
             .convert = rgb555_to_yuv420p
         },
+        [PIX_FMT_GRAY8] = { 
+            .convert = rgb555_to_gray
+        },
     },
     [PIX_FMT_RGB565] = {
         [PIX_FMT_YUV420P] = { 
             .convert = rgb565_to_yuv420p
         },
+        [PIX_FMT_GRAY8] = { 
+            .convert = rgb565_to_gray
+        },
     },
     [PIX_FMT_GRAY8] = {
+        [PIX_FMT_RGB555] = { 
+            .convert = gray_to_rgb555
+        },
+        [PIX_FMT_RGB565] = { 
+            .convert = gray_to_rgb565
+        },
         [PIX_FMT_RGB24] = { 
             .convert = gray_to_rgb24
         },
+        [PIX_FMT_BGR24] = { 
+            .convert = gray_to_bgr24
+        },
+        [PIX_FMT_RGBA32] = { 
+            .convert = gray_to_rgba32
+        },
         [PIX_FMT_MONOWHITE] = { 
             .convert = gray_to_monowhite
         },
@@ -1054,7 +1126,7 @@ static int avpicture_alloc(AVPicture *picture,
 
 static void avpicture_free(AVPicture *picture)
 {
-    free(picture->data[0]);
+    av_free(picture->data[0]);
 }
 
 /* XXX: always use linesize. Return -1 if not supported */
@@ -1072,10 +1144,10 @@ int img_convert(AVPicture *dst, int dst_pix_fmt,
         return -1;
     if (src_width <= 0 || src_height <= 0)
         return 0;
-    
+
     dst_width = src_width;
     dst_height = src_height;
-    
+
     dst_pix = &pix_fmt_info[dst_pix_fmt];
     src_pix = &pix_fmt_info[src_pix_fmt];
     if (src_pix_fmt == dst_pix_fmt) {
@@ -1173,10 +1245,12 @@ int img_convert(AVPicture *dst, int dst_pix_fmt,
         img_copy(dst->data[0], dst->linesize[0],
                  src->data[0], src->linesize[0],
                  dst_width, dst_height);
+
         for(i = 1;i <= 2; i++)
-            resize_func(dst->data[1], dst->linesize[1],
-                        src->data[1], src->linesize[1],
+            resize_func(dst->data[i], dst->linesize[i],
+                        src->data[i], src->linesize[i],
                         w, h);
+       return 0;
     }
 
     /* try to use an intermediate format */
@@ -1275,6 +1349,15 @@ static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lu
     }
 #else
 
+    {
+        mmx_t rounder;
+        rounder.uw[0]=4;
+        rounder.uw[1]=4;
+        rounder.uw[2]=4;
+        rounder.uw[3]=4;
+        pxor_r2r(mm7,mm7);
+        movq_m2r(rounder,mm6);
+    }
     for (;size > 3; size-=4) {
         DEINT_LINE_LUM
         lum_m4+=4;
@@ -1309,6 +1392,15 @@ static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2
     }
 #else
 
+    {
+        mmx_t rounder;
+        rounder.uw[0]=4;
+        rounder.uw[1]=4;
+        rounder.uw[2]=4;
+        rounder.uw[3]=4;
+        pxor_r2r(mm7,mm7);
+        movq_m2r(rounder,mm6);
+    }
     for (;size > 3; size-=4) {
         DEINT_INPLACE_LINE_LUM
         lum_m4+=4;
@@ -1391,19 +1483,6 @@ int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
     if ((width & 3) != 0 || (height & 3) != 0)
         return -1;
 
-#ifdef HAVE_MMX
-    {
-        mmx_t rounder;
-        rounder.uw[0]=4;
-        rounder.uw[1]=4;
-        rounder.uw[2]=4;
-        rounder.uw[3]=4;
-        pxor_r2r(mm7,mm7);
-        movq_m2r(rounder,mm6);
-    }
-#endif
-
-    
     for(i=0;i<3;i++) {
         if (i == 1) {
             switch(pix_fmt) {