#ifndef _FFIMGFMT_H_
#define _FFIMGFMT_H_

//================================ ffdshow ==================================
#define ODD2EVEN(x) x&1?x+1:x

enum
{
 FF_CSP_NULL       =     0,

 FF_CSP_420P       =1U<< 0,
 FF_CSP_422P       =1U<< 1,
 FF_CSP_444P       =1U<< 2,
 FF_CSP_411P       =1U<< 3,
 FF_CSP_410P       =1U<< 4,

 FF_CSP_YUY2       =1U<< 5,
 FF_CSP_UYVY       =1U<< 6,
 FF_CSP_YVYU       =1U<< 7,
 FF_CSP_VYUY       =1U<< 8,

 FF_CSP_ABGR       =1U<< 9,  // [a|b|g|r]
 FF_CSP_RGBA       =1U<<10,  // [r|g|b|a]
 FF_CSP_BGR32      =1U<<11,
 FF_CSP_BGR24      =1U<<12,
 FF_CSP_BGR15      =1U<<13,
 FF_CSP_BGR16      =1U<<14,
 FF_CSP_RGB32      =1U<<15,
 FF_CSP_RGB24      =1U<<16,
 FF_CSP_RGB15      =1U<<17,
 FF_CSP_RGB16      =1U<<18,

 FF_CSP_PAL8       =1U<<19,
 FF_CSP_CLJR       =1U<<20,
 FF_CSP_Y800       =1U<<21,
 FF_CSP_NV12       =1U<<22
};

#define FF_CSPS_NUM 23

#define FF_CSPS_MASK            ((2<<FF_CSPS_NUM)-1)
#define FF_CSPS_MASK_YUV_PLANAR (FF_CSP_420P|FF_CSP_422P|FF_CSP_444P|FF_CSP_411P|FF_CSP_410P)
#define FF_CSPS_MASK_YUV_PACKED (FF_CSP_YUY2|FF_CSP_UYVY|FF_CSP_YVYU|FF_CSP_VYUY)
#define FF_CSPS_MASK_RGB        (FF_CSP_RGBA|FF_CSP_RGB32|FF_CSP_RGB24|FF_CSP_RGB15|FF_CSP_RGB16)
#define FF_CSPS_MASK_BGR        (FF_CSP_ABGR|FF_CSP_BGR32|FF_CSP_BGR24|FF_CSP_BGR15|FF_CSP_BGR16)

#define FF_CSP_FLAGS_VFLIP      (1U<<31)   // flip mask
#define FF_CSP_FLAGS_INTERLACED (1U<<30)
#define FF_CSP_FLAGS_YUV_ADJ    (1U<<29)   // YUV planes are stored consecutively in one memory block
#define FF_CSP_FLAGS_YUV_ORDER  (1U<<28)   // UV ordered chroma planes (not VU as default)
#define FF_CSP_FLAGS_YUV_JPEG   (1U<<27)

#include <stddef.h>
typedef ptrdiff_t stride_t;

//==================================== xvid4 =====================================

#define XVID4_CSP_PLANAR   (1<< 0) /* 4:2:0 planar */
#define XVID4_CSP_I420     (1<< 1) /* 4:2:0 packed(planar win32) */
#define XVID4_CSP_YV12     (1<< 2) /* 4:2:0 packed(planar win32) */
#define XVID4_CSP_YUY2     (1<< 3) /* 4:2:2 packed */
#define XVID4_CSP_UYVY     (1<< 4) /* 4:2:2 packed */
#define XVID4_CSP_YVYU     (1<< 5) /* 4:2:2 packed */
#define XVID4_CSP_BGRA     (1<< 6) /* 32-bit bgra packed */
#define XVID4_CSP_ABGR     (1<< 7) /* 32-bit abgr packed */
#define XVID4_CSP_RGBA     (1<< 8) /* 32-bit rgba packed */
#define XVID4_CSP_BGR      (1<< 9) /* 24-bit bgr packed */
#define XVID4_CSP_RGB555   (1<<10) /* 16-bit rgb555 packed */
#define XVID4_CSP_RGB565   (1<<11) /* 16-bit rgb565 packed */
#define XVID4_CSP_SLICE    (1<<12) /* decoder only: 4:2:0 planar, per slice rendering */
#define XVID4_CSP_INTERNAL (1<<13) /* decoder only: 4:2:0 planar, returns ptrs to internal buffers */
#define XVID4_CSP_NULL     (1<<14) /* decoder only: dont output anything */
#define XVID4_CSP_VFLIP    (1<<31) /* vertical flip mask */

static __inline int csp_xvid4_2ffdshow(int csp)
{
 switch (csp)
  {
   case XVID4_CSP_BGR   :return FF_CSP_RGB24;
   case XVID4_CSP_YV12  :return FF_CSP_420P|FF_CSP_FLAGS_YUV_ADJ;
   case XVID4_CSP_YUY2  :return FF_CSP_YUY2;
   case XVID4_CSP_UYVY  :return FF_CSP_UYVY;
   case XVID4_CSP_I420  :return FF_CSP_420P|FF_CSP_FLAGS_YUV_ADJ|FF_CSP_FLAGS_YUV_ORDER;
   case XVID4_CSP_RGB555:return FF_CSP_RGB15;
   case XVID4_CSP_RGB565:return FF_CSP_RGB16;
   case XVID4_CSP_PLANAR:return FF_CSP_420P;
   case XVID4_CSP_YVYU  :return FF_CSP_YVYU;
   case XVID4_CSP_BGRA  :return FF_CSP_RGB32;
   case XVID4_CSP_ABGR  :return FF_CSP_ABGR;
   case XVID4_CSP_RGBA  :return FF_CSP_RGBA;
   default              :return FF_CSP_NULL;
  }
}

//================================= libavcodec ===================================

enum PixelFormat {
    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_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)
    PIX_FMT_YUV444P,   ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
    PIX_FMT_RGB32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
    PIX_FMT_YUV410P,   ///< Planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
    PIX_FMT_YUV411P,   ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
    PIX_FMT_RGB565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), in cpu endianness
    PIX_FMT_RGB555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
    PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
    PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black
    PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white
    PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
    PIX_FMT_YUVJ420P,  ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
    PIX_FMT_YUVJ422P,  ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
    PIX_FMT_YUVJ444P,  ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
    PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
    PIX_FMT_XVMC_MPEG2_IDCT,
    PIX_FMT_UYVY422,   ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
    PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
    PIX_FMT_BGR32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
    PIX_FMT_BGR565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), in cpu endianness
    PIX_FMT_BGR555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
    PIX_FMT_BGR8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
    PIX_FMT_BGR4,      ///< Packed RGB 1:2:1,  4bpp, (msb)1B 2G 1R(lsb)
    PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
    PIX_FMT_RGB8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
    PIX_FMT_RGB4,      ///< Packed RGB 1:2:1,  4bpp, (msb)2R 3G 3B(lsb)
    PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)2R 3G 3B(lsb)
    PIX_FMT_NV12,      ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
    PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped

    PIX_FMT_RGB32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
    PIX_FMT_BGR32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness

    PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
    PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
    PIX_FMT_YUV440P,   ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
    PIX_FMT_YUVJ440P,  ///< Planar YUV 4:4:0 full scale (jpeg)
    PIX_FMT_YUVA420P,  ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
    PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
};

static __inline int csp_lavc2ffdshow(enum PixelFormat pix_fmt)
{
 switch (pix_fmt)
  {
   case PIX_FMT_YUV420P :return FF_CSP_420P;
   case PIX_FMT_YUVJ420P:return FF_CSP_420P|FF_CSP_FLAGS_YUV_JPEG;
   case PIX_FMT_YUV422P :return FF_CSP_422P;
   case PIX_FMT_YUVJ422P:return FF_CSP_422P|FF_CSP_FLAGS_YUV_JPEG;
   case PIX_FMT_YUV444P :return FF_CSP_444P;
   case PIX_FMT_YUVJ444P:return FF_CSP_444P|FF_CSP_FLAGS_YUV_JPEG;
   case PIX_FMT_YUV411P :return FF_CSP_411P;
   case PIX_FMT_YUV410P :return FF_CSP_410P;
   case PIX_FMT_YUYV422 :return FF_CSP_YUY2;
   case PIX_FMT_UYVY422 :return FF_CSP_UYVY;
   case PIX_FMT_RGB24   :return FF_CSP_RGB24;
   case PIX_FMT_BGR24   :return FF_CSP_BGR24;
   case PIX_FMT_RGB32   :return FF_CSP_RGB32;
   case PIX_FMT_RGB555  :return FF_CSP_RGB15;
   case PIX_FMT_RGB565  :return FF_CSP_RGB16;
   case PIX_FMT_PAL8    :return FF_CSP_PAL8;
   case PIX_FMT_GRAY8   :return FF_CSP_Y800;
   default              :return FF_CSP_NULL;
  }
}
static __inline enum PixelFormat csp_ffdshow2lavc(int pix_fmt)
{
 switch (pix_fmt&FF_CSPS_MASK)
  {
   case FF_CSP_420P:return pix_fmt&FF_CSP_FLAGS_YUV_JPEG?PIX_FMT_YUVJ420P:PIX_FMT_YUV420P;
   case FF_CSP_422P:return pix_fmt&FF_CSP_FLAGS_YUV_JPEG?PIX_FMT_YUVJ422P:PIX_FMT_YUV422P;
   case FF_CSP_444P:return pix_fmt&FF_CSP_FLAGS_YUV_JPEG?PIX_FMT_YUVJ444P:PIX_FMT_YUV444P;
   case FF_CSP_411P:return PIX_FMT_YUV411P;
   case FF_CSP_410P:return PIX_FMT_YUV410P;
   case FF_CSP_YUY2:return PIX_FMT_YUYV422;
   case FF_CSP_UYVY:return PIX_FMT_UYVY422;
   case FF_CSP_RGB24:return PIX_FMT_RGB24;
   case FF_CSP_BGR24:return PIX_FMT_BGR24;
   case FF_CSP_RGB32:return PIX_FMT_RGB32;
   case FF_CSP_RGB15:return PIX_FMT_RGB555;
   case FF_CSP_RGB16:return PIX_FMT_RGB565;
   case FF_CSP_PAL8:return PIX_FMT_PAL8;
   case FF_CSP_Y800:return PIX_FMT_GRAY8;
   default         :return PIX_FMT_NB;
  }
}

//=================================== mplayer ===================================

// RGB/BGR Formats

#define IMGFMT_RGB_MASK 0xFFFFFF00
#define IMGFMT_RGB (('R'<<24)|('G'<<16)|('B'<<8))
#define IMGFMT_RGB1  (IMGFMT_RGB|1)
#define IMGFMT_RGB4  (IMGFMT_RGB|4)
#define IMGFMT_RG4B  (IMGFMT_RGB|4|128) // RGB4 with 1 pixel per byte
#define IMGFMT_RGB8  (IMGFMT_RGB|8)
#define IMGFMT_RGB15 (IMGFMT_RGB|15)
#define IMGFMT_RGB16 (IMGFMT_RGB|16)
#define IMGFMT_RGB24 (IMGFMT_RGB|24)
#define IMGFMT_RGB32 (IMGFMT_RGB|32)

#define IMGFMT_BGR_MASK 0xFFFFFF00
#define IMGFMT_BGR (('B'<<24)|('G'<<16)|('R'<<8))
#define IMGFMT_BGR1 (IMGFMT_BGR|1)
#define IMGFMT_BGR4 (IMGFMT_BGR|4)
#define IMGFMT_BG4B (IMGFMT_BGR|4|128) // BGR4 with 1 pixel per byte
#define IMGFMT_BGR8 (IMGFMT_BGR|8)
#define IMGFMT_BGR15 (IMGFMT_BGR|15)
#define IMGFMT_BGR16 (IMGFMT_BGR|16)
#define IMGFMT_BGR24 (IMGFMT_BGR|24)
#define IMGFMT_BGR32 (IMGFMT_BGR|32)

#define IMGFMT_IS_RGB(fmt) (((fmt)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
#define IMGFMT_IS_BGR(fmt) (((fmt)&IMGFMT_BGR_MASK)==IMGFMT_BGR)

#define IMGFMT_RGB_DEPTH(fmt) ((fmt)&0x3F)
#define IMGFMT_BGR_DEPTH(fmt) ((fmt)&0x3F)

// Planar YUV Formats

#define IMGFMT_YVU9 0x39555659
#define IMGFMT_IF09 0x39304649
#define IMGFMT_YV12 0x32315659
#define IMGFMT_I420 0x30323449
#define IMGFMT_IYUV 0x56555949
#define IMGFMT_CLPL 0x4C504C43
#define IMGFMT_Y800 0x30303859
#define IMGFMT_Y8   0x20203859
#define IMGFMT_NV12 0x3231564E
#define IMGFMT_NV21 0x3132564E

// unofficial Planar Formats, FIXME if official 4CC exists
#define IMGFMT_444P 0x50343434
#define IMGFMT_422P 0x50323234
#define IMGFMT_411P 0x50313134

// Packed YUV Formats

#define IMGFMT_IUYV 0x56595549
#define IMGFMT_IY41 0x31435949
#define IMGFMT_IYU1 0x31555949
#define IMGFMT_IYU2 0x32555949
#define IMGFMT_UYVY 0x59565955
#define IMGFMT_VYUY 0x59555956
#define IMGFMT_UYNV 0x564E5955
#define IMGFMT_cyuv 0x76757963
#define IMGFMT_Y422 0x32323459
#define IMGFMT_YUY2 0x32595559
#define IMGFMT_YUNV 0x564E5559
#define IMGFMT_YVYU 0x55595659
#define IMGFMT_Y41P 0x50313459
#define IMGFMT_Y211 0x31313259
#define IMGFMT_Y41T 0x54313459
#define IMGFMT_Y42T 0x54323459
#define IMGFMT_V422 0x32323456
#define IMGFMT_V655 0x35353656
#define IMGFMT_CLJR 0x524A4C43
#define IMGFMT_YUVP 0x50565559
#define IMGFMT_UYVP 0x50565955

static __inline int csp_mplayercsp2Bpp(int mplayercsp)
{
 // return byte per pixel for the first plane.
 // IMGFMT_NV21,IMGFMT_NV12 are troublesome, because bpp is different in first plane and second plane.
 switch (mplayercsp)
  {
   case IMGFMT_YV12 :return 1;
   case IMGFMT_422P :return 1;
   case IMGFMT_444P :return 1;
   case IMGFMT_411P :return 1;
   case IMGFMT_YVU9 :return 1;

   case IMGFMT_YUY2 :return 2;
   case IMGFMT_UYVY :return 2;
   case IMGFMT_YVYU :return 2;
   case IMGFMT_VYUY :return 2;

   case IMGFMT_RGB32 :return 4;

   case IMGFMT_BGR15:return 2;
   case IMGFMT_BGR16:return 2;
   case IMGFMT_BGR24:return 3;
   case IMGFMT_BGR32:return 4;

   case IMGFMT_RGB15:return 2;
   case IMGFMT_RGB16:return 2;
   case IMGFMT_RGB24:return 3;

   case IMGFMT_Y800 :return 1;
   case IMGFMT_NV12 :return 1;
   case IMGFMT_NV21 :return 1;
   default          :return 1;
  }
}

static __inline int csp_ffdshow2mplayer(int csp)
{
 switch (csp&FF_CSPS_MASK)
  {
   case FF_CSP_420P :return IMGFMT_YV12;
   case FF_CSP_422P :return IMGFMT_422P;
   case FF_CSP_444P :return IMGFMT_444P;
   case FF_CSP_411P :return IMGFMT_411P;
   case FF_CSP_410P :return IMGFMT_YVU9;
/*
   case FF_CSP_YUY2 :return IMGFMT_YVYU;
   case FF_CSP_UYVY :return IMGFMT_VYUY;
   case FF_CSP_YVYU :return IMGFMT_YUY2;
   case FF_CSP_VYUY :return IMGFMT_UYVY;
*/
   case FF_CSP_YUY2 :return IMGFMT_YUY2;
   case FF_CSP_UYVY :return IMGFMT_UYVY;
   case FF_CSP_YVYU :return IMGFMT_YVYU;
   case FF_CSP_VYUY :return IMGFMT_VYUY;

   case FF_CSP_ABGR :return IMGFMT_RGB32;
   case FF_CSP_RGBA :return IMGFMT_RGB32;

   case FF_CSP_RGB15:return IMGFMT_BGR15;
   case FF_CSP_RGB16:return IMGFMT_BGR16;
   case FF_CSP_RGB24:return IMGFMT_BGR24;
   case FF_CSP_RGB32:return IMGFMT_BGR32;

   case FF_CSP_BGR15:return IMGFMT_RGB15;
   case FF_CSP_BGR16:return IMGFMT_RGB16;
   case FF_CSP_BGR24:return IMGFMT_RGB24;
   case FF_CSP_BGR32:return IMGFMT_RGB32;

   case FF_CSP_Y800 :return IMGFMT_Y800;
   case FF_CSP_NV12 :return csp&FF_CSP_FLAGS_YUV_ORDER?IMGFMT_NV12:IMGFMT_NV21;
   default          :return 0;
  }
}

#define SWS_IN_CSPS \
 (                  \
  FF_CSP_420P|      \
  FF_CSP_444P|      \
  FF_CSP_422P|      \
  FF_CSP_411P|      \
  FF_CSP_410P|      \
  FF_CSP_YUY2|      \
  FF_CSP_UYVY|      \
  FF_CSP_YVYU|      \
  FF_CSP_VYUY|      \
  FF_CSP_BGR32|     \
  FF_CSP_BGR24|     \
  FF_CSP_BGR16|     \
  FF_CSP_BGR15|     \
  FF_CSP_RGB32|     \
  FF_CSP_RGB24|     \
  FF_CSP_RGB16|     \
  FF_CSP_RGB15|     \
  FF_CSP_NV12|      \
  FF_CSP_Y800       \
 )
#define SWS_OUT_CSPS \
 (                   \
  FF_CSP_420P|       \
  FF_CSP_444P|       \
  FF_CSP_422P|       \
  FF_CSP_411P|       \
  FF_CSP_410P|       \
  FF_CSP_YUY2|       \
  FF_CSP_UYVY|       \
  FF_CSP_YVYU|       \
  FF_CSP_VYUY|       \
  FF_CSP_RGB32|      \
  FF_CSP_RGB24|      \
  FF_CSP_RGB16|      \
  FF_CSP_RGB15|      \
  FF_CSP_BGR32|      \
  FF_CSP_BGR24|      \
  FF_CSP_BGR16|      \
  FF_CSP_BGR15|      \
  FF_CSP_NV12|       \
  FF_CSP_Y800        \
 )

static __inline int csp_supSWSin(int x)
{
 return (x&FF_CSPS_MASK)&SWS_IN_CSPS;
}
static __inline int csp_supSWSout(int x)
{
 return (x&FF_CSPS_MASK)&SWS_OUT_CSPS;
}

#endif

#if defined(__cplusplus) && !defined(FF_CSP_ONLY)

#ifndef _FFIMGFMTCPP_H_
#define _FFIMGFMTCPP_H_

#include "array_allocator.h"
#include "char_t.h"

struct TcspInfo
{
 int id;
 const char_t *name;
 int Bpp,bpp;
 unsigned int numPlanes;
 unsigned int shiftX[4],shiftY[4];
 unsigned int black[4];
 FOURCC fcc,fcccsp;const GUID *subtype;
 int packedLumaOffset,packedChromaOffset;
};
extern const TcspInfo cspInfos[];
struct TcspInfos :std::vector<const TcspInfo*,array_allocator<const TcspInfo*,FF_CSPS_NUM*2> >
{
private:
 struct TsortFc
  {
  private:
   int csp;
  public:
   TsortFc(int Icsp):csp(Icsp) {}
   bool operator ()(const TcspInfo* csp1,const TcspInfo* csp2);
  };
public:
 void sort(int csp);
};

static __inline const TcspInfo* csp_getInfo(int csp)
{
 switch (csp&(FF_CSPS_MASK|FF_CSP_FLAGS_YUV_ORDER))
  {
   case FF_CSP_420P|FF_CSP_FLAGS_YUV_ORDER:
    {
     extern TcspInfo cspInfoIYUV;
     return &cspInfoIYUV;
    }
   case FF_CSP_NV12|FF_CSP_FLAGS_YUV_ORDER:
    {
     extern TcspInfo cspInfoNV21;
     return &cspInfoNV21;
    }
   default:
    csp&=FF_CSPS_MASK;
    if (csp==0) return NULL;
    int i=0;
    while (csp>>=1)
     i++;
    if (i<=FF_CSPS_NUM)
     return &cspInfos[i];
    else
     return NULL;
  }
}
const TcspInfo* csp_getInfoFcc(FOURCC fcc);

static __inline int csp_isYUVplanar(int x)
{
 return x&FF_CSPS_MASK&FF_CSPS_MASK_YUV_PLANAR;
}
static __inline int csp_isYUVpacked(int x)
{
 return x&FF_CSPS_MASK&FF_CSPS_MASK_YUV_PACKED;
}
static __inline int csp_isYUV(int x)
{
 return csp_isYUVpacked(x)|csp_isYUVplanar(x);
}
static __inline int csp_isRGB_RGB(int x)
{
 return x&FF_CSPS_MASK&FF_CSPS_MASK_RGB;
}
static __inline int csp_isRGB_BGR(int x)
{
 return x&FF_CSPS_MASK&FF_CSPS_MASK_BGR;
}
static __inline int csp_isRGB(int x)
{
 return csp_isRGB_RGB(x)|csp_isRGB_BGR(x);
}
static __inline int csp_isPAL(int x)
{
 return x&FF_CSPS_MASK&FF_CSP_PAL8;
}
static __inline int csp_supXvid(int x)
{
 return (x&FF_CSPS_MASK)&(FF_CSP_RGB24|FF_CSP_420P|FF_CSP_YUY2|FF_CSP_UYVY|FF_CSP_YVYU|FF_CSP_VYUY|FF_CSP_RGB15|FF_CSP_RGB16|FF_CSP_RGB32|FF_CSP_ABGR|FF_CSP_RGBA);
}

bool csp_inFOURCCmask(int x,FOURCC fcc);

extern char_t* csp_getName(const TcspInfo *cspInfo,int csp,char_t *buf,size_t len);
extern char_t* csp_getName(int csp,char_t *buf,size_t len);
extern int csp_bestMatch(int inCSP,int wantedCSPS,int *rank=NULL);

static __inline void csp_yuv_adj_to_plane(int &csp,const TcspInfo *cspInfo,unsigned int dy,unsigned char *data[4],stride_t stride[4])
{
 if (csp_isYUVplanar(csp) && (csp&FF_CSP_FLAGS_YUV_ADJ))
  {
   csp&=~FF_CSP_FLAGS_YUV_ADJ;
   data[2]=data[0]+stride[0]*(dy>>cspInfo->shiftY[0]);stride[1]=stride[0]>>cspInfo->shiftX[1];
   data[1]=data[2]+stride[1]*(dy>>cspInfo->shiftY[1]);stride[2]=stride[0]>>cspInfo->shiftX[2];
  }
}
static __inline void csp_yuv_order(int &csp,unsigned char *data[4],stride_t stride[4])
{
 if (csp_isYUVplanar(csp) && (csp&FF_CSP_FLAGS_YUV_ORDER))
  {
   csp&=~FF_CSP_FLAGS_YUV_ORDER;
   std::swap(data[1],data[2]);
   std::swap(stride[1],stride[2]);
  }
}
static __inline void csp_vflip(int &csp,const TcspInfo *cspInfo,unsigned char *data[],stride_t stride[],unsigned int dy)
{
 if (csp&FF_CSP_FLAGS_VFLIP)
  {
   csp&=~FF_CSP_FLAGS_VFLIP;
   for (unsigned int i=0;i<cspInfo->numPlanes;i++)
    {
     data[i]+=stride[i]*((dy>>cspInfo->shiftY[i])-1);
     stride[i]*=-1;
    }
  }
}

int getBMPcolorspace(const BITMAPINFOHEADER *hdr,const TcspInfos &forcedCsps);

struct TcspFcc
{
 const char_t *name;
 FOURCC fcc;int csp;bool flip;
 bool supEnc;
};
extern const TcspFcc cspFccs[];

#endif

#endif
