📄 softidct.c
字号:
return ERR_NOT_SUPPORTED;
if (Mode==0 && (p->Mode & IDCTMODE_QPEL))
{
p->IDCT.MComp8x8 = p->QPELMComp8x8;
p->IDCT.MComp16x16 = p->QPELMComp16x16;
}
else
{
p->IDCT.MComp8x8 = (idctmcomp) SoftMComp8x8;
p->IDCT.MComp16x16 = (idctmcomp) SoftMComp16x16;
}
#if defined(CONFIG_IDCT_LOWRES)
if (p->Shift == 1)
{
p->IDCT.Process = ProcessHalf[Mode];
p->IDCT.Copy16x16 = Copy16x16Half[Mode];
p->IDCT.Intra8x8 = (idctintra)Intra8x8Half;
}
else
if (p->Shift == 2)
{
p->IDCT.Process = ProcessQuarter[Mode];
p->IDCT.Intra8x8 = (idctintra)Intra8x8Quarter;
p->IDCT.Copy16x16 = NULL;
}
else
#endif
#ifdef CONFIG_IDCT_SWAP
if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
{
p->IDCT.Process = ProcessSwap[Mode];
p->IDCT.Copy16x16 = Copy16x16Swap[Mode];
p->IDCT.Intra8x8 = p->Intra8x8Swap;
p->IDCT.MComp8x8 = (idctmcomp) SoftMComp8x8Swap;
p->IDCT.MComp16x16 = (idctmcomp) SoftMComp16x16Swap;
if (Mode == 0)
{
p->Tab[0] = 2*(8*p->BufWidth); //Y[0;0] -> Y[1;0]
p->Tab[1] = 2*(8-8*p->BufWidth); //Y[1;0] -> Y[0;1]
p->Tab[2] = 2*(8*p->BufWidth); //Y[0;1] -> Y[1;1]
}
}
else
#endif
{
p->IDCT.Process = Process[Mode];
p->IDCT.Copy16x16 = Copy16x16[Mode];
p->IDCT.Intra8x8 = p->Intra8x8;
}
#if defined(MIPS64)
p->IDCT.Inter8x8 = Inter8x8Add;
#endif
}
return ConnectionUpdate((node*)p,IDCT_OUTPUT,p->Out.Pin.Node,p->Out.Pin.No);
}
#ifdef CONFIG_IDCT_SWAP
static int ChangeSwap(softidct* p)
{
if (p->BufCount > 0)
{
int No;
planes TmpPlanes;
video TmpFormat;
int Brightness;
video Format[2];
planes Planes[2];
TmpFormat = p->Out.Format.Format.Video;
TmpFormat.Width = p->BufWidth - 2*EDGE;
TmpFormat.Height = p->BufHeight - 2*EDGE;
if (SurfaceAlloc(TmpPlanes,&TmpFormat) == ERR_NONE)
{
if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
{
SurfaceCopy(&Format[0],&TmpFormat,Planes[0],TmpPlanes,NULL);
Unlock(p,0);
}
for (No=1;No<p->BufCount;++No)
if (Lock(p,No,Planes[0],&Brightness,&Format[0])==ERR_NONE)
{
SwapInt(&p->BufWidth,&p->BufHeight);
if (Lock(p,0,Planes[1],&Brightness,&Format[1])==ERR_NONE)
{
block Tmp;
SurfaceRotate(&Format[0],&Format[1],Planes[0],Planes[1],DIR_SWAPXY);
Unlock(p,0);
SwapPByte(&p->Buffer[No],&p->Buffer[0]);
Tmp = p->_Buffer[0];
p->_Buffer[0] = p->_Buffer[No];
p->_Buffer[No] = Tmp;
p->BufBorder[No] = 0;
SwapInt(&p->BufAlloc[No],&p->BufAlloc[0]);
}
SwapInt(&p->BufWidth,&p->BufHeight);
Unlock(p,No);
}
SwapInt(&p->BufWidth,&p->BufHeight);
if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
{
SurfaceRotate(&TmpFormat,&Format[0],TmpPlanes,Planes[0],DIR_SWAPXY);
Unlock(p,0);
p->BufBorder[0] = 0;
}
SwapInt(&p->BufWidth,&p->BufHeight);
SurfaceFree(TmpPlanes);
}
}
p->Out.Format.Format.Video.Direction ^= DIR_SWAPXY;
SwapInt(&p->Out.Format.Format.Video.Width,&p->Out.Format.Format.Video.Height);
SwapInt(&p->OutWidth,&p->OutHeight);
return UpdateFormat(p);
}
#endif
static int Send(softidct* p,tick_t RefTime,const flowstate* State);
static int VerifyShift(softidct* p,int Shift)
{
// have to keep dword pitch alignment
if (p->BufferWidth && Shift>0)
{
int AlignX = (8 << p->UVX2) - 1;
int BufWidth = ((p->BufferWidth+AlignX)&~AlignX) >> (Shift+p->UVX2);
if (BufWidth & 1)
{
Shift -= 2;
}
else
if (BufWidth & 3)
{
--Shift;
}
if (Shift<0)
Shift=0;
}
return Shift;
}
static int SetShift(softidct* p,int Shift,int Count)
{
#if !defined(CONFIG_IDCT_LOWRES)
return ERR_NOT_SUPPORTED;
#else
if (Shift<0 || Shift>2)
return ERR_NOT_SUPPORTED;
#ifdef CONFIG_IDCT_SWAP
if (Shift>0 && (p->Out.Format.Format.Video.Direction & DIR_SWAPXY))
ChangeSwap(p);
#endif
Shift = VerifyShift(p,Shift);
if (p->Shift != Shift)
{
flowstate State;
blitfx FX;
planes Src[MAXIDCTBUF];
planes Dst;
video SrcFormat;
video DstFormat;
uint8_t *TmpPtr = NULL;
planes Tmp;
block TmpBlock;
int Diff = Shift - p->Shift;
int i;
if (AllocBlock(p->BufSize+16,&TmpBlock,0,HEAP_ANYWR))
{
TmpPtr = (uint8_t*)ALIGN16((uintptr_t)TmpBlock.Ptr);
Tmp[0] = TmpPtr + EDGE + EDGE*p->BufWidth;
Tmp[1] = TmpPtr + p->YToU + (EDGE >> p->UVX2) + (EDGE >> p->UVY2)*(p->BufWidth >> p->UVX2);
Tmp[2] = (uint8_t*)Tmp[1] + (p->YToU >> (p->UVX2+p->UVY2));
}
for (i=0;i<Count;++i)
Lock(p,i,Src[i],NULL,&SrcFormat);
p->Out.Format.Format.Video.Width = p->OutWidth >> Shift;
p->Out.Format.Format.Video.Height = p->OutHeight >> Shift;
memset(&FX,0,sizeof(FX));
if (Diff>0)
{
FX.ScaleX = SCALE_ONE >> Diff;
FX.ScaleY = SCALE_ONE >> Diff;
}
else
{
FX.ScaleX = SCALE_ONE << -Diff;
FX.ScaleY = SCALE_ONE << -Diff;
}
p->Shift = Shift;
UpdateRounding(p);
UpdateFormat(p);
for (i=0;i<Count;++i)
{
if (TmpPtr)
SurfaceCopy(&SrcFormat,&SrcFormat,Src[i],Tmp,NULL);
if (p->BufAlloc[i] < p->BufSize)
{
uint8_t* Ptr;
block Block;
if (!AllocBuffer(p,i,&Block,&Ptr)) // realloc buffer if neccessary)
{
if (TmpPtr)
FreeBlock(&TmpBlock);
SetShift(p,Shift - Diff,i); // restore (shrinking won't need more memory)
return ERR_OUT_OF_MEMORY;
}
FreeBlock(&p->_Buffer[i]);
p->Buffer[i] = Ptr;
p->_Buffer[i] = Block;
p->BufAlloc[i] = p->BufSize;
}
if (TmpPtr)
{
Lock(p,i,Dst,NULL,&DstFormat);
SurfaceCopy(&SrcFormat,&DstFormat,Tmp,Dst,&FX);
}
p->BufBorder[i] = 0;
}
if (TmpPtr)
FreeBlock(&TmpBlock);
State.CurrTime = TIME_RESEND;
State.DropLevel = 0;
Send(p,TIME_UNKNOWN,&State);
}
return ERR_NONE;
#endif
}
static int UpdateMode(softidct* p)
{
if (p->Mode & ~p->ModeSupported)
return ERR_NOT_SUPPORTED;
#ifdef CONFIG_IDCT_SWAP
if (p->Mode && (p->Out.Format.Format.Video.Direction & DIR_SWAPXY))
ChangeSwap(p);
#endif
#if defined(CONFIG_IDCT_LOWRES)
if (p->Mode && p->Shift)
return SetShift(p,0,p->BufCount);
#endif
UpdateRounding(p);
UpdateFormat(p);
return ERR_NONE;
}
static int SetFormat(softidct* p, const video* Format)
{
SetBufferCount(p,0,0);
PacketFormatClear(&p->Out.Format);
if (Format)
{
size_t Area;
if (!(Format->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444)))
return ERR_NOT_SUPPORTED;
p->Out.Format.Type = PACKET_VIDEO;
p->Out.Format.Format.Video = *Format;
if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
SwapInt(&p->Out.Format.Format.Video.Width,&p->Out.Format.Format.Video.Height);
p->Out.Format.Format.Video.Direction = 0;
p->Out.Format.Format.Video.Pixel.Flags |= PF_16ALIGNED | PF_SAFEBORDER;
p->MaxCount = MAXBUF;
p->Rounding = 0;
Area = p->Out.Format.Format.Video.Width * p->Out.Format.Format.Video.Height;
if (Area >= 1024*1024 && AvailMemory() < Area*2)
{
video Desktop;
size_t DesktopArea;
QueryDesktop(&Desktop);
DesktopArea = Desktop.Width * Desktop.Height;
if (Area >= DesktopArea*4 && p->Shift<1)
p->Shift = 1;
if (Area >= DesktopArea*16 && p->Shift<2)
p->Shift = 2;
}
p->Shift = VerifyShift(p,p->Shift);
#if defined(MIPS64)
if (p->Shift>0)
return ERR_NOT_SUPPORTED; // fallback to mips32
#endif
p->OutWidth = p->Out.Format.Format.Video.Width;
p->OutHeight = p->Out.Format.Format.Video.Height;
p->Out.Format.Format.Video.Width >>= p->Shift;
p->Out.Format.Format.Video.Height >>= p->Shift;
UpdateRounding(p);
}
#ifdef FREESCALE_MX1
if (p->MX1)
{
volatile int* Cmd = p->MX1-64; //0x22400
volatile int* GCCR = p->MX1-6972; //0x1B810
if (Format)
{
*GCCR |= 2;
ThreadSleep(1);
*Cmd = 0x284C+0x20;
ThreadSleep(1);
*Cmd = 0x284D;
}
else
{
*Cmd = 0x00;
*GCCR &= ~2;
}
}
#endif
return UpdateFormat(p);
}
static int Set(softidct* p, int No, const void* Data, int Size)
{
flowstate State;
int Result = ERR_INVALID_PARAM;
switch (No)
{
case NODE_SETTINGSCHANGED:
p->NeedLast = QueryAdvanced(ADVANCED_SLOW_VIDEO);
break;
case IDCT_SHOW:
SETVALUE(p->ShowNext,int,ERR_NONE);
if (p->ShowNext >= p->BufCount) p->ShowNext = -1;
break;
case FLOW_FLUSH:
p->ShowCurr = -1;
p->ShowNext = -1;
return ERR_NONE;
case IDCT_BACKUP:
assert(Size == sizeof(idctbackup));
Result = IDCTRestore(&p->IDCT,(idctbackup*)Data);
break;
case IDCT_MODE: SETVALUECMP(p->Mode,int,UpdateMode(p),EqInt); break;
case IDCT_BUFFERWIDTH: SETVALUE(p->BufferWidth,int,ERR_NONE); break;
case IDCT_BUFFERHEIGHT: SETVALUE(p->BufferHeight,int,ERR_NONE); break;
case IDCT_FORMAT:
assert(Size == sizeof(video) || !Data);
Result = SetFormat(p,(const video*)Data);
break;
case IDCT_OUTPUT|PIN_PROCESS: SETVALUE(p->Out.Process,packetprocess,ERR_NONE); break;
#ifdef CONFIG_IDCT_SWAP
case IDCT_OUTPUT|PIN_FORMAT:
assert(Size == sizeof(packetformat) || !Data);
if (Data && QueryAdvanced(ADVANCED_IDCTSWAP) && !p->Shift && !p->Mode &&
!(p->Out.Format.Format.Video.Pixel.Flags & PF_YUV422) &&
PacketFormatRotatedVideo(&p->Out.Format,(packetformat*)Data,DIR_SWAPXY))
Result = ChangeSwap(p);
break;
#endif
case IDCT_OUTPUT: SETVALUE(p->Out.Pin,pin,ERR_NONE); break;
case IDCT_ROUNDING: SETVALUE(p->Rounding,bool_t,UpdateRounding(p)); break;
case IDCT_SHIFT:
assert(Size == sizeof(int));
Result = SetShift(p,*(const int*)Data,p->BufCount);
break;
case IDCT_BUFFERCOUNT:
assert(Size == sizeof(int));
Result = ERR_NONE;
if (p->BufCount < *(const int*)Data)
Result = SetBufferCount(p,*(const int*)Data,0);
break;
case FLOW_RESEND:
State.CurrTime = TIME_RESEND;
State.DropLevel = 0;
Result = Send(p,TIME_UNKNOWN,&State);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -