changeset 30110:19414a605695

Add support for 16-bit per component YUV formats.
author reimar
date Thu, 31 Dec 2009 22:53:25 +0000
parents 0f25d3062987
children ee5c7a825348
files codec-cfg.c fmt-conversion.c libmpcodecs/img_format.c libmpcodecs/img_format.h libmpcodecs/mp_image.c libmpcodecs/mp_image.h libmpcodecs/vf.c libmpcodecs/vf_scale.c libvo/gl_common.c libvo/vo_gl.c libvo/vo_gl2.c m_option.c
diffstat 12 files changed, 117 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/codec-cfg.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/codec-cfg.c	Thu Dec 31 22:53:25 2009 +0000
@@ -152,6 +152,15 @@
 		{"NV21",  IMGFMT_NV21},
 		{"YVU9",  IMGFMT_YVU9},
 		{"IF09",  IMGFMT_IF09},
+		{"444P16LE", IMGFMT_444P16_LE},
+		{"444P16BE", IMGFMT_444P16_BE},
+		{"422P16LE", IMGFMT_422P16_LE},
+		{"422P16BE", IMGFMT_422P16_BE},
+		{"420P16LE", IMGFMT_420P16_LE},
+		{"420P16BE", IMGFMT_420P16_BE},
+		{"444P16", IMGFMT_444P16},
+		{"422P16", IMGFMT_422P16},
+		{"420P16", IMGFMT_420P16},
 		{"444P",  IMGFMT_444P},
 		{"422P",  IMGFMT_422P},
 		{"411P",  IMGFMT_411P},
--- a/fmt-conversion.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/fmt-conversion.c	Thu Dec 31 22:53:25 2009 +0000
@@ -59,6 +59,12 @@
     {IMGFMT_422P,  PIX_FMT_YUV422P},
     {IMGFMT_444P,  PIX_FMT_YUV444P},
     {IMGFMT_440P,  PIX_FMT_YUV440P},
+    {IMGFMT_420P16_LE,  PIX_FMT_YUV420P16LE},
+    {IMGFMT_420P16_BE,  PIX_FMT_YUV420P16BE},
+    {IMGFMT_422P16_LE,  PIX_FMT_YUV422P16LE},
+    {IMGFMT_422P16_BE,  PIX_FMT_YUV422P16BE},
+    {IMGFMT_444P16_LE,  PIX_FMT_YUV444P16LE},
+    {IMGFMT_444P16_BE,  PIX_FMT_YUV444P16BE},
 
     // YUVJ are YUV formats that use the full Y range and not just
     // 16 - 235 (see colorspaces.txt).
--- a/libmpcodecs/img_format.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/img_format.c	Thu Dec 31 22:53:25 2009 +0000
@@ -37,6 +37,12 @@
 	case IMGFMT_CLPL: return "Planar CLPL";
 	case IMGFMT_Y800: return "Planar Y800";
 	case IMGFMT_Y8: return "Planar Y8";
+	case IMGFMT_420P16_LE: return "Planar 420P 16-bit little-endian";
+	case IMGFMT_420P16_BE: return "Planar 420P 16-bit big-endian";
+	case IMGFMT_422P16_LE: return "Planar 422P 16-bit little-endian";
+	case IMGFMT_422P16_BE: return "Planar 422P 16-bit big-endian";
+	case IMGFMT_444P16_LE: return "Planar 444P 16-bit little-endian";
+	case IMGFMT_444P16_BE: return "Planar 444P 16-bit big-endian";
 	case IMGFMT_444P: return "Planar 444P";
 	case IMGFMT_422P: return "Planar 422P";
 	case IMGFMT_411P: return "Planar 411P";
@@ -83,8 +89,13 @@
 int mp_get_chroma_shift(int format, int *x_shift, int *y_shift)
 {
     int xs = 0, ys = 0;
+    int bpp;
+    int bpp_factor = 1;
     int err = 0;
     switch (format) {
+    case IMGFMT_420P16_LE:
+    case IMGFMT_420P16_BE:
+        bpp_factor = 2;
     case IMGFMT_I420:
     case IMGFMT_IYUV:
     case IMGFMT_YV12:
@@ -96,10 +107,16 @@
         xs = 2;
         ys = 2;
         break;
+    case IMGFMT_444P16_LE:
+    case IMGFMT_444P16_BE:
+        bpp_factor = 2;
     case IMGFMT_444P:
         xs = 0;
         ys = 0;
         break;
+    case IMGFMT_422P16_LE:
+    case IMGFMT_422P16_BE:
+        bpp_factor = 2;
     case IMGFMT_422P:
         xs = 1;
         ys = 0;
@@ -118,5 +135,7 @@
     }
     if (x_shift) *x_shift = xs;
     if (y_shift) *y_shift = ys;
-    return err ? 0 : 8 + (16 >> (xs + ys));
+    bpp = 8 + (16 >> (xs + ys));
+    bpp *= bpp_factor;
+    return err ? 0 : bpp;
 }
--- a/libmpcodecs/img_format.h	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/img_format.h	Thu Dec 31 22:53:25 2009 +0000
@@ -73,6 +73,26 @@
 #define IMGFMT_411P 0x50313134
 #define IMGFMT_440P 0x50303434
 #define IMGFMT_HM12 0x32314D48
+#define IMGFMT_444P16_LE 0x51343434
+#define IMGFMT_444P16_BE 0x34343451
+#define IMGFMT_422P16_LE 0x51323234
+#define IMGFMT_422P16_BE 0x34323251
+#define IMGFMT_420P16_LE 0x51303234
+#define IMGFMT_420P16_BE 0x34323051
+#if HAVE_BIGENDIAN
+#define IMGFMT_444P16 IMGFMT_444P16_BE
+#define IMGFMT_422P16 IMGFMT_422P16_BE
+#define IMGFMT_420P16 IMGFMT_420P16_BE
+#else
+#define IMGFMT_444P16 IMGFMT_444P16_LE
+#define IMGFMT_422P16 IMGFMT_422P16_LE
+#define IMGFMT_420P16 IMGFMT_420P16_LE
+#endif
+
+#define IMGFMT_IS_YUVP16_LE(fmt) (((fmt  ^ IMGFMT_420P16_LE) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16_BE(fmt) (((fmt  ^ IMGFMT_420P16_BE) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16_NE(fmt) (((fmt  ^ IMGFMT_420P16   ) & 0xff0000ff) == 0)
+#define IMGFMT_IS_YUVP16(fmt)    (IMGFMT_IS_YUVP16_LE(fmt) || IMGFMT_IS_YUVP16_BE(fmt))
 
 /* Packed YUV Formats */
 
--- a/libmpcodecs/mp_image.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/mp_image.c	Thu Dec 31 22:53:25 2009 +0000
@@ -29,17 +29,18 @@
   else
     mpi->planes[0]=memalign(64, mpi->bpp*mpi->width*(mpi->height+2)/8);
   if(mpi->flags&MP_IMGFLAG_PLANAR){
+    int bpp = IMGFMT_IS_YUVP16(fmt)? 2 : 1;
     // YV12/I420/YVU9/IF09. feel free to add other planar formats here...
-    if(!mpi->stride[0]) mpi->stride[0]=mpi->width;
-    if(!mpi->stride[1]) mpi->stride[1]=mpi->stride[2]=mpi->chroma_width;
+    if(!mpi->stride[0]) mpi->stride[0]=bpp*mpi->width;
+    if(!mpi->stride[1]) mpi->stride[1]=mpi->stride[2]=bpp*mpi->chroma_width;
     if(mpi->flags&MP_IMGFLAG_SWAPPED){
       // I420/IYUV  (Y,U,V)
-      mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height;
-      mpi->planes[2]=mpi->planes[1]+mpi->chroma_width*mpi->chroma_height;
+      mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+      mpi->planes[2]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
     } else {
       // YV12,YVU9,IF09  (Y,V,U)
-      mpi->planes[2]=mpi->planes[0]+mpi->width*mpi->height;
-      mpi->planes[1]=mpi->planes[2]+mpi->chroma_width*mpi->chroma_height;
+      mpi->planes[2]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+      mpi->planes[1]=mpi->planes[2]+mpi->stride[1]*mpi->chroma_height;
     }
   } else {
     if(!mpi->stride[0]) mpi->stride[0]=mpi->width*mpi->bpp/8;
--- a/libmpcodecs/mp_image.h	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/mp_image.h	Thu Dec 31 22:53:25 2009 +0000
@@ -152,6 +152,12 @@
     case IMGFMT_422P:
     case IMGFMT_411P:
     case IMGFMT_440P:
+    case IMGFMT_444P16_LE:
+    case IMGFMT_444P16_BE:
+    case IMGFMT_422P16_LE:
+    case IMGFMT_422P16_BE:
+    case IMGFMT_420P16_LE:
+    case IMGFMT_420P16_BE:
 	return;
     case IMGFMT_Y800:
     case IMGFMT_Y8:
--- a/libmpcodecs/vf.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/vf.c	Thu Dec 31 22:53:25 2009 +0000
@@ -383,25 +383,26 @@
 	  else
 	     mpi->planes[0]=memalign(64, mpi->bpp*mpi->width*(mpi->height+2)/8);
 	  if(mpi->flags&MP_IMGFLAG_PLANAR){
+	      int bpp = IMGFMT_IS_YUVP16(mpi->imgfmt)? 2 : 1;
 	      // YV12/I420/YVU9/IF09. feel free to add other planar formats here...
 	      //if(!mpi->stride[0])
-	      mpi->stride[0]=mpi->width;
+	      mpi->stride[0]=bpp*mpi->width;
 	      //if(!mpi->stride[1])
 	      if(mpi->num_planes > 2){
-	      mpi->stride[1]=mpi->stride[2]=mpi->chroma_width;
+	      mpi->stride[1]=mpi->stride[2]=bpp*mpi->chroma_width;
 	      if(mpi->flags&MP_IMGFLAG_SWAPPED){
 	          // I420/IYUV  (Y,U,V)
-	          mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height;
-	          mpi->planes[2]=mpi->planes[1]+mpi->chroma_width*mpi->chroma_height;
+	          mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+	          mpi->planes[2]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
 	      } else {
 	          // YV12,YVU9,IF09  (Y,V,U)
-	          mpi->planes[2]=mpi->planes[0]+mpi->width*mpi->height;
-	          mpi->planes[1]=mpi->planes[2]+mpi->chroma_width*mpi->chroma_height;
+	          mpi->planes[2]=mpi->planes[0]+mpi->stride[0]*mpi->height;
+	          mpi->planes[1]=mpi->planes[2]+mpi->stride[1]*mpi->chroma_height;
 	      }
 	      } else {
 	          // NV12/NV21
 	          mpi->stride[1]=mpi->chroma_width;
-	          mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height;
+	          mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->height;
 	      }
 	  } else {
 	      //if(!mpi->stride[0])
--- a/libmpcodecs/vf_scale.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libmpcodecs/vf_scale.c	Thu Dec 31 22:53:25 2009 +0000
@@ -64,6 +64,12 @@
     IMGFMT_YUY2,
     IMGFMT_UYVY,
     IMGFMT_440P,
+    IMGFMT_444P16_LE,
+    IMGFMT_444P16_BE,
+    IMGFMT_422P16_LE,
+    IMGFMT_422P16_BE,
+    IMGFMT_420P16_LE,
+    IMGFMT_420P16_BE,
 // RGB and grayscale (Y8 and Y800):
     IMGFMT_BGR32,
     IMGFMT_RGB32,
@@ -474,6 +480,12 @@
     case IMGFMT_422P:
     case IMGFMT_411P:
     case IMGFMT_440P:
+    case IMGFMT_444P16_LE:
+    case IMGFMT_444P16_BE:
+    case IMGFMT_422P16_LE:
+    case IMGFMT_422P16_BE:
+    case IMGFMT_420P16_LE:
+    case IMGFMT_420P16_BE:
     case IMGFMT_BGR8:
     case IMGFMT_RGB8:
     case IMGFMT_BG4B:
--- a/libvo/gl_common.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libvo/gl_common.c	Thu Dec 31 22:53:25 2009 +0000
@@ -234,9 +234,15 @@
   if (!gl_format) gl_format = &dummy2;
   if (!gl_type) gl_type = &dummy2;
 
-  // these are all the same for our purpose
-  if (mp_get_chroma_shift(fmt, NULL, NULL))
-    fmt = IMGFMT_YV12;
+  if (mp_get_chroma_shift(fmt, NULL, NULL)) {
+    // reduce the possible cases a bit
+    if (IMGFMT_IS_YUVP16_LE(fmt))
+      fmt = IMGFMT_420P16_LE;
+    else if (IMGFMT_IS_YUVP16_BE(fmt))
+      fmt = IMGFMT_420P16_BE;
+    else
+      fmt = IMGFMT_YV12;
+  }
 
   *bpp = IMGFMT_IS_BGR(fmt)?IMGFMT_BGR_DEPTH(fmt):IMGFMT_RGB_DEPTH(fmt);
   *gl_texfmt = 3;
@@ -254,6 +260,13 @@
       *gl_format = GL_RGBA;
       *gl_type = GL_UNSIGNED_BYTE;
       break;
+    case IMGFMT_420P16:
+      supported = 0; // no native YUV support
+      *gl_texfmt = 1;
+      *bpp = 16;
+      *gl_format = GL_LUMINANCE;
+      *gl_type = GL_UNSIGNED_SHORT;
+      break;
     case IMGFMT_YV12:
       supported = 0; // no native YV12 support
     case IMGFMT_Y800:
--- a/libvo/vo_gl.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libvo/vo_gl.c	Thu Dec 31 22:53:25 2009 +0000
@@ -971,7 +971,8 @@
       caps |= VFCAP_OSD | VFCAP_EOSD | (scaled_osd ? 0 : VFCAP_EOSD_UNSCALED);
     if (format == IMGFMT_RGB24 || format == IMGFMT_RGBA)
         return caps;
-    if (use_yuv && mp_get_chroma_shift(format, NULL, NULL))
+    if (use_yuv && mp_get_chroma_shift(format, NULL, NULL) &&
+        (IMGFMT_IS_YUVP16_NE(format) || !IMGFMT_IS_YUVP16(format)))
         return caps;
     // HACK, otherwise we get only b&w with some filters (e.g. -vf eq)
     // ideally MPlayer should be fixed instead not to use Y800 when it has the choice
--- a/libvo/vo_gl2.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/libvo/vo_gl2.c	Thu Dec 31 22:53:25 2009 +0000
@@ -822,7 +822,8 @@
 static int
 query_format(uint32_t format)
 {
-  if (use_yuv && mp_get_chroma_shift(format, NULL, NULL))
+  if (use_yuv && mp_get_chroma_shift(format, NULL, NULL) &&
+      (IMGFMT_IS_YUVP16_NE(format) || !IMGFMT_IS_YUVP16(format)))
     return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
            VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
   switch(format) {
--- a/m_option.c	Thu Dec 31 19:59:58 2009 +0000
+++ b/m_option.c	Thu Dec 31 22:53:25 2009 +0000
@@ -1032,6 +1032,15 @@
   const char* name;
   unsigned int fmt;
 } mp_imgfmt_list[] = {
+  {"444p16le", IMGFMT_444P16_LE},
+  {"444p16be", IMGFMT_444P16_BE},
+  {"422p16le", IMGFMT_422P16_LE},
+  {"422p16be", IMGFMT_422P16_BE},
+  {"420p16le", IMGFMT_420P16_LE},
+  {"420p16be", IMGFMT_420P16_BE},
+  {"444p16", IMGFMT_444P16},
+  {"422p16", IMGFMT_422P16},
+  {"420p16", IMGFMT_420P16},
   {"444p", IMGFMT_444P},
   {"422p", IMGFMT_422P},
   {"411p", IMGFMT_411P},