714 lines
15 KiB
C
714 lines
15 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* This program is free software ; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*
|
||
|
* $Id: helper_video.c 548 2006-01-08 22:41:57Z picard $
|
||
|
*
|
||
|
* The Core Pocket Media Player
|
||
|
* Copyright (c) 2004-2005 Gabor Kovacs
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
bool_t EqSubtitle(const subtitle* a, const subtitle* b)
|
||
|
{
|
||
|
return a->FourCC == b->FourCC;
|
||
|
}
|
||
|
|
||
|
bool_t EqAudio(const audio* a, const audio* b)
|
||
|
{
|
||
|
return a->Bits == b->Bits &&
|
||
|
a->Channels == b->Channels &&
|
||
|
a->SampleRate == b->SampleRate &&
|
||
|
a->FracBits == b->FracBits &&
|
||
|
a->Flags == b->Flags &&
|
||
|
a->Format == b->Format;
|
||
|
}
|
||
|
|
||
|
bool_t EqFrac(const fraction* a, const fraction* b)
|
||
|
{
|
||
|
if (a->Den == b->Den && a->Num == b->Num)
|
||
|
return 1;
|
||
|
if (!a->Den) return b->Den==0;
|
||
|
if (!b->Den) return 0;
|
||
|
return (int64_t)b->Den * a->Num == (int64_t)a->Den * b->Num;
|
||
|
}
|
||
|
|
||
|
int BitMaskSize(uint32_t Mask)
|
||
|
{
|
||
|
int i;
|
||
|
for (i=0;Mask;++i)
|
||
|
Mask &= Mask - 1;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
int BitMaskPos(uint32_t Mask)
|
||
|
{
|
||
|
int i;
|
||
|
for (i=0;Mask && !(Mask&1);++i)
|
||
|
Mask >>= 1;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
int ScaleRound(int v,int Num,int Den)
|
||
|
{
|
||
|
int64_t i;
|
||
|
if (!Den)
|
||
|
return 0;
|
||
|
i = (int64_t)v * Num;
|
||
|
if (i<0)
|
||
|
i-=Den/2;
|
||
|
else
|
||
|
i+=Den/2;
|
||
|
i/=Den;
|
||
|
return (int)i;
|
||
|
}
|
||
|
|
||
|
void FillColor(uint8_t* Dst,int DstPitch,int x,int y,int Width,int Height,int BPP,int Value)
|
||
|
{
|
||
|
if (Width>0 && Height>0)
|
||
|
{
|
||
|
uint16_t *p16,*p16e;
|
||
|
uint32_t *p32,*p32e;
|
||
|
uint8_t* End;
|
||
|
|
||
|
Dst += y*DstPitch + (x*BPP)/8;
|
||
|
End = Dst + Height * DstPitch;
|
||
|
do
|
||
|
{
|
||
|
switch (BPP)
|
||
|
{
|
||
|
case 1:
|
||
|
Value &= 1;
|
||
|
memset(Dst,Value * 0xFF,Width >> 3);
|
||
|
break;
|
||
|
case 2:
|
||
|
Value &= 3;
|
||
|
memset(Dst,Value * 0x55,Width >> 2);
|
||
|
break;
|
||
|
case 4:
|
||
|
Value &= 15;
|
||
|
memset(Dst,Value * 0x11,Width >> 1);
|
||
|
break;
|
||
|
case 8:
|
||
|
memset(Dst,Value,Width);
|
||
|
break;
|
||
|
case 16:
|
||
|
p16 = (uint16_t*)Dst;
|
||
|
p16e = p16+Width;
|
||
|
for (;p16!=p16e;++p16)
|
||
|
*p16 = (uint16_t)Value;
|
||
|
break;
|
||
|
case 32:
|
||
|
p32 = (uint32_t*)Dst;
|
||
|
p32e = p32+Width;
|
||
|
for (;p32!=p32e;++p32)
|
||
|
*p32 = Value;
|
||
|
break;
|
||
|
}
|
||
|
Dst += DstPitch;
|
||
|
}
|
||
|
while (Dst != End);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool_t EqBlitFX(const blitfx* a, const blitfx* b)
|
||
|
{
|
||
|
return a->Flags == b->Flags &&
|
||
|
a->Contrast == b->Contrast &&
|
||
|
a->Saturation == b->Saturation &&
|
||
|
a->Brightness == b->Brightness &&
|
||
|
a->Direction == b->Direction &&
|
||
|
a->RGBAdjust[0] == b->RGBAdjust[0] &&
|
||
|
a->RGBAdjust[1] == b->RGBAdjust[1] &&
|
||
|
a->RGBAdjust[2] == b->RGBAdjust[2] &&
|
||
|
a->ScaleX == b->ScaleX &&
|
||
|
a->ScaleY == b->ScaleY;
|
||
|
}
|
||
|
|
||
|
int CombineDir(int Src, int Blit, int Dst)
|
||
|
{
|
||
|
//order of transformations
|
||
|
// SrcMirror
|
||
|
// SrcSwap
|
||
|
// BlitSwap
|
||
|
// BlitMirror
|
||
|
// DstSwap
|
||
|
// DstMirror
|
||
|
|
||
|
//should be combined to a single
|
||
|
// Swap
|
||
|
// Mirror
|
||
|
|
||
|
if (Dst & DIR_SWAPXY)
|
||
|
{
|
||
|
if (Blit & DIR_MIRRORLEFTRIGHT)
|
||
|
Dst ^= DIR_MIRRORUPDOWN;
|
||
|
if (Blit & DIR_MIRRORUPDOWN)
|
||
|
Dst ^= DIR_MIRRORLEFTRIGHT;
|
||
|
}
|
||
|
else
|
||
|
Dst ^= Blit & (DIR_MIRRORUPDOWN|DIR_MIRRORLEFTRIGHT);
|
||
|
Dst ^= Blit & DIR_SWAPXY;
|
||
|
Dst ^= Src & DIR_SWAPXY;
|
||
|
if (Dst & DIR_SWAPXY)
|
||
|
{
|
||
|
if (Src & DIR_MIRRORLEFTRIGHT)
|
||
|
Dst ^= DIR_MIRRORUPDOWN;
|
||
|
if (Src & DIR_MIRRORUPDOWN)
|
||
|
Dst ^= DIR_MIRRORLEFTRIGHT;
|
||
|
}
|
||
|
else
|
||
|
Dst ^= Src & (DIR_MIRRORUPDOWN|DIR_MIRRORLEFTRIGHT);
|
||
|
|
||
|
return Dst;
|
||
|
}
|
||
|
|
||
|
int SurfaceRotate(const video* SrcFormat, const video* DstFormat,
|
||
|
const planes Src, planes Dst, int Dir)
|
||
|
{
|
||
|
blitfx FX;
|
||
|
memset(&FX,0,sizeof(FX));
|
||
|
FX.ScaleX = SCALE_ONE;
|
||
|
FX.ScaleY = SCALE_ONE;
|
||
|
FX.Direction = Dir;
|
||
|
return SurfaceCopy(SrcFormat,DstFormat,Src,Dst,&FX);
|
||
|
}
|
||
|
|
||
|
|
||
|
int SurfaceCopy(const video* SrcFormat, const video* DstFormat,
|
||
|
const planes Src, planes Dst, const blitfx* FX)
|
||
|
{
|
||
|
void* Blit;
|
||
|
rect SrcRect;
|
||
|
rect DstRect;
|
||
|
|
||
|
VirtToPhy(NULL,&SrcRect,SrcFormat);
|
||
|
VirtToPhy(NULL,&DstRect,DstFormat);
|
||
|
|
||
|
Blit = BlitCreate(DstFormat,SrcFormat,FX,NULL);
|
||
|
if (!Blit)
|
||
|
return ERR_NOT_SUPPORTED;
|
||
|
|
||
|
BlitAlign(Blit,&DstRect,&SrcRect);
|
||
|
BlitImage(Blit,Dst,*(const constplanes*)Src,NULL,-1,-1);
|
||
|
BlitRelease(Blit);
|
||
|
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
int SurfaceAlloc(planes Ptr, const video* p)
|
||
|
{
|
||
|
int i;
|
||
|
for (i=0;i<MAXPLANES;++i)
|
||
|
Ptr[i] = NULL;
|
||
|
|
||
|
if (p->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444|PF_YUV410))
|
||
|
{
|
||
|
int x,y,s;
|
||
|
PlanarYUV(&p->Pixel,&x,&y,&s);
|
||
|
Ptr[0] = Alloc16(p->Height * p->Pitch);
|
||
|
Ptr[1] = Alloc16((p->Height>>y) * (p->Pitch>>s));
|
||
|
Ptr[2] = Alloc16((p->Height>>y) * (p->Pitch>>s));
|
||
|
if (!Ptr[0] || !Ptr[1] || !Ptr[2])
|
||
|
{
|
||
|
SurfaceFree(Ptr);
|
||
|
return ERR_OUT_OF_MEMORY;
|
||
|
}
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
Ptr[0] = Alloc16(GetImageSize(p));
|
||
|
return Ptr[0] ? ERR_NONE : ERR_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
void SurfaceFree(planes p)
|
||
|
{
|
||
|
int i;
|
||
|
for (i=0;i<MAXPLANES;++i)
|
||
|
{
|
||
|
Free16(p[i]);
|
||
|
p[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int DefaultAspect(int Width,int Height)
|
||
|
{
|
||
|
return ASPECT_ONE; //todo?
|
||
|
}
|
||
|
|
||
|
void DefaultPitch(video* p)
|
||
|
{
|
||
|
p->Pitch = p->Width*GetBPP(&p->Pixel);
|
||
|
if (p->Pixel.Flags & PF_RGB)
|
||
|
p->Pitch = ((p->Pitch+31)>>5)*4; // dword align
|
||
|
else
|
||
|
p->Pitch = (p->Pitch+7)>>3; // byte align
|
||
|
}
|
||
|
|
||
|
void DefaultRGB(pixel* p, int BitCount,
|
||
|
int RBits, int GBits, int BBits,
|
||
|
int RGaps, int GGaps, int BGaps)
|
||
|
{
|
||
|
p->Flags = PF_RGB;
|
||
|
p->BitCount = BitCount;
|
||
|
p->BitMask[0] = ((1<<RBits)-1) << (RGaps+GBits+GGaps+BBits+BGaps);
|
||
|
p->BitMask[1] = ((1<<GBits)-1) << (GGaps+BBits+BGaps);
|
||
|
p->BitMask[2] = ((1<<BBits)-1) << (BGaps);
|
||
|
}
|
||
|
|
||
|
bool_t Compressed(const pixel* Fmt)
|
||
|
{
|
||
|
return (Fmt->Flags & PF_FOURCC) && !AnyYUV(Fmt);
|
||
|
}
|
||
|
|
||
|
bool_t PlanarYUV(const pixel* Fmt, int* x, int* y,int *s)
|
||
|
{
|
||
|
if (PlanarYUV420(Fmt))
|
||
|
{
|
||
|
if (x) *x = 1;
|
||
|
if (y) *y = 1;
|
||
|
if (s)
|
||
|
{
|
||
|
if (Fmt->Flags & PF_FOURCC &&
|
||
|
((Fmt->FourCC == FOURCC_IMC2) || (Fmt->FourCC == FOURCC_IMC4)))
|
||
|
*s = 0; // interleaved uv scanlines
|
||
|
else
|
||
|
*s = 1;
|
||
|
}
|
||
|
return 1;
|
||
|
|
||
|
}
|
||
|
if (PlanarYUV422(Fmt))
|
||
|
{
|
||
|
if (x) *x = 1;
|
||
|
if (s) *s = 1;
|
||
|
if (y) *y = 0;
|
||
|
return 1;
|
||
|
|
||
|
}
|
||
|
if (PlanarYUV444(Fmt))
|
||
|
{
|
||
|
if (x) *x = 0;
|
||
|
if (y) *y = 0;
|
||
|
if (s) *s = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
if (PlanarYUV410(Fmt))
|
||
|
{
|
||
|
if (x) *x = 2;
|
||
|
if (s) *s = 2;
|
||
|
if (y) *y = 2;
|
||
|
return 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (x) *x = 0;
|
||
|
if (y) *y = 0;
|
||
|
if (s) *s = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
typedef struct rgbfourcc
|
||
|
{
|
||
|
uint32_t FourCC;
|
||
|
int BitCount;
|
||
|
uint32_t BitMask[3];
|
||
|
|
||
|
} rgbfourcc;
|
||
|
|
||
|
static const rgbfourcc RGBFourCC[] =
|
||
|
{
|
||
|
{ FOURCC_RGB32, 32, { 0xFF0000, 0xFF00, 0xFF }},
|
||
|
{ FOURCC_RGB24, 24, { 0xFF0000, 0xFF00, 0xFF }},
|
||
|
{ FOURCC_RGB16, 16, { 0xF800, 0x07E0, 0x001F }},
|
||
|
{ FOURCC_RGB15, 16, { 0x7C00, 0x03E0, 0x001F }},
|
||
|
{ FOURCC_BGR32, 32, { 0xFF, 0xFF00, 0xFF0000 }},
|
||
|
{ FOURCC_BGR24, 24, { 0xFF, 0xFF00, 0xFF0000 }},
|
||
|
{ FOURCC_BGR16, 16, { 0x001F, 0x07E0, 0xF800 }},
|
||
|
{ FOURCC_BGR15, 16, { 0x001F, 0x03E0, 0x7C00 }},
|
||
|
{0},
|
||
|
};
|
||
|
|
||
|
uint32_t DefFourCC(const pixel* Fmt)
|
||
|
{
|
||
|
uint32_t FourCC=0;
|
||
|
if (Fmt->Flags & PF_YUV420)
|
||
|
return FOURCC_I420;
|
||
|
if (Fmt->Flags & PF_YUV422)
|
||
|
return FOURCC_YV16;
|
||
|
if (Fmt->Flags & PF_YUV410)
|
||
|
return FOURCC_YUV9;
|
||
|
|
||
|
if (Fmt->Flags & PF_FOURCC)
|
||
|
{
|
||
|
FourCC = Fmt->FourCC;
|
||
|
if (FourCC == FOURCC_YVU9)
|
||
|
FourCC = FOURCC_YUV9;
|
||
|
if (FourCC == FOURCC_IYUV || FourCC == FOURCC_YV12)
|
||
|
FourCC = FOURCC_I420;
|
||
|
if (FourCC == FOURCC_YUNV || FourCC == FOURCC_V422 || FourCC == FOURCC_YUYV)
|
||
|
FourCC = FOURCC_YUY2;
|
||
|
if (FourCC == FOURCC_Y422 || FourCC == FOURCC_UYNV)
|
||
|
FourCC = FOURCC_UYVY;
|
||
|
}
|
||
|
else
|
||
|
if (Fmt->Flags & PF_RGB)
|
||
|
{
|
||
|
const rgbfourcc *i;
|
||
|
for (i=RGBFourCC;i->FourCC;++i)
|
||
|
if (i->BitCount == Fmt->BitCount &&
|
||
|
i->BitMask[0] == Fmt->BitMask[0] &&
|
||
|
i->BitMask[1] == Fmt->BitMask[1] &&
|
||
|
i->BitMask[2] == Fmt->BitMask[2])
|
||
|
{
|
||
|
FourCC = i->FourCC;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return FourCC;
|
||
|
}
|
||
|
|
||
|
bool_t PlanarYUV420(const pixel* Fmt)
|
||
|
{
|
||
|
if (Fmt->Flags & PF_YUV420)
|
||
|
return 1;
|
||
|
|
||
|
return (Fmt->Flags & PF_FOURCC) &&
|
||
|
((Fmt->FourCC == FOURCC_YV12) ||
|
||
|
(Fmt->FourCC == FOURCC_IYUV) ||
|
||
|
(Fmt->FourCC == FOURCC_I420) ||
|
||
|
(Fmt->FourCC == FOURCC_IMC2) ||
|
||
|
(Fmt->FourCC == FOURCC_IMC4));
|
||
|
}
|
||
|
|
||
|
bool_t PlanarYUV410(const pixel* Fmt)
|
||
|
{
|
||
|
if (Fmt->Flags & PF_YUV410)
|
||
|
return 1;
|
||
|
|
||
|
return (Fmt->Flags & PF_FOURCC) &&
|
||
|
((Fmt->FourCC == FOURCC_YVU9) ||
|
||
|
(Fmt->FourCC == FOURCC_YUV9));
|
||
|
}
|
||
|
|
||
|
bool_t PlanarYUV422(const pixel* Fmt)
|
||
|
{
|
||
|
if (Fmt->Flags & PF_YUV422)
|
||
|
return 1;
|
||
|
|
||
|
return (Fmt->Flags & PF_FOURCC) && (Fmt->FourCC == FOURCC_YV16);
|
||
|
}
|
||
|
|
||
|
bool_t PlanarYUV444(const pixel* Fmt)
|
||
|
{
|
||
|
return (Fmt->Flags & PF_YUV444) != 0;
|
||
|
}
|
||
|
|
||
|
bool_t PackedYUV(const pixel* Fmt)
|
||
|
{
|
||
|
return (Fmt->Flags & PF_FOURCC) &&
|
||
|
|
||
|
((Fmt->FourCC == FOURCC_YUY2) ||
|
||
|
(Fmt->FourCC == FOURCC_YUNV) ||
|
||
|
(Fmt->FourCC == FOURCC_V422) ||
|
||
|
(Fmt->FourCC == FOURCC_YUYV) ||
|
||
|
(Fmt->FourCC == FOURCC_VYUY) ||
|
||
|
(Fmt->FourCC == FOURCC_UYVY) ||
|
||
|
(Fmt->FourCC == FOURCC_Y422) ||
|
||
|
(Fmt->FourCC == FOURCC_YVYU) ||
|
||
|
(Fmt->FourCC == FOURCC_UYNV));
|
||
|
}
|
||
|
|
||
|
bool_t AnyYUV(const pixel* Fmt)
|
||
|
{
|
||
|
return PlanarYUV420(Fmt) ||
|
||
|
PlanarYUV410(Fmt) ||
|
||
|
PlanarYUV422(Fmt) ||
|
||
|
PlanarYUV444(Fmt) ||
|
||
|
PackedYUV(Fmt);
|
||
|
}
|
||
|
|
||
|
uint32_t RGBToFormat(rgbval_t RGB, const pixel* Fmt)
|
||
|
{
|
||
|
uint32_t v;
|
||
|
int R,G,B;
|
||
|
int Y,U,V;
|
||
|
int Pos[3];
|
||
|
|
||
|
R = (INT32LE(RGB) >> 0) & 255;
|
||
|
G = (INT32LE(RGB) >> 8) & 255;
|
||
|
B = (INT32LE(RGB) >> 16) & 255;
|
||
|
|
||
|
if (AnyYUV(Fmt))
|
||
|
{
|
||
|
Y = ((2105 * R) + (4128 * G) + (802 * B))/0x2000 + 16;
|
||
|
V = ((3596 * R) - (3015 * G) - (582 * B))/0x2000 + 128;
|
||
|
U = (-(1212 * R) - (2384 * G) + (3596 * B))/0x2000 + 128;
|
||
|
|
||
|
if (Fmt->Flags & PF_INVERTED)
|
||
|
{
|
||
|
Y ^= 255;
|
||
|
U ^= 255;
|
||
|
V ^= 255;
|
||
|
}
|
||
|
v = (Fmt->BitMask[0] / 255) * Y;
|
||
|
v += (Fmt->BitMask[1] / 255) * U;
|
||
|
v += (Fmt->BitMask[2] / 255) * V;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (Fmt->Flags & PF_INVERTED)
|
||
|
{
|
||
|
R ^= 255;
|
||
|
G ^= 255;
|
||
|
B ^= 255;
|
||
|
}
|
||
|
|
||
|
Pos[0] = BitMaskPos(Fmt->BitMask[0]) + BitMaskSize(Fmt->BitMask[0]);
|
||
|
Pos[1] = BitMaskPos(Fmt->BitMask[1]) + BitMaskSize(Fmt->BitMask[1]);
|
||
|
Pos[2] = BitMaskPos(Fmt->BitMask[2]) + BitMaskSize(Fmt->BitMask[2]);
|
||
|
|
||
|
v = ((R << Pos[0]) & (Fmt->BitMask[0] << 8)) |
|
||
|
((G << Pos[1]) & (Fmt->BitMask[1] << 8)) |
|
||
|
((B << Pos[2]) & (Fmt->BitMask[2] << 8));
|
||
|
v >>= 8;
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
void FillInfo(pixel* Fmt)
|
||
|
{
|
||
|
Fmt->BitCount = GetBPP(Fmt);
|
||
|
if (PlanarYUV(Fmt,NULL,NULL,NULL))
|
||
|
{
|
||
|
if (Fmt->Flags & (PF_YUV420|PF_YUV422|PF_YUV444|PF_YUV410))
|
||
|
{
|
||
|
Fmt->BitMask[0] = 0x000000FF;
|
||
|
Fmt->BitMask[1] = 0x0000FF00;
|
||
|
Fmt->BitMask[2] = 0x00FF0000;
|
||
|
}
|
||
|
else
|
||
|
switch (Fmt->FourCC)
|
||
|
{
|
||
|
case FOURCC_IMC4:
|
||
|
case FOURCC_I420:
|
||
|
case FOURCC_IYUV:
|
||
|
case FOURCC_YUV9:
|
||
|
Fmt->BitMask[0] = 0x000000FF;
|
||
|
Fmt->BitMask[1] = 0x0000FF00;
|
||
|
Fmt->BitMask[2] = 0x00FF0000;
|
||
|
break;
|
||
|
case FOURCC_IMC2:
|
||
|
case FOURCC_YV16:
|
||
|
case FOURCC_YV12:
|
||
|
case FOURCC_YVU9:
|
||
|
Fmt->BitMask[0] = 0x000000FF;
|
||
|
Fmt->BitMask[1] = 0x00FF0000;
|
||
|
Fmt->BitMask[2] = 0x0000FF00;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (PackedYUV(Fmt))
|
||
|
switch (Fmt->FourCC)
|
||
|
{
|
||
|
case FOURCC_YUY2:
|
||
|
case FOURCC_YUNV:
|
||
|
case FOURCC_V422:
|
||
|
case FOURCC_YUYV:
|
||
|
Fmt->BitMask[0] = 0x00FF00FF;
|
||
|
Fmt->BitMask[1] = 0x0000FF00;
|
||
|
Fmt->BitMask[2] = 0xFF000000;
|
||
|
break;
|
||
|
case FOURCC_YVYU:
|
||
|
Fmt->BitMask[0] = 0x00FF00FF;
|
||
|
Fmt->BitMask[1] = 0xFF000000;
|
||
|
Fmt->BitMask[2] = 0x0000FF00;
|
||
|
break;
|
||
|
case FOURCC_UYVY:
|
||
|
case FOURCC_Y422:
|
||
|
case FOURCC_UYNV:
|
||
|
Fmt->BitMask[0] = 0xFF00FF00;
|
||
|
Fmt->BitMask[1] = 0x000000FF;
|
||
|
Fmt->BitMask[2] = 0x00FF0000;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int GetImageSize(const video* p)
|
||
|
{
|
||
|
int Size = p->Pitch * p->Height;
|
||
|
if (PlanarYUV420(&p->Pixel))
|
||
|
Size = (Size*3)/2; //1:0.25:0.25
|
||
|
else
|
||
|
if (PlanarYUV422(&p->Pixel))
|
||
|
Size *= 2; //1:0.5:0.5
|
||
|
else
|
||
|
if (PlanarYUV444(&p->Pixel))
|
||
|
Size *= 3; //1:1:1
|
||
|
return Size;
|
||
|
}
|
||
|
|
||
|
int GetBPP(const pixel* Fmt)
|
||
|
{
|
||
|
if (Fmt->Flags & (PF_RGB | PF_PALETTE))
|
||
|
return Fmt->BitCount;
|
||
|
if (PlanarYUV(Fmt,NULL,NULL,NULL))
|
||
|
return 8;
|
||
|
if (PackedYUV(Fmt))
|
||
|
return 16;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool_t EqPoint(const point* a, const point* b)
|
||
|
{
|
||
|
return a->x==b->x && a->y==b->y;
|
||
|
}
|
||
|
|
||
|
bool_t EqRect(const rect* a, const rect* b)
|
||
|
{
|
||
|
return a->x==b->x && a->y==b->y && a->Width==b->Width && a->Height==b->Height;
|
||
|
}
|
||
|
|
||
|
bool_t EqPixel(const pixel* a, const pixel* b)
|
||
|
{
|
||
|
if (a->Flags != b->Flags)
|
||
|
return 0;
|
||
|
|
||
|
if ((a->Flags & PF_PALETTE) &&
|
||
|
a->BitCount != b->BitCount)
|
||
|
return 0;
|
||
|
|
||
|
if ((a->Flags & PF_RGB) &&
|
||
|
(a->BitCount != b->BitCount ||
|
||
|
a->BitMask[0] != b->BitMask[0] ||
|
||
|
a->BitMask[1] != b->BitMask[1] ||
|
||
|
a->BitMask[2] != b->BitMask[2]))
|
||
|
return 0;
|
||
|
|
||
|
if ((a->Flags & PF_FOURCC) && a->FourCC != b->FourCC)
|
||
|
return 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bool_t EqVideo(const video* a, const video* b)
|
||
|
{
|
||
|
// no direction check here!
|
||
|
return a->Width == b->Width &&
|
||
|
a->Height == b->Height &&
|
||
|
a->Pitch == b->Pitch &&
|
||
|
EqPixel(&a->Pixel,&b->Pixel);
|
||
|
}
|
||
|
|
||
|
void ClipRectPhy(rect* Physical, const video* p)
|
||
|
{
|
||
|
if (Physical->x < 0)
|
||
|
{
|
||
|
Physical->Width += Physical->x;
|
||
|
Physical->x = 0;
|
||
|
}
|
||
|
if (Physical->y < 0)
|
||
|
{
|
||
|
Physical->Height += Physical->y;
|
||
|
Physical->y = 0;
|
||
|
}
|
||
|
if (Physical->x + Physical->Width > p->Width)
|
||
|
{
|
||
|
Physical->Width = p->Width - Physical->x;
|
||
|
if (Physical->Width < 0)
|
||
|
{
|
||
|
Physical->Width = 0;
|
||
|
Physical->x = 0;
|
||
|
}
|
||
|
}
|
||
|
if (Physical->y + Physical->Height > p->Height)
|
||
|
{
|
||
|
Physical->Height = p->Height - Physical->y;
|
||
|
if (Physical->Height < 0)
|
||
|
{
|
||
|
Physical->Height = 0;
|
||
|
Physical->y = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void VirtToPhy(const rect* Virtual, rect* Physical, const video* p)
|
||
|
{
|
||
|
if (Virtual)
|
||
|
{
|
||
|
*Physical = *Virtual;
|
||
|
|
||
|
if (p->Pixel.Flags & PF_PIXELDOUBLE)
|
||
|
{
|
||
|
Physical->x >>= 1;
|
||
|
Physical->y >>= 1;
|
||
|
Physical->Width >>= 1;
|
||
|
Physical->Height >>= 1;
|
||
|
}
|
||
|
|
||
|
if (p->Direction & DIR_SWAPXY)
|
||
|
SwapRect(Physical);
|
||
|
|
||
|
if (p->Direction & DIR_MIRRORLEFTRIGHT)
|
||
|
Physical->x = p->Width - Physical->x - Physical->Width;
|
||
|
|
||
|
if (p->Direction & DIR_MIRRORUPDOWN)
|
||
|
Physical->y = p->Height - Physical->y - Physical->Height;
|
||
|
|
||
|
ClipRectPhy(Physical,p);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Physical->x = 0;
|
||
|
Physical->y = 0;
|
||
|
Physical->Width = p->Width;
|
||
|
Physical->Height = p->Height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PhyToVirt(const rect* Physical, rect* Virtual, const video* p)
|
||
|
{
|
||
|
if (Physical)
|
||
|
*Virtual = *Physical;
|
||
|
else
|
||
|
{
|
||
|
Virtual->x = 0;
|
||
|
Virtual->y = 0;
|
||
|
Virtual->Width = p->Width;
|
||
|
Virtual->Height = p->Height;
|
||
|
}
|
||
|
|
||
|
if (p->Direction & DIR_MIRRORLEFTRIGHT)
|
||
|
Virtual->x = p->Width - Virtual->x - Virtual->Width;
|
||
|
|
||
|
if (p->Direction & DIR_MIRRORUPDOWN)
|
||
|
Virtual->y = p->Height - Virtual->y - Virtual->Height;
|
||
|
|
||
|
if (p->Direction & DIR_SWAPXY)
|
||
|
SwapRect(Virtual);
|
||
|
|
||
|
if (p->Pixel.Flags & PF_PIXELDOUBLE)
|
||
|
{
|
||
|
Virtual->x <<= 1;
|
||
|
Virtual->y <<= 1;
|
||
|
Virtual->Width <<= 1;
|
||
|
Virtual->Height <<= 1;
|
||
|
}
|
||
|
}
|
||
|
|