⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blit_soft.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
 *
 * 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: blit_soft.c 607 2006-01-22 20:58:29Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"
#include "../dyncode/dyncode.h"
#include "../cpu/cpu.h"
#include "blit_soft.h"

//#define BLITTEST

/*
TV range:
+16  (219)
+128 (224)
+128 (224)

PC range:
+0   (255)
+128 (255)
+128 (255)

ranges:
R,G,B,Y [0..1]
Cb,Cr   [-0.5..0.5]

Y' = Kr * R' + (1 - Kr - Kb) * G' + Kb * B'
Cb = 0.5 * (B' - Y') / (1 - Kb)
Cr = 0.5 * (R' - Y') / (1 - Kr)

Kb = 0.114
Kr = 0.299

ITU-R BT 601
    Y'= 0.299   *R' + 0.587   *G' + 0.114   *B'
    Cb=-0.168736*R' - 0.331264*G' + 0.5     *B'
    Cr= 0.5     *R' - 0.418688*G' - 0.081312*B'

    R'= Y'            + 1.403*Cr
    G'= Y' - 0.344*Cb - 0.714*Cr
    B'= Y' + 1.773*Cb 

Kb = 0.0722
Kr = 0.2126

ITU-R BT 709
    Y'= 0.2215*R' + 0.7154*G' + 0.0721*B'
    Cb=-0.1145*R' - 0.3855*G' + 0.5000*B'
    Cr= 0.5016*R' - 0.4556*G' - 0.0459*B'

    R'= Y'             + 1.5701*Cr
    G'= Y' - 0.1870*Cb - 0.4664*Cr
    B'= Y' - 1.8556*Cb 
*/

#define CM(i) ((int16_t)((i)*8192))

#if defined(_M_IX86) && !defined(TARGET_SYMBIAN)

static const int16_t YUVToRGB[4][8] =
{
	// TV range BT-601
	{ CM(1.164),-16,CM(1.596),CM(-0.813),-128,CM(2.017),CM(-0.392),-128 },
	// TV range BT-709
	{ CM(1.164),-16,CM(1.786),CM(-0.530),-128,CM(2.111),CM(-0.213),-128 },
	// PC range BT-601
	{ CM(1),0,CM(1.402),CM(-0.71414),-128,CM(1.772),CM(-0.34414),-128 },
	// PC range BT-709
	{ CM(1),0,CM(1.5701),CM(-0.4664),-128,CM(1.8556),CM(-0.1870),-128 },
};

static const int16_t* GetYUVToRGB(const pixel* Src)
{
	int i = 0;
	if (Src->Flags & PF_YUV_BT709)
		i += 1;
	if (Src->Flags & PF_YUV_PC)
		i += 2;

	return YUVToRGB[i];
}

#endif

#define SAT(Value) (Value < 0 ? 0: (Value > 255 ? 255: Value))

static const rgbval_t Gray1[2] = { 
	CRGB(0,0,0),CRGB(255,255,255)
};
static const rgbval_t Gray2[4] = { 
	CRGB(0,0,0),CRGB(85,85,85),CRGB(170,170,170),CRGB(255,255,255) 
};
static const rgbval_t Gray4[16] = {
	CRGB(0,0,0),CRGB(17,17,17),CRGB(34,34,34),CRGB(51,51,51),
	CRGB(68,68,68),CRGB(85,85,85),CRGB(102,102,102),CRGB(119,119,119),
	CRGB(136,136,136),CRGB(153,153,153),CRGB(170,170,170),CRGB(187,187,187),
	CRGB(204,204,204),CRGB(221,221,221),CRGB(238,238,238),CRGB(255,255,255)
};

#if defined(_M_IX86) && !defined(TARGET_SYMBIAN)

#define DECLARE_BLITMMX(name) \
extern void STDCALL name##_mmx(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast); \
extern void STDCALL name##_mmx2(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast); \
extern void STDCALL name##_3dnow(blit_soft* This, uint8_t** DstPtr,uint8_t** SrcPtr,int DstPitch,int SrcPitch,int Width,int Height,uintptr_t Src2SrcLast);

DECLARE_BLITMMX(blit_i420_i420)
DECLARE_BLITMMX(blit_i420_yuy2)
DECLARE_BLITMMX(blit_i420_rgb32)
DECLARE_BLITMMX(blit_i420_rgb24)
DECLARE_BLITMMX(blit_i420_bgr32)
DECLARE_BLITMMX(blit_i420_bgr24)
DECLARE_BLITMMX(blit_rgb32_rgb32)
DECLARE_BLITMMX(blit_rgb24_rgb24)
DECLARE_BLITMMX(blit_rgb16_rgb16)

typedef struct blitmmx
{
	uint32_t In;
	uint32_t Out;
	blitsoftentry Func[3];

} blitmmx;

static const blitmmx BlitMMX[] = 
{
	{ FOURCC_I420, FOURCC_I420, { blit_i420_i420_mmx, blit_i420_i420_mmx2, blit_i420_i420_3dnow }},
	{ FOURCC_I420, FOURCC_YUY2, { blit_i420_yuy2_mmx, blit_i420_yuy2_mmx2, blit_i420_yuy2_3dnow }},
	{ FOURCC_I420, FOURCC_RGB32,{ blit_i420_rgb32_mmx,blit_i420_rgb32_mmx2,blit_i420_rgb32_3dnow }},
	{ FOURCC_I420, FOURCC_RGB24,{ blit_i420_rgb24_mmx,blit_i420_rgb24_mmx2,blit_i420_rgb24_3dnow }},
	{ FOURCC_I420, FOURCC_BGR32,{ blit_i420_bgr32_mmx,blit_i420_bgr32_mmx2,blit_i420_bgr32_3dnow }},
	{ FOURCC_I420, FOURCC_BGR24,{ blit_i420_bgr24_mmx,blit_i420_bgr24_mmx2,blit_i420_bgr24_3dnow }},
	{ FOURCC_RGB32,FOURCC_RGB32,{ blit_rgb32_rgb32_mmx,blit_rgb32_rgb32_mmx2,blit_rgb32_rgb32_3dnow }},
	{ FOURCC_RGB24,FOURCC_RGB24,{ blit_rgb24_rgb24_mmx,blit_rgb24_rgb24_mmx2,blit_rgb24_rgb24_3dnow }},
	{ FOURCC_RGB16,FOURCC_RGB16,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
	{ FOURCC_RGB15,FOURCC_RGB15,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
	{ FOURCC_BGR32,FOURCC_BGR32,{ blit_rgb32_rgb32_mmx,blit_rgb32_rgb32_mmx2,blit_rgb32_rgb32_3dnow }},
	{ FOURCC_BGR24,FOURCC_BGR24,{ blit_rgb24_rgb24_mmx,blit_rgb24_rgb24_mmx2,blit_rgb24_rgb24_3dnow }},
	{ FOURCC_BGR16,FOURCC_BGR16,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
	{ FOURCC_BGR15,FOURCC_BGR15,{ blit_rgb16_rgb16_mmx,blit_rgb16_rgb16_mmx2,blit_rgb16_rgb16_3dnow }},
	{0},
};

#endif

typedef struct blitpack
{
	blitfx FX;
	video Dst;
	video Src;
	rect DstRect;
	rect SrcRect;
	blit_soft Code[2];
	bool_t SafeBorder;
	int RScaleX;
	int RScaleY;
	struct blitpack* Next;

} blitpack;

static NOINLINE void FreeBlit(blit_soft* p)
{
	CodeDone(&p->Code);
	free(p->LookUp_Data);
	p->LookUp_Data = NULL;
}

static INLINE struct blitpack* _BlitAlloc()
{
	blitpack* p = (blitpack*) malloc(sizeof(blitpack));
	if (!p) return NULL;

	memset(p,0,sizeof(blitpack));
	CodeInit(&p->Code[0].Code);
	CodeInit(&p->Code[1].Code);
	return p;
}

static INLINE void _BlitFree(struct blitpack* p)
{
	FreeBlit(&p->Code[0]);
	FreeBlit(&p->Code[1]);
	free(p);
}

#ifdef CONFIG_CONTEXT

void Blit_Init()
{
}

void Blit_Done()
{
	blitpack* p;
	while ((p = Context()->Blit)!=NULL)
	{
		Context()->Blit = p->Next;
		_BlitFree(p);
	}
}

static INLINE void BlitFree(struct blitpack* p)
{
	p->Next = Context()->Blit;
	Context()->Blit = p;
}

static INLINE struct blitpack* BlitAlloc()
{
	blitpack* p = Context()->Blit;
	if (p)
		Context()->Blit = p->Next;
	else
		p = _BlitAlloc();
	return p;
}

#else
#define BlitAlloc _BlitAlloc
#define BlitFree _BlitFree
#endif

static const rgb* DefaultPal(const pixel* Format)
{
	if (Format->Flags & PF_PALETTE)
	{
		if (!Format->Palette)
			switch (Format->BitCount)
			{
			case 1: return (const rgb*)Gray1;
			case 2: return (const rgb*)Gray2;
			case 4: return (const rgb*)Gray4;
			}
		return Format->Palette;
	}
	return NULL;
}

static int CalcScale(int v, int Min, int Max)
{
	if (v > Max) v = Max;
	if (v < Min) v = Min;
	return v;
}

static int CalcRScale(int v, int Gray)
{
	if (v<=0) return 16;

	v = (16*1024 << 16) / v;

	if (Gray) // only 100% and 200% scale
		return v > 12288 ? 16:8;

	//align to 100%
	if (v > 16834-1024 && v < 16384+1024) 
		v = 16384;
	//align to 200%
	if (v > 8192-1024 && v < 8192+1024) 
		v = 8192;
	//align to 50%
	if (v > 32768-2048 && v < 32768+2048) 
		v = 32768;

#if defined(SH3)
	if (v < 12288)
		return 8;
	return 16;
//	if (v<1024) v=1024;
//	return ((v+1024) >> 11) << 1;
#else
	if (v<512) v=512;
	return (v+512) >> 10;
#endif
}

static NOINLINE bool_t EnlargeIfNeeded(int* v,int Align,int Side,int Limit)
{
	int Needed = Align - (*v & (Align-1));
	if (Needed < Align && Needed <= (Limit-Side))
	{
		*v += Needed;
		return 1;
	}
	return 0;
}

void BlitAlign(blitpack* p, rect* DstRect, rect* SrcRect)
{
	int i;
	int ShrinkX,ShrinkY;
	int SrcRight;
	int SrcBottom;
	int SrcAdjWidth,SrcAdjHeight;
	int RScaleX,RScaleY;
	blit_soft* Code;

	if (!p) return;

	RScaleX = p->RScaleX;
	RScaleY = p->RScaleY;
	Code = &p->Code[0];

	p->SafeBorder = 0;

	if (Code->ArithStretch && (RScaleX != 16) && (RScaleX != 32))
	{
		//avoid bilinear scale overrun (shrink source)

		if ((p->Src.Pixel.Flags & PF_SAFEBORDER) && Code->DstAlignSize > 2)
			p->SafeBorder = 1; // build a one pixel border before blitting on right and bottom side
		else
		{
			//only horizontal bilinear filtering is supported (arm_stretch)
			if (SrcRect->Width>2) 
				SrcRect->Width -= 2;
		}
	}

	// convert source to destination space
	if (p->FX.Direction & DIR_SWAPXY)
	{
		SwapInt(&RScaleX,&RScaleY);
		SwapRect(SrcRect);
	}

	SrcRight = SrcRect->x + SrcRect->Width;
	SrcBottom = SrcRect->y + SrcRect->Height;

	SrcAdjWidth = SrcRect->Width * 16 / RScaleX;
	SrcAdjHeight = SrcRect->Height * 16 / RScaleY;

	if (p->FX.Flags & BLITFX_ENLARGEIFNEEDED)
	{
		SrcRight = p->Src.Width;
		SrcBottom = p->Src.Height;
		if (p->FX.Direction & DIR_SWAPXY)
			SwapInt(&SrcRight,&SrcBottom);

		if (p->Src.Pixel.Flags & PF_SAFEBORDER)
		{
			SrcRight += 16;
			SrcBottom += 16;
		}

		if (EnlargeIfNeeded(&SrcAdjWidth,Code->DstAlignSize,SrcRect->x+SrcRect->Width,SrcRight))
			SrcRect->Width = -1; // need calc
		if (EnlargeIfNeeded(&SrcAdjHeight,Code->DstAlignSize,SrcRect->y+SrcRect->Height,SrcBottom))
			SrcRect->Height = -1; // need calc
	}

	ShrinkX = DstRect->Width - SrcAdjWidth;
	if (ShrinkX>=0) //shrink destination?
	{
		ShrinkX >>= 1;
		DstRect->x += ShrinkX;
		DstRect->Width = SrcAdjWidth;
	}
	else //adjust source position
	{
		ShrinkX = 0;
		SrcRect->x += (SrcAdjWidth - DstRect->Width) * RScaleX >> 5;
		SrcRect->Width = -1; // need calc
	}
	
	ShrinkY = DstRect->Height - SrcAdjHeight;
	if (ShrinkY>=0) //shrink Dst?
	{
		ShrinkY >>= 1;
		DstRect->y += ShrinkY;
		DstRect->Height = SrcAdjHeight;
	}
	else //adjust source position
	{
		ShrinkY = 0;
		SrcRect->y += (SrcAdjHeight - DstRect->Height) * RScaleY >> 5;
		SrcRect->Height = -1; // need calc
	}

	i = DstRect->Width & (Code->DstAlignSize-1); 
	DstRect->Width -= i; 
	i >>= 1;
	ShrinkX += i;
	DstRect->x += i;

	i = DstRect->Height & (Code->DstAlignSize-1);
	DstRect->Height -= i;
	i >>= 1;
	ShrinkY += i;
	DstRect->y += i;

	i = DstRect->x & (Code->DstAlignPos-1);
	if (i && ShrinkX < i)
	{
		DstRect->Width -= Code->DstAlignPos - i;
		DstRect->Width &= ~(Code->DstAlignSize-1); 
		DstRect->x += Code->DstAlignPos - i;
	}
	else
		DstRect->x -= i;

	i = DstRect->y & (Code->DstAlignPos-1);
	if (i && ShrinkY < i)
	{
		DstRect->Height -= Code->DstAlignPos - i;
		DstRect->Height &= ~(Code->DstAlignSize-1);
		DstRect->y += Code->DstAlignPos - i;
	}
	else
		DstRect->y -= i;

	SrcRect->x &= ~(Code->SrcAlignPos-1);
	SrcRect->y &= ~(Code->SrcAlignPos-1);

	// convert source back to it's space (if needed)
	if (SrcRect->Width < 0)
		SrcRect->Width = (DstRect->Width * RScaleX / 16 + 1) & ~1;
	if (SrcRect->Height < 0)
		SrcRect->Height = (DstRect->Height * RScaleY / 16 + 1) & ~1;

	if (SrcRect->x + SrcRect->Width > SrcRight)
		SrcRect->Width = SrcRight - SrcRect->x;

	if (SrcRect->y + SrcRect->Height > SrcBottom)
		SrcRect->Height = SrcBottom - SrcRect->y;

	if (p->FX.Direction & DIR_SWAPXY)
		SwapRect(SrcRect);

	p->DstRect = *DstRect;
	p->SrcRect = *SrcRect;
}

static NOINLINE void CodeRelease(blit_soft* p)
{
	//todo... better palette handling
	if (p->Dst.Palette)
		memset(&p->Dst,0,sizeof(p->Dst));
	if (p->Src.Palette)
		memset(&p->Src,0,sizeof(p->Src));
}

void BlitRelease(blitpack* p)
{
	if (p)
	{
		CodeRelease(&p->Code[0]);
		CodeRelease(&p->Code[1]);
		BlitFree(p);
	}
}

int AnyAlign(rect* DstRect, rect* SrcRect, const blitfx* FX, 
			  int DstAlignSize, int DstAlignPos,
			  int MinScale, int MaxScale)
{
	int i,ShrinkX,ShrinkY;
	int ScaleX,ScaleY;
	int SrcRight;
	int SrcBottom;
	int SrcAdjWidth,SrcAdjHeight;

	if (!DstRect || !SrcRect || !FX)
		return ERR_INVALID_PARAM;

	ScaleX = CalcScale(FX->ScaleX,MinScale,MaxScale);
	ScaleY = CalcScale(FX->ScaleY,MinScale,MaxScale);
	SrcRight = SrcRect->x + SrcRect->Width;
	SrcBottom = SrcRect->y + SrcRect->Height;

	// convert source to destination space
	if (FX->Direction & DIR_SWAPXY)
	{
		SwapInt(&ScaleX,&ScaleY);
		SwapRect(SrcRect);
	}

	SrcAdjWidth = (SrcRect->Width * ScaleX + 32768) >> 16;
	SrcAdjHeight = (SrcRect->Height * ScaleY + 32768) >> 16;

	ShrinkX = DstRect->Width - SrcAdjWidth;
	if (ShrinkX>0) //shrink destination?
	{
		ShrinkX >>= 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -