Planar 16bit 420 422 444 YUV support (output is only supported in some
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 21 Apr 2009 01:08:03 +0000 (01:08 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 21 Apr 2009 01:08:03 +0000 (01:08 +0000)
unscaled convertions).
This, like gray16 converts down to 8bit, which is a big FIXME & patch welcome,
we should preserve more bits.

Originally committed as revision 29217 to svn://svn.mplayerhq.hu/mplayer/trunk/libswscale

libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/swscale_template.c

index 0583cb0..fcd809e 100644 (file)
@@ -134,6 +134,12 @@ unsigned swscale_version(void)
         || (x)==PIX_FMT_YUV440P     \
         || (x)==PIX_FMT_MONOWHITE   \
         || (x)==PIX_FMT_MONOBLACK   \
+        || (x)==PIX_FMT_YUV420PLE   \
+        || (x)==PIX_FMT_YUV422PLE   \
+        || (x)==PIX_FMT_YUV444PLE   \
+        || (x)==PIX_FMT_YUV420PBE   \
+        || (x)==PIX_FMT_YUV422PBE   \
+        || (x)==PIX_FMT_YUV444PBE   \
     )
 #define isSupportedOut(x)   (       \
            (x)==PIX_FMT_YUV420P     \
@@ -152,6 +158,12 @@ unsigned swscale_version(void)
         || (x)==PIX_FMT_GRAY8       \
         || (x)==PIX_FMT_YUV410P     \
         || (x)==PIX_FMT_YUV440P     \
+        || (x)==PIX_FMT_YUV420PLE   \
+        || (x)==PIX_FMT_YUV422PLE   \
+        || (x)==PIX_FMT_YUV444PLE   \
+        || (x)==PIX_FMT_YUV420PBE   \
+        || (x)==PIX_FMT_YUV422PBE   \
+        || (x)==PIX_FMT_YUV444PBE   \
     )
 #define isPacked(x)         (       \
            (x)==PIX_FMT_PAL8        \
@@ -467,6 +479,18 @@ const char *sws_format_name(enum PixelFormat format)
             return "vdpau_wmv3";
         case PIX_FMT_VDPAU_VC1:
             return "vdpau_vc1";
+        case PIX_FMT_YUV420PLE:
+            return "yuv420ple";
+        case PIX_FMT_YUV422PLE:
+            return "yuv422ple";
+        case PIX_FMT_YUV444PLE:
+            return "yuv444ple";
+        case PIX_FMT_YUV420PBE:
+            return "yuv420pbe";
+        case PIX_FMT_YUV422PBE:
+            return "yuv422pbe";
+        case PIX_FMT_YUV444PBE:
+            return "yuv444pbe";
         default:
             return "Unknown format";
     }
@@ -2196,6 +2220,8 @@ static void getSubSampleFactors(int *h, int *v, int format){
         *v=0;
         break;
     case PIX_FMT_YUV420P:
+    case PIX_FMT_YUV420PLE:
+    case PIX_FMT_YUV420PBE:
     case PIX_FMT_YUVA420P:
     case PIX_FMT_GRAY16BE:
     case PIX_FMT_GRAY16LE:
@@ -2214,10 +2240,14 @@ static void getSubSampleFactors(int *h, int *v, int format){
         *v=2;
         break;
     case PIX_FMT_YUV444P:
+    case PIX_FMT_YUV444PLE:
+    case PIX_FMT_YUV444PBE:
         *h=0;
         *v=0;
         break;
     case PIX_FMT_YUV422P:
+    case PIX_FMT_YUV422PLE:
+    case PIX_FMT_YUV422PBE:
         *h=1;
         *v=0;
         break;
@@ -2574,7 +2604,10 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
             || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
             || (isPlanarYUV(srcFormat) && isGray(dstFormat))
             || (isPlanarYUV(dstFormat) && isGray(srcFormat))
-            || (isGray(dstFormat) && isGray(srcFormat)))
+            || (isGray(dstFormat) && isGray(srcFormat))
+            || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
+                && c->chrDstHSubSample == c->chrSrcHSubSample
+                && c->chrDstVSubSample == c->chrSrcVSubSample))
         {
             if (isPacked(c->srcFormat))
                 c->swScale= packedCopy;
index 5c56ffe..3995887 100644 (file)
@@ -294,9 +294,15 @@ const char *sws_format_name(int format);
 #define is16BPS(x)      (           \
            (x)==PIX_FMT_GRAY16BE    \
         || (x)==PIX_FMT_GRAY16LE    \
+        || (x)==PIX_FMT_YUV420PLE   \
+        || (x)==PIX_FMT_YUV422PLE   \
+        || (x)==PIX_FMT_YUV444PLE   \
+        || (x)==PIX_FMT_YUV420PBE   \
+        || (x)==PIX_FMT_YUV422PBE   \
+        || (x)==PIX_FMT_YUV444PBE   \
     )
 #define isBE(x) ((x)&1)
-#define isPlanarYUV(x)  (           \
+#define isPlanar8YUV(x) (           \
            (x)==PIX_FMT_YUV410P     \
         || (x)==PIX_FMT_YUV420P     \
         || (x)==PIX_FMT_YUVA420P    \
@@ -307,6 +313,15 @@ const char *sws_format_name(int format);
         || (x)==PIX_FMT_NV12        \
         || (x)==PIX_FMT_NV21        \
     )
+#define isPlanarYUV(x)  (           \
+        isPlanar8YUV(x)             \
+        || (x)==PIX_FMT_YUV420PLE   \
+        || (x)==PIX_FMT_YUV422PLE   \
+        || (x)==PIX_FMT_YUV444PLE   \
+        || (x)==PIX_FMT_YUV420PBE   \
+        || (x)==PIX_FMT_YUV422PBE   \
+        || (x)==PIX_FMT_YUV444PBE   \
+    )
 #define isYUV(x)        (           \
            (x)==PIX_FMT_UYVY422     \
         || (x)==PIX_FMT_YUYV422     \
index a5bd2f5..fe68c16 100644 (file)
@@ -1671,6 +1671,39 @@ static inline void RENAME(yuy2ToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t
     assert(src1 == src2);
 }
 
+static inline void RENAME(LEToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1, const uint8_t *src2, long width, uint32_t *unused)
+{
+#if HAVE_MMX
+    __asm__ volatile(
+    "mov                    %0, %%"REG_a"       \n\t"
+    "1:                                         \n\t"
+    "movq    (%1, %%"REG_a",2), %%mm0           \n\t"
+    "movq   8(%1, %%"REG_a",2), %%mm1           \n\t"
+    "movq    (%2, %%"REG_a",2), %%mm2           \n\t"
+    "movq   8(%2, %%"REG_a",2), %%mm3           \n\t"
+    "psrlw                  $8, %%mm0           \n\t"
+    "psrlw                  $8, %%mm1           \n\t"
+    "psrlw                  $8, %%mm2           \n\t"
+    "psrlw                  $8, %%mm3           \n\t"
+    "packuswb            %%mm1, %%mm0           \n\t"
+    "packuswb            %%mm3, %%mm2           \n\t"
+    "movq                %%mm0, (%3, %%"REG_a") \n\t"
+    "movq                %%mm2, (%4, %%"REG_a") \n\t"
+    "add                    $8, %%"REG_a"       \n\t"
+    " js                    1b                  \n\t"
+    : : "g" ((x86_reg)-width), "r" (src1+width*2), "r" (src2+width*2), "r" (dstU+width), "r" (dstV+width)
+    : "%"REG_a
+    );
+#else
+    int i;
+    for (i=0; i<width; i++)
+    {
+        dstU[i]= src1[2*i + 1];
+        dstV[i]= src2[2*i + 1];
+    }
+#endif
+}
+
 /* This is almost identical to the previous, end exists only because
  * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
 static inline void RENAME(uyvyToY)(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused)
@@ -1732,6 +1765,40 @@ static inline void RENAME(uyvyToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t
     assert(src1 == src2);
 }
 
+static inline void RENAME(BEToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1, const uint8_t *src2, long width, uint32_t *unused)
+{
+#if HAVE_MMX
+    __asm__ volatile(
+    "movq "MANGLE(bm01010101)", %%mm4           \n\t"
+    "mov                    %0, %%"REG_a"       \n\t"
+    "1:                                         \n\t"
+    "movq    (%1, %%"REG_a",2), %%mm0           \n\t"
+    "movq   8(%1, %%"REG_a",2), %%mm1           \n\t"
+    "movq    (%2, %%"REG_a",2), %%mm2           \n\t"
+    "movq   8(%2, %%"REG_a",2), %%mm3           \n\t"
+    "pand                %%mm4, %%mm0           \n\t"
+    "pand                %%mm4, %%mm1           \n\t"
+    "pand                %%mm4, %%mm2           \n\t"
+    "pand                %%mm4, %%mm3           \n\t"
+    "packuswb            %%mm1, %%mm0           \n\t"
+    "packuswb            %%mm3, %%mm2           \n\t"
+    "movq                %%mm0, (%3, %%"REG_a") \n\t"
+    "movq                %%mm2, (%4, %%"REG_a") \n\t"
+    "add                    $8, %%"REG_a"       \n\t"
+    " js                    1b                  \n\t"
+    : : "g" ((x86_reg)-width), "r" (src1+width*2), "r" (src2+width*2), "r" (dstU+width), "r" (dstV+width)
+    : "%"REG_a
+    );
+#else
+    int i;
+    for (i=0; i<width; i++)
+    {
+        dstU[i]= src1[2*i];
+        dstV[i]= src2[2*i];
+    }
+#endif
+}
+
 #define BGR2Y(type, name, shr, shg, shb, maskr, maskg, maskb, RY, GY, BY, S)\
 static inline void RENAME(name)(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused)\
 {\
@@ -3085,6 +3152,12 @@ static void RENAME(sws_init_swScale)(SwsContext *c)
         case PIX_FMT_PAL8     :
         case PIX_FMT_BGR4_BYTE:
         case PIX_FMT_RGB4_BYTE: c->hcscale_internal = RENAME(palToUV); break;
+        case PIX_FMT_YUV420PBE:
+        case PIX_FMT_YUV422PBE:
+        case PIX_FMT_YUV444PBE: c->hcscale_internal = RENAME(BEToUV); break;
+        case PIX_FMT_YUV420PLE:
+        case PIX_FMT_YUV422PLE:
+        case PIX_FMT_YUV444PLE: c->hcscale_internal = RENAME(LEToUV); break;
     }
     if (c->chrSrcHSubSample) {
         switch(srcFormat) {
@@ -3118,8 +3191,14 @@ static void RENAME(sws_init_swScale)(SwsContext *c)
     c->hascale_internal = NULL;
     switch (srcFormat) {
     case PIX_FMT_YUYV422  :
+    case PIX_FMT_YUV420PBE:
+    case PIX_FMT_YUV422PBE:
+    case PIX_FMT_YUV444PBE:
     case PIX_FMT_GRAY16BE : c->hyscale_internal = RENAME(yuy2ToY); break;
     case PIX_FMT_UYVY422  :
+    case PIX_FMT_YUV420PLE:
+    case PIX_FMT_YUV422PLE:
+    case PIX_FMT_YUV444PLE:
     case PIX_FMT_GRAY16LE : c->hyscale_internal = RENAME(uyvyToY); break;
     case PIX_FMT_BGR24    : c->hyscale_internal = RENAME(bgr24ToY); break;
     case PIX_FMT_BGR565   : c->hyscale_internal = RENAME(bgr16ToY); break;