Import VSFilter from guliverkli.
Originally committed to SVN as r1399.
This commit is contained in:
parent
5d21970bbc
commit
1fb4f58ff2
157 changed files with 50923 additions and 5 deletions
561
vsfilter/Copy.cpp
Normal file
561
vsfilter/Copy.cpp
Normal file
|
@ -0,0 +1,561 @@
|
|||
// Copyright 2003-2006 Gabest
|
||||
// http://www.gabest.org
|
||||
//
|
||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
|
||||
// http://www.gnu.org/copyleft/gpl.html
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <math.h>
|
||||
#include "DirectVobSubFilter.h"
|
||||
#include "dsutil/DSUtil.h"
|
||||
#include "dsutil/MediaTypes.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include "include/moreuuids.h"
|
||||
|
||||
extern int c2y_yb[256];
|
||||
extern int c2y_yg[256];
|
||||
extern int c2y_yr[256];
|
||||
extern void ColorConvInit();
|
||||
|
||||
void BltLineRGB32(DWORD* d, BYTE* sub, int w, const GUID& subtype)
|
||||
{
|
||||
if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
|
||||
{
|
||||
BYTE* db = (BYTE*)d;
|
||||
BYTE* dbtend = db + w;
|
||||
|
||||
for(; db < dbtend; sub+=4, db++)
|
||||
{
|
||||
if(sub[3] < 0xff)
|
||||
{
|
||||
int y = (c2y_yb[sub[0]] + c2y_yg[sub[1]] + c2y_yr[sub[2]] + 0x108000) >> 16;
|
||||
*db = y; // w/o colors
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_YUY2)
|
||||
{
|
||||
WORD* ds = (WORD*)d;
|
||||
WORD* dstend = ds + w;
|
||||
|
||||
for(; ds < dstend; sub+=4, ds++)
|
||||
{
|
||||
if(sub[3] < 0xff)
|
||||
{
|
||||
int y = (c2y_yb[sub[0]] + c2y_yg[sub[1]] + c2y_yr[sub[2]] + 0x108000) >> 16;
|
||||
*ds = 0x8000|y; // w/o colors
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB555)
|
||||
{
|
||||
WORD* ds = (WORD*)d;
|
||||
WORD* dstend = ds + w;
|
||||
|
||||
for(; ds < dstend; sub+=4, ds++)
|
||||
{
|
||||
if(sub[3] < 0xff)
|
||||
{
|
||||
*ds = ((*((DWORD*)sub)>>9)&0x7c00)|((*((DWORD*)sub)>>6)&0x03e0)|((*((DWORD*)sub)>>3)&0x001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB565)
|
||||
{
|
||||
WORD* ds = (WORD*)d;
|
||||
WORD* dstend = ds + w;
|
||||
|
||||
for(; ds < dstend; sub+=4, ds++)
|
||||
{
|
||||
if(sub[3] < 0xff)
|
||||
{
|
||||
*ds = ((*((DWORD*)sub)>>8)&0xf800)|((*((DWORD*)sub)>>5)&0x07e0)|((*((DWORD*)sub)>>3)&0x001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB24)
|
||||
{
|
||||
BYTE* dt = (BYTE*)d;
|
||||
BYTE* dstend = dt + w*3;
|
||||
|
||||
for(; dt < dstend; sub+=4, dt+=3)
|
||||
{
|
||||
if(sub[3] < 0xff)
|
||||
{
|
||||
dt[0] = sub[0];
|
||||
dt[1] = sub[1];
|
||||
dt[2] = sub[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_ARGB32)
|
||||
{
|
||||
DWORD* dstend = d + w;
|
||||
|
||||
for(; d < dstend; sub+=4, d++)
|
||||
{
|
||||
if(sub[3] < 0xff) *d = *((DWORD*)sub)&0xffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ResX2 */
|
||||
void Scale2x(const GUID& subtype, BYTE* d, int dpitch, BYTE* s, int spitch, int w, int h)
|
||||
{
|
||||
if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
|
||||
{
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch) // TODO: replace this mess with mmx code
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
for(BYTE* s3 = s1 + (w-1); s1 < s3; s1 += 1, d1 += 2)
|
||||
{
|
||||
d1[0] = s1[0];
|
||||
d1[1] = (s1[0]+s1[1])>>1;
|
||||
}
|
||||
|
||||
d1[0] = d1[1] = s1[0];
|
||||
|
||||
s1 += 1;
|
||||
d1 += 2;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines8(d, h*2, dpitch);
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_YUY2)
|
||||
{
|
||||
unsigned __int64 __0xffffffff00000000 = 0xffffffff00000000;
|
||||
unsigned __int64 __0x00000000ffffffff = 0x00000000ffffffff;
|
||||
unsigned __int64 __0x00ff00ff00ff00ff = 0x00ff00ff00ff00ff;
|
||||
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
// row0, 4 pixels: y1|u1|y2|v1|y3|u2|y4|v2
|
||||
// ->
|
||||
// row0, 8 pixels: y1|u1|(y1+y2)/2|v1|y2|(u1+u2)/2|(y2+y3)/2|(v1+v2)/2
|
||||
|
||||
__asm
|
||||
{
|
||||
mov esi, s1
|
||||
mov edi, d1
|
||||
|
||||
mov ecx, w
|
||||
shr ecx, 1
|
||||
dec ecx
|
||||
|
||||
movq mm4, __0x00ff00ff00ff00ff
|
||||
movq mm5, __0x00000000ffffffff
|
||||
movq mm6, __0xffffffff00000000
|
||||
row_loop1:
|
||||
movq mm0, [esi]
|
||||
movq mm2, mm0
|
||||
|
||||
pand mm0, mm4 // mm0 = 00y400y300y200y1
|
||||
psrlw mm2, 8 // mm2 = 00u200v200u100v1
|
||||
|
||||
|
||||
movq mm1, mm0
|
||||
|
||||
pand mm0, mm5 // mm0 = 0000000000y200y1
|
||||
|
||||
psllq mm1, 16
|
||||
pand mm1, mm6 // mm1 = 00y300y200000000
|
||||
|
||||
por mm1, mm0 // mm1 = 00y300y200y200y1
|
||||
|
||||
punpcklwd mm0, mm0 // mm0 = 00y200y200y100y1
|
||||
|
||||
paddw mm0, mm1
|
||||
psrlw mm0, 1 // mm0 = (mm0 + mm1) / 2
|
||||
|
||||
|
||||
movq mm1, mm2
|
||||
punpckldq mm1, mm1 // mm1 = 00u100v100u100v1
|
||||
|
||||
paddw mm1, mm2
|
||||
psrlw mm1, 1 // mm1 = (mm1 + mm2) / 2
|
||||
|
||||
|
||||
psllw mm1, 8
|
||||
por mm0, mm1 // mm0 = (v1+v2)/2|(y2+y3)/2|(u1+u2)/2|y2|v1|(y1+y2)/2|u1|y1
|
||||
|
||||
movq [edi], mm0
|
||||
|
||||
lea esi, [esi+4]
|
||||
lea edi, [edi+8]
|
||||
|
||||
dec ecx
|
||||
jnz row_loop1
|
||||
|
||||
mov s1, esi
|
||||
mov d1, edi
|
||||
};
|
||||
|
||||
*d1++ = s1[0];
|
||||
*d1++ = s1[1];
|
||||
*d1++ =(s1[0]+s1[2])>>1;
|
||||
*d1++ = s1[3];
|
||||
|
||||
*d1++ = s1[2];
|
||||
*d1++ = s1[1];
|
||||
*d1++ = s1[2];
|
||||
*d1++ = s1[3];
|
||||
|
||||
s1 += 4;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines8(d, h*2, dpitch);
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB555)
|
||||
{
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch) // TODO: replace this mess with mmx code
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
for(BYTE* s3 = s1 + (w-1)*2; s1 < s3; s1 += 2, d1 += 4)
|
||||
{
|
||||
*((WORD*)d1) = *((WORD*)s1);
|
||||
*((WORD*)d1+1) =
|
||||
((((*((WORD*)s1)&0x7c00) + (*((WORD*)s1+1)&0x7c00)) >> 1)&0x7c00)|
|
||||
((((*((WORD*)s1)&0x03e0) + (*((WORD*)s1+1)&0x03e0)) >> 1)&0x03e0)|
|
||||
((((*((WORD*)s1)&0x001f) + (*((WORD*)s1+1)&0x001f)) >> 1)&0x001f);
|
||||
}
|
||||
|
||||
*((WORD*)d1) = *((WORD*)s1);
|
||||
*((WORD*)d1+1) = *((WORD*)s1);
|
||||
|
||||
s1 += 2;
|
||||
d1 += 4;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines555(d, h*2, dpitch);
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB565)
|
||||
{
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch) // TODO: replace this mess with mmx code
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
for(BYTE* s3 = s1 + (w-1)*2; s1 < s3; s1 += 2, d1 += 4)
|
||||
{
|
||||
*((WORD*)d1) = *((WORD*)s1);
|
||||
*((WORD*)d1+1) =
|
||||
((((*((WORD*)s1)&0xf800) + (*((WORD*)s1+1)&0xf800)) >> 1)&0xf800)|
|
||||
((((*((WORD*)s1)&0x07e0) + (*((WORD*)s1+1)&0x07e0)) >> 1)&0x07e0)|
|
||||
((((*((WORD*)s1)&0x001f) + (*((WORD*)s1+1)&0x001f)) >> 1)&0x001f);
|
||||
}
|
||||
|
||||
*((WORD*)d1) = *((WORD*)s1);
|
||||
*((WORD*)d1+1) = *((WORD*)s1);
|
||||
|
||||
s1 += 2;
|
||||
d1 += 4;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines565(d, h*2, dpitch);
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB24)
|
||||
{
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch) // TODO: replace this mess with mmx code
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
for(BYTE* s3 = s1 + (w-1)*3; s1 < s3; s1 += 3, d1 += 6)
|
||||
{
|
||||
d1[0] = s1[0];
|
||||
d1[1] = s1[1];
|
||||
d1[2] = s1[2];
|
||||
d1[3] = (s1[0]+s1[3])>>1;
|
||||
d1[4] = (s1[1]+s1[4])>>1;
|
||||
d1[5] = (s1[2]+s1[5])>>1;
|
||||
}
|
||||
|
||||
d1[0] = d1[3] = s1[0];
|
||||
d1[1] = d1[4] = s1[1];
|
||||
d1[2] = d1[5] = s1[2];
|
||||
|
||||
s1 += 3;
|
||||
d1 += 6;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines8(d, h*2, dpitch);
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_ARGB32)
|
||||
{
|
||||
BYTE* s1;
|
||||
BYTE* s2;
|
||||
BYTE* d1;
|
||||
|
||||
for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
|
||||
{
|
||||
BYTE* stmp = s1 + spitch;
|
||||
BYTE* dtmp = d1 + dpitch;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov esi, s1
|
||||
mov edi, d1
|
||||
|
||||
mov ecx, w
|
||||
dec ecx
|
||||
|
||||
pxor mm0, mm0
|
||||
row_loop3:
|
||||
movq mm1, [esi]
|
||||
movq mm2, mm1
|
||||
|
||||
punpcklbw mm1, mm0 // mm1 = 00xx00r100g100b1
|
||||
punpckhbw mm2, mm0 // mm2 = 00xx00r200g200b2
|
||||
|
||||
paddw mm2, mm1
|
||||
psrlw mm2, 1 // mm2 = (mm1 + mm2) / 2
|
||||
|
||||
packuswb mm1, mm2
|
||||
|
||||
movq [edi], mm1
|
||||
|
||||
lea esi, [esi+4]
|
||||
lea edi, [edi+8]
|
||||
|
||||
dec ecx
|
||||
jnz row_loop3
|
||||
|
||||
mov s1, esi
|
||||
mov d1, edi
|
||||
};
|
||||
|
||||
*((DWORD*)d1) = *((DWORD*)s1);
|
||||
*((DWORD*)d1+1) = *((DWORD*)s1);
|
||||
|
||||
s1 += 4;
|
||||
d1 += 8;
|
||||
|
||||
s1 = stmp;
|
||||
d1 = dtmp;
|
||||
}
|
||||
|
||||
AvgLines8(d, h*2, dpitch);
|
||||
}
|
||||
|
||||
__asm emms;
|
||||
}
|
||||
|
||||
HRESULT CDirectVobSubFilter::Copy(BYTE* pSub, BYTE* pIn, CSize sub, CSize in, int bpp, const GUID& subtype, DWORD black)
|
||||
{
|
||||
int wIn = in.cx, hIn = in.cy, pitchIn = wIn*bpp>>3;
|
||||
int wSub = sub.cx, hSub = sub.cy, pitchSub = wSub*bpp>>3;
|
||||
bool fScale2x = wIn*2 <= wSub;
|
||||
|
||||
if(fScale2x) wIn <<= 1, hIn <<= 1;
|
||||
|
||||
int left = ((wSub - wIn)>>1)&~1;
|
||||
int mid = wIn;
|
||||
int right = left + ((wSub - wIn)&1);
|
||||
|
||||
int dpLeft = left*bpp>>3;
|
||||
int dpMid = mid*bpp>>3;
|
||||
int dpRight = right*bpp>>3;
|
||||
|
||||
ASSERT(wSub >= wIn);
|
||||
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
|
||||
j += (hSub - hIn) >> 1;
|
||||
|
||||
for(; i < j; i++, pSub += pitchSub)
|
||||
{
|
||||
memsetd(pSub, black, dpLeft+dpMid+dpRight);
|
||||
}
|
||||
|
||||
j += hIn;
|
||||
|
||||
if(hIn > hSub)
|
||||
pIn += pitchIn * ((hIn - hSub) >> (fScale2x?2:1));
|
||||
|
||||
if(fScale2x)
|
||||
{
|
||||
Scale2x(subtype,
|
||||
pSub + dpLeft, pitchSub, pIn, pitchIn,
|
||||
in.cx, (min(j, hSub) - i) >> 1);
|
||||
|
||||
for(int k = min(j, hSub); i < k; i++, pIn += pitchIn, pSub += pitchSub)
|
||||
{
|
||||
memsetd(pSub, black, dpLeft);
|
||||
memsetd(pSub + dpLeft+dpMid, black, dpRight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = min(j, hSub); i < k; i++, pIn += pitchIn, pSub += pitchSub)
|
||||
{
|
||||
memsetd(pSub, black, dpLeft);
|
||||
memcpy(pSub + dpLeft, pIn, dpMid);
|
||||
memsetd(pSub + dpLeft+dpMid, black, dpRight);
|
||||
}
|
||||
}
|
||||
|
||||
j = hSub;
|
||||
|
||||
for(; i < j; i++, pSub += pitchSub)
|
||||
{
|
||||
memsetd(pSub, black, dpLeft+dpMid+dpRight);
|
||||
}
|
||||
}
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
void CDirectVobSubFilter::PrintMessages(BYTE* pOut)
|
||||
{
|
||||
if(!m_hdc || !m_hbm)
|
||||
return;
|
||||
|
||||
ColorConvInit();
|
||||
|
||||
const GUID& subtype = m_pOutput->CurrentMediaType().subtype;
|
||||
|
||||
BITMAPINFOHEADER bihOut;
|
||||
ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
|
||||
|
||||
CString msg, tmp;
|
||||
|
||||
if(m_fOSD)
|
||||
{
|
||||
tmp.Format(_T("in: %dx%d %s\nout: %dx%d %s\n"),
|
||||
m_w, m_h,
|
||||
Subtype2String(m_pInput->CurrentMediaType().subtype),
|
||||
bihOut.biWidth, bihOut.biHeight,
|
||||
Subtype2String(m_pOutput->CurrentMediaType().subtype));
|
||||
msg += tmp;
|
||||
|
||||
tmp.Format(_T("real fps: %.3f, current fps: %.3f\nmedia time: %d, subtitle time: %d [ms]\nframe number: %d (calculated)\nrate: %.4f\n"),
|
||||
m_fps, m_fMediaFPSEnabled?m_MediaFPS:fabs(m_fps),
|
||||
(int)m_tPrev.Millisecs(), (int)(CalcCurrentTime()/10000),
|
||||
(int)(m_tPrev.m_time * m_fps / 10000000),
|
||||
m_pInput->CurrentRate());
|
||||
msg += tmp;
|
||||
|
||||
CAutoLock cAutoLock(&m_csQueueLock);
|
||||
|
||||
if(m_pSubPicQueue)
|
||||
{
|
||||
int nSubPics = -1;
|
||||
REFERENCE_TIME rtNow = -1, rtStart = -1, rtStop = -1;
|
||||
m_pSubPicQueue->GetStats(nSubPics, rtNow, rtStart, rtStop);
|
||||
tmp.Format(_T("queue stats: %I64d - %I64d [ms]\n"), rtStart/10000, rtStop/10000);
|
||||
msg += tmp;
|
||||
|
||||
for(int i = 0; i < nSubPics; i++)
|
||||
{
|
||||
m_pSubPicQueue->GetStats(i, rtStart, rtStop);
|
||||
tmp.Format(_T("%d: %I64d - %I64d [ms]\n"), i, rtStart/10000, rtStop/10000);
|
||||
msg += tmp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(msg.IsEmpty()) return;
|
||||
|
||||
HANDLE hOldBitmap = SelectObject(m_hdc, m_hbm);
|
||||
HANDLE hOldFont = SelectObject(m_hdc, m_hfont);
|
||||
|
||||
SetTextColor(m_hdc, 0xffffff);
|
||||
SetBkMode(m_hdc, TRANSPARENT);
|
||||
SetMapMode(m_hdc, MM_TEXT);
|
||||
|
||||
BITMAP bm;
|
||||
GetObject(m_hbm, sizeof(BITMAP), &bm);
|
||||
|
||||
CRect r(0, 0, bm.bmWidth, bm.bmHeight);
|
||||
DrawText(m_hdc, msg, _tcslen(msg), &r, DT_CALCRECT|DT_EXTERNALLEADING|DT_NOPREFIX|DT_WORDBREAK);
|
||||
|
||||
r += CPoint(10, 10);
|
||||
r &= CRect(0, 0, bm.bmWidth, bm.bmHeight);
|
||||
|
||||
DrawText(m_hdc, msg, _tcslen(msg), &r, DT_LEFT|DT_TOP|DT_NOPREFIX|DT_WORDBREAK);
|
||||
|
||||
BYTE* pIn = (BYTE*)bm.bmBits;
|
||||
int pitchIn = bm.bmWidthBytes;
|
||||
int pitchOut = bihOut.biWidth * bihOut.biBitCount >> 3;
|
||||
|
||||
if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
|
||||
pitchOut = bihOut.biWidth;
|
||||
|
||||
pitchIn = (pitchIn+3)&~3;
|
||||
pitchOut = (pitchOut+3)&~3;
|
||||
|
||||
if(bihOut.biHeight > 0 && bihOut.biCompression <= 3) // flip if the dst bitmap is flipped rgb (m_hbm is a top-down bitmap, not like the subpictures)
|
||||
{
|
||||
pOut += pitchOut * (abs(bihOut.biHeight)-1);
|
||||
pitchOut = -pitchOut;
|
||||
}
|
||||
|
||||
pIn += pitchIn * r.top;
|
||||
pOut += pitchOut * r.top;
|
||||
|
||||
for(int w = min(r.right, m_w), h = r.Height(); h--; pIn += pitchIn, pOut += pitchOut)
|
||||
{
|
||||
BltLineRGB32((DWORD*)pOut, pIn, w, subtype);
|
||||
memsetd(pIn, 0xff000000, r.right*4);
|
||||
}
|
||||
|
||||
SelectObject(m_hdc, hOldBitmap);
|
||||
SelectObject(m_hdc, hOldFont);
|
||||
}
|
629
vsfilter/DirectVobSub.cpp
Normal file
629
vsfilter/DirectVobSub.cpp
Normal file
|
@ -0,0 +1,629 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DirectVobSub.h"
|
||||
#include "VSFilter.h"
|
||||
|
||||
CDirectVobSub::CDirectVobSub()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
BYTE* pData;
|
||||
UINT nSize;
|
||||
|
||||
m_iSelectedLanguage = 0;
|
||||
m_fHideSubtitles = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_HIDE), 0);
|
||||
m_fDoPreBuffering = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_DOPREBUFFERING), 1);
|
||||
m_fOverridePlacement = !!theApp.GetProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_OVERRIDEPLACEMENT), 0);
|
||||
m_PlacementXperc = theApp.GetProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_XPERC), 50);
|
||||
m_PlacementYperc = theApp.GetProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_YPERC), 90);
|
||||
m_fBufferVobSub = !!theApp.GetProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_BUFFER), 1);
|
||||
m_fOnlyShowForcedVobSubs = !!theApp.GetProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_ONLYSHOWFORCEDSUBS), 0);
|
||||
m_fPolygonize = !!theApp.GetProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_POLYGONIZE), 0);
|
||||
m_defStyle <<= theApp.GetProfileString(ResStr(IDS_R_TEXT), ResStr(IDS_RT_STYLE), _T(""));
|
||||
m_fFlipPicture = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_FLIPPICTURE), 0);
|
||||
m_fFlipSubtitles = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_FLIPSUBTITLES), 0);
|
||||
m_fOSD = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SHOWOSDSTATS), 0);
|
||||
m_fSaveFullPath = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SAVEFULLPATH), 0);
|
||||
m_nReloaderDisableCount = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_DISABLERELOADER), 0) ? 1 : 0;
|
||||
m_SubtitleDelay = theApp.GetProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLEDELAY), 0);
|
||||
m_SubtitleSpeedMul = theApp.GetProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLESPEEDMUL), 1000);
|
||||
m_SubtitleSpeedDiv = theApp.GetProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLESPEEDDIV), 1000);
|
||||
m_fMediaFPSEnabled = !!theApp.GetProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPSENABLED), 0);
|
||||
pData = NULL;
|
||||
if(theApp.GetProfileBinary(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPS), &pData, &nSize) && pData)
|
||||
{
|
||||
if(nSize != sizeof(m_MediaFPS)) m_MediaFPS = 25.0;
|
||||
else memcpy(&m_MediaFPS, pData, sizeof(m_MediaFPS));
|
||||
delete [] pData;
|
||||
}
|
||||
m_ZoomRect.left = m_ZoomRect.top = 0;
|
||||
m_ZoomRect.right = m_ZoomRect.bottom = 1;
|
||||
|
||||
m_fForced = false;
|
||||
}
|
||||
|
||||
CDirectVobSub::~CDirectVobSub()
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_FileName(WCHAR* fn)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!fn) return E_POINTER;
|
||||
|
||||
#ifdef UNICODE
|
||||
wcscpy(fn, m_FileName);
|
||||
#else
|
||||
mbstowcs(fn, m_FileName, m_FileName.GetLength()+1);
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_FileName(WCHAR* fn)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!fn) return E_POINTER;
|
||||
|
||||
CString tmp = fn;
|
||||
if(!m_FileName.Left(m_FileName.ReverseFind('.')+1).CompareNoCase(tmp.Left(tmp.ReverseFind('.')+1))) return S_FALSE;
|
||||
|
||||
#ifdef UNICODE
|
||||
m_FileName = fn;
|
||||
#else
|
||||
CHARSETINFO cs={0};
|
||||
::TranslateCharsetInfo((DWORD *)DEFAULT_CHARSET, &cs, TCI_SRCCHARSET);
|
||||
CHAR* buff = m_FileName.GetBuffer(MAX_PATH*2);
|
||||
int len = WideCharToMultiByte(cs.ciACP/*CP_OEMCP*/, NULL, fn, -1, buff, MAX_PATH*2, NULL, NULL);
|
||||
m_FileName.ReleaseBuffer(len+1);
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_LanguageCount(int* nLangs)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return nLangs ? *nLangs = 0, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_LanguageName(int iLanguage, WCHAR** ppName)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_SelectedLanguage(int* iSelected)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return iSelected ? *iSelected = m_iSelectedLanguage, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_SelectedLanguage(int iSelected)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_iSelectedLanguage == iSelected) return S_FALSE;
|
||||
|
||||
int nCount;
|
||||
if(FAILED(get_LanguageCount(&nCount))
|
||||
|| iSelected < 0
|
||||
|| iSelected >= nCount)
|
||||
return E_FAIL;
|
||||
|
||||
m_iSelectedLanguage = iSelected;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_HideSubtitles(bool* fHideSubtitles)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return fHideSubtitles ? *fHideSubtitles = m_fHideSubtitles, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_HideSubtitles(bool fHideSubtitles)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fHideSubtitles == fHideSubtitles) return S_FALSE;
|
||||
|
||||
m_fHideSubtitles = fHideSubtitles;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_PreBuffering(bool* fDoPreBuffering)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return fDoPreBuffering ? *fDoPreBuffering = m_fDoPreBuffering, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_PreBuffering(bool fDoPreBuffering)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fDoPreBuffering == fDoPreBuffering) return S_FALSE;
|
||||
|
||||
m_fDoPreBuffering = fDoPreBuffering;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_Placement(bool* fOverridePlacement, int* xperc, int* yperc)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fOverridePlacement) *fOverridePlacement = m_fOverridePlacement;
|
||||
if(xperc) *xperc = m_PlacementXperc;
|
||||
if(yperc) *yperc = m_PlacementYperc;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_Placement(bool fOverridePlacement, int xperc, int yperc)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fOverridePlacement == fOverridePlacement && m_PlacementXperc == xperc && m_PlacementYperc == yperc) return S_FALSE;
|
||||
|
||||
m_fOverridePlacement = fOverridePlacement;
|
||||
m_PlacementXperc = xperc;
|
||||
m_PlacementYperc = yperc;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_VobSubSettings(bool* fBuffer, bool* fOnlyShowForcedSubs, bool* fPolygonize)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fBuffer) *fBuffer = m_fBufferVobSub;
|
||||
if(fOnlyShowForcedSubs) *fOnlyShowForcedSubs = m_fOnlyShowForcedVobSubs;
|
||||
if(fPolygonize) *fPolygonize = m_fPolygonize;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_VobSubSettings(bool fBuffer, bool fOnlyShowForcedSubs, bool fPolygonize)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fBufferVobSub == fBuffer && m_fOnlyShowForcedVobSubs == fOnlyShowForcedSubs && m_fPolygonize == fPolygonize) return S_FALSE;
|
||||
|
||||
m_fBufferVobSub = fBuffer;
|
||||
m_fOnlyShowForcedVobSubs = fOnlyShowForcedSubs;
|
||||
m_fPolygonize = fPolygonize;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_TextSettings(void* lf, int lflen, COLORREF* color, bool* fShadow, bool* fOutline, bool* fAdvancedRenderer)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(lf)
|
||||
{
|
||||
if(lflen == sizeof(LOGFONTA))
|
||||
strncpy_s(((LOGFONTA*)lf)->lfFaceName, LF_FACESIZE, CStringA(m_defStyle.fontName), _TRUNCATE);
|
||||
else if(lflen == sizeof(LOGFONTW))
|
||||
wcsncpy_s(((LOGFONTW*)lf)->lfFaceName, LF_FACESIZE, CStringW(m_defStyle.fontName), _TRUNCATE);
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
|
||||
((LOGFONT*)lf)->lfCharSet = m_defStyle.charSet;
|
||||
((LOGFONT*)lf)->lfItalic = m_defStyle.fItalic;
|
||||
((LOGFONT*)lf)->lfHeight = m_defStyle.fontSize;
|
||||
((LOGFONT*)lf)->lfWeight = m_defStyle.fontWeight;
|
||||
((LOGFONT*)lf)->lfStrikeOut = m_defStyle.fStrikeOut;
|
||||
((LOGFONT*)lf)->lfUnderline = m_defStyle.fUnderline;
|
||||
}
|
||||
|
||||
if(color) *color = m_defStyle.colors[0];
|
||||
if(fShadow) *fShadow = m_defStyle.shadowDepth>0;
|
||||
if(fOutline) *fOutline = m_defStyle.outlineWidth>0;
|
||||
if(fAdvancedRenderer) *fAdvancedRenderer = m_fAdvancedRenderer;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_TextSettings(void* lf, int lflen, COLORREF color, bool fShadow, bool fOutline, bool fAdvancedRenderer)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(lf)
|
||||
{
|
||||
if(lflen == sizeof(LOGFONTA))
|
||||
m_defStyle.fontName = ((LOGFONTA*)lf)->lfFaceName;
|
||||
else if(lflen == sizeof(LOGFONTW))
|
||||
m_defStyle.fontName = ((LOGFONTW*)lf)->lfFaceName;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
|
||||
m_defStyle.charSet = ((LOGFONT*)lf)->lfCharSet;
|
||||
m_defStyle.fItalic = !!((LOGFONT*)lf)->lfItalic;
|
||||
m_defStyle.fontSize = ((LOGFONT*)lf)->lfHeight;
|
||||
m_defStyle.fontWeight = ((LOGFONT*)lf)->lfWeight;
|
||||
m_defStyle.fStrikeOut = !!((LOGFONT*)lf)->lfStrikeOut;
|
||||
m_defStyle.fUnderline = !!((LOGFONT*)lf)->lfUnderline;
|
||||
|
||||
if(m_defStyle.fontSize < 0)
|
||||
{
|
||||
HDC hdc = ::GetDC(0);
|
||||
m_defStyle.fontSize = -m_defStyle.fontSize * 72 / GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
::ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_defStyle.colors[0] = color;
|
||||
m_defStyle.shadowDepth = fShadow?2:0;
|
||||
m_defStyle.outlineWidth = fOutline?2:0;
|
||||
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_Flip(bool* fPicture, bool* fSubtitles)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fPicture) *fPicture = m_fFlipPicture;
|
||||
if(fSubtitles) *fSubtitles = m_fFlipSubtitles;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_Flip(bool fPicture, bool fSubtitles)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fFlipPicture == fPicture && m_fFlipSubtitles == fSubtitles) return S_FALSE;
|
||||
|
||||
m_fFlipPicture = fPicture;
|
||||
m_fFlipSubtitles = fSubtitles;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_OSD(bool* fOSD)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return fOSD ? *fOSD = m_fOSD, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_OSD(bool fOSD)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fOSD == fOSD) return S_FALSE;
|
||||
|
||||
m_fOSD = fOSD;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_SaveFullPath(bool* fSaveFullPath)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
return fSaveFullPath ? *fSaveFullPath = m_fSaveFullPath, S_OK : E_POINTER;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_SaveFullPath(bool fSaveFullPath)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fSaveFullPath == fSaveFullPath) return S_FALSE;
|
||||
|
||||
m_fSaveFullPath = fSaveFullPath;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_SubtitleTiming(int* delay, int* speedmul, int* speeddiv)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(delay) *delay = m_SubtitleDelay;
|
||||
if(speedmul) *speedmul = m_SubtitleSpeedMul;
|
||||
if(speeddiv) *speeddiv = m_SubtitleSpeedDiv;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_SubtitleTiming(int delay, int speedmul, int speeddiv)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_SubtitleDelay == delay && m_SubtitleSpeedMul == speedmul && m_SubtitleSpeedDiv == speeddiv) return S_FALSE;
|
||||
|
||||
m_SubtitleDelay = delay;
|
||||
m_SubtitleSpeedMul = speedmul;
|
||||
if(speeddiv > 0) m_SubtitleSpeedDiv = speeddiv;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_MediaFPS(bool* fEnabled, double* fps)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fEnabled) *fEnabled = m_fMediaFPSEnabled;
|
||||
if(fps) *fps = m_MediaFPS;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_MediaFPS(bool fEnabled, double fps)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(m_fMediaFPSEnabled == fEnabled && m_MediaFPS == fps) return S_FALSE;
|
||||
|
||||
m_fMediaFPSEnabled = fEnabled;
|
||||
if(fps > 0) m_MediaFPS = fps;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_ZoomRect(NORMALIZEDRECT* rect)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!rect) return E_POINTER;
|
||||
|
||||
*rect = m_ZoomRect;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_ZoomRect(NORMALIZEDRECT* rect)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!rect) return E_POINTER;
|
||||
|
||||
if(!memcmp(&m_ZoomRect, rect, sizeof(m_ZoomRect))) return S_FALSE;
|
||||
|
||||
m_ZoomRect = *rect;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::UpdateRegistry()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_HIDE), m_fHideSubtitles);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_DOPREBUFFERING), m_fDoPreBuffering);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_OVERRIDEPLACEMENT), m_fOverridePlacement);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_XPERC), m_PlacementXperc);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TEXT), ResStr(IDS_RT_YPERC), m_PlacementYperc);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_BUFFER), m_fBufferVobSub);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_ONLYSHOWFORCEDSUBS), m_fOnlyShowForcedVobSubs);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_VOBSUB), ResStr(IDS_RV_POLYGONIZE), m_fPolygonize);
|
||||
CString style;
|
||||
theApp.WriteProfileString(ResStr(IDS_R_TEXT), ResStr(IDS_RT_STYLE), style <<= m_defStyle);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_FLIPPICTURE), m_fFlipPicture);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_FLIPSUBTITLES), m_fFlipSubtitles);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SHOWOSDSTATS), m_fOSD);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SAVEFULLPATH), m_fSaveFullPath);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLEDELAY), m_SubtitleDelay);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLESPEEDMUL), m_SubtitleSpeedMul);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_SUBTITLESPEEDDIV), m_SubtitleSpeedDiv);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPSENABLED), m_fMediaFPSEnabled);
|
||||
theApp.WriteProfileBinary(ResStr(IDS_R_TIMING), ResStr(IDS_RTM_MEDIAFPS), (BYTE*)&m_MediaFPS, sizeof(m_MediaFPS));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::HasConfigDialog(int iSelected)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::ShowConfigDialog(int iSelected, HWND hWndParent)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::IsSubtitleReloaderLocked(bool* fLocked)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!fLocked) return E_POINTER;
|
||||
|
||||
bool fDisabled;
|
||||
get_SubtitleReloader(&fDisabled);
|
||||
|
||||
*fLocked = fDisabled || m_nReloaderDisableCount > 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::LockSubtitleReloader(bool fLock)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fLock) m_nReloaderDisableCount++;
|
||||
else m_nReloaderDisableCount--;
|
||||
|
||||
ASSERT(m_nReloaderDisableCount >= 0);
|
||||
if(m_nReloaderDisableCount < 0) m_nReloaderDisableCount = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_SubtitleReloader(bool* fDisabled)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(fDisabled) *fDisabled = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_DISABLERELOADER), 0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_SubtitleReloader(bool fDisable)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
bool b;
|
||||
get_SubtitleReloader(&b);
|
||||
if(b == fDisable) return S_FALSE;
|
||||
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_DISABLERELOADER), fDisable);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_ExtendPicture(int* horizontal, int* vertical, int* resx2, int* resx2minw, int* resx2minh)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(horizontal) *horizontal = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_MOD32FIX), 0) & 1;
|
||||
if(vertical) *vertical = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EXTPIC), 1);
|
||||
if(resx2) *resx2 = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2), 2) & 3;
|
||||
if(resx2minw) *resx2minw = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2MINW), 384);
|
||||
if(resx2minh) *resx2minh = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2MINH), 288);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_ExtendPicture(int horizontal, int vertical, int resx2, int resx2minw, int resx2minh)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
int i[5];
|
||||
get_ExtendPicture(i, i+1, i+2, i+3, i+4);
|
||||
if(i[0] == horizontal && i[1] == vertical && i[2] == resx2 && i[3] == resx2minw && i[4] == resx2minh) return S_FALSE;
|
||||
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_MOD32FIX), horizontal & 1);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EXTPIC), vertical);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2), resx2 & 3);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2MINW), resx2minw);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_RESX2MINH), resx2minh);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_LoadSettings(int* level, bool* fExternalLoad, bool* fWebLoad, bool* fEmbeddedLoad)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(level) *level = theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_LOADLEVEL), 0) & 3;
|
||||
if(fExternalLoad) *fExternalLoad = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EXTERNALLOAD), 1);
|
||||
if(fWebLoad) *fWebLoad = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_WEBLOAD), 0);
|
||||
if(fEmbeddedLoad) *fEmbeddedLoad = !!theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EMBEDDEDLOAD), 1);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_LoadSettings(int level, bool fExternalLoad, bool fWebLoad, bool fEmbeddedLoad)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
int i;
|
||||
bool b[3];
|
||||
get_LoadSettings(&i, b, b+1, b+2);
|
||||
if(i == level && b[0] == fExternalLoad && b[1] == fWebLoad && b[2] == fEmbeddedLoad) return S_FALSE;
|
||||
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_LOADLEVEL), level & 3);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EXTERNALLOAD), fExternalLoad);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_WEBLOAD), fWebLoad);
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_EMBEDDEDLOAD), fEmbeddedLoad);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IDirectVobSub2
|
||||
|
||||
STDMETHODIMP CDirectVobSub::AdviseSubClock(ISubClock* pSubClock)
|
||||
{
|
||||
m_pSubClock = pSubClock;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(bool) CDirectVobSub::get_Forced()
|
||||
{
|
||||
return m_fForced;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_Forced(bool fForced)
|
||||
{
|
||||
m_fForced = fForced;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::get_TextSettings(STSStyle* pDefStyle)
|
||||
{
|
||||
CheckPointer(pDefStyle, E_POINTER);
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
*pDefStyle = m_defStyle;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDirectVobSub::put_TextSettings(STSStyle* pDefStyle)
|
||||
{
|
||||
CheckPointer(pDefStyle, E_POINTER);
|
||||
|
||||
CAutoLock cAutoLock(&m_propsLock);
|
||||
|
||||
if(!memcmp(&m_defStyle, pDefStyle, sizeof(m_defStyle)))
|
||||
return S_FALSE;
|
||||
|
||||
m_defStyle = *pDefStyle;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// IFilterVersion
|
||||
|
||||
STDMETHODIMP_(DWORD) CDirectVobSub::GetFilterVersion()
|
||||
{
|
||||
return 0x0234;
|
||||
}
|
124
vsfilter/DirectVobSub.h
Normal file
124
vsfilter/DirectVobSub.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDirectVobSub.h"
|
||||
#include "include/IFilterVersion.h"
|
||||
|
||||
class CDirectVobSub : public IDirectVobSub2, public IFilterVersion
|
||||
{
|
||||
protected:
|
||||
CDirectVobSub();
|
||||
virtual ~CDirectVobSub();
|
||||
|
||||
protected:
|
||||
CCritSec m_propsLock;
|
||||
|
||||
CString m_FileName;
|
||||
int m_iSelectedLanguage;
|
||||
bool m_fHideSubtitles;
|
||||
bool m_fDoPreBuffering;
|
||||
bool m_fOverridePlacement;
|
||||
int m_PlacementXperc, m_PlacementYperc;
|
||||
bool m_fBufferVobSub, m_fOnlyShowForcedVobSubs, m_fPolygonize;
|
||||
|
||||
STSStyle m_defStyle;
|
||||
|
||||
bool m_fAdvancedRenderer;
|
||||
bool m_fFlipPicture, m_fFlipSubtitles;
|
||||
bool m_fOSD;
|
||||
int m_nReloaderDisableCount;
|
||||
int m_SubtitleDelay, m_SubtitleSpeedMul, m_SubtitleSpeedDiv;
|
||||
bool m_fMediaFPSEnabled;
|
||||
double m_MediaFPS;
|
||||
bool m_fSaveFullPath;
|
||||
NORMALIZEDRECT m_ZoomRect;
|
||||
|
||||
CComPtr<ISubClock> m_pSubClock;
|
||||
bool m_fForced;
|
||||
|
||||
public:
|
||||
|
||||
// IDirectVobSub
|
||||
|
||||
STDMETHODIMP get_FileName(WCHAR* fn);
|
||||
STDMETHODIMP put_FileName(WCHAR* fn);
|
||||
STDMETHODIMP get_LanguageCount(int* nLangs);
|
||||
STDMETHODIMP get_LanguageName(int iLanguage, WCHAR** ppName);
|
||||
STDMETHODIMP get_SelectedLanguage(int* iSelected);
|
||||
STDMETHODIMP put_SelectedLanguage(int iSelected);
|
||||
STDMETHODIMP get_HideSubtitles(bool* fHideSubtitles);
|
||||
STDMETHODIMP put_HideSubtitles(bool fHideSubtitles);
|
||||
STDMETHODIMP get_PreBuffering(bool* fDoPreBuffering);
|
||||
STDMETHODIMP put_PreBuffering(bool fDoPreBuffering);
|
||||
STDMETHODIMP get_Placement(bool* fOverridePlacement, int* xperc, int* yperc);
|
||||
STDMETHODIMP put_Placement(bool fOverridePlacement, int xperc, int yperc);
|
||||
STDMETHODIMP get_VobSubSettings(bool* fBuffer, bool* fOnlyShowForcedSubs, bool* fPolygonize);
|
||||
STDMETHODIMP put_VobSubSettings(bool fBuffer, bool fOnlyShowForcedSubs, bool fPolygonize);
|
||||
STDMETHODIMP get_TextSettings(void* lf, int lflen, COLORREF* color, bool* fShadow, bool* fOutline, bool* fAdvancedRenderer);
|
||||
STDMETHODIMP put_TextSettings(void* lf, int lflen, COLORREF color, bool fShadow, bool fOutline, bool fAdvancedRenderer);
|
||||
STDMETHODIMP get_Flip(bool* fPicture, bool* fSubtitles);
|
||||
STDMETHODIMP put_Flip(bool fPicture, bool fSubtitles);
|
||||
STDMETHODIMP get_OSD(bool* fShowOSD);
|
||||
STDMETHODIMP put_OSD(bool fShowOSD);
|
||||
STDMETHODIMP get_SaveFullPath(bool* fSaveFullPath);
|
||||
STDMETHODIMP put_SaveFullPath(bool fSaveFullPath);
|
||||
STDMETHODIMP get_SubtitleTiming(int* delay, int* speedmul, int* speeddiv);
|
||||
STDMETHODIMP put_SubtitleTiming(int delay, int speedmul, int speeddiv);
|
||||
STDMETHODIMP get_MediaFPS(bool* fEnabled, double* fps);
|
||||
STDMETHODIMP put_MediaFPS(bool fEnabled, double fps);
|
||||
STDMETHODIMP get_ZoomRect(NORMALIZEDRECT* rect);
|
||||
STDMETHODIMP put_ZoomRect(NORMALIZEDRECT* rect);
|
||||
STDMETHODIMP get_ColorFormat(int* iPosition) {return E_NOTIMPL;}
|
||||
STDMETHODIMP put_ColorFormat(int iPosition) {return E_NOTIMPL;}
|
||||
|
||||
STDMETHODIMP UpdateRegistry();
|
||||
|
||||
STDMETHODIMP HasConfigDialog(int iSelected);
|
||||
STDMETHODIMP ShowConfigDialog(int iSelected, HWND hWndParent);
|
||||
|
||||
// settings for the rest are stored in the registry
|
||||
|
||||
STDMETHODIMP IsSubtitleReloaderLocked(bool* fLocked);
|
||||
STDMETHODIMP LockSubtitleReloader(bool fLock);
|
||||
STDMETHODIMP get_SubtitleReloader(bool* fDisabled);
|
||||
STDMETHODIMP put_SubtitleReloader(bool fDisable);
|
||||
|
||||
// the followings need a partial or full reloading of the filter
|
||||
|
||||
STDMETHODIMP get_ExtendPicture(int* horizontal, int* vertical, int* resx2, int* resx2minw, int* resx2minh);
|
||||
STDMETHODIMP put_ExtendPicture(int horizontal, int vertical, int resx2, int resx2minw, int resx2minh);
|
||||
STDMETHODIMP get_LoadSettings(int* level, bool* fExternalLoad, bool* fWebLoad, bool* fEmbeddedLoad);
|
||||
STDMETHODIMP put_LoadSettings(int level, bool fExternalLoad, bool fWebLoad, bool fEmbeddedLoad);
|
||||
|
||||
// IDirectVobSub2
|
||||
|
||||
STDMETHODIMP AdviseSubClock(ISubClock* pSubClock);
|
||||
STDMETHODIMP_(bool) get_Forced();
|
||||
STDMETHODIMP put_Forced(bool fForced);
|
||||
STDMETHODIMP get_TextSettings(STSStyle* pDefStyle);
|
||||
STDMETHODIMP put_TextSettings(STSStyle* pDefStyle);
|
||||
|
||||
// IFilterVersion
|
||||
|
||||
STDMETHODIMP_(DWORD) GetFilterVersion();
|
||||
};
|
1716
vsfilter/DirectVobSubFilter.cpp
Normal file
1716
vsfilter/DirectVobSubFilter.cpp
Normal file
File diff suppressed because it is too large
Load diff
196
vsfilter/DirectVobSubFilter.h
Normal file
196
vsfilter/DirectVobSubFilter.h
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlsync.h>
|
||||
#include "DirectVobSub.h"
|
||||
#include "BaseVideoFilter/BaseVideoFilter.h"
|
||||
#include "subtitles/VobSubFile.h"
|
||||
#include "subtitles/RTS.h"
|
||||
#include "subtitles/SSF.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HWND hSystrayWnd;
|
||||
IFilterGraph* graph;
|
||||
IDirectVobSub* dvs;
|
||||
bool fRunOnce, fShowIcon;
|
||||
} SystrayIconData;
|
||||
|
||||
/* This is for graphedit */
|
||||
|
||||
[uuid("93A22E7A-5091-45ef-BA61-6DA26156A5D0")]
|
||||
class CDirectVobSubFilter
|
||||
: public CBaseVideoFilter
|
||||
, public CDirectVobSub
|
||||
, public ISpecifyPropertyPages
|
||||
, public IAMStreamSelect
|
||||
, public CAMThread
|
||||
{
|
||||
friend class CTextInputPin;
|
||||
|
||||
CCritSec m_csQueueLock;
|
||||
CComPtr<ISubPicQueue> m_pSubPicQueue;
|
||||
void InitSubPicQueue();
|
||||
SubPicDesc m_spd;
|
||||
|
||||
bool AdjustFrameSize(CSize& s);
|
||||
|
||||
protected:
|
||||
void GetOutputSize(int& w, int& h, int& arx, int& ary);
|
||||
HRESULT Transform(IMediaSample* pIn);
|
||||
|
||||
public:
|
||||
CDirectVobSubFilter(LPUNKNOWN punk, HRESULT* phr, const GUID& clsid = __uuidof(CDirectVobSubFilter));
|
||||
virtual ~CDirectVobSubFilter();
|
||||
|
||||
DECLARE_IUNKNOWN;
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
|
||||
|
||||
// CBaseFilter
|
||||
|
||||
CBasePin* GetPin(int n);
|
||||
int GetPinCount();
|
||||
|
||||
STDMETHODIMP JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR pName);
|
||||
STDMETHODIMP QueryFilterInfo(FILTER_INFO* pInfo);
|
||||
|
||||
// CTransformFilter
|
||||
HRESULT SetMediaType(PIN_DIRECTION dir, const CMediaType* pMediaType),
|
||||
CheckConnect(PIN_DIRECTION dir, IPin* pPin),
|
||||
CompleteConnect(PIN_DIRECTION dir, IPin* pReceivePin),
|
||||
BreakConnect(PIN_DIRECTION dir),
|
||||
StartStreaming(),
|
||||
StopStreaming(),
|
||||
NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
||||
|
||||
CAtlArray<CTextInputPin*> m_pTextInput;
|
||||
|
||||
// IDirectVobSub
|
||||
STDMETHODIMP put_FileName(WCHAR* fn);
|
||||
STDMETHODIMP get_LanguageCount(int* nLangs);
|
||||
STDMETHODIMP get_LanguageName(int iLanguage, WCHAR** ppName);
|
||||
STDMETHODIMP put_SelectedLanguage(int iSelected);
|
||||
STDMETHODIMP put_HideSubtitles(bool fHideSubtitles);
|
||||
STDMETHODIMP put_PreBuffering(bool fDoPreBuffering);
|
||||
STDMETHODIMP put_Placement(bool fOverridePlacement, int xperc, int yperc);
|
||||
STDMETHODIMP put_VobSubSettings(bool fBuffer, bool fOnlyShowForcedSubs, bool fPolygonize);
|
||||
STDMETHODIMP put_TextSettings(void* lf, int lflen, COLORREF color, bool fShadow, bool fOutline, bool fAdvancedRenderer);
|
||||
STDMETHODIMP put_SubtitleTiming(int delay, int speedmul, int speeddiv);
|
||||
STDMETHODIMP get_MediaFPS(bool* fEnabled, double* fps);
|
||||
STDMETHODIMP put_MediaFPS(bool fEnabled, double fps);
|
||||
STDMETHODIMP get_ZoomRect(NORMALIZEDRECT* rect);
|
||||
STDMETHODIMP put_ZoomRect(NORMALIZEDRECT* rect);
|
||||
STDMETHODIMP HasConfigDialog(int iSelected);
|
||||
STDMETHODIMP ShowConfigDialog(int iSelected, HWND hWndParent);
|
||||
|
||||
// IDirectVobSub2
|
||||
STDMETHODIMP put_TextSettings(STSStyle* pDefStyle);
|
||||
|
||||
// ISpecifyPropertyPages
|
||||
STDMETHODIMP GetPages(CAUUID* pPages);
|
||||
|
||||
// IAMStreamSelect
|
||||
STDMETHODIMP Count(DWORD* pcStreams);
|
||||
STDMETHODIMP Enable(long lIndex, DWORD dwFlags);
|
||||
STDMETHODIMP Info(long lIndex, AM_MEDIA_TYPE** ppmt, DWORD* pdwFlags, LCID* plcid, DWORD* pdwGroup, WCHAR** ppszName, IUnknown** ppObject, IUnknown** ppUnk);
|
||||
|
||||
// CPersistStream
|
||||
STDMETHODIMP GetClassID(CLSID* pClsid);
|
||||
|
||||
protected:
|
||||
HRESULT ChangeMediaType(int iPosition);
|
||||
|
||||
HDC m_hdc;
|
||||
HBITMAP m_hbm;
|
||||
HFONT m_hfont;
|
||||
void PrintMessages(BYTE* pOut);
|
||||
|
||||
/* ResX2 */
|
||||
CAutoVectorPtr<BYTE> m_pTempPicBuff;
|
||||
HRESULT Copy(BYTE* pSub, BYTE* pIn, CSize sub, CSize in, int bpp, const GUID& subtype, DWORD black);
|
||||
|
||||
// segment start time, absolute time
|
||||
CRefTime m_tPrev;
|
||||
REFERENCE_TIME CalcCurrentTime();
|
||||
|
||||
double m_fps;
|
||||
|
||||
// 3.x- versions of microsoft's mpeg4 codec output flipped image
|
||||
bool m_fMSMpeg4Fix;
|
||||
|
||||
// DivxPlus puts our picture upside-down on the tv
|
||||
bool m_fDivxPlusFix;
|
||||
|
||||
// don't set the "hide subtitles" stream until we are finished with loading
|
||||
bool m_fLoading;
|
||||
|
||||
bool Open();
|
||||
|
||||
int FindPreferedLanguage(bool fHideToo = true);
|
||||
void UpdatePreferedLanguages(CString lang);
|
||||
|
||||
CCritSec m_csSubLock;
|
||||
CInterfaceList<ISubStream> m_pSubStreams;
|
||||
DWORD_PTR m_nSubtitleId;
|
||||
void UpdateSubtitle(bool fApplyDefStyle = true);
|
||||
void SetSubtitle(ISubStream* pSubStream, bool fApplyDefStyle = true);
|
||||
void InvalidateSubtitle(REFERENCE_TIME rtInvalidate = -1, DWORD_PTR nSubtitleId = -1);
|
||||
|
||||
// the text input pin is using these
|
||||
void AddSubStream(ISubStream* pSubStream);
|
||||
void RemoveSubStream(ISubStream* pSubStream);
|
||||
void Post_EC_OLE_EVENT(CString str, DWORD_PTR nSubtitleId = -1);
|
||||
|
||||
private:
|
||||
class CFileReloaderData
|
||||
{
|
||||
public:
|
||||
ATL::CEvent EndThreadEvent, RefreshEvent;
|
||||
CAtlList<CString> files;
|
||||
CAtlArray<CTime> mtime;
|
||||
} m_frd;
|
||||
|
||||
void SetupFRD(CStringArray& paths, CAtlArray<HANDLE>& handles);
|
||||
DWORD ThreadProc();
|
||||
|
||||
private:
|
||||
HANDLE m_hSystrayThread;
|
||||
SystrayIconData m_tbid;
|
||||
};
|
||||
|
||||
/* The "auto-loading" version */
|
||||
|
||||
[uuid("9852A670-F845-491b-9BE6-EBD841B8A613")]
|
||||
class CDirectVobSubFilter2 : public CDirectVobSubFilter
|
||||
{
|
||||
bool ShouldWeAutoload(IFilterGraph* pGraph);
|
||||
void GetRidOfInternalScriptRenderer();
|
||||
|
||||
public:
|
||||
CDirectVobSubFilter2(LPUNKNOWN punk, HRESULT* phr, const GUID& clsid = __uuidof(CDirectVobSubFilter2));
|
||||
|
||||
HRESULT CheckConnect(PIN_DIRECTION dir, IPin* pPin);
|
||||
STDMETHODIMP JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR pName);
|
||||
HRESULT CheckInputType(const CMediaType* mtIn);
|
||||
};
|
||||
|
1177
vsfilter/DirectVobSubPropPage.cpp
Normal file
1177
vsfilter/DirectVobSubPropPage.cpp
Normal file
File diff suppressed because it is too large
Load diff
207
vsfilter/DirectVobSubPropPage.h
Normal file
207
vsfilter/DirectVobSubPropPage.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <afxcmn.h>
|
||||
#include "IDirectVobSub.h"
|
||||
|
||||
class CDVSBasePPage : public CBasePropertyPage
|
||||
{
|
||||
public:
|
||||
// we have to override these to use external, resource-only dlls
|
||||
STDMETHODIMP GetPageInfo(LPPROPPAGEINFO pPageInfo);
|
||||
STDMETHODIMP Activate(HWND hwndParent, LPCRECT pRect, BOOL fModal);
|
||||
|
||||
protected:
|
||||
CComQIPtr<IDirectVobSub2> m_pDirectVobSub;
|
||||
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) {return(false);}
|
||||
virtual void UpdateObjectData(bool fSave) {}
|
||||
virtual void UpdateControlData(bool fSave) {}
|
||||
|
||||
protected:
|
||||
CDVSBasePPage(TCHAR* pName, LPUNKNOWN lpunk, int DialogId, int TitleId);
|
||||
|
||||
bool m_fDisableInstantUpdate;
|
||||
|
||||
private:
|
||||
BOOL m_bIsInitialized;
|
||||
|
||||
HRESULT OnConnect(IUnknown* pUnknown), OnDisconnect(), OnActivate(), OnDeactivate(), OnApplyChanges();
|
||||
BOOL OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
private:
|
||||
bool m_fAttached;
|
||||
void AttachControls(), DetachControls();
|
||||
|
||||
CMap<UINT, UINT&, CWnd*, CWnd*> m_controls;
|
||||
|
||||
protected:
|
||||
void BindControl(UINT id, CWnd& control);
|
||||
};
|
||||
|
||||
[uuid("60765CF5-01C2-4ee7-A44B-C791CF25FEA0")]
|
||||
class CDVSMainPPage : public CDVSBasePPage
|
||||
{
|
||||
void FreeLangs(), AllocLangs(int nLangs);
|
||||
|
||||
WCHAR m_fn[MAX_PATH];
|
||||
int m_iSelectedLanguage, m_nLangs;
|
||||
WCHAR** m_ppLangs;
|
||||
bool m_fOverridePlacement;
|
||||
int m_PlacementXperc, m_PlacementYperc;
|
||||
STSStyle m_defStyle;
|
||||
bool m_fOnlyShowForcedVobSubs;
|
||||
|
||||
CEdit m_fnedit;
|
||||
CComboBox m_langs;
|
||||
CButton m_oplacement;
|
||||
CSpinButtonCtrl m_subposx, m_subposy;
|
||||
CButton m_font, m_forcedsubs;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSMainPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
virtual ~CDVSMainPPage();
|
||||
};
|
||||
|
||||
[uuid("0180E49C-13BF-46db-9AFD-9F52292E1C22")]
|
||||
class CDVSGeneralPPage : public CDVSBasePPage
|
||||
{
|
||||
int m_HorExt, m_VerExt, m_ResX2, m_ResX2minw, m_ResX2minh;
|
||||
int m_LoadLevel;
|
||||
bool m_fExternalLoad, m_fWebLoad, m_fEmbeddedLoad;
|
||||
|
||||
CComboBox m_verext;
|
||||
CButton m_mod32fix;
|
||||
CComboBox m_resx2;
|
||||
CSpinButtonCtrl m_resx2w, m_resx2h;
|
||||
CComboBox m_load;
|
||||
CButton m_extload, m_webload, m_embload;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSGeneralPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("A8B25C0E-0894-4531-B668-AB1599FAF7F6")]
|
||||
class CDVSMiscPPage : public CDVSBasePPage
|
||||
{
|
||||
bool m_fFlipPicture, m_fFlipSubtitles, m_fHideSubtitles, m_fOSD, m_fDoPreBuffering, m_fReloaderDisabled, m_fSaveFullPath;
|
||||
|
||||
CButton m_flippic, m_flipsub, m_hidesub, m_showosd, m_prebuff, m_autoreload, m_savefullpath, m_instupd;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSMiscPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("ACE4747B-35BD-4e97-9DD7-1D4245B0695C")]
|
||||
class CDVSTimingPPage : public CDVSBasePPage
|
||||
{
|
||||
int m_SubtitleSpeedMul, m_SubtitleSpeedDiv, m_SubtitleDelay;
|
||||
bool m_fMediaFPSEnabled;
|
||||
double m_MediaFPS;
|
||||
|
||||
CButton m_modfps;
|
||||
CEdit m_fps;
|
||||
CSpinButtonCtrl m_subdelay, m_subspeedmul, m_subspeeddiv;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSTimingPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("F544E0F5-CA3C-47ea-A64D-35FCF1602396")]
|
||||
class CDVSAboutPPage : public CDVSBasePPage
|
||||
{
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
public:
|
||||
CDVSAboutPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("525F116F-04AD-40a2-AE2F-A0C4E1AFEF98")]
|
||||
class CDVSZoomPPage : public CDVSBasePPage
|
||||
{
|
||||
NORMALIZEDRECT m_rect;
|
||||
|
||||
CSpinButtonCtrl m_posx, m_posy, m_scalex, m_scaley;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSZoomPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("C2D6D98F-09CA-4524-AF64-1049B5665C9C")]
|
||||
class CDVSColorPPage : public CDVSBasePPage
|
||||
{
|
||||
CListBox m_preflist, m_dynchglist;
|
||||
CButton m_forcergb;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSColorPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("CE77C59C-CFD2-429f-868C-8B04D23F94CA")]
|
||||
class CDVSPathsPPage : public CDVSBasePPage
|
||||
{
|
||||
CStringArray m_paths;
|
||||
|
||||
CListBox m_pathlist;
|
||||
CEdit m_path;
|
||||
CButton m_browse, m_remove, m_add;
|
||||
|
||||
protected:
|
||||
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
virtual void UpdateControlData(bool fSave);
|
||||
virtual void UpdateObjectData(bool fSave);
|
||||
|
||||
public:
|
||||
CDVSPathsPPage(LPUNKNOWN lpunk, HRESULT* phr);
|
||||
};
|
291
vsfilter/IDirectVobSub.h
Normal file
291
vsfilter/IDirectVobSub.h
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "subtitles/STS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
[uuid("EBE1FB08-3957-47ca-AF13-5827E5442E56")]
|
||||
interface IDirectVobSub : public IUnknown
|
||||
{
|
||||
STDMETHOD(get_FileName) (THIS_
|
||||
WCHAR* fn // fn should point to a buffer allocated to at least the length of MAX_PATH (=260)
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_FileName) (THIS_
|
||||
WCHAR* fn
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_LanguageCount) (THIS_
|
||||
int* nLangs
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_LanguageName) (THIS_
|
||||
int iLanguage,
|
||||
WCHAR** ppName // the returned *ppName is allocated with CoTaskMemAlloc
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_SelectedLanguage) (THIS_
|
||||
int* iSelected
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_SelectedLanguage) (THIS_
|
||||
int iSelected
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_HideSubtitles) (THIS_
|
||||
bool* fHideSubtitles
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_HideSubtitles) (THIS_
|
||||
bool fHideSubtitles
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_PreBuffering) (THIS_
|
||||
bool* fDoPreBuffering
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_PreBuffering) (THIS_
|
||||
bool fDoPreBuffering
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_Placement) (THIS_
|
||||
bool* fOverridePlacement,
|
||||
int* xperc,
|
||||
int* yperc
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_Placement) (THIS_
|
||||
bool fOverridePlacement,
|
||||
int xperc,
|
||||
int yperc
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_VobSubSettings) (THIS_
|
||||
bool* fBuffer,
|
||||
bool* fOnlyShowForcedSubs,
|
||||
bool* fPolygonize
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_VobSubSettings) (THIS_
|
||||
bool fBuffer,
|
||||
bool fOnlyShowForcedSubs,
|
||||
bool fPolygonize
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_TextSettings) (THIS_
|
||||
void* lf,
|
||||
int lflen, // depending on lflen, lf must point to LOGFONTA or LOGFONTW
|
||||
COLORREF* color,
|
||||
bool* fShadow,
|
||||
bool* fOutline,
|
||||
bool* fAdvancedRenderer
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_TextSettings) (THIS_
|
||||
void* lf,
|
||||
int lflen,
|
||||
COLORREF color,
|
||||
bool fShadow,
|
||||
bool fOutline,
|
||||
bool fAdvancedRenderer
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_Flip) (THIS_
|
||||
bool* fPicture,
|
||||
bool* fSubtitles
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_Flip) (THIS_
|
||||
bool fPicture,
|
||||
bool fSubtitles
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_OSD) (THIS_
|
||||
bool* fOSD
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_OSD) (THIS_
|
||||
bool fOSD
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_SaveFullPath) (THIS_
|
||||
bool* fSaveFullPath
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_SaveFullPath) (THIS_
|
||||
bool fSaveFullPath
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_SubtitleTiming) (THIS_
|
||||
int* delay,
|
||||
int* speedmul,
|
||||
int* speeddiv
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_SubtitleTiming) (THIS_
|
||||
int delay,
|
||||
int speedmul,
|
||||
int speeddiv
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_MediaFPS) (THIS_
|
||||
bool* fEnabled,
|
||||
double* fps
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_MediaFPS) (THIS_
|
||||
bool fEnabled,
|
||||
double fps
|
||||
) PURE;
|
||||
|
||||
// no longer supported
|
||||
|
||||
STDMETHOD(get_ColorFormat) (THIS_
|
||||
int* iPosition
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_ColorFormat) (THIS_
|
||||
int iPosition
|
||||
) PURE;
|
||||
|
||||
//
|
||||
|
||||
STDMETHOD(get_ZoomRect) (THIS_
|
||||
NORMALIZEDRECT* rect
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_ZoomRect) (THIS_
|
||||
NORMALIZEDRECT* rect
|
||||
) PURE;
|
||||
|
||||
//
|
||||
|
||||
STDMETHOD(UpdateRegistry) (THIS_
|
||||
) PURE;
|
||||
|
||||
//
|
||||
|
||||
STDMETHOD(HasConfigDialog) (THIS_
|
||||
int iSelected
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(ShowConfigDialog) (THIS_ // if available, this will popup a child dialog allowing the user to edit the style options
|
||||
int iSelected,
|
||||
HWND hWndParent
|
||||
) PURE;
|
||||
|
||||
//
|
||||
|
||||
STDMETHOD(IsSubtitleReloaderLocked) (THIS_
|
||||
bool* fLocked
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(LockSubtitleReloader) (THIS_
|
||||
bool fLock
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_SubtitleReloader) (THIS_
|
||||
bool* fDisabled
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_SubtitleReloader) (THIS_
|
||||
bool fDisable
|
||||
) PURE;
|
||||
|
||||
//
|
||||
|
||||
STDMETHOD(get_ExtendPicture) (THIS_
|
||||
int* horizontal, // 0 - disabled, 1 - mod32 extension (width = (width+31)&~31)
|
||||
int* vertical, // 0 - disabled, 1 - 16:9, 2 - 4:3, 0x80 - crop (use crop together with 16:9 or 4:3, eg 0x81 will crop to 16:9 if the picture was taller)
|
||||
int* resx2, // 0 - disabled, 1 - enabled, 2 - depends on the original resolution
|
||||
int* resx2minw, // resolution doubler will be used if width*height <= resx2minw*resx2minh (resx2minw*resx2minh equals to 384*288 by default)
|
||||
int* resx2minh
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_ExtendPicture) (THIS_
|
||||
int horizontal,
|
||||
int vertical,
|
||||
int resx2,
|
||||
int resx2minw,
|
||||
int resx2minh
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_LoadSettings) (THIS_
|
||||
int* level, // 0 - when needed, 1 - always, 2 - disabled
|
||||
bool* fExternalLoad,
|
||||
bool* fWebLoad,
|
||||
bool* fEmbeddedLoad
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_LoadSettings) (THIS_
|
||||
int level,
|
||||
bool fExternalLoad,
|
||||
bool fWebLoad,
|
||||
bool fEmbeddedLoad
|
||||
) PURE;
|
||||
};
|
||||
|
||||
[uuid("FE6EC6A0-21CA-4970-9EF0-B296F7F38AF0")]
|
||||
interface ISubClock : public IUnknown
|
||||
{
|
||||
STDMETHOD(SetTime)(REFERENCE_TIME rt) PURE;
|
||||
STDMETHOD_(REFERENCE_TIME, GetTime)() PURE;
|
||||
};
|
||||
|
||||
[uuid("0665B760-FBC1-46C3-A35F-E471527C96A4")]
|
||||
interface ISubClock2 : public ISubClock
|
||||
{
|
||||
STDMETHOD(SetAvgTimePerFrame)(REFERENCE_TIME rt) PURE;
|
||||
STDMETHOD(GetAvgTimePerFrame)(REFERENCE_TIME* prt) PURE; // return S_OK only if *prt was set and is valid
|
||||
};
|
||||
|
||||
[uuid("AB52FC9C-2415-4dca-BC1C-8DCC2EAE8150")]
|
||||
interface IDirectVobSub2 : public IDirectVobSub
|
||||
{
|
||||
STDMETHOD(AdviseSubClock) (THIS_
|
||||
ISubClock* pSubClock
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(bool, get_Forced) (THIS_
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_Forced) (THIS_
|
||||
bool fForced
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(get_TextSettings) (THIS_
|
||||
STSStyle* pDefStyle
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(put_TextSettings) (THIS_
|
||||
STSStyle* pDefStyle
|
||||
) PURE;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
26
vsfilter/StdAfx.cpp
Normal file
26
vsfilter/StdAfx.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// stdafx.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
57
vsfilter/StdAfx.h
Normal file
57
vsfilter/StdAfx.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently,
|
||||
// but are changed infrequently
|
||||
|
||||
#if !defined(AFX_STDAFX_H__E8AD1C3F_323D_4812_A1DE_AA2419CE2AF3__INCLUDED_)
|
||||
#define AFX_STDAFX_H__E8AD1C3F_323D_4812_A1DE_AA2419CE2AF3__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define STRICT
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#define _ATL_APARTMENT_THREADED
|
||||
|
||||
#include <afxwin.h>
|
||||
#include <afxdisp.h>
|
||||
|
||||
#include <atlbase.h>
|
||||
//You may derive a class from CComModule and use it if you want to override
|
||||
//something, but do not change the name of _Module
|
||||
extern CComModule _Module;
|
||||
#include <atlcom.h>
|
||||
|
||||
#define AFX_CLASS AFX_CLASS_IMPORT
|
||||
|
||||
#include <streams.h>
|
||||
#include <dvdmedia.h>
|
||||
#include "dsutil/DSUtil.h"
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__E8AD1C3F_323D_4812_A1DE_AA2419CE2AF3__INCLUDED)
|
282
vsfilter/StyleEditorDialog.cpp
Normal file
282
vsfilter/StyleEditorDialog.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// StyleEditorDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <math.h>
|
||||
#include <afxdlgs.h>
|
||||
#include "StyleEditorDialog.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC(CColorStatic, CStatic)
|
||||
|
||||
BEGIN_MESSAGE_MAP(CColorStatic, CStatic)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CStyleEditorDialog dialog
|
||||
|
||||
IMPLEMENT_DYNAMIC(CStyleEditorDialog, CDialog)
|
||||
CStyleEditorDialog::CStyleEditorDialog(CString title, STSStyle* pstss, CWnd* pParent /*=NULL*/)
|
||||
: CDialog(CStyleEditorDialog::IDD, pParent)
|
||||
, m_title(title)
|
||||
, m_stss(*pstss)
|
||||
, m_pParent(pParent)
|
||||
, m_iCharset(0)
|
||||
, m_spacing(0)
|
||||
, m_angle(0)
|
||||
, m_scalex(0)
|
||||
, m_scaley(0)
|
||||
, m_borderstyle(0)
|
||||
, m_borderwidth(0)
|
||||
, m_shadowdepth(0)
|
||||
, m_screenalignment(0)
|
||||
, m_margin(0,0,0,0)
|
||||
, m_linkalphasliders(FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
CStyleEditorDialog::~CStyleEditorDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
DDX_Control(pDX, IDC_BUTTON1, m_font);
|
||||
DDX_CBIndex(pDX, IDC_COMBO1, m_iCharset);
|
||||
DDX_Control(pDX, IDC_COMBO1, m_charset);
|
||||
DDX_Text(pDX, IDC_EDIT3, m_spacing);
|
||||
DDX_Control(pDX, IDC_SPIN3, m_spacingspin);
|
||||
DDX_Text(pDX, IDC_EDIT11, m_angle);
|
||||
DDX_Control(pDX, IDC_SPIN10, m_anglespin);
|
||||
DDX_Text(pDX, IDC_EDIT5, m_scalex);
|
||||
DDX_Control(pDX, IDC_SPIN4, m_scalexspin);
|
||||
DDX_Text(pDX, IDC_EDIT6, m_scaley);
|
||||
DDX_Control(pDX, IDC_SPIN5, m_scaleyspin);
|
||||
DDX_Radio(pDX, IDC_RADIO1, m_borderstyle);
|
||||
DDX_Text(pDX, IDC_EDIT1, m_borderwidth);
|
||||
DDX_Control(pDX, IDC_SPIN1, m_borderwidthspin);
|
||||
DDX_Text(pDX, IDC_EDIT2, m_shadowdepth);
|
||||
DDX_Control(pDX, IDC_SPIN2, m_shadowdepthspin);
|
||||
DDX_Radio(pDX, IDC_RADIO3, m_screenalignment);
|
||||
DDX_Text(pDX, IDC_EDIT7, m_margin.left);
|
||||
DDX_Control(pDX, IDC_SPIN6, m_marginleftspin);
|
||||
DDX_Text(pDX, IDC_EDIT8, m_margin.right);
|
||||
DDX_Control(pDX, IDC_SPIN7, m_marginrightspin);
|
||||
DDX_Text(pDX, IDC_EDIT9, m_margin.top);
|
||||
DDX_Control(pDX, IDC_SPIN8, m_margintopspin);
|
||||
DDX_Text(pDX, IDC_EDIT10, m_margin.bottom);
|
||||
DDX_Control(pDX, IDC_SPIN9, m_marginbottomspin);
|
||||
DDX_Control(pDX, IDC_COLORPRI, m_color[0]);
|
||||
DDX_Control(pDX, IDC_COLORSEC, m_color[1]);
|
||||
DDX_Control(pDX, IDC_COLOROUTL, m_color[2]);
|
||||
DDX_Control(pDX, IDC_COLORSHAD, m_color[3]);
|
||||
DDX_Slider(pDX, IDC_SLIDER2, m_alpha[0]);
|
||||
DDX_Slider(pDX, IDC_SLIDER3, m_alpha[1]);
|
||||
DDX_Slider(pDX, IDC_SLIDER5, m_alpha[2]);
|
||||
DDX_Slider(pDX, IDC_SLIDER6, m_alpha[3]);
|
||||
DDX_Control(pDX, IDC_SLIDER2, m_alphasliders[0]);
|
||||
DDX_Control(pDX, IDC_SLIDER3, m_alphasliders[1]);
|
||||
DDX_Control(pDX, IDC_SLIDER5, m_alphasliders[2]);
|
||||
DDX_Control(pDX, IDC_SLIDER6, m_alphasliders[3]);
|
||||
DDX_Check(pDX, IDC_CHECK1, m_linkalphasliders);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::UpdateControlData(bool fSave)
|
||||
{
|
||||
if(fSave)
|
||||
{
|
||||
UpdateData();
|
||||
|
||||
if(m_iCharset >= 0) m_stss.charSet = m_charset.GetItemData(m_iCharset);
|
||||
m_stss.fontSpacing = m_spacing;
|
||||
m_stss.fontAngleZ = m_angle;
|
||||
m_stss.fontScaleX = m_scalex;
|
||||
m_stss.fontScaleY = m_scaley;
|
||||
|
||||
m_stss.borderStyle = m_borderstyle;
|
||||
m_stss.outlineWidth = m_borderwidth;
|
||||
m_stss.shadowDepth = m_shadowdepth;
|
||||
|
||||
m_stss.scrAlignment = m_screenalignment+1;
|
||||
m_stss.marginRect = m_margin;
|
||||
|
||||
for(int i = 0; i < 4; i++) m_stss.alpha[i] = 255-m_alpha[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_font.SetWindowText(m_stss.fontName);
|
||||
m_iCharset = -1;
|
||||
for(int i = 0; i < CharSetLen; i++)
|
||||
{
|
||||
CString str;
|
||||
str.Format(_T("%s (%d)"), CharSetNames[i], CharSetList[i]);
|
||||
m_charset.AddString(str);
|
||||
m_charset.SetItemData(i, CharSetList[i]);
|
||||
if(m_stss.charSet == CharSetList[i]) m_iCharset = i;
|
||||
}
|
||||
// TODO: allow floats in these edit boxes
|
||||
m_spacing = m_stss.fontSpacing;
|
||||
m_spacingspin.SetRange32(-10000, 10000);
|
||||
while(m_stss.fontAngleZ < 0) m_stss.fontAngleZ += 360;
|
||||
m_angle = fmod(m_stss.fontAngleZ, 360);
|
||||
m_anglespin.SetRange32(0, 359);
|
||||
m_scalex = m_stss.fontScaleX;
|
||||
m_scalexspin.SetRange32(-10000, 10000);
|
||||
m_scaley = m_stss.fontScaleY;
|
||||
m_scaleyspin.SetRange32(-10000, 10000);
|
||||
|
||||
m_borderstyle = m_stss.borderStyle;
|
||||
m_borderwidth = m_stss.outlineWidth;
|
||||
m_borderwidthspin.SetRange32(0, 10000);
|
||||
m_shadowdepth = m_stss.shadowDepth;
|
||||
m_shadowdepthspin.SetRange32(0, 10000);
|
||||
|
||||
m_screenalignment = m_stss.scrAlignment-1;
|
||||
m_margin = m_stss.marginRect;
|
||||
m_marginleftspin.SetRange32(-10000, 10000);
|
||||
m_marginrightspin.SetRange32(-10000, 10000);
|
||||
m_margintopspin.SetRange32(-10000, 10000);
|
||||
m_marginbottomspin.SetRange32(-10000, 10000);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
m_color[i].SetColorPtr(&m_stss.colors[i]);
|
||||
m_alpha[i] = 255-m_stss.alpha[i];
|
||||
m_alphasliders[i].SetRange(0, 255);
|
||||
}
|
||||
|
||||
m_linkalphasliders = FALSE;
|
||||
|
||||
UpdateData(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::AskColor(int i)
|
||||
{
|
||||
CColorDialog dlg(m_stss.colors[i]);
|
||||
dlg.m_cc.Flags |= CC_FULLOPEN;
|
||||
if(dlg.DoModal() == IDOK)
|
||||
{
|
||||
m_stss.colors[i] = dlg.m_cc.rgbResult;
|
||||
m_color[i].Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CStyleEditorDialog, CDialog)
|
||||
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
|
||||
ON_STN_CLICKED(IDC_COLORPRI, OnStnClickedColorpri)
|
||||
ON_STN_CLICKED(IDC_COLORSEC, OnStnClickedColorsec)
|
||||
ON_STN_CLICKED(IDC_COLOROUTL, OnStnClickedColoroutl)
|
||||
ON_STN_CLICKED(IDC_COLORSHAD, OnStnClickedColorshad)
|
||||
ON_BN_CLICKED(IDC_CHECK1, OnBnClickedCheck1)
|
||||
ON_WM_HSCROLL()
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CStyleEditorDialog message handlers
|
||||
|
||||
BOOL CStyleEditorDialog::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
SetWindowText(_T("Style Editor - \"") + m_title + _T("\""));
|
||||
|
||||
UpdateControlData(false);
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnOK()
|
||||
{
|
||||
UpdateControlData(true);
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnBnClickedButton1()
|
||||
{
|
||||
LOGFONT lf;
|
||||
lf <<= m_stss;
|
||||
|
||||
CFontDialog dlg(&lf, CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT|CF_FORCEFONTEXIST|CF_SCALABLEONLY|CF_EFFECTS);
|
||||
if(dlg.DoModal() == IDOK)
|
||||
{
|
||||
CString str(lf.lfFaceName);
|
||||
if(str.GetLength() > 16) str = str.Left(14) + _T("...");
|
||||
m_font.SetWindowText(str);
|
||||
|
||||
for(int i = 0, j = m_charset.GetCount(); i < j; i++)
|
||||
{
|
||||
if(m_charset.GetItemData(i) == lf.lfCharSet)
|
||||
{
|
||||
m_charset.SetCurSel(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_stss = lf;
|
||||
}
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnStnClickedColorpri()
|
||||
{
|
||||
AskColor(0);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnStnClickedColorsec()
|
||||
{
|
||||
AskColor(1);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnStnClickedColoroutl()
|
||||
{
|
||||
AskColor(2);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnStnClickedColorshad()
|
||||
{
|
||||
AskColor(3);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnBnClickedCheck1()
|
||||
{
|
||||
UpdateData();
|
||||
|
||||
int avg = 0;
|
||||
for(int i = 0; i < 4; i++) avg += m_alphasliders[i].GetPos();
|
||||
avg /= 4;
|
||||
for(int i = 0; i < 4; i++) m_alphasliders[i].SetPos(avg);
|
||||
}
|
||||
|
||||
void CStyleEditorDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
||||
{
|
||||
if(m_linkalphasliders && pScrollBar)
|
||||
{
|
||||
int pos = ((CSliderCtrl*)pScrollBar)->GetPos();
|
||||
for(int i = 0; i < 4; i++) m_alphasliders[i].SetPos(pos);
|
||||
}
|
||||
|
||||
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
|
||||
}
|
116
vsfilter/StyleEditorDialog.h
Normal file
116
vsfilter/StyleEditorDialog.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "resource.h"
|
||||
#include "afxwin.h"
|
||||
#include "afxcmn.h"
|
||||
#include "subtitles/STS.h"
|
||||
|
||||
// CColorStatic dialog
|
||||
|
||||
class CColorStatic : public CStatic
|
||||
{
|
||||
DECLARE_DYNAMIC(CColorStatic)
|
||||
|
||||
COLORREF* m_pColor;
|
||||
|
||||
public:
|
||||
CColorStatic(CWnd* pParent = NULL) : m_pColor(NULL) {}
|
||||
virtual ~CColorStatic() {}
|
||||
|
||||
void SetColorPtr(COLORREF* pColor) {m_pColor = pColor;}
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
protected:
|
||||
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
||||
{
|
||||
CRect r;
|
||||
GetClientRect(r);
|
||||
CDC::FromHandle(lpDrawItemStruct->hDC)->FillSolidRect(r, m_pColor ? *m_pColor : ::GetSysColor(COLOR_BTNFACE));
|
||||
}
|
||||
};
|
||||
|
||||
// CStyleEditorDialog dialog
|
||||
|
||||
class CStyleEditorDialog : public CDialog
|
||||
{
|
||||
DECLARE_DYNAMIC(CStyleEditorDialog)
|
||||
|
||||
CString m_title;
|
||||
CWnd* m_pParent;
|
||||
|
||||
void UpdateControlData(bool fSave);
|
||||
void AskColor(int i);
|
||||
|
||||
public:
|
||||
CStyleEditorDialog(CString title, STSStyle* pstss, CWnd* pParent = NULL); // standard constructor
|
||||
virtual ~CStyleEditorDialog();
|
||||
|
||||
// Dialog Data
|
||||
enum { IDD = IDD_STYLEDIALOG };
|
||||
|
||||
STSStyle m_stss;
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
CButton m_font;
|
||||
int m_iCharset;
|
||||
CComboBox m_charset;
|
||||
int m_spacing;
|
||||
CSpinButtonCtrl m_spacingspin;
|
||||
int m_angle;
|
||||
CSpinButtonCtrl m_anglespin;
|
||||
int m_scalex;
|
||||
CSpinButtonCtrl m_scalexspin;
|
||||
int m_scaley;
|
||||
CSpinButtonCtrl m_scaleyspin;
|
||||
int m_borderstyle;
|
||||
int m_borderwidth;
|
||||
CSpinButtonCtrl m_borderwidthspin;
|
||||
int m_shadowdepth;
|
||||
CSpinButtonCtrl m_shadowdepthspin;
|
||||
int m_screenalignment;
|
||||
CRect m_margin;
|
||||
CSpinButtonCtrl m_marginleftspin;
|
||||
CSpinButtonCtrl m_marginrightspin;
|
||||
CSpinButtonCtrl m_margintopspin;
|
||||
CSpinButtonCtrl m_marginbottomspin;
|
||||
CColorStatic m_color[4];
|
||||
int m_alpha[4];
|
||||
CSliderCtrl m_alphasliders[4];
|
||||
BOOL m_linkalphasliders;
|
||||
|
||||
afx_msg void OnBnClickedButton1();
|
||||
afx_msg void OnStnClickedColorpri();
|
||||
afx_msg void OnStnClickedColorsec();
|
||||
afx_msg void OnStnClickedColoroutl();
|
||||
afx_msg void OnStnClickedColorshad();
|
||||
afx_msg void OnBnClickedCheck1();
|
||||
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
};
|
421
vsfilter/Systray.cpp
Normal file
421
vsfilter/Systray.cpp
Normal file
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "DirectVobSubFilter.h"
|
||||
#include "DSUtil/DSUtil.h"
|
||||
|
||||
// hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
|
||||
static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd);
|
||||
|
||||
static HHOOK g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
|
||||
|
||||
static UINT WM_DVSPREVSUB = RegisterWindowMessage(TEXT("WM_DVSPREVSUB"));
|
||||
static UINT WM_DVSNEXTSUB = RegisterWindowMessage(TEXT("WM_DVSNEXTSUB"));
|
||||
static UINT WM_DVSHIDESUB = RegisterWindowMessage(TEXT("WM_DVSHIDESUB"));
|
||||
static UINT WM_DVSSHOWSUB = RegisterWindowMessage(TEXT("WM_DVSSHOWSUB"));
|
||||
static UINT WM_DVSSHOWHIDESUB = RegisterWindowMessage(TEXT("WM_DVSSHOWHIDESUB"));
|
||||
static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||
static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
|
||||
|
||||
LRESULT CALLBACK HookProc(UINT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
MSG* msg = (MSG*)lParam;
|
||||
|
||||
if(msg->message == WM_KEYDOWN)
|
||||
{
|
||||
switch(msg->wParam)
|
||||
{
|
||||
case VK_F13: PostMessage(HWND_BROADCAST, WM_DVSPREVSUB, 0, 0); break;
|
||||
case VK_F14: PostMessage(HWND_BROADCAST, WM_DVSNEXTSUB, 0, 0); break;
|
||||
case VK_F15: PostMessage(HWND_BROADCAST, WM_DVSHIDESUB, 0, 0); break;
|
||||
case VK_F16: PostMessage(HWND_BROADCAST, WM_DVSSHOWSUB, 0, 0); break;
|
||||
case VK_F17: PostMessage(HWND_BROADCAST, WM_DVSSHOWHIDESUB, 0, 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Always call next hook in chain
|
||||
return CallNextHookEx(g_hHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
class CSystrayWindow : public CWnd
|
||||
{
|
||||
SystrayIconData* m_tbid;
|
||||
|
||||
void StepSub(int dir)
|
||||
{
|
||||
int iSelected, nLangs;
|
||||
if(FAILED(m_tbid->dvs->get_LanguageCount(&nLangs))) return;
|
||||
if(FAILED(m_tbid->dvs->get_SelectedLanguage(&iSelected))) return;
|
||||
if(nLangs > 0) m_tbid->dvs->put_SelectedLanguage((iSelected+dir+nLangs)%nLangs);
|
||||
}
|
||||
|
||||
void ShowSub(bool fShow)
|
||||
{
|
||||
m_tbid->dvs->put_HideSubtitles(!fShow);
|
||||
}
|
||||
|
||||
void ToggleSub()
|
||||
{
|
||||
bool fShow;
|
||||
if(FAILED(m_tbid->dvs->get_HideSubtitles(&fShow))) return;
|
||||
m_tbid->dvs->put_HideSubtitles(!fShow);
|
||||
}
|
||||
|
||||
public:
|
||||
CSystrayWindow(SystrayIconData* tbid) : m_tbid(tbid) {}
|
||||
|
||||
protected:
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnDestroy();
|
||||
afx_msg void OnTimer(UINT nIDEvent);
|
||||
afx_msg LRESULT OnDVSPrevSub(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnDVSNextSub(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnDVSHideSub(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnDVSShowSub(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnDVSShowHideSub(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnTaskBarRestart(WPARAM, LPARAM);
|
||||
afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM);
|
||||
};
|
||||
|
||||
BEGIN_MESSAGE_MAP(CSystrayWindow, CWnd)
|
||||
ON_WM_CREATE()
|
||||
ON_WM_CLOSE()
|
||||
ON_WM_DESTROY()
|
||||
ON_WM_TIMER()
|
||||
ON_REGISTERED_MESSAGE(WM_DVSPREVSUB, OnDVSPrevSub)
|
||||
ON_REGISTERED_MESSAGE(WM_DVSNEXTSUB, OnDVSNextSub)
|
||||
ON_REGISTERED_MESSAGE(WM_DVSHIDESUB, OnDVSHideSub)
|
||||
ON_REGISTERED_MESSAGE(WM_DVSSHOWSUB, OnDVSShowSub)
|
||||
ON_REGISTERED_MESSAGE(WM_DVSSHOWHIDESUB, OnDVSShowHideSub)
|
||||
ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
|
||||
ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
int CSystrayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
if(CWnd::OnCreate(lpCreateStruct) == -1)
|
||||
return -1;
|
||||
|
||||
if(g_hHook == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
// g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, AfxGetInstanceHandle(), 0);
|
||||
}
|
||||
|
||||
SetTimer(1, 5000, NULL);
|
||||
|
||||
PostMessage(s_uTaskbarRestart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSystrayWindow::OnClose()
|
||||
{
|
||||
DestroyWindow();
|
||||
}
|
||||
|
||||
void CSystrayWindow::OnDestroy()
|
||||
{
|
||||
NOTIFYICONDATA tnid;
|
||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
tnid.hWnd = m_hWnd;
|
||||
tnid.uID = IDI_ICON1;
|
||||
Shell_NotifyIcon(NIM_DELETE, &tnid);
|
||||
|
||||
if(g_hHook != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
UnhookWindowsHookEx(g_hHook);
|
||||
g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
void CSystrayWindow::OnTimer(UINT nIDEvent)
|
||||
{
|
||||
if(nIDEvent == 1)
|
||||
{
|
||||
UINT fScreenSaver = 0;
|
||||
if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fScreenSaver, 0))
|
||||
{
|
||||
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
|
||||
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fScreenSaver, 0, SPIF_SENDWININICHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
CWnd::OnTimer(nIDEvent);
|
||||
}
|
||||
|
||||
LRESULT CSystrayWindow::OnDVSPrevSub(WPARAM, LPARAM)
|
||||
{StepSub(-1); return 0;}
|
||||
LRESULT CSystrayWindow::OnDVSNextSub(WPARAM, LPARAM)
|
||||
{StepSub(+1); return 0;}
|
||||
LRESULT CSystrayWindow::OnDVSHideSub(WPARAM, LPARAM)
|
||||
{ShowSub(false); return 0;}
|
||||
LRESULT CSystrayWindow::OnDVSShowSub(WPARAM, LPARAM)
|
||||
{ShowSub(true); return 0;}
|
||||
LRESULT CSystrayWindow::OnDVSShowHideSub(WPARAM, LPARAM)
|
||||
{ToggleSub(); return 0;}
|
||||
|
||||
LRESULT CSystrayWindow::OnTaskBarRestart(WPARAM, LPARAM)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
if(m_tbid->fShowIcon)
|
||||
{
|
||||
NOTIFYICONDATA tnid;
|
||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
tnid.hWnd = m_hWnd;
|
||||
tnid.uID = IDI_ICON1;
|
||||
tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1));
|
||||
// tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_LOADTRANSPARENT);
|
||||
tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
|
||||
tnid.uCallbackMessage = WM_NOTIFYICON;
|
||||
lstrcpyn(tnid.szTip, TEXT("DirectVobSub"), sizeof(tnid.szTip));
|
||||
|
||||
BOOL res = Shell_NotifyIcon(NIM_ADD, &tnid);
|
||||
|
||||
if(tnid.hIcon) DestroyIcon(tnid.hIcon);
|
||||
|
||||
return res?0:-1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CSystrayWindow::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if((UINT)wParam != IDI_ICON1)
|
||||
return -1;
|
||||
|
||||
HWND hWnd = m_hWnd;
|
||||
|
||||
switch((UINT)lParam)
|
||||
{
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
// IMPORTANT: we must not hold the graph at the same time as showing the property page
|
||||
// or else when closing the app the graph doesn't get released and dvobsub's JoinFilterGraph
|
||||
// is never called to close us down.
|
||||
|
||||
CComPtr<IBaseFilter> pBF2;
|
||||
|
||||
BeginEnumFilters(m_tbid->graph, pEF, pBF)
|
||||
{
|
||||
if(!CComQIPtr<IDirectVobSub>(pBF))
|
||||
continue;
|
||||
|
||||
if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
|
||||
{
|
||||
HWND hwnd;
|
||||
if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
|
||||
|| SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
|
||||
hWnd = hwnd;
|
||||
}
|
||||
|
||||
pBF2 = pBF;
|
||||
|
||||
break;
|
||||
}
|
||||
EndEnumFilters
|
||||
|
||||
if(pBF2)
|
||||
ShowPPage(pBF2, hWnd);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
POINT p;
|
||||
GetCursorPos(&p);
|
||||
|
||||
CInterfaceArray<IAMStreamSelect> pStreams;
|
||||
CStringArray names;
|
||||
|
||||
BeginEnumFilters(m_tbid->graph, pEF, pBF)
|
||||
{
|
||||
CString name = GetFilterName(pBF);
|
||||
if(name.IsEmpty()) continue;
|
||||
|
||||
if(CComQIPtr<IAMStreamSelect> pSS = pBF)
|
||||
{
|
||||
pStreams.Add(pSS);
|
||||
names.Add(name);
|
||||
}
|
||||
}
|
||||
EndEnumFilters
|
||||
|
||||
CMenu popup;
|
||||
popup.CreatePopupMenu();
|
||||
|
||||
for(int j = 0; j < pStreams.GetCount(); j++)
|
||||
{
|
||||
bool fMMSwitcher = !names[j].Compare(_T("Morgan Stream Switcher"));
|
||||
|
||||
DWORD cStreams = 0;
|
||||
pStreams[j]->Count(&cStreams);
|
||||
|
||||
DWORD flags, group, prevgroup = -1;
|
||||
|
||||
for(UINT i = 0; i < cStreams; i++)
|
||||
{
|
||||
WCHAR* pName = NULL;
|
||||
|
||||
if(S_OK == pStreams[j]->Info(i, 0, &flags, 0, &group, &pName, 0, 0))
|
||||
{
|
||||
if(prevgroup != group && i > 1)
|
||||
{
|
||||
if(fMMSwitcher) {cStreams = i; break;}
|
||||
popup.AppendMenu(MF_SEPARATOR);
|
||||
}
|
||||
prevgroup = group;
|
||||
|
||||
if(pName)
|
||||
{
|
||||
popup.AppendMenu(MF_ENABLED|MF_STRING|(flags?MF_CHECKED:MF_UNCHECKED), (1<<15)|(j<<8)|(i), CString(pName));
|
||||
CoTaskMemFree(pName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cStreams > 0) popup.AppendMenu(MF_SEPARATOR);
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
TCHAR* str;
|
||||
for(i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++)
|
||||
{
|
||||
if(_tcsncmp(str, _T("DivX MPEG"), 9) || m_tbid->fRunOnce) // divx3's ppage will crash if the graph hasn't been run at least once yet
|
||||
popup.AppendMenu(MF_ENABLED|MF_STRING|MF_UNCHECKED, (1<<14)|(i), str);
|
||||
|
||||
delete [] str;
|
||||
}
|
||||
|
||||
SetForegroundWindow();
|
||||
UINT id = popup.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, CWnd::FromHandle(hWnd), 0);
|
||||
PostMessage(WM_NULL);
|
||||
|
||||
if(id & (1<<15))
|
||||
{
|
||||
pStreams[(id>>8)&0x3f]->Enable(id&0xff, AMSTREAMSELECTENABLE_ENABLE);
|
||||
}
|
||||
else if(id & (1<<14))
|
||||
{
|
||||
if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
|
||||
{
|
||||
HWND hwnd;
|
||||
if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
|
||||
|| SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
|
||||
hWnd = hwnd;
|
||||
}
|
||||
|
||||
CallPPage(m_tbid->graph, id&0xff, hWnd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
DWORD CALLBACK SystrayThreadProc(void* pParam)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
CSystrayWindow wnd((SystrayIconData*)pParam);
|
||||
if(!wnd.CreateEx(0, AfxRegisterWndClass(0), _T("DVSWND"), WS_OVERLAPPED, CRect(0, 0, 0, 0), NULL, 0, NULL))
|
||||
return -1;
|
||||
|
||||
((SystrayIconData*)pParam)->hSystrayWnd = wnd.m_hWnd;
|
||||
|
||||
MSG msg;
|
||||
while(GetMessage(&msg, NULL/*wnd.m_hWnd*/, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: replace this function
|
||||
|
||||
// hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
|
||||
static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd)
|
||||
{
|
||||
int i = 0;
|
||||
bool fFound = false;
|
||||
|
||||
WCHAR* wstr = NULL;
|
||||
CComPtr<IBaseFilter> pFilter;
|
||||
CAUUID caGUID;
|
||||
caGUID.pElems = NULL;
|
||||
|
||||
BeginEnumFilters(pGraph, pEF, pBF)
|
||||
{
|
||||
CComQIPtr<ISpecifyPropertyPages> pSPS = pBF;
|
||||
if(!pSPS) continue;
|
||||
|
||||
if(i == idx)
|
||||
{
|
||||
pFilter = pBF;
|
||||
pSPS->GetPages(&caGUID);
|
||||
wstr = _wcsdup(CStringW(GetFilterName(pBF))); // double char-wchar conversion happens in the non-unicode build, but anyway... :)
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
EndEnumFilters
|
||||
|
||||
TCHAR* ret = NULL;
|
||||
|
||||
if(pFilter)
|
||||
{
|
||||
if(hWnd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ShowPPage(pFilter, hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ret = new TCHAR[wcslen(wstr)+1])
|
||||
_tcscpy(ret, CString(wstr));
|
||||
}
|
||||
}
|
||||
|
||||
if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
|
||||
if(wstr) free(wstr);
|
||||
|
||||
return(ret);
|
||||
}
|
24
vsfilter/Systray.h
Normal file
24
vsfilter/Systray.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern DWORD CALLBACK SystrayThreadProc(void* pParam);
|
46
vsfilter/TextInputPin.cpp
Normal file
46
vsfilter/TextInputPin.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DirectVobSubFilter.h"
|
||||
#include "TextInputPin.h"
|
||||
#include "DSUtil/DSUtil.h"
|
||||
|
||||
CTextInputPin::CTextInputPin(CDirectVobSubFilter* pFilter, CCritSec* pLock, CCritSec* pSubLock, HRESULT* phr)
|
||||
: CSubtitleInputPin(pFilter, pLock, pSubLock, phr)
|
||||
, m_pDVS(pFilter)
|
||||
{
|
||||
}
|
||||
|
||||
void CTextInputPin::AddSubStream(ISubStream* pSubStream)
|
||||
{
|
||||
m_pDVS->AddSubStream(pSubStream);
|
||||
}
|
||||
|
||||
void CTextInputPin::RemoveSubStream(ISubStream* pSubStream)
|
||||
{
|
||||
m_pDVS->RemoveSubStream(pSubStream);
|
||||
}
|
||||
|
||||
void CTextInputPin::InvalidateSubtitle(REFERENCE_TIME rtStart, ISubStream* pSubStream)
|
||||
{
|
||||
m_pDVS->InvalidateSubtitle(rtStart, (DWORD_PTR)(ISubStream*)pSubStream);
|
||||
}
|
40
vsfilter/TextInputPin.h
Normal file
40
vsfilter/TextInputPin.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "subtitles/SubtitleInputPin.h"
|
||||
|
||||
class CDirectVobSubFilter;
|
||||
|
||||
class CTextInputPin : public CSubtitleInputPin
|
||||
{
|
||||
CDirectVobSubFilter* m_pDVS;
|
||||
|
||||
protected:
|
||||
void AddSubStream(ISubStream* pSubStream);
|
||||
void RemoveSubStream(ISubStream* pSubStream);
|
||||
void InvalidateSubtitle(REFERENCE_TIME rtStart, ISubStream* pSubStream);
|
||||
|
||||
public:
|
||||
CTextInputPin(CDirectVobSubFilter* pFilter, CCritSec* pLock, CCritSec* pSubLock, HRESULT* phr);
|
||||
};
|
||||
|
178
vsfilter/VSFilter.cpp
Normal file
178
vsfilter/VSFilter.cpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DirectVobSubFilter.h"
|
||||
#include "DirectVobSubPropPage.h"
|
||||
#include "VSFilter.h"
|
||||
#include "DSUtil/MediaTypes.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include "include/moreuuids.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CVSFilterApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CVSFilterApp, CWinApp)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
CVSFilterApp::CVSFilterApp()
|
||||
{
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
|
||||
|
||||
BOOL CVSFilterApp::InitInstance()
|
||||
{
|
||||
if(!CWinApp::InitInstance())
|
||||
return FALSE;
|
||||
|
||||
SetRegistryKey(_T("Gabest"));
|
||||
|
||||
DllEntryPoint(AfxGetInstanceHandle(), DLL_PROCESS_ATTACH, 0); // "DllMain" of the dshow baseclasses
|
||||
|
||||
STARTUPINFO si;
|
||||
GetStartupInfo(&si);
|
||||
m_AppName = CString(si.lpTitle);
|
||||
m_AppName.Replace('\\', '/');
|
||||
m_AppName = m_AppName.Mid(m_AppName.ReverseFind('/')+1);
|
||||
m_AppName.MakeLower();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int CVSFilterApp::ExitInstance()
|
||||
{
|
||||
DllEntryPoint(AfxGetInstanceHandle(), DLL_PROCESS_DETACH, 0); // "DllMain" of the dshow baseclasses
|
||||
|
||||
return CWinApp::ExitInstance();
|
||||
}
|
||||
|
||||
HINSTANCE CVSFilterApp::LoadAppLangResourceDLL()
|
||||
{
|
||||
CString fn;
|
||||
fn.ReleaseBufferSetLength(::GetModuleFileName(m_hInstance, fn.GetBuffer(MAX_PATH), MAX_PATH));
|
||||
fn = fn.Mid(fn.ReverseFind('\\')+1);
|
||||
fn = fn.Left(fn.ReverseFind('.')+1);
|
||||
fn = fn + _T("lang");
|
||||
return ::LoadLibrary(fn);
|
||||
}
|
||||
|
||||
CVSFilterApp theApp;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
|
||||
{
|
||||
{&MEDIATYPE_NULL, &MEDIASUBTYPE_NULL},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_YUY2},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_YV12},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_I420},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_IYUV},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_RGB565},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_RGB555},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_RGB24},
|
||||
};
|
||||
|
||||
const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
|
||||
{
|
||||
{&MEDIATYPE_Text, &MEDIASUBTYPE_None},
|
||||
};
|
||||
|
||||
const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
|
||||
{
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_None},
|
||||
};
|
||||
|
||||
const AMOVIESETUP_PIN sudpPins[] =
|
||||
{
|
||||
{L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
|
||||
{L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut},
|
||||
{L"Input2", TRUE, FALSE, FALSE, TRUE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2}
|
||||
};
|
||||
|
||||
/*const*/ AMOVIESETUP_FILTER sudFilter[] =
|
||||
{
|
||||
{&__uuidof(CDirectVobSubFilter), L"DirectVobSub", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins},
|
||||
{&__uuidof(CDirectVobSubFilter2), L"DirectVobSub (auto-loading version)", MERIT_PREFERRED+2, countof(sudpPins), sudpPins},
|
||||
};
|
||||
|
||||
CFactoryTemplate g_Templates[] =
|
||||
{
|
||||
{sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CDirectVobSubFilter>, NULL, &sudFilter[0]},
|
||||
{sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CDirectVobSubFilter2>, NULL, &sudFilter[1]},
|
||||
{L"DVSMainPPage", &__uuidof(CDVSMainPPage), CreateInstance<CDVSMainPPage>},
|
||||
{L"DVSGeneralPPage", &__uuidof(CDVSGeneralPPage), CreateInstance<CDVSGeneralPPage>},
|
||||
{L"DVSMiscPPage", &__uuidof(CDVSMiscPPage), CreateInstance<CDVSMiscPPage>},
|
||||
{L"DVSTimingPPage", &__uuidof(CDVSTimingPPage), CreateInstance<CDVSTimingPPage>},
|
||||
{L"DVSZoomPPage", &__uuidof(CDVSZoomPPage), CreateInstance<CDVSZoomPPage>},
|
||||
{L"DVSColorPPage", &__uuidof(CDVSColorPPage), CreateInstance<CDVSColorPPage>},
|
||||
{L"DVSPathsPPage", &__uuidof(CDVSPathsPPage), CreateInstance<CDVSPathsPPage>},
|
||||
{L"DVSAboutPPage", &__uuidof(CDVSAboutPPage), CreateInstance<CDVSAboutPPage>},
|
||||
};
|
||||
|
||||
int g_cTemplates = countof(g_Templates);
|
||||
|
||||
//////////////////////////////
|
||||
/*removeme*/
|
||||
extern void JajDeGonoszVagyok();
|
||||
|
||||
STDAPI DllRegisterServer()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
if(theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SEENDIVXWARNING), 0) != 1)
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_SEENDIVXWARNING), 0);
|
||||
|
||||
if(theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_VMRZOOMENABLED), -1) == -1)
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_VMRZOOMENABLED), 0);
|
||||
|
||||
if(theApp.GetProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_ENABLEZPICON), -1) == -1)
|
||||
theApp.WriteProfileInt(ResStr(IDS_R_GENERAL), ResStr(IDS_RG_ENABLEZPICON), 0);
|
||||
|
||||
/*removeme*/
|
||||
JajDeGonoszVagyok();
|
||||
|
||||
return AMovieDllRegisterServer2(TRUE);
|
||||
}
|
||||
|
||||
STDAPI DllUnregisterServer()
|
||||
{
|
||||
// DVS_WriteProfileInt2(IDS_R_GENERAL, IDS_RG_SEENDIVXWARNING, 0);
|
||||
|
||||
return AMovieDllRegisterServer2(FALSE);
|
||||
}
|
||||
|
||||
void CALLBACK DirectVobSub(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
if(FAILED(::CoInitialize(0))) return;
|
||||
|
||||
CComPtr<IBaseFilter> pFilter;
|
||||
CComQIPtr<ISpecifyPropertyPages> pSpecify;
|
||||
|
||||
if(SUCCEEDED(pFilter.CoCreateInstance(__uuidof(CDirectVobSubFilter))) && (pSpecify = pFilter))
|
||||
{
|
||||
ShowPPage(pFilter, hwnd);
|
||||
}
|
||||
|
||||
::CoUninitialize();
|
||||
}
|
10
vsfilter/VSFilter.def
Normal file
10
vsfilter/VSFilter.def
Normal file
|
@ -0,0 +1,10 @@
|
|||
; VSFilter.def : Declares the module parameters.
|
||||
|
||||
LIBRARY "VSFilter.dll"
|
||||
|
||||
EXPORTS
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllGetClassObject PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
DirectVobSub
|
45
vsfilter/VSFilter.h
Normal file
45
vsfilter/VSFilter.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
class CVSFilterApp : public CWinApp
|
||||
{
|
||||
public:
|
||||
CVSFilterApp();
|
||||
|
||||
CString m_AppName;
|
||||
|
||||
protected:
|
||||
HINSTANCE LoadAppLangResourceDLL();
|
||||
|
||||
public:
|
||||
BOOL InitInstance();
|
||||
BOOL ExitInstance();
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
extern CVSFilterApp theApp;
|
||||
|
||||
#define ResStr(id) CString(MAKEINTRESOURCE(id))
|
666
vsfilter/basevideofilter/BaseVideoFilter.cpp
Normal file
666
vsfilter/basevideofilter/BaseVideoFilter.cpp
Normal file
|
@ -0,0 +1,666 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include <mmintrin.h>
|
||||
#include "BaseVideoFilter.h"
|
||||
#include "../dsutil/DSUtil.h"
|
||||
#include "../dsutil/MediaTypes.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include "../include/moreuuids.h"
|
||||
|
||||
//
|
||||
// CBaseVideoFilter
|
||||
//
|
||||
|
||||
CBaseVideoFilter::CBaseVideoFilter(TCHAR* pName, LPUNKNOWN lpunk, HRESULT* phr, REFCLSID clsid, long cBuffers)
|
||||
: CTransformFilter(pName, lpunk, clsid)
|
||||
, m_cBuffers(cBuffers)
|
||||
{
|
||||
if(phr) *phr = S_OK;
|
||||
|
||||
if(!(m_pInput = new CBaseVideoInputPin(NAME("CBaseVideoInputPin"), this, phr, L"Video"))) *phr = E_OUTOFMEMORY;
|
||||
if(FAILED(*phr)) return;
|
||||
|
||||
if(!(m_pOutput = new CBaseVideoOutputPin(NAME("CBaseVideoOutputPin"), this, phr, L"Output"))) *phr = E_OUTOFMEMORY;
|
||||
if(FAILED(*phr)) {delete m_pInput, m_pInput = NULL; return;}
|
||||
|
||||
m_wout = m_win = m_w = 0;
|
||||
m_hout = m_hin = m_h = 0;
|
||||
m_arxout = m_arxin = m_arx = 0;
|
||||
m_aryout = m_aryin = m_ary = 0;
|
||||
}
|
||||
|
||||
CBaseVideoFilter::~CBaseVideoFilter()
|
||||
{
|
||||
}
|
||||
|
||||
int CBaseVideoFilter::GetPinCount()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
CBasePin* CBaseVideoFilter::GetPin(int n)
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0: return m_pInput;
|
||||
case 1: return m_pOutput;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::Receive(IMediaSample* pIn)
|
||||
{
|
||||
_mm_empty(); // just for safety
|
||||
|
||||
CAutoLock cAutoLock(&m_csReceive);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
|
||||
if(pProps->dwStreamId != AM_STREAM_MEDIA)
|
||||
return m_pOutput->Deliver(pIn);
|
||||
|
||||
AM_MEDIA_TYPE* pmt;
|
||||
if(SUCCEEDED(pIn->GetMediaType(&pmt)) && pmt)
|
||||
{
|
||||
CMediaType mt(*pmt);
|
||||
m_pInput->SetMediaType(&mt);
|
||||
DeleteMediaType(pmt);
|
||||
}
|
||||
|
||||
if(FAILED(hr = Transform(pIn)))
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::GetDeliveryBuffer(int w, int h, IMediaSample** ppOut)
|
||||
{
|
||||
CheckPointer(ppOut, E_POINTER);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if(FAILED(hr = ReconnectOutput(w, h)))
|
||||
return hr;
|
||||
|
||||
if(FAILED(hr = m_pOutput->GetDeliveryBuffer(ppOut, NULL, NULL, 0)))
|
||||
return hr;
|
||||
|
||||
AM_MEDIA_TYPE* pmt;
|
||||
if(SUCCEEDED((*ppOut)->GetMediaType(&pmt)) && pmt)
|
||||
{
|
||||
CMediaType mt = *pmt;
|
||||
m_pOutput->SetMediaType(&mt);
|
||||
DeleteMediaType(pmt);
|
||||
}
|
||||
|
||||
(*ppOut)->SetDiscontinuity(FALSE);
|
||||
(*ppOut)->SetSyncPoint(TRUE);
|
||||
|
||||
// FIXME: hell knows why but without this the overlay mixer starts very skippy
|
||||
// (don't enable this for other renderers, the old for example will go crazy if you do)
|
||||
if(GetCLSID(m_pOutput->GetConnected()) == CLSID_OverlayMixer)
|
||||
(*ppOut)->SetDiscontinuity(TRUE);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::ReconnectOutput(int w, int h)
|
||||
{
|
||||
CMediaType& mt = m_pOutput->CurrentMediaType();
|
||||
|
||||
int w_org = m_w;
|
||||
int h_org = m_h;
|
||||
|
||||
bool fForceReconnection = false;
|
||||
if(w != m_w || h != m_h)
|
||||
{
|
||||
fForceReconnection = true;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if(fForceReconnection || m_w != m_wout || m_h != m_hout || m_arx != m_arxout || m_ary != m_aryout)
|
||||
{
|
||||
if(GetCLSID(m_pOutput->GetConnected()) == CLSID_VideoRenderer)
|
||||
{
|
||||
NotifyEvent(EC_ERRORABORT, 0, 0);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER* bmi = NULL;
|
||||
|
||||
if(mt.formattype == FORMAT_VideoInfo)
|
||||
{
|
||||
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.Format();
|
||||
SetRect(&vih->rcSource, 0, 0, m_w, m_h);
|
||||
SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
|
||||
bmi = &vih->bmiHeader;
|
||||
bmi->biXPelsPerMeter = m_w * m_ary;
|
||||
bmi->biYPelsPerMeter = m_h * m_arx;
|
||||
}
|
||||
else if(mt.formattype == FORMAT_VideoInfo2)
|
||||
{
|
||||
VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)mt.Format();
|
||||
SetRect(&vih->rcSource, 0, 0, m_w, m_h);
|
||||
SetRect(&vih->rcTarget, 0, 0, m_w, m_h);
|
||||
bmi = &vih->bmiHeader;
|
||||
vih->dwPictAspectRatioX = m_arx;
|
||||
vih->dwPictAspectRatioY = m_ary;
|
||||
}
|
||||
|
||||
bmi->biWidth = m_w;
|
||||
bmi->biHeight = m_h;
|
||||
bmi->biSizeImage = m_w*m_h*bmi->biBitCount>>3;
|
||||
|
||||
hr = m_pOutput->GetConnected()->QueryAccept(&mt);
|
||||
ASSERT(SUCCEEDED(hr)); // should better not fail, after all "mt" is the current media type, just with a different resolution
|
||||
HRESULT hr1 = 0, hr2 = 0;
|
||||
CComPtr<IMediaSample> pOut;
|
||||
if(SUCCEEDED(hr1 = m_pOutput->GetConnected()->ReceiveConnection(m_pOutput, &mt))
|
||||
&& SUCCEEDED(hr2 = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0)))
|
||||
{
|
||||
AM_MEDIA_TYPE* pmt;
|
||||
if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
|
||||
{
|
||||
CMediaType mt = *pmt;
|
||||
m_pOutput->SetMediaType(&mt);
|
||||
DeleteMediaType(pmt);
|
||||
}
|
||||
else // stupid overlay mixer won't let us know the new pitch...
|
||||
{
|
||||
long size = pOut->GetSize();
|
||||
bmi->biWidth = size / bmi->biHeight * 8 / bmi->biBitCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_w = w_org;
|
||||
m_h = h_org;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
m_wout = m_w;
|
||||
m_hout = m_h;
|
||||
m_arxout = m_arx;
|
||||
m_aryout = m_ary;
|
||||
|
||||
// some renderers don't send this
|
||||
NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(m_w, m_h), 0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE* pIn, int w, int h, int pitchIn, const GUID& subtype, bool fInterlaced)
|
||||
{
|
||||
int abs_h = abs(h);
|
||||
BYTE* pInYUV[3] = {pIn, pIn + pitchIn*abs_h, pIn + pitchIn*abs_h + (pitchIn>>1)*(abs_h>>1)};
|
||||
return CopyBuffer(pOut, pInYUV, w, h, pitchIn, subtype, fInterlaced);
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::CopyBuffer(BYTE* pOut, BYTE** ppIn, int w, int h, int pitchIn, const GUID& subtype, bool fInterlaced)
|
||||
{
|
||||
BITMAPINFOHEADER bihOut;
|
||||
ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
|
||||
|
||||
int pitchOut = 0;
|
||||
|
||||
if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
|
||||
{
|
||||
pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
|
||||
|
||||
if(bihOut.biHeight > 0)
|
||||
{
|
||||
pOut += pitchOut*(h-1);
|
||||
pitchOut = -pitchOut;
|
||||
if(h < 0) h = -h;
|
||||
}
|
||||
}
|
||||
|
||||
if(h < 0)
|
||||
{
|
||||
h = -h;
|
||||
ppIn[0] += pitchIn*(h-1);
|
||||
ppIn[1] += (pitchIn>>1)*((h>>1)-1);
|
||||
ppIn[2] += (pitchIn>>1)*((h>>1)-1);
|
||||
pitchIn = -pitchIn;
|
||||
}
|
||||
|
||||
if(subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV || subtype == MEDIASUBTYPE_YV12)
|
||||
{
|
||||
BYTE* pIn = ppIn[0];
|
||||
BYTE* pInU = ppIn[1];
|
||||
BYTE* pInV = ppIn[2];
|
||||
|
||||
if(subtype == MEDIASUBTYPE_YV12) {BYTE* tmp = pInU; pInU = pInV; pInV = tmp;}
|
||||
|
||||
BYTE* pOutU = pOut + bihOut.biWidth*h;
|
||||
BYTE* pOutV = pOut + bihOut.biWidth*h*5/4;
|
||||
|
||||
if(bihOut.biCompression == '21VY') {BYTE* tmp = pOutU; pOutU = pOutV; pOutV = tmp;}
|
||||
|
||||
ASSERT(w <= abs(pitchIn));
|
||||
|
||||
if(bihOut.biCompression == '2YUY')
|
||||
{
|
||||
BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pIn, pInU, pInV, pitchIn, fInterlaced);
|
||||
}
|
||||
else if(bihOut.biCompression == '024I' || bihOut.biCompression == 'VUYI' || bihOut.biCompression == '21VY')
|
||||
{
|
||||
BitBltFromI420ToI420(w, h, pOut, pOutU, pOutV, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
|
||||
}
|
||||
else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
|
||||
{
|
||||
if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pIn, pInU, pInV, pitchIn))
|
||||
{
|
||||
for(DWORD y = 0; y < h; y++, pOut += pitchOut)
|
||||
memset(pOut, 0, pitchOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_YUY2)
|
||||
{
|
||||
if(bihOut.biCompression == '2YUY')
|
||||
{
|
||||
BitBltFromYUY2ToYUY2(w, h, pOut, bihOut.biWidth*2, ppIn[0], pitchIn);
|
||||
}
|
||||
else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
|
||||
{
|
||||
if(!BitBltFromYUY2ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn))
|
||||
{
|
||||
for(DWORD y = 0; y < h; y++, pOut += pitchOut)
|
||||
memset(pOut, 0, pitchOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_RGB24 || subtype == MEDIASUBTYPE_RGB565)
|
||||
{
|
||||
int sbpp =
|
||||
subtype == MEDIASUBTYPE_ARGB32 || subtype == MEDIASUBTYPE_RGB32 ? 32 :
|
||||
subtype == MEDIASUBTYPE_RGB24 ? 24 :
|
||||
subtype == MEDIASUBTYPE_RGB565 ? 16 : 0;
|
||||
|
||||
if(bihOut.biCompression == '2YUY')
|
||||
{
|
||||
// TODO
|
||||
// BitBltFromRGBToYUY2();
|
||||
}
|
||||
else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
|
||||
{
|
||||
if(!BitBltFromRGBToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, ppIn[0], pitchIn, sbpp))
|
||||
{
|
||||
for(DWORD y = 0; y < h; y++, pOut += pitchOut)
|
||||
memset(pOut, 0, pitchOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::CheckInputType(const CMediaType* mtIn)
|
||||
{
|
||||
BITMAPINFOHEADER bih;
|
||||
ExtractBIH(mtIn, &bih);
|
||||
|
||||
return mtIn->majortype == MEDIATYPE_Video
|
||||
&& (mtIn->subtype == MEDIASUBTYPE_YV12
|
||||
|| mtIn->subtype == MEDIASUBTYPE_I420
|
||||
|| mtIn->subtype == MEDIASUBTYPE_IYUV
|
||||
|| mtIn->subtype == MEDIASUBTYPE_YUY2
|
||||
|| mtIn->subtype == MEDIASUBTYPE_ARGB32
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB32
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB24
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB565)
|
||||
&& (mtIn->formattype == FORMAT_VideoInfo
|
||||
|| mtIn->formattype == FORMAT_VideoInfo2)
|
||||
&& bih.biHeight > 0
|
||||
? S_OK
|
||||
: VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
|
||||
{
|
||||
if(FAILED(CheckInputType(mtIn)) || mtOut->majortype != MEDIATYPE_Video)
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
|
||||
if(mtIn->majortype == MEDIATYPE_Video
|
||||
&& (mtIn->subtype == MEDIASUBTYPE_YV12
|
||||
|| mtIn->subtype == MEDIASUBTYPE_I420
|
||||
|| mtIn->subtype == MEDIASUBTYPE_IYUV))
|
||||
{
|
||||
if(mtOut->subtype != MEDIASUBTYPE_YV12
|
||||
&& mtOut->subtype != MEDIASUBTYPE_I420
|
||||
&& mtOut->subtype != MEDIASUBTYPE_IYUV
|
||||
&& mtOut->subtype != MEDIASUBTYPE_YUY2
|
||||
&& mtOut->subtype != MEDIASUBTYPE_ARGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB24
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB565)
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
else if(mtIn->majortype == MEDIATYPE_Video
|
||||
&& (mtIn->subtype == MEDIASUBTYPE_YUY2))
|
||||
{
|
||||
if(mtOut->subtype != MEDIASUBTYPE_YUY2
|
||||
&& mtOut->subtype != MEDIASUBTYPE_ARGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB24
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB565)
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
else if(mtIn->majortype == MEDIATYPE_Video
|
||||
&& (mtIn->subtype == MEDIASUBTYPE_ARGB32
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB32
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB24
|
||||
|| mtIn->subtype == MEDIASUBTYPE_RGB565))
|
||||
{
|
||||
if(mtOut->subtype != MEDIASUBTYPE_ARGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB32
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB24
|
||||
&& mtOut->subtype != MEDIASUBTYPE_RGB565)
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::CheckOutputType(const CMediaType& mtOut)
|
||||
{
|
||||
int wout = 0, hout = 0, arxout = 0, aryout = 0;
|
||||
return ExtractDim(&mtOut, wout, hout, arxout, aryout)
|
||||
&& m_h == abs((int)hout)
|
||||
&& mtOut.subtype != MEDIASUBTYPE_ARGB32
|
||||
? S_OK
|
||||
: VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
|
||||
{
|
||||
if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
|
||||
|
||||
BITMAPINFOHEADER bih;
|
||||
ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
|
||||
|
||||
long cBuffers = m_pOutput->CurrentMediaType().formattype == FORMAT_VideoInfo ? 1 : m_cBuffers;
|
||||
|
||||
pProperties->cBuffers = m_cBuffers;
|
||||
pProperties->cbBuffer = bih.biSizeImage;
|
||||
pProperties->cbAlign = 1;
|
||||
pProperties->cbPrefix = 0;
|
||||
|
||||
HRESULT hr;
|
||||
ALLOCATOR_PROPERTIES Actual;
|
||||
if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
|
||||
return hr;
|
||||
|
||||
return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
|
||||
? E_FAIL
|
||||
: NOERROR;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::GetMediaType(int iPosition, CMediaType* pmt)
|
||||
{
|
||||
if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
|
||||
|
||||
struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
|
||||
{
|
||||
{&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
|
||||
{&MEDIASUBTYPE_I420, 3, 12, '024I'},
|
||||
{&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
|
||||
{&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
|
||||
{&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
|
||||
{&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
|
||||
{&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
|
||||
{&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
|
||||
{&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
|
||||
{&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
|
||||
{&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
|
||||
{&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
|
||||
{&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
|
||||
{&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
|
||||
};
|
||||
|
||||
// this will make sure we won't connect to the old renderer in dvd mode
|
||||
// that renderer can't switch the format dynamically
|
||||
|
||||
bool fFoundDVDNavigator = false;
|
||||
CComPtr<IBaseFilter> pBF = this;
|
||||
CComPtr<IPin> pPin = m_pInput;
|
||||
for(; !fFoundDVDNavigator && (pBF = GetUpStreamFilter(pBF, pPin)); pPin = GetFirstPin(pBF))
|
||||
fFoundDVDNavigator = GetCLSID(pBF) == CLSID_DVDNavigator;
|
||||
|
||||
if(fFoundDVDNavigator || m_pInput->CurrentMediaType().formattype == FORMAT_VideoInfo2)
|
||||
iPosition = iPosition*2;
|
||||
|
||||
//
|
||||
|
||||
if(iPosition < 0) return E_INVALIDARG;
|
||||
if(iPosition >= 2*countof(fmts)) return VFW_S_NO_MORE_ITEMS;
|
||||
|
||||
pmt->majortype = MEDIATYPE_Video;
|
||||
pmt->subtype = *fmts[iPosition/2].subtype;
|
||||
|
||||
int w = m_win, h = m_hin, arx = m_arxin, ary = m_aryin;
|
||||
GetOutputSize(w, h, arx, ary);
|
||||
|
||||
BITMAPINFOHEADER bihOut;
|
||||
memset(&bihOut, 0, sizeof(bihOut));
|
||||
bihOut.biSize = sizeof(bihOut);
|
||||
bihOut.biWidth = w;
|
||||
bihOut.biHeight = h;
|
||||
bihOut.biPlanes = fmts[iPosition/2].biPlanes;
|
||||
bihOut.biBitCount = fmts[iPosition/2].biBitCount;
|
||||
bihOut.biCompression = fmts[iPosition/2].biCompression;
|
||||
bihOut.biSizeImage = w*h*bihOut.biBitCount>>3;
|
||||
|
||||
if(iPosition&1)
|
||||
{
|
||||
pmt->formattype = FORMAT_VideoInfo;
|
||||
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
|
||||
memset(vih, 0, sizeof(VIDEOINFOHEADER));
|
||||
vih->bmiHeader = bihOut;
|
||||
vih->bmiHeader.biXPelsPerMeter = vih->bmiHeader.biWidth * ary;
|
||||
vih->bmiHeader.biYPelsPerMeter = vih->bmiHeader.biHeight * arx;
|
||||
}
|
||||
else
|
||||
{
|
||||
pmt->formattype = FORMAT_VideoInfo2;
|
||||
VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
|
||||
memset(vih, 0, sizeof(VIDEOINFOHEADER2));
|
||||
vih->bmiHeader = bihOut;
|
||||
vih->dwPictAspectRatioX = arx;
|
||||
vih->dwPictAspectRatioY = ary;
|
||||
if(IsVideoInterlaced()) vih->dwInterlaceFlags = AMINTERLACE_IsInterlaced;
|
||||
}
|
||||
|
||||
CMediaType& mt = m_pInput->CurrentMediaType();
|
||||
|
||||
// these fields have the same field offset in all four structs
|
||||
((VIDEOINFOHEADER*)pmt->Format())->AvgTimePerFrame = ((VIDEOINFOHEADER*)mt.Format())->AvgTimePerFrame;
|
||||
((VIDEOINFOHEADER*)pmt->Format())->dwBitRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitRate;
|
||||
((VIDEOINFOHEADER*)pmt->Format())->dwBitErrorRate = ((VIDEOINFOHEADER*)mt.Format())->dwBitErrorRate;
|
||||
|
||||
CorrectMediaType(pmt);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoFilter::SetMediaType(PIN_DIRECTION dir, const CMediaType* pmt)
|
||||
{
|
||||
if(dir == PINDIR_INPUT)
|
||||
{
|
||||
m_w = m_h = m_arx = m_ary = 0;
|
||||
ExtractDim(pmt, m_w, m_h, m_arx, m_ary);
|
||||
m_win = m_w;
|
||||
m_hin = m_h;
|
||||
m_arxin = m_arx;
|
||||
m_aryin = m_ary;
|
||||
GetOutputSize(m_w, m_h, m_arx, m_ary);
|
||||
}
|
||||
else if(dir == PINDIR_OUTPUT)
|
||||
{
|
||||
int wout = 0, hout = 0, arxout = 0, aryout = 0;
|
||||
ExtractDim(pmt, wout, hout, arxout, aryout);
|
||||
if(m_w == wout && m_h == hout && m_arx == arxout && m_ary == aryout)
|
||||
{
|
||||
m_wout = wout;
|
||||
m_hout = hout;
|
||||
m_arxout = arxout;
|
||||
m_aryout = aryout;
|
||||
}
|
||||
}
|
||||
|
||||
return __super::SetMediaType(dir, pmt);
|
||||
}
|
||||
|
||||
//
|
||||
// CBaseVideoInputAllocator
|
||||
//
|
||||
|
||||
CBaseVideoInputAllocator::CBaseVideoInputAllocator(HRESULT* phr)
|
||||
: CMemAllocator(NAME("CBaseVideoInputAllocator"), NULL, phr)
|
||||
{
|
||||
if(phr) *phr = S_OK;
|
||||
}
|
||||
|
||||
void CBaseVideoInputAllocator::SetMediaType(const CMediaType& mt)
|
||||
{
|
||||
m_mt = mt;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseVideoInputAllocator::GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags)
|
||||
{
|
||||
if(!m_bCommitted)
|
||||
return VFW_E_NOT_COMMITTED;
|
||||
|
||||
HRESULT hr = __super::GetBuffer(ppBuffer, pStartTime, pEndTime, dwFlags);
|
||||
|
||||
if(SUCCEEDED(hr) && m_mt.majortype != GUID_NULL)
|
||||
{
|
||||
(*ppBuffer)->SetMediaType(&m_mt);
|
||||
m_mt.majortype = GUID_NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// CBaseVideoInputPin
|
||||
//
|
||||
|
||||
CBaseVideoInputPin::CBaseVideoInputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName)
|
||||
: CTransformInputPin(pObjectName, pFilter, phr, pName)
|
||||
, m_pAllocator(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CBaseVideoInputPin::~CBaseVideoInputPin()
|
||||
{
|
||||
delete m_pAllocator;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseVideoInputPin::GetAllocator(IMemAllocator** ppAllocator)
|
||||
{
|
||||
CheckPointer(ppAllocator, E_POINTER);
|
||||
|
||||
if(m_pAllocator == NULL)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
m_pAllocator = new CBaseVideoInputAllocator(&hr);
|
||||
m_pAllocator->AddRef();
|
||||
}
|
||||
|
||||
(*ppAllocator = m_pAllocator)->AddRef();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseVideoInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt)
|
||||
{
|
||||
CAutoLock cObjectLock(m_pLock);
|
||||
|
||||
if(m_Connected)
|
||||
{
|
||||
CMediaType mt(*pmt);
|
||||
|
||||
if(FAILED(CheckMediaType(&mt)))
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
|
||||
ALLOCATOR_PROPERTIES props, actual;
|
||||
|
||||
CComPtr<IMemAllocator> pMemAllocator;
|
||||
if(FAILED(GetAllocator(&pMemAllocator))
|
||||
|| FAILED(pMemAllocator->Decommit())
|
||||
|| FAILED(pMemAllocator->GetProperties(&props)))
|
||||
return E_FAIL;
|
||||
|
||||
BITMAPINFOHEADER bih;
|
||||
if(ExtractBIH(pmt, &bih) && bih.biSizeImage)
|
||||
props.cbBuffer = bih.biSizeImage;
|
||||
|
||||
if(FAILED(pMemAllocator->SetProperties(&props, &actual))
|
||||
|| FAILED(pMemAllocator->Commit())
|
||||
|| props.cbBuffer != actual.cbBuffer)
|
||||
return E_FAIL;
|
||||
|
||||
if(m_pAllocator)
|
||||
m_pAllocator->SetMediaType(mt);
|
||||
|
||||
return SetMediaType(&mt) == S_OK
|
||||
? S_OK
|
||||
: VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
return __super::ReceiveConnection(pConnector, pmt);
|
||||
}
|
||||
|
||||
//
|
||||
// CBaseVideoOutputPin
|
||||
//
|
||||
|
||||
CBaseVideoOutputPin::CBaseVideoOutputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName)
|
||||
: CTransformOutputPin(pObjectName, pFilter, phr, pName)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CBaseVideoOutputPin::CheckMediaType(const CMediaType* mtOut)
|
||||
{
|
||||
if(IsConnected())
|
||||
{
|
||||
HRESULT hr = ((CBaseVideoFilter*)m_pFilter)->CheckOutputType(*mtOut);
|
||||
if(FAILED(hr)) return hr;
|
||||
}
|
||||
|
||||
return __super::CheckMediaType(mtOut);
|
||||
}
|
92
vsfilter/basevideofilter/BaseVideoFilter.h
Normal file
92
vsfilter/basevideofilter/BaseVideoFilter.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class CBaseVideoFilter : public CTransformFilter
|
||||
{
|
||||
private:
|
||||
HRESULT Receive(IMediaSample* pIn);
|
||||
HRESULT ReconnectOutput(int w, int h);
|
||||
|
||||
// these are private for a reason, don't bother them
|
||||
DWORD m_win, m_hin, m_arxin, m_aryin;
|
||||
DWORD m_wout, m_hout, m_arxout, m_aryout;
|
||||
|
||||
long m_cBuffers;
|
||||
|
||||
protected:
|
||||
CCritSec m_csReceive;
|
||||
|
||||
int m_w, m_h, m_arx, m_ary;
|
||||
|
||||
HRESULT GetDeliveryBuffer(int w, int h, IMediaSample** ppOut);
|
||||
HRESULT CopyBuffer(BYTE* pOut, BYTE* pIn, int w, int h, int pitchIn, const GUID& subtype, bool fInterlaced = false);
|
||||
HRESULT CopyBuffer(BYTE* pOut, BYTE** ppIn, int w, int h, int pitchIn, const GUID& subtype, bool fInterlaced = false);
|
||||
|
||||
virtual void GetOutputSize(int& w, int& h, int& arx, int& ary) {}
|
||||
virtual HRESULT Transform(IMediaSample* pIn) = 0;
|
||||
virtual HRESULT IsVideoInterlaced() {return false;}
|
||||
|
||||
public:
|
||||
CBaseVideoFilter(TCHAR* pName, LPUNKNOWN lpunk, HRESULT* phr, REFCLSID clsid, long cBuffers = 1);
|
||||
virtual ~CBaseVideoFilter();
|
||||
|
||||
int GetPinCount();
|
||||
CBasePin* GetPin(int n);
|
||||
|
||||
HRESULT CheckInputType(const CMediaType* mtIn);
|
||||
HRESULT CheckOutputType(const CMediaType& mtOut);
|
||||
HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut);
|
||||
HRESULT DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties);
|
||||
HRESULT GetMediaType(int iPosition, CMediaType* pMediaType);
|
||||
HRESULT SetMediaType(PIN_DIRECTION dir, const CMediaType* pmt);
|
||||
};
|
||||
|
||||
class CBaseVideoInputAllocator : public CMemAllocator
|
||||
{
|
||||
CMediaType m_mt;
|
||||
|
||||
public:
|
||||
CBaseVideoInputAllocator(HRESULT* phr);
|
||||
void SetMediaType(const CMediaType& mt);
|
||||
STDMETHODIMP GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags);
|
||||
};
|
||||
|
||||
class CBaseVideoInputPin : public CTransformInputPin
|
||||
{
|
||||
CBaseVideoInputAllocator* m_pAllocator;
|
||||
|
||||
public:
|
||||
CBaseVideoInputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName);
|
||||
~CBaseVideoInputPin();
|
||||
|
||||
STDMETHODIMP GetAllocator(IMemAllocator** ppAllocator);
|
||||
STDMETHODIMP ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt);
|
||||
};
|
||||
|
||||
class CBaseVideoOutputPin : public CTransformOutputPin
|
||||
{
|
||||
public:
|
||||
CBaseVideoOutputPin(TCHAR* pObjectName, CBaseVideoFilter* pFilter, HRESULT* phr, LPCWSTR pName);
|
||||
|
||||
HRESULT CheckMediaType(const CMediaType* mtOut);
|
||||
};
|
199
vsfilter/basevideofilter/basevideofilter.vcproj
Normal file
199
vsfilter/basevideofilter/basevideofilter.vcproj
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="basevideofilter"
|
||||
ProjectGUID="{B0CD35D2-65C8-48D0-BEC8-D235137F62F6}"
|
||||
RootNamespace="basevideofilter"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\BaseVideoFilter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\BaseVideoFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
29
vsfilter/basevideofilter/stdafx.cpp
Normal file
29
vsfilter/basevideofilter/stdafx.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// mpeg2decds.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
43
vsfilter/basevideofilter/stdafx.h
Normal file
43
vsfilter/basevideofilter/stdafx.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
#endif
|
||||
|
||||
#include <afx.h>
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
#include <streams.h>
|
||||
#include <dvdmedia.h>
|
||||
#include <amvideo.h>
|
|
@ -23,10 +23,10 @@
|
|||
#include <afxdlgs.h>
|
||||
#include <atlpath.h>
|
||||
#include "resource.h"
|
||||
#include "..\..\..\subtitles\VobSubFile.h"
|
||||
#include "..\..\..\subtitles\RTS.h"
|
||||
#include "..\..\..\subtitles\SSF.h"
|
||||
#include "..\..\..\SubPic\MemSubPic.h"
|
||||
#include "subtitles/VobSubFile.h"
|
||||
#include "subtitles/RTS.h"
|
||||
#include "subtitles/SSF.h"
|
||||
#include "SubPic/MemSubPic.h"
|
||||
|
||||
// Be sure to have <csri/csri.h> in include path
|
||||
#define CSRIAPI extern "C" __declspec(dllexport)
|
||||
|
@ -42,7 +42,7 @@ extern "C" struct csri_vsfilter_inst {
|
|||
size_t readorder;
|
||||
};
|
||||
typedef struct csri_vsfilter_inst csri_inst;
|
||||
#include <csri/csri.h>
|
||||
#include "../csri/include/csri/csri.h"
|
||||
static csri_rend csri_vsfilter = "vsfilter";
|
||||
|
||||
|
||||
|
|
396
vsfilter/dsutil/DSMPropertyBag.cpp
Normal file
396
vsfilter/dsutil/DSMPropertyBag.cpp
Normal file
|
@ -0,0 +1,396 @@
|
|||
#include "StdAfx.h"
|
||||
#include "DSUtil.h"
|
||||
#include "DSMPropertyBag.h"
|
||||
|
||||
//
|
||||
// IDSMPropertyBagImpl
|
||||
//
|
||||
|
||||
IDSMPropertyBagImpl::IDSMPropertyBagImpl()
|
||||
{
|
||||
}
|
||||
|
||||
IDSMPropertyBagImpl::~IDSMPropertyBagImpl()
|
||||
{
|
||||
}
|
||||
|
||||
// IPropertyBag
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog)
|
||||
{
|
||||
CheckPointer(pVar, E_POINTER);
|
||||
if(pVar->vt != VT_EMPTY) return E_INVALIDARG;
|
||||
CStringW value = Lookup(pszPropName);
|
||||
if(value.IsEmpty()) return E_FAIL;
|
||||
CComVariant(value).Detach(pVar);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::Write(LPCOLESTR pszPropName, VARIANT* pVar)
|
||||
{
|
||||
return SetProperty(pszPropName, pVar);
|
||||
}
|
||||
|
||||
// IPropertyBag2
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::Read(ULONG cProperties, PROPBAG2* pPropBag, IErrorLog* pErrLog, VARIANT* pvarValue, HRESULT* phrError)
|
||||
{
|
||||
CheckPointer(pPropBag, E_POINTER);
|
||||
CheckPointer(pvarValue, E_POINTER);
|
||||
CheckPointer(phrError, E_POINTER);
|
||||
for(ULONG i = 0; i < cProperties; phrError[i] = S_OK, i++)
|
||||
CComVariant(Lookup(pPropBag[i].pstrName)).Detach(pvarValue);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::Write(ULONG cProperties, PROPBAG2* pPropBag, VARIANT* pvarValue)
|
||||
{
|
||||
CheckPointer(pPropBag, E_POINTER);
|
||||
CheckPointer(pvarValue, E_POINTER);
|
||||
for(ULONG i = 0; i < cProperties; i++)
|
||||
SetProperty(pPropBag[i].pstrName, &pvarValue[i]);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::CountProperties(ULONG* pcProperties)
|
||||
{
|
||||
CheckPointer(pcProperties, E_POINTER);
|
||||
*pcProperties = GetSize();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2* pPropBag, ULONG* pcProperties)
|
||||
{
|
||||
CheckPointer(pPropBag, E_POINTER);
|
||||
CheckPointer(pcProperties, E_POINTER);
|
||||
for(ULONG i = 0; i < cProperties; i++, iProperty++, (*pcProperties)++)
|
||||
{
|
||||
CStringW key = GetKeyAt(iProperty);
|
||||
pPropBag[i].pstrName = (BSTR)CoTaskMemAlloc((key.GetLength()+1)*sizeof(WCHAR));
|
||||
if(!pPropBag[i].pstrName) return E_FAIL;
|
||||
wcscpy(pPropBag[i].pstrName, key);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMPropertyBagImpl::LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown* pUnkObject, IErrorLog* pErrLog)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// IDSMProperyBag
|
||||
|
||||
HRESULT IDSMPropertyBagImpl::SetProperty(LPCWSTR key, LPCWSTR value)
|
||||
{
|
||||
CheckPointer(key, E_POINTER);
|
||||
CheckPointer(value, E_POINTER);
|
||||
if(!Lookup(key).IsEmpty()) SetAt(key, value);
|
||||
else Add(key, value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IDSMPropertyBagImpl::SetProperty(LPCWSTR key, VARIANT* var)
|
||||
{
|
||||
CheckPointer(key, E_POINTER);
|
||||
CheckPointer(var, E_POINTER);
|
||||
if((var->vt & (VT_BSTR | VT_BYREF)) != VT_BSTR) return E_INVALIDARG;
|
||||
return SetProperty(key, var->bstrVal);
|
||||
}
|
||||
|
||||
HRESULT IDSMPropertyBagImpl::GetProperty(LPCWSTR key, BSTR* value)
|
||||
{
|
||||
CheckPointer(key, E_POINTER);
|
||||
CheckPointer(value, E_POINTER);
|
||||
int i = FindKey(key);
|
||||
if(i < 0) return E_FAIL;
|
||||
*value = GetValueAt(i).AllocSysString();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IDSMPropertyBagImpl::DelAllProperties()
|
||||
{
|
||||
RemoveAll();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IDSMPropertyBagImpl::DelProperty(LPCWSTR key)
|
||||
{
|
||||
return Remove(key) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// CDSMResource
|
||||
//
|
||||
|
||||
CCritSec CDSMResource::m_csResources;
|
||||
CAtlMap<DWORD, CDSMResource*> CDSMResource::m_resources;
|
||||
|
||||
CDSMResource::CDSMResource()
|
||||
: mime(_T("application/octet-stream"))
|
||||
, tag(0)
|
||||
{
|
||||
CAutoLock cAutoLock(&m_csResources);
|
||||
m_resources.SetAt((DWORD)this, this);
|
||||
}
|
||||
|
||||
CDSMResource::CDSMResource(const CDSMResource& r)
|
||||
{
|
||||
*this = r;
|
||||
|
||||
CAutoLock cAutoLock(&m_csResources);
|
||||
m_resources.SetAt((DWORD)this, this);
|
||||
}
|
||||
|
||||
CDSMResource::CDSMResource(LPCWSTR name, LPCWSTR desc, LPCWSTR mime, BYTE* pData, int len, DWORD_PTR tag)
|
||||
{
|
||||
this->name = name;
|
||||
this->desc = desc;
|
||||
this->mime = mime;
|
||||
data.SetCount(len);
|
||||
memcpy(data.GetData(), pData, data.GetCount());
|
||||
this->tag = tag;
|
||||
|
||||
CAutoLock cAutoLock(&m_csResources);
|
||||
m_resources.SetAt((DWORD)this, this);
|
||||
}
|
||||
|
||||
CDSMResource::~CDSMResource()
|
||||
{
|
||||
CAutoLock cAutoLock(&m_csResources);
|
||||
m_resources.RemoveKey((DWORD)this);
|
||||
}
|
||||
|
||||
void CDSMResource::operator = (const CDSMResource& r)
|
||||
{
|
||||
tag = r.tag;
|
||||
name = r.name;
|
||||
desc = r.desc;
|
||||
mime = r.mime;
|
||||
data.Copy(r.data);
|
||||
}
|
||||
|
||||
//
|
||||
// IDSMResourceBagImpl
|
||||
//
|
||||
|
||||
IDSMResourceBagImpl::IDSMResourceBagImpl()
|
||||
{
|
||||
}
|
||||
|
||||
// IDSMResourceBag
|
||||
|
||||
STDMETHODIMP_(DWORD) IDSMResourceBagImpl::ResGetCount()
|
||||
{
|
||||
return m_resources.GetCount();
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMResourceBagImpl::ResGet(DWORD iIndex, BSTR* ppName, BSTR* ppDesc, BSTR* ppMime, BYTE** ppData, DWORD* pDataLen, DWORD_PTR* pTag)
|
||||
{
|
||||
if(ppData) CheckPointer(pDataLen, E_POINTER);
|
||||
|
||||
if((INT_PTR)iIndex >= m_resources.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
CDSMResource& r = m_resources[iIndex];
|
||||
|
||||
if(ppName) *ppName = r.name.AllocSysString();
|
||||
if(ppDesc) *ppDesc = r.desc.AllocSysString();
|
||||
if(ppMime) *ppMime = r.mime.AllocSysString();
|
||||
if(ppData) {*pDataLen = r.data.GetCount(); memcpy(*ppData = (BYTE*)CoTaskMemAlloc(*pDataLen), r.data.GetData(), *pDataLen);}
|
||||
if(pTag) *pTag = r.tag;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMResourceBagImpl::ResSet(DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag)
|
||||
{
|
||||
if((INT_PTR)iIndex >= m_resources.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
CDSMResource& r = m_resources[iIndex];
|
||||
|
||||
if(pName) r.name = pName;
|
||||
if(pDesc) r.desc = pDesc;
|
||||
if(pMime) r.mime = pMime;
|
||||
if(pData || len == 0) {r.data.SetCount(len); if(pData) memcpy(r.data.GetData(), pData, r.data.GetCount());}
|
||||
r.tag = tag;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMResourceBagImpl::ResAppend(LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag)
|
||||
{
|
||||
return ResSet(m_resources.Add(CDSMResource()), pName, pDesc, pMime, pData, len, tag);
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMResourceBagImpl::ResRemoveAt(DWORD iIndex)
|
||||
{
|
||||
if((INT_PTR)iIndex >= m_resources.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
m_resources.RemoveAt(iIndex);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMResourceBagImpl::ResRemoveAll(DWORD_PTR tag)
|
||||
{
|
||||
if(tag)
|
||||
{
|
||||
for(int i = m_resources.GetCount() - 1; i >= 0; i--)
|
||||
if(m_resources[i].tag == tag)
|
||||
m_resources.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_resources.RemoveAll();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// CDSMChapter
|
||||
//
|
||||
|
||||
CDSMChapter::CDSMChapter()
|
||||
{
|
||||
order = counter++;
|
||||
rt = 0;
|
||||
}
|
||||
|
||||
CDSMChapter::CDSMChapter(REFERENCE_TIME rt, LPCWSTR name)
|
||||
{
|
||||
order = counter++;
|
||||
this->rt = rt;
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
void CDSMChapter::operator = (const CDSMChapter& c)
|
||||
{
|
||||
order = c.counter;
|
||||
rt = c.rt;
|
||||
name = c.name;
|
||||
}
|
||||
|
||||
int CDSMChapter::counter = 0;
|
||||
|
||||
int CDSMChapter::Compare(const void* a, const void* b)
|
||||
{
|
||||
const CDSMChapter* ca = (const CDSMChapter*)a;
|
||||
const CDSMChapter* cb = (const CDSMChapter*)b;
|
||||
|
||||
if(ca->rt > cb->rt) return 1;
|
||||
else if(ca->rt < cb->rt) return -1;
|
||||
|
||||
return ca->order - cb->order;
|
||||
}
|
||||
|
||||
//
|
||||
// IDSMChapterBagImpl
|
||||
//
|
||||
|
||||
IDSMChapterBagImpl::IDSMChapterBagImpl()
|
||||
{
|
||||
m_fSorted = false;
|
||||
}
|
||||
|
||||
// IDSMRChapterBag
|
||||
|
||||
STDMETHODIMP_(DWORD) IDSMChapterBagImpl::ChapGetCount()
|
||||
{
|
||||
return m_chapters.GetCount();
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapGet(DWORD iIndex, REFERENCE_TIME* prt, BSTR* ppName)
|
||||
{
|
||||
if((INT_PTR)iIndex >= m_chapters.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
CDSMChapter& c = m_chapters[iIndex];
|
||||
|
||||
if(prt) *prt = c.rt;
|
||||
if(ppName) *ppName = c.name.AllocSysString();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapSet(DWORD iIndex, REFERENCE_TIME rt, LPCWSTR pName)
|
||||
{
|
||||
if((INT_PTR)iIndex >= m_chapters.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
CDSMChapter& c = m_chapters[iIndex];
|
||||
|
||||
c.rt = rt;
|
||||
if(pName) c.name = pName;
|
||||
|
||||
m_fSorted = false;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapAppend(REFERENCE_TIME rt, LPCWSTR pName)
|
||||
{
|
||||
return ChapSet(m_chapters.Add(CDSMChapter()), rt, pName);
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapRemoveAt(DWORD iIndex)
|
||||
{
|
||||
if((INT_PTR)iIndex >= m_chapters.GetCount())
|
||||
return E_INVALIDARG;
|
||||
|
||||
m_chapters.RemoveAt(iIndex);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapRemoveAll()
|
||||
{
|
||||
m_chapters.RemoveAll();
|
||||
|
||||
m_fSorted = false;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(long) IDSMChapterBagImpl::ChapLookup(REFERENCE_TIME* prt, BSTR* ppName)
|
||||
{
|
||||
CheckPointer(prt, -1);
|
||||
|
||||
ChapSort();
|
||||
|
||||
int i = range_bsearch(m_chapters, *prt);
|
||||
if(i < 0) return -1;
|
||||
|
||||
*prt = m_chapters[i].rt;
|
||||
if(ppName) *ppName = m_chapters[i].name.AllocSysString();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
STDMETHODIMP IDSMChapterBagImpl::ChapSort()
|
||||
{
|
||||
if(m_fSorted) return S_FALSE;
|
||||
qsort(m_chapters.GetData(), m_chapters.GetCount(), sizeof(CDSMChapter), CDSMChapter::Compare);
|
||||
m_fSorted = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// CDSMChapterBag
|
||||
//
|
||||
|
||||
CDSMChapterBag::CDSMChapterBag(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CUnknown(_T("CDSMChapterBag"), NULL)
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CDSMChapterBag::NonDelegatingQueryInterface(REFIID riid, void** ppv)
|
||||
{
|
||||
CheckPointer(ppv, E_POINTER);
|
||||
|
||||
return
|
||||
QI(IDSMChapterBag)
|
||||
__super::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
173
vsfilter/dsutil/DSMPropertyBag.h
Normal file
173
vsfilter/dsutil/DSMPropertyBag.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
#pragma once
|
||||
#include <atlcoll.h>
|
||||
#include <atlsimpcoll.h>
|
||||
|
||||
// IDSMPropertyBag
|
||||
|
||||
[uuid("232FD5D2-4954-41E7-BF9B-09E1257B1A95")]
|
||||
interface IDSMPropertyBag : public IPropertyBag2
|
||||
{
|
||||
STDMETHOD(SetProperty) (LPCWSTR key, LPCWSTR value) = 0;
|
||||
STDMETHOD(SetProperty) (LPCWSTR key, VARIANT* var) = 0;
|
||||
STDMETHOD(GetProperty) (LPCWSTR key, BSTR* value) = 0;
|
||||
STDMETHOD(DelAllProperties) () = 0;
|
||||
STDMETHOD(DelProperty) (LPCWSTR key) = 0;
|
||||
};
|
||||
|
||||
class IDSMPropertyBagImpl : public ATL::CSimpleMap<CStringW, CStringW>, public IDSMPropertyBag, public IPropertyBag
|
||||
{
|
||||
BOOL Add(const CStringW& key, const CStringW& val) {return __super::Add(key, val);}
|
||||
BOOL SetAt(const CStringW& key, const CStringW& val) {return __super::SetAt(key, val);}
|
||||
|
||||
public:
|
||||
IDSMPropertyBagImpl();
|
||||
virtual ~IDSMPropertyBagImpl();
|
||||
|
||||
// IPropertyBag
|
||||
|
||||
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog);
|
||||
STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT* pVar);
|
||||
|
||||
// IPropertyBag2
|
||||
|
||||
STDMETHODIMP Read(ULONG cProperties, PROPBAG2* pPropBag, IErrorLog* pErrLog, VARIANT* pvarValue, HRESULT* phrError);
|
||||
STDMETHODIMP Write(ULONG cProperties, PROPBAG2* pPropBag, VARIANT* pvarValue);
|
||||
STDMETHODIMP CountProperties(ULONG* pcProperties);
|
||||
STDMETHODIMP GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2* pPropBag, ULONG* pcProperties);
|
||||
STDMETHODIMP LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown* pUnkObject, IErrorLog* pErrLog);
|
||||
|
||||
// IDSMPropertyBag
|
||||
|
||||
STDMETHODIMP SetProperty(LPCWSTR key, LPCWSTR value);
|
||||
STDMETHODIMP SetProperty(LPCWSTR key, VARIANT* var);
|
||||
STDMETHODIMP GetProperty(LPCWSTR key, BSTR* value);
|
||||
STDMETHODIMP DelAllProperties();
|
||||
STDMETHODIMP DelProperty(LPCWSTR key);
|
||||
};
|
||||
|
||||
// IDSMResourceBag
|
||||
|
||||
[uuid("EBAFBCBE-BDE0-489A-9789-05D5692E3A93")]
|
||||
interface IDSMResourceBag : public IUnknown
|
||||
{
|
||||
STDMETHOD_(DWORD, ResGetCount) () = 0;
|
||||
STDMETHOD(ResGet) (DWORD iIndex, BSTR* ppName, BSTR* ppDesc, BSTR* ppMime, BYTE** ppData, DWORD* pDataLen, DWORD_PTR* pTag) = 0;
|
||||
STDMETHOD(ResSet) (DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag) = 0;
|
||||
STDMETHOD(ResAppend) (LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag) = 0;
|
||||
STDMETHOD(ResRemoveAt) (DWORD iIndex) = 0;
|
||||
STDMETHOD(ResRemoveAll) (DWORD_PTR tag) = 0;
|
||||
};
|
||||
|
||||
class CDSMResource
|
||||
{
|
||||
public:
|
||||
DWORD_PTR tag;
|
||||
CStringW name, desc, mime;
|
||||
CAtlArray<BYTE> data;
|
||||
CDSMResource();
|
||||
CDSMResource(const CDSMResource& r);
|
||||
CDSMResource(LPCWSTR name, LPCWSTR desc, LPCWSTR mime, BYTE* pData, int len, DWORD_PTR tag = 0);
|
||||
virtual ~CDSMResource();
|
||||
void operator = (const CDSMResource& r);
|
||||
|
||||
// global access to all resources
|
||||
static CCritSec m_csResources;
|
||||
static CAtlMap<DWORD, CDSMResource*> m_resources;
|
||||
};
|
||||
|
||||
class IDSMResourceBagImpl : public IDSMResourceBag
|
||||
{
|
||||
protected:
|
||||
CAtlArray<CDSMResource> m_resources;
|
||||
|
||||
public:
|
||||
IDSMResourceBagImpl();
|
||||
|
||||
void operator += (const CDSMResource& r) {m_resources.Add(r);}
|
||||
|
||||
// IDSMResourceBag
|
||||
|
||||
STDMETHODIMP_(DWORD) ResGetCount();
|
||||
STDMETHODIMP ResGet(DWORD iIndex, BSTR* ppName, BSTR* ppDesc, BSTR* ppMime, BYTE** ppData, DWORD* pDataLen, DWORD_PTR* pTag = NULL);
|
||||
STDMETHODIMP ResSet(DWORD iIndex, LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag = 0);
|
||||
STDMETHODIMP ResAppend(LPCWSTR pName, LPCWSTR pDesc, LPCWSTR pMime, BYTE* pData, DWORD len, DWORD_PTR tag = 0);
|
||||
STDMETHODIMP ResRemoveAt(DWORD iIndex);
|
||||
STDMETHODIMP ResRemoveAll(DWORD_PTR tag = 0);
|
||||
};
|
||||
|
||||
// IDSMChapterBag
|
||||
|
||||
[uuid("2D0EBE73-BA82-4E90-859B-C7C48ED3650F")]
|
||||
interface IDSMChapterBag : public IUnknown
|
||||
{
|
||||
STDMETHOD_(DWORD, ChapGetCount) () = 0;
|
||||
STDMETHOD(ChapGet) (DWORD iIndex, REFERENCE_TIME* prt, BSTR* ppName) = 0;
|
||||
STDMETHOD(ChapSet) (DWORD iIndex, REFERENCE_TIME rt, LPCWSTR pName) = 0;
|
||||
STDMETHOD(ChapAppend) (REFERENCE_TIME rt, LPCWSTR pName) = 0;
|
||||
STDMETHOD(ChapRemoveAt) (DWORD iIndex) = 0;
|
||||
STDMETHOD(ChapRemoveAll) () = 0;
|
||||
STDMETHOD_(long, ChapLookup) (REFERENCE_TIME* prt, BSTR* ppName) = 0;
|
||||
STDMETHOD(ChapSort) () = 0;
|
||||
};
|
||||
|
||||
class CDSMChapter
|
||||
{
|
||||
static int counter;
|
||||
int order;
|
||||
|
||||
public:
|
||||
REFERENCE_TIME rt;
|
||||
CStringW name;
|
||||
CDSMChapter();
|
||||
CDSMChapter(REFERENCE_TIME rt, LPCWSTR name);
|
||||
void operator = (const CDSMChapter& c);
|
||||
static int Compare(const void* a, const void* b);
|
||||
};
|
||||
|
||||
class IDSMChapterBagImpl : public IDSMChapterBag
|
||||
{
|
||||
protected:
|
||||
CAtlArray<CDSMChapter> m_chapters;
|
||||
bool m_fSorted;
|
||||
|
||||
public:
|
||||
IDSMChapterBagImpl();
|
||||
|
||||
void operator += (const CDSMChapter& c) {m_chapters.Add(c); m_fSorted = false;}
|
||||
|
||||
// IDSMChapterBag
|
||||
|
||||
STDMETHODIMP_(DWORD) ChapGetCount();
|
||||
STDMETHODIMP ChapGet(DWORD iIndex, REFERENCE_TIME* prt, BSTR* ppName = NULL);
|
||||
STDMETHODIMP ChapSet(DWORD iIndex, REFERENCE_TIME rt, LPCWSTR pName);
|
||||
STDMETHODIMP ChapAppend(REFERENCE_TIME rt, LPCWSTR pName);
|
||||
STDMETHODIMP ChapRemoveAt(DWORD iIndex);
|
||||
STDMETHODIMP ChapRemoveAll();
|
||||
STDMETHODIMP_(long) ChapLookup(REFERENCE_TIME* prt, BSTR* ppName = NULL);
|
||||
STDMETHODIMP ChapSort();
|
||||
};
|
||||
|
||||
class CDSMChapterBag : public CUnknown, public IDSMChapterBagImpl
|
||||
{
|
||||
public:
|
||||
CDSMChapterBag(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
|
||||
DECLARE_IUNKNOWN;
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
int range_bsearch(const CAtlArray<T>& array, REFERENCE_TIME rt)
|
||||
{
|
||||
int i = 0, j = array.GetCount() - 1, ret = -1;
|
||||
if(j >= 0 && rt >= array[j].rt) return j;
|
||||
while(i < j)
|
||||
{
|
||||
int mid = (i + j) >> 1;
|
||||
REFERENCE_TIME midrt = array[mid].rt;
|
||||
if(rt == midrt) {ret = mid; break;}
|
||||
else if(rt < midrt) {ret = -1; if(j == mid) mid--; j = mid;}
|
||||
else if(rt > midrt) {ret = mid; if(i == mid) mid++; i = mid;}
|
||||
}
|
||||
return ret;
|
||||
}
|
2218
vsfilter/dsutil/DSUtil.cpp
Normal file
2218
vsfilter/dsutil/DSUtil.cpp
Normal file
File diff suppressed because it is too large
Load diff
203
vsfilter/dsutil/DSUtil.h
Normal file
203
vsfilter/dsutil/DSUtil.h
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Removing this section, don't want automatic linking.
|
||||
* Use project dependencies in VS to link the right things.
|
||||
* -jfs
|
||||
*
|
||||
#ifdef UNICODE
|
||||
#ifdef DEBUG
|
||||
#pragma comment(lib, "dsutilDU")
|
||||
#else
|
||||
#pragma comment(lib, "dsutilRU")
|
||||
#endif
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
#pragma comment(lib, "dsutilD")
|
||||
#else
|
||||
#pragma comment(lib, "dsutilR")
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
#include "NullRenderers.h"
|
||||
//#include "MediaTypes.h"
|
||||
#include "MediaTypeEx.h"
|
||||
#include "vd.h"
|
||||
#include "text.h"
|
||||
|
||||
extern void DumpStreamConfig(TCHAR* fn, IAMStreamConfig* pAMVSCCap);
|
||||
extern int CountPins(IBaseFilter* pBF, int& nIn, int& nOut, int& nInC, int& nOutC);
|
||||
extern bool IsSplitter(IBaseFilter* pBF, bool fCountConnectedOnly = false);
|
||||
extern bool IsMultiplexer(IBaseFilter* pBF, bool fCountConnectedOnly = false);
|
||||
extern bool IsStreamStart(IBaseFilter* pBF);
|
||||
extern bool IsStreamEnd(IBaseFilter* pBF);
|
||||
extern bool IsVideoRenderer(IBaseFilter* pBF);
|
||||
extern bool IsAudioWaveRenderer(IBaseFilter* pBF);
|
||||
extern IBaseFilter* GetUpStreamFilter(IBaseFilter* pBF, IPin* pInputPin = NULL);
|
||||
extern IPin* GetUpStreamPin(IBaseFilter* pBF, IPin* pInputPin = NULL);
|
||||
extern IPin* GetFirstPin(IBaseFilter* pBF, PIN_DIRECTION dir = PINDIR_INPUT);
|
||||
extern IPin* GetFirstDisconnectedPin(IBaseFilter* pBF, PIN_DIRECTION dir);
|
||||
extern void NukeDownstream(IBaseFilter* pBF, IFilterGraph* pFG);
|
||||
extern void NukeDownstream(IPin* pPin, IFilterGraph* pFG);
|
||||
extern IBaseFilter* FindFilter(LPCWSTR clsid, IFilterGraph* pFG);
|
||||
extern IBaseFilter* FindFilter(const CLSID& clsid, IFilterGraph* pFG);
|
||||
extern CStringW GetFilterName(IBaseFilter* pBF);
|
||||
extern CStringW GetPinName(IPin* pPin);
|
||||
extern IFilterGraph* GetGraphFromFilter(IBaseFilter* pBF);
|
||||
extern IBaseFilter* GetFilterFromPin(IPin* pPin);
|
||||
extern IPin* AppendFilter(IPin* pPin, CString DisplayName, IGraphBuilder* pGB);
|
||||
extern IPin* InsertFilter(IPin* pPin, CString DisplayName, IGraphBuilder* pGB);
|
||||
extern void ExtractMediaTypes(IPin* pPin, CAtlArray<GUID>& types);
|
||||
extern void ExtractMediaTypes(IPin* pPin, CAtlList<CMediaType>& mts);
|
||||
extern void ShowPPage(CString DisplayName, HWND hParentWnd);
|
||||
extern void ShowPPage(IUnknown* pUnknown, HWND hParentWnd);
|
||||
extern CLSID GetCLSID(IBaseFilter* pBF);
|
||||
extern CLSID GetCLSID(IPin* pPin);
|
||||
extern bool IsCLSIDRegistered(LPCTSTR clsid);
|
||||
extern bool IsCLSIDRegistered(const CLSID& clsid);
|
||||
extern void CStringToBin(CString str, CAtlArray<BYTE>& data);
|
||||
extern CString BinToCString(BYTE* ptr, int len);
|
||||
typedef enum {CDROM_NotFound, CDROM_Audio, CDROM_VideoCD, CDROM_DVDVideo, CDROM_Unknown} cdrom_t;
|
||||
extern cdrom_t GetCDROMType(TCHAR drive, CAtlList<CString>& files);
|
||||
extern CString GetDriveLabel(TCHAR drive);
|
||||
extern bool GetKeyFrames(CString fn, CUIntArray& kfs);
|
||||
extern DVD_HMSF_TIMECODE RT2HMSF(REFERENCE_TIME rt, double fps = 0);
|
||||
extern REFERENCE_TIME HMSF2RT(DVD_HMSF_TIMECODE hmsf, double fps = 0);
|
||||
extern void memsetd(void* dst, unsigned int c, int nbytes);
|
||||
extern bool ExtractBIH(const AM_MEDIA_TYPE* pmt, BITMAPINFOHEADER* bih);
|
||||
extern bool ExtractBIH(IMediaSample* pMS, BITMAPINFOHEADER* bih);
|
||||
extern bool ExtractDim(const AM_MEDIA_TYPE* pmt, int& w, int& h, int& arx, int& ary);
|
||||
extern bool MakeMPEG2MediaType(CMediaType& mt, BYTE* seqhdr, DWORD len, int w, int h);
|
||||
extern unsigned __int64 GetFileVersion(LPCTSTR fn);
|
||||
extern bool CreateFilter(CStringW DisplayName, IBaseFilter** ppBF, CStringW& FriendlyName);
|
||||
extern IBaseFilter* AppendFilter(IPin* pPin, IMoniker* pMoniker, IGraphBuilder* pGB);
|
||||
extern CStringW GetFriendlyName(CStringW DisplayName);
|
||||
extern HRESULT LoadExternalObject(LPCTSTR path, REFCLSID clsid, REFIID iid, void** ppv);
|
||||
extern HRESULT LoadExternalFilter(LPCTSTR path, REFCLSID clsid, IBaseFilter** ppBF);
|
||||
extern HRESULT LoadExternalPropertyPage(IPersist* pP, REFCLSID clsid, IPropertyPage** ppPP);
|
||||
extern void UnloadExternalObjects();
|
||||
extern CString MakeFullPath(LPCTSTR path);
|
||||
extern CString GetMediaTypeName(const GUID& guid);
|
||||
extern GUID GUIDFromCString(CString str);
|
||||
extern HRESULT GUIDFromCString(CString str, GUID& guid);
|
||||
extern CString CStringFromGUID(const GUID& guid);
|
||||
extern CStringW UTF8To16(LPCSTR utf8);
|
||||
extern CStringA UTF16To8(LPCWSTR utf16);
|
||||
extern CString ISO6391ToLanguage(LPCSTR code);
|
||||
extern CString ISO6392ToLanguage(LPCSTR code);
|
||||
extern CString ISO6391To6392(LPCSTR code);
|
||||
extern CString ISO6392To6391(LPCSTR code);
|
||||
extern CString LanguageToISO6392(LPCTSTR lang);
|
||||
extern int MakeAACInitData(BYTE* pData, int profile, int freq, int channels);
|
||||
extern BOOL CFileGetStatus(LPCTSTR lpszFileName, CFileStatus& status);
|
||||
extern bool DeleteRegKey(LPCTSTR pszKey, LPCTSTR pszSubkey);
|
||||
extern bool SetRegKeyValue(LPCTSTR pszKey, LPCTSTR pszSubkey, LPCTSTR pszValueName, LPCTSTR pszValue);
|
||||
extern bool SetRegKeyValue(LPCTSTR pszKey, LPCTSTR pszSubkey, LPCTSTR pszValue);
|
||||
extern void RegisterSourceFilter(const CLSID& clsid, const GUID& subtype2, LPCTSTR chkbytes, LPCTSTR ext = NULL, ...);
|
||||
extern void RegisterSourceFilter(const CLSID& clsid, const GUID& subtype2, const CAtlList<CString>& chkbytes, LPCTSTR ext = NULL, ...);
|
||||
extern void UnRegisterSourceFilter(const GUID& subtype);
|
||||
|
||||
class CPinInfo : public PIN_INFO
|
||||
{
|
||||
public:
|
||||
CPinInfo() {pFilter = NULL;}
|
||||
~CPinInfo() {if(pFilter) pFilter->Release();}
|
||||
};
|
||||
|
||||
class CFilterInfo : public FILTER_INFO
|
||||
{
|
||||
public:
|
||||
CFilterInfo() {pGraph = NULL;}
|
||||
~CFilterInfo() {if(pGraph) pGraph->Release();}
|
||||
};
|
||||
|
||||
#define BeginEnumFilters(pFilterGraph, pEnumFilters, pBaseFilter) \
|
||||
{CComPtr<IEnumFilters> pEnumFilters; \
|
||||
if(pFilterGraph && SUCCEEDED(pFilterGraph->EnumFilters(&pEnumFilters))) \
|
||||
{ \
|
||||
for(CComPtr<IBaseFilter> pBaseFilter; S_OK == pEnumFilters->Next(1, &pBaseFilter, 0); pBaseFilter = NULL) \
|
||||
{ \
|
||||
|
||||
#define EndEnumFilters }}}
|
||||
|
||||
#define BeginEnumCachedFilters(pGraphConfig, pEnumFilters, pBaseFilter) \
|
||||
{CComPtr<IEnumFilters> pEnumFilters; \
|
||||
if(pGraphConfig && SUCCEEDED(pGraphConfig->EnumCacheFilter(&pEnumFilters))) \
|
||||
{ \
|
||||
for(CComPtr<IBaseFilter> pBaseFilter; S_OK == pEnumFilters->Next(1, &pBaseFilter, 0); pBaseFilter = NULL) \
|
||||
{ \
|
||||
|
||||
#define EndEnumCachedFilters }}}
|
||||
|
||||
#define BeginEnumPins(pBaseFilter, pEnumPins, pPin) \
|
||||
{CComPtr<IEnumPins> pEnumPins; \
|
||||
if(pBaseFilter && SUCCEEDED(pBaseFilter->EnumPins(&pEnumPins))) \
|
||||
{ \
|
||||
for(CComPtr<IPin> pPin; S_OK == pEnumPins->Next(1, &pPin, 0); pPin = NULL) \
|
||||
{ \
|
||||
|
||||
#define EndEnumPins }}}
|
||||
|
||||
#define BeginEnumMediaTypes(pPin, pEnumMediaTypes, pMediaType) \
|
||||
{CComPtr<IEnumMediaTypes> pEnumMediaTypes; \
|
||||
if(pPin && SUCCEEDED(pPin->EnumMediaTypes(&pEnumMediaTypes))) \
|
||||
{ \
|
||||
AM_MEDIA_TYPE* pMediaType = NULL; \
|
||||
for(; S_OK == pEnumMediaTypes->Next(1, &pMediaType, NULL); DeleteMediaType(pMediaType), pMediaType = NULL) \
|
||||
{ \
|
||||
|
||||
#define EndEnumMediaTypes(pMediaType) } if(pMediaType) DeleteMediaType(pMediaType); }}
|
||||
|
||||
#define BeginEnumSysDev(clsid, pMoniker) \
|
||||
{CComPtr<ICreateDevEnum> pDevEnum4$##clsid; \
|
||||
pDevEnum4$##clsid.CoCreateInstance(CLSID_SystemDeviceEnum); \
|
||||
CComPtr<IEnumMoniker> pClassEnum4$##clsid; \
|
||||
if(SUCCEEDED(pDevEnum4$##clsid->CreateClassEnumerator(clsid, &pClassEnum4$##clsid, 0)) \
|
||||
&& pClassEnum4$##clsid) \
|
||||
{ \
|
||||
for(CComPtr<IMoniker> pMoniker; pClassEnum4$##clsid->Next(1, &pMoniker, 0) == S_OK; pMoniker = NULL) \
|
||||
{ \
|
||||
|
||||
#define EndEnumSysDev }}}
|
||||
|
||||
#define QI(i) (riid == __uuidof(i)) ? GetInterface((i*)this, ppv) :
|
||||
#define QI2(i) (riid == IID_##i) ? GetInterface((i*)this, ppv) :
|
||||
|
||||
template <typename T> __inline void INITDDSTRUCT(T& dd)
|
||||
{
|
||||
ZeroMemory(&dd, sizeof(dd));
|
||||
dd.dwSize = sizeof(dd);
|
||||
}
|
||||
|
||||
#define countof(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
template <class T>
|
||||
static CUnknown* WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
|
||||
{
|
||||
*phr = S_OK;
|
||||
CUnknown* punk = new T(lpunk, phr);
|
||||
if(punk == NULL) *phr = E_OUTOFMEMORY;
|
||||
return punk;
|
||||
}
|
94
vsfilter/dsutil/FontInstaller.cpp
Normal file
94
vsfilter/dsutil/FontInstaller.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "StdAfx.h"
|
||||
#include ".\fontinstaller.h"
|
||||
|
||||
CFontInstaller::CFontInstaller()
|
||||
{
|
||||
if(HMODULE hGdi = GetModuleHandle(_T("gdi32.dll")))
|
||||
{
|
||||
pAddFontMemResourceEx = (HANDLE (WINAPI *)(PVOID,DWORD,PVOID,DWORD*))GetProcAddress(hGdi, "AddFontMemResourceEx");
|
||||
pAddFontResourceEx = (int (WINAPI *)(LPCTSTR,DWORD,PVOID))GetProcAddress(hGdi, "AddFontResourceExA");
|
||||
pRemoveFontMemResourceEx = (BOOL (WINAPI *)(HANDLE))GetProcAddress(hGdi, "RemoveFontMemResourceEx");
|
||||
pRemoveFontResourceEx = (BOOL (WINAPI *)(LPCTSTR,DWORD,PVOID))GetProcAddress(hGdi, "RemoveFontResourceExA");
|
||||
}
|
||||
|
||||
if(HMODULE hGdi = GetModuleHandle(_T("kernel32.dll")))
|
||||
{
|
||||
pMoveFileEx = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, DWORD))GetProcAddress(hGdi, "MoveFileExA");
|
||||
}
|
||||
}
|
||||
|
||||
CFontInstaller::~CFontInstaller()
|
||||
{
|
||||
UninstallFonts();
|
||||
}
|
||||
|
||||
bool CFontInstaller::InstallFont(const CAtlArray<BYTE>& data)
|
||||
{
|
||||
return InstallFont(data.GetData(), data.GetCount());
|
||||
}
|
||||
|
||||
bool CFontInstaller::InstallFont(const void* pData, UINT len)
|
||||
{
|
||||
return InstallFontFile(pData, len) || InstallFontMemory(pData, len);
|
||||
}
|
||||
|
||||
void CFontInstaller::UninstallFonts()
|
||||
{
|
||||
if(pRemoveFontMemResourceEx)
|
||||
{
|
||||
POSITION pos = m_fonts.GetHeadPosition();
|
||||
while(pos) pRemoveFontMemResourceEx(m_fonts.GetNext(pos));
|
||||
m_fonts.RemoveAll();
|
||||
}
|
||||
|
||||
if(pRemoveFontResourceEx)
|
||||
{
|
||||
POSITION pos = m_files.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
CString fn = m_files.GetNext(pos);
|
||||
pRemoveFontResourceEx(fn, FR_PRIVATE, 0);
|
||||
if(!DeleteFile(fn) && pMoveFileEx)
|
||||
pMoveFileEx(fn, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||||
}
|
||||
|
||||
m_files.RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool CFontInstaller::InstallFontMemory(const void* pData, UINT len)
|
||||
{
|
||||
if(!pAddFontMemResourceEx)
|
||||
return false;
|
||||
|
||||
DWORD nFonts = 0;
|
||||
HANDLE hFont = pAddFontMemResourceEx((PVOID)pData, len, NULL, &nFonts);
|
||||
if(hFont && nFonts > 0) m_fonts.AddTail(hFont);
|
||||
return hFont && nFonts > 0;
|
||||
}
|
||||
|
||||
bool CFontInstaller::InstallFontFile(const void* pData, UINT len)
|
||||
{
|
||||
if(!pAddFontResourceEx)
|
||||
return false;
|
||||
|
||||
CFile f;
|
||||
TCHAR path[MAX_PATH], fn[MAX_PATH];
|
||||
if(!GetTempPath(MAX_PATH, path) || !GetTempFileName(path, _T("g_font"), 0, fn))
|
||||
return false;
|
||||
|
||||
if(f.Open(fn, CFile::modeWrite))
|
||||
{
|
||||
f.Write(pData, len);
|
||||
f.Close();
|
||||
|
||||
if(pAddFontResourceEx(fn, FR_PRIVATE, 0) > 0)
|
||||
{
|
||||
m_files.AddTail(fn);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteFile(fn);
|
||||
return false;
|
||||
}
|
25
vsfilter/dsutil/FontInstaller.h
Normal file
25
vsfilter/dsutil/FontInstaller.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
|
||||
class CFontInstaller
|
||||
{
|
||||
HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID,DWORD,PVOID,DWORD*);
|
||||
BOOL (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
|
||||
int (WINAPI *pAddFontResourceEx)(LPCTSTR,DWORD,PVOID);
|
||||
BOOL (WINAPI *pRemoveFontResourceEx)(LPCTSTR,DWORD,PVOID);
|
||||
BOOL (WINAPI *pMoveFileEx)(LPCTSTR, LPCTSTR,DWORD);
|
||||
|
||||
CAtlList<HANDLE> m_fonts;
|
||||
CAtlList<CString> m_files;
|
||||
bool InstallFontMemory(const void* pData, UINT len);
|
||||
bool InstallFontFile(const void* pData, UINT len);
|
||||
|
||||
public:
|
||||
CFontInstaller();
|
||||
virtual ~CFontInstaller();
|
||||
|
||||
bool InstallFont(const CAtlArray<BYTE>& data);
|
||||
bool InstallFont(const void* pData, UINT len);
|
||||
void UninstallFonts();
|
||||
};
|
641
vsfilter/dsutil/MediaTypeEx.cpp
Normal file
641
vsfilter/dsutil/MediaTypeEx.cpp
Normal file
|
@ -0,0 +1,641 @@
|
|||
#include "StdAfx.h"
|
||||
#include "DSUtil.h"
|
||||
#include "MediaTypeEx.h"
|
||||
|
||||
#include <mmreg.h>
|
||||
#include <initguid.h>
|
||||
#include "../include/moreuuids.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
WAVEFORMATEX Format;
|
||||
BYTE bBigEndian;
|
||||
BYTE bsid;
|
||||
BYTE lfeon;
|
||||
BYTE copyrightb;
|
||||
BYTE nAuxBitsCode; // Aux bits per frame
|
||||
} DOLBYAC3WAVEFORMAT;
|
||||
#pragma pack(pop)
|
||||
|
||||
CMediaTypeEx::CMediaTypeEx()
|
||||
{
|
||||
}
|
||||
|
||||
CString CMediaTypeEx::ToString(IPin* pPin)
|
||||
{
|
||||
CString packing, type, codec, dim, rate, dur;
|
||||
|
||||
// TODO
|
||||
|
||||
if(majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
|
||||
{
|
||||
packing = _T("Encrypted MPEG2 Pack");
|
||||
}
|
||||
else if(majortype == MEDIATYPE_MPEG2_PACK)
|
||||
{
|
||||
packing = _T("MPEG2 Pack");
|
||||
}
|
||||
else if(majortype == MEDIATYPE_MPEG2_PES)
|
||||
{
|
||||
packing = _T("MPEG2 PES");
|
||||
}
|
||||
|
||||
if(majortype == MEDIATYPE_Video)
|
||||
{
|
||||
type = _T("Video");
|
||||
|
||||
BITMAPINFOHEADER bih;
|
||||
bool fBIH = ExtractBIH(this, &bih);
|
||||
|
||||
int w, h, arx, ary;
|
||||
bool fDim = ExtractDim(this, w, h, arx, ary);
|
||||
|
||||
if(fBIH && bih.biCompression)
|
||||
{
|
||||
codec = GetVideoCodecName(subtype, bih.biCompression);
|
||||
}
|
||||
|
||||
if(codec.IsEmpty())
|
||||
{
|
||||
if(formattype == FORMAT_MPEGVideo) codec = _T("MPEG1 Video");
|
||||
else if(formattype == FORMAT_MPEG2_VIDEO) codec = _T("MPEG2 Video");
|
||||
else if(formattype == FORMAT_DiracVideoInfo) codec = _T("Dirac Video");
|
||||
}
|
||||
|
||||
if(fDim)
|
||||
{
|
||||
dim.Format(_T("%dx%d"), w, h);
|
||||
if(w*ary != h*arx) dim.Format(_T("%s (%d:%d)"), CString(dim), arx, ary);
|
||||
}
|
||||
|
||||
if(formattype == FORMAT_VideoInfo || formattype == FORMAT_MPEGVideo)
|
||||
{
|
||||
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pbFormat;
|
||||
if(vih->AvgTimePerFrame) rate.Format(_T("%0.2ffps "), 10000000.0f / vih->AvgTimePerFrame);
|
||||
if(vih->dwBitRate) rate.Format(_T("%s%dKbps"), CString(rate), vih->dwBitRate/1000);
|
||||
}
|
||||
else if(formattype == FORMAT_VideoInfo2 || formattype == FORMAT_MPEG2_VIDEO || formattype == FORMAT_DiracVideoInfo)
|
||||
{
|
||||
VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)pbFormat;
|
||||
if(vih->AvgTimePerFrame) rate.Format(_T("%0.2ffps "), 10000000.0f / vih->AvgTimePerFrame);
|
||||
if(vih->dwBitRate) rate.Format(_T("%s%dKbps"), CString(rate), vih->dwBitRate/1000);
|
||||
}
|
||||
|
||||
rate.Trim();
|
||||
|
||||
if(subtype == MEDIASUBTYPE_DVD_SUBPICTURE)
|
||||
{
|
||||
type = _T("Subtitle");
|
||||
codec = _T("DVD Subpicture");
|
||||
}
|
||||
}
|
||||
else if(majortype == MEDIATYPE_Audio)
|
||||
{
|
||||
type = _T("Audio");
|
||||
|
||||
if(formattype == FORMAT_WaveFormatEx)
|
||||
{
|
||||
WAVEFORMATEX* wfe = (WAVEFORMATEX*)Format();
|
||||
|
||||
if(wfe->wFormatTag/* > WAVE_FORMAT_PCM && wfe->wFormatTag < WAVE_FORMAT_EXTENSIBLE
|
||||
&& wfe->wFormatTag != WAVE_FORMAT_IEEE_FLOAT*/
|
||||
|| subtype != GUID_NULL)
|
||||
{
|
||||
codec = GetAudioCodecName(subtype, wfe->wFormatTag);
|
||||
dim.Format(_T("%dHz"), wfe->nSamplesPerSec);
|
||||
if(wfe->nChannels == 1) dim.Format(_T("%s mono"), CString(dim));
|
||||
else if(wfe->nChannels == 2) dim.Format(_T("%s stereo"), CString(dim));
|
||||
else dim.Format(_T("%s %dch"), CString(dim), wfe->nChannels);
|
||||
if(wfe->nAvgBytesPerSec) rate.Format(_T("%dKbps"), wfe->nAvgBytesPerSec*8/1000);
|
||||
}
|
||||
}
|
||||
else if(formattype == FORMAT_VorbisFormat)
|
||||
{
|
||||
VORBISFORMAT* vf = (VORBISFORMAT*)Format();
|
||||
|
||||
codec = GetAudioCodecName(subtype, 0);
|
||||
dim.Format(_T("%dHz"), vf->nSamplesPerSec);
|
||||
if(vf->nChannels == 1) dim.Format(_T("%s mono"), CString(dim));
|
||||
else if(vf->nChannels == 2) dim.Format(_T("%s stereo"), CString(dim));
|
||||
else dim.Format(_T("%s %dch"), CString(dim), vf->nChannels);
|
||||
if(vf->nAvgBitsPerSec) rate.Format(_T("%dKbps"), vf->nAvgBitsPerSec/1000);
|
||||
}
|
||||
else if(formattype == FORMAT_VorbisFormat2)
|
||||
{
|
||||
VORBISFORMAT2* vf = (VORBISFORMAT2*)Format();
|
||||
|
||||
codec = GetAudioCodecName(subtype, 0);
|
||||
dim.Format(_T("%dHz"), vf->SamplesPerSec);
|
||||
if(vf->Channels == 1) dim.Format(_T("%s mono"), CString(dim));
|
||||
else if(vf->Channels == 2) dim.Format(_T("%s stereo"), CString(dim));
|
||||
else dim.Format(_T("%s %dch"), CString(dim), vf->Channels);
|
||||
}
|
||||
}
|
||||
else if(majortype == MEDIATYPE_Text)
|
||||
{
|
||||
type = _T("Text");
|
||||
}
|
||||
else if(majortype == MEDIATYPE_Subtitle)
|
||||
{
|
||||
type = _T("Subtitle");
|
||||
codec = GetSubtitleCodecName(subtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = _T("Unknown");
|
||||
}
|
||||
|
||||
if(CComQIPtr<IMediaSeeking> pMS = pPin)
|
||||
{
|
||||
REFERENCE_TIME rtDur = 0;
|
||||
if(SUCCEEDED(pMS->GetDuration(&rtDur)) && rtDur)
|
||||
{
|
||||
rtDur /= 10000000;
|
||||
int s = rtDur%60;
|
||||
rtDur /= 60;
|
||||
int m = rtDur%60;
|
||||
rtDur /= 60;
|
||||
int h = rtDur;
|
||||
if(h) dur.Format(_T("%d:%02d:%02d"), h, m, s);
|
||||
else if(m) dur.Format(_T("%02d:%02d"), m, s);
|
||||
else if(s) dur.Format(_T("%ds"), s);
|
||||
}
|
||||
}
|
||||
|
||||
CString str;
|
||||
if(!codec.IsEmpty()) str += codec + _T(" ");
|
||||
if(!dim.IsEmpty()) str += dim + _T(" ");
|
||||
if(!rate.IsEmpty()) str += rate + _T(" ");
|
||||
if(!dur.IsEmpty()) str += dur + _T(" ");
|
||||
str.Trim(_T(" ,"));
|
||||
|
||||
if(!str.IsEmpty()) str = type + _T(": ") + str;
|
||||
else str = type;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
CString CMediaTypeEx::GetVideoCodecName(const GUID& subtype, DWORD biCompression)
|
||||
{
|
||||
CString str;
|
||||
|
||||
static CAtlMap<DWORD, CString> names;
|
||||
|
||||
if(names.IsEmpty())
|
||||
{
|
||||
names['WMV1'] = _T("Windows Media Video 7");
|
||||
names['WMV2'] = _T("Windows Media Video 8");
|
||||
names['WMV3'] = _T("Windows Media Video 9");
|
||||
names['DIV3'] = _T("DivX 3");
|
||||
names['DX50'] = _T("DivX 5");
|
||||
names['MP4V'] = _T("MPEG4 Video");
|
||||
names['AVC1'] = _T("MPEG4 Video (H264)");
|
||||
names['H264'] = _T("MPEG4 Video (H264)");
|
||||
names['RV10'] = _T("RealVideo 1");
|
||||
names['RV20'] = _T("RealVideo 2");
|
||||
names['RV30'] = _T("RealVideo 3");
|
||||
names['RV40'] = _T("RealVideo 4");
|
||||
names['FLV1'] = _T("Flash Video 1");
|
||||
// names[''] = _T("");
|
||||
}
|
||||
|
||||
if(biCompression)
|
||||
{
|
||||
BYTE* b = (BYTE*)&biCompression;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
if(b[i] >= 'a' && b[i] <= 'z')
|
||||
b[i] = toupper(b[i]);
|
||||
|
||||
if(!names.Lookup(MAKEFOURCC(b[3], b[2], b[1], b[0]), str))
|
||||
{
|
||||
if(subtype == MEDIASUBTYPE_DiracVideo) str = _T("Dirac Video");
|
||||
// else if(subtype == ) str = _T("");
|
||||
else if(biCompression < 256) str.Format(_T("%d"), biCompression);
|
||||
else str.Format(_T("%4.4hs"), &biCompression);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
CString CMediaTypeEx::GetAudioCodecName(const GUID& subtype, WORD wFormatTag)
|
||||
{
|
||||
CString str;
|
||||
|
||||
static CAtlMap<WORD, CString> names;
|
||||
|
||||
if(names.IsEmpty())
|
||||
{
|
||||
names[WAVE_FORMAT_PCM] = _T("PCM");
|
||||
names[WAVE_FORMAT_EXTENSIBLE] = _T("WAVE_FORMAT_EXTENSIBLE");
|
||||
names[WAVE_FORMAT_IEEE_FLOAT] = _T("IEEE Float");
|
||||
names[WAVE_FORMAT_ADPCM] = _T("MS ADPCM");
|
||||
names[WAVE_FORMAT_ALAW] = _T("aLaw");
|
||||
names[WAVE_FORMAT_MULAW] = _T("muLaw");
|
||||
names[WAVE_FORMAT_DRM] = _T("DRM");
|
||||
names[WAVE_FORMAT_OKI_ADPCM] = _T("OKI ADPCM");
|
||||
names[WAVE_FORMAT_DVI_ADPCM] = _T("DVI ADPCM");
|
||||
names[WAVE_FORMAT_IMA_ADPCM] = _T("IMA ADPCM");
|
||||
names[WAVE_FORMAT_MEDIASPACE_ADPCM] = _T("Mediaspace ADPCM");
|
||||
names[WAVE_FORMAT_SIERRA_ADPCM] = _T("Sierra ADPCM");
|
||||
names[WAVE_FORMAT_G723_ADPCM] = _T("G723 ADPCM");
|
||||
names[WAVE_FORMAT_DIALOGIC_OKI_ADPCM] = _T("Dialogic OKI ADPCM");
|
||||
names[WAVE_FORMAT_MEDIAVISION_ADPCM] = _T("Media Vision ADPCM");
|
||||
names[WAVE_FORMAT_YAMAHA_ADPCM] = _T("Yamaha ADPCM");
|
||||
names[WAVE_FORMAT_DSPGROUP_TRUESPEECH] = _T("DSP Group Truespeech");
|
||||
names[WAVE_FORMAT_DOLBY_AC2] = _T("Dolby AC2");
|
||||
names[WAVE_FORMAT_GSM610] = _T("GSM610");
|
||||
names[WAVE_FORMAT_MSNAUDIO] = _T("MSN Audio");
|
||||
names[WAVE_FORMAT_ANTEX_ADPCME] = _T("Antex ADPCME");
|
||||
names[WAVE_FORMAT_CS_IMAADPCM] = _T("Crystal Semiconductor IMA ADPCM");
|
||||
names[WAVE_FORMAT_ROCKWELL_ADPCM] = _T("Rockwell ADPCM");
|
||||
names[WAVE_FORMAT_ROCKWELL_DIGITALK] = _T("Rockwell Digitalk");
|
||||
names[WAVE_FORMAT_G721_ADPCM] = _T("G721");
|
||||
names[WAVE_FORMAT_G728_CELP] = _T("G728");
|
||||
names[WAVE_FORMAT_MSG723] = _T("MSG723");
|
||||
names[WAVE_FORMAT_MPEG] = _T("MPEG Audio");
|
||||
names[WAVE_FORMAT_MPEGLAYER3] = _T("MPEG Audio Layer 3");
|
||||
names[WAVE_FORMAT_LUCENT_G723] = _T("Lucent G723");
|
||||
names[WAVE_FORMAT_VOXWARE] = _T("Voxware");
|
||||
names[WAVE_FORMAT_G726_ADPCM] = _T("G726");
|
||||
names[WAVE_FORMAT_G722_ADPCM] = _T("G722");
|
||||
names[WAVE_FORMAT_G729A] = _T("G729A");
|
||||
names[WAVE_FORMAT_MEDIASONIC_G723] = _T("MediaSonic G723");
|
||||
names[WAVE_FORMAT_ZYXEL_ADPCM] = _T("ZyXEL ADPCM");
|
||||
names[WAVE_FORMAT_RHETOREX_ADPCM] = _T("Rhetorex ADPCM");
|
||||
names[WAVE_FORMAT_VIVO_G723] = _T("Vivo G723");
|
||||
names[WAVE_FORMAT_VIVO_SIREN] = _T("Vivo Siren");
|
||||
names[WAVE_FORMAT_DIGITAL_G723] = _T("Digital G723");
|
||||
names[WAVE_FORMAT_SANYO_LD_ADPCM] = _T("Sanyo LD ADPCM");
|
||||
names[WAVE_FORMAT_CREATIVE_ADPCM] = _T("Creative ADPCM");
|
||||
names[WAVE_FORMAT_CREATIVE_FASTSPEECH8] = _T("Creative Fastspeech 8");
|
||||
names[WAVE_FORMAT_CREATIVE_FASTSPEECH10] = _T("Creative Fastspeech 10");
|
||||
names[WAVE_FORMAT_UHER_ADPCM] = _T("UHER ADPCM");
|
||||
names[WAVE_FORMAT_DOLBY_AC3] = _T("Dolby AC3");
|
||||
names[WAVE_FORMAT_DVD_DTS] = _T("DTS");
|
||||
names[WAVE_FORMAT_AAC] = _T("AAC");
|
||||
names[WAVE_FORMAT_FLAC] = _T("FLAC");
|
||||
names[WAVE_FORMAT_TTA1] = _T("TTA");
|
||||
names[WAVE_FORMAT_14_4] = _T("RealAudio 14.4");
|
||||
names[WAVE_FORMAT_28_8] = _T("RealAudio 28.8");
|
||||
names[WAVE_FORMAT_ATRC] = _T("RealAudio ATRC");
|
||||
names[WAVE_FORMAT_COOK] = _T("RealAudio COOK");
|
||||
names[WAVE_FORMAT_DNET] = _T("RealAudio DNET");
|
||||
names[WAVE_FORMAT_RAAC] = _T("RealAudio RAAC");
|
||||
names[WAVE_FORMAT_RACP] = _T("RealAudio RACP");
|
||||
names[WAVE_FORMAT_SIPR] = _T("RealAudio SIPR");
|
||||
names[WAVE_FORMAT_PS2_PCM] = _T("PS2 PCM");
|
||||
names[WAVE_FORMAT_PS2_ADPCM] = _T("PS2 ADPCM");
|
||||
names[0x0160] = _T("Windows Media Audio");
|
||||
names[0x0161] = _T("Windows Media Audio");
|
||||
names[0x0162] = _T("Windows Media Audio");
|
||||
names[0x0163] = _T("Windows Media Audio");
|
||||
// names[] = _T("");
|
||||
}
|
||||
|
||||
if(!names.Lookup(wFormatTag, str))
|
||||
{
|
||||
if(subtype == MEDIASUBTYPE_Vorbis) str = _T("Vorbis (deprecated)");
|
||||
else if(subtype == MEDIASUBTYPE_Vorbis2) str = _T("Vorbis");
|
||||
else if(subtype == MEDIASUBTYPE_MP4A) str = _T("MPEG4 Audio");
|
||||
else if(subtype == MEDIASUBTYPE_FLAC_FRAMED) str = _T("FLAC (framed)");
|
||||
else if(subtype == MEDIASUBTYPE_DOLBY_AC3) str += _T("Dolby AC3");
|
||||
else if(subtype == MEDIASUBTYPE_DTS) str += _T("DTS");
|
||||
// else if(subtype == ) str = _T("");
|
||||
else str.Format(_T("0x%04x"), wFormatTag);
|
||||
}
|
||||
|
||||
if(wFormatTag == WAVE_FORMAT_PCM)
|
||||
{
|
||||
if(subtype == MEDIASUBTYPE_DOLBY_AC3) str += _T(" (AC3)");
|
||||
else if(subtype == MEDIASUBTYPE_DTS) str += _T(" (DTS)");
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
CString CMediaTypeEx::GetSubtitleCodecName(const GUID& subtype)
|
||||
{
|
||||
CString str;
|
||||
|
||||
static CAtlMap<GUID, CString> names;
|
||||
|
||||
if(names.IsEmpty())
|
||||
{
|
||||
names[MEDIASUBTYPE_UTF8] = _T("UTF-8");
|
||||
names[MEDIASUBTYPE_SSA] = _T("SubStation Alpha");
|
||||
names[MEDIASUBTYPE_ASS] = _T("Advanced SubStation Alpha");
|
||||
names[MEDIASUBTYPE_ASS2] = _T("Advanced SubStation Alpha");
|
||||
names[MEDIASUBTYPE_SSF] = _T("Stuctured Subtitle Format");
|
||||
names[MEDIASUBTYPE_USF] = _T("Universal Subtitle Format");
|
||||
names[MEDIASUBTYPE_VOBSUB] = _T("VobSub");
|
||||
// names[''] = _T("");
|
||||
}
|
||||
|
||||
if(names.Lookup(subtype, str))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void CMediaTypeEx::Dump(CAtlList<CString>& sl)
|
||||
{
|
||||
CString str;
|
||||
|
||||
sl.RemoveAll();
|
||||
|
||||
int fmtsize = 0;
|
||||
|
||||
CString major = CStringFromGUID(majortype);
|
||||
CString sub = CStringFromGUID(subtype);
|
||||
CString format = CStringFromGUID(formattype);
|
||||
|
||||
sl.AddTail(ToString() + _T("\n"));
|
||||
|
||||
sl.AddTail(_T("AM_MEDIA_TYPE: "));
|
||||
str.Format(_T("majortype: %s %s"), CString(GuidNames[majortype]), major);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("subtype: %s %s"), CString(GuidNames[subtype]), sub);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("formattype: %s %s"), CString(GuidNames[formattype]), format);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("bFixedSizeSamples: %d"), bFixedSizeSamples);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("bTemporalCompression: %d"), bTemporalCompression);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("lSampleSize: %d"), lSampleSize);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("cbFormat: %d"), cbFormat);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
|
||||
if(formattype == FORMAT_VideoInfo || formattype == FORMAT_VideoInfo2
|
||||
|| formattype == FORMAT_MPEGVideo || formattype == FORMAT_MPEG2_VIDEO)
|
||||
{
|
||||
fmtsize =
|
||||
formattype == FORMAT_VideoInfo ? sizeof(VIDEOINFOHEADER) :
|
||||
formattype == FORMAT_VideoInfo2 ? sizeof(VIDEOINFOHEADER2) :
|
||||
formattype == FORMAT_MPEGVideo ? sizeof(MPEG1VIDEOINFO)-1 :
|
||||
formattype == FORMAT_MPEG2_VIDEO ? sizeof(MPEG2VIDEOINFO)-4 :
|
||||
0;
|
||||
|
||||
VIDEOINFOHEADER& vih = *(VIDEOINFOHEADER*)pbFormat;
|
||||
BITMAPINFOHEADER* bih = &vih.bmiHeader;
|
||||
|
||||
sl.AddTail(_T("VIDEOINFOHEADER:"));
|
||||
str.Format(_T("rcSource: (%d,%d)-(%d,%d)"), vih.rcSource);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("rcTarget: (%d,%d)-(%d,%d)"), vih.rcTarget);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwBitRate: %d"), vih.dwBitRate);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwBitErrorRate: %d"), vih.dwBitErrorRate);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("AvgTimePerFrame: %I64d"), vih.AvgTimePerFrame);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
|
||||
if(formattype == FORMAT_VideoInfo2 || formattype == FORMAT_MPEG2_VIDEO)
|
||||
{
|
||||
VIDEOINFOHEADER2& vih = *(VIDEOINFOHEADER2*)pbFormat;
|
||||
bih = &vih.bmiHeader;
|
||||
|
||||
sl.AddTail(_T("VIDEOINFOHEADER2:"));
|
||||
str.Format(_T("dwInterlaceFlags: 0x%08x"), vih.dwInterlaceFlags);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwCopyProtectFlags: 0x%08x"), vih.dwCopyProtectFlags);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwPictAspectRatioX: %d"), vih.dwPictAspectRatioX);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwPictAspectRatioY: %d"), vih.dwPictAspectRatioY);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwControlFlags: 0x%08x"), vih.dwControlFlags);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwReserved2: 0x%08x"), vih.dwReserved2);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
|
||||
if(formattype == FORMAT_MPEGVideo)
|
||||
{
|
||||
MPEG1VIDEOINFO& mvih = *(MPEG1VIDEOINFO*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("MPEG1VIDEOINFO:"));
|
||||
str.Format(_T("dwStartTimeCode: %d"), mvih.dwStartTimeCode);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("cbSequenceHeader: %d"), mvih.cbSequenceHeader);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
else if(formattype == FORMAT_MPEG2_VIDEO)
|
||||
{
|
||||
MPEG2VIDEOINFO& mvih = *(MPEG2VIDEOINFO*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("MPEG2VIDEOINFO:"));
|
||||
str.Format(_T("dwStartTimeCode: %d"), mvih.dwStartTimeCode);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("cbSequenceHeader: %d"), mvih.cbSequenceHeader);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwProfile: 0x%08x"), mvih.dwProfile);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwLevel: 0x%08x"), mvih.dwLevel);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwFlags: 0x%08x"), mvih.dwFlags);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
|
||||
sl.AddTail(_T("BITMAPINFOHEADER:"));
|
||||
str.Format(_T("biSize: %d"), bih->biSize);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biWidth: %d"), bih->biWidth);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biHeight: %d"), bih->biHeight);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biPlanes: %d"), bih->biPlanes);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biBitCount: %d"), bih->biBitCount);
|
||||
sl.AddTail(str);
|
||||
if(bih->biCompression < 256) str.Format(_T("biCompression: %d"), bih->biCompression);
|
||||
else str.Format(_T("biCompression: %4.4hs"), &bih->biCompression);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biSizeImage: %d"), bih->biSizeImage);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biXPelsPerMeter: %d"), bih->biXPelsPerMeter);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biYPelsPerMeter: %d"), bih->biYPelsPerMeter);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biClrUsed: %d"), bih->biClrUsed);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("biClrImportant: %d"), bih->biClrImportant);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
else if(formattype == FORMAT_WaveFormatEx)
|
||||
{
|
||||
fmtsize = sizeof(WAVEFORMATEX);
|
||||
|
||||
WAVEFORMATEX& wfe = *(WAVEFORMATEX*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("WAVEFORMATEX:"));
|
||||
str.Format(_T("wFormatTag: 0x%04x"), wfe.wFormatTag);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nChannels: %d"), wfe.nChannels);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nSamplesPerSec: %d"), wfe.nSamplesPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nAvgBytesPerSec: %d"), wfe.nAvgBytesPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nBlockAlign: %d"), wfe.nBlockAlign);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("wBitsPerSample: %d"), wfe.wBitsPerSample);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("cbSize: %d (extra bytes)"), wfe.cbSize);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
|
||||
if(wfe.wFormatTag != WAVE_FORMAT_PCM && wfe.cbSize > 0)
|
||||
{
|
||||
if(wfe.wFormatTag == WAVE_FORMAT_EXTENSIBLE && wfe.cbSize == sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX))
|
||||
{
|
||||
fmtsize = sizeof(WAVEFORMATEXTENSIBLE);
|
||||
|
||||
WAVEFORMATEXTENSIBLE& wfe = *(WAVEFORMATEXTENSIBLE*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("WAVEFORMATEXTENSIBLE:"));
|
||||
if(wfe.Format.wBitsPerSample != 0) str.Format(_T("wValidBitsPerSample: %d"), wfe.Samples.wValidBitsPerSample);
|
||||
else str.Format(_T("wSamplesPerBlock: %d"), wfe.Samples.wSamplesPerBlock);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("dwChannelMask: 0x%08x"), wfe.dwChannelMask);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("SubFormat: %s"), CStringFromGUID(wfe.SubFormat));
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
else if(wfe.wFormatTag == WAVE_FORMAT_DOLBY_AC3 && wfe.cbSize == sizeof(DOLBYAC3WAVEFORMAT)-sizeof(WAVEFORMATEX))
|
||||
{
|
||||
fmtsize = sizeof(DOLBYAC3WAVEFORMAT);
|
||||
|
||||
DOLBYAC3WAVEFORMAT& wfe = *(DOLBYAC3WAVEFORMAT*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("DOLBYAC3WAVEFORMAT:"));
|
||||
str.Format(_T("bBigEndian: %d"), wfe.bBigEndian);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("bsid: %d"), wfe.bsid);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("lfeon: %d"), wfe.lfeon);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("copyrightb: %d"), wfe.copyrightb);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nAuxBitsCode: %d"), wfe.nAuxBitsCode);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(formattype == FORMAT_VorbisFormat)
|
||||
{
|
||||
fmtsize = sizeof(VORBISFORMAT);
|
||||
|
||||
VORBISFORMAT& vf = *(VORBISFORMAT*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("VORBISFORMAT:"));
|
||||
str.Format(_T("nChannels: %d"), vf.nChannels);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nSamplesPerSec: %d"), vf.nSamplesPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nMinBitsPerSec: %d"), vf.nMinBitsPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nAvgBitsPerSec: %d"), vf.nAvgBitsPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("nMaxBitsPerSec: %d"), vf.nMaxBitsPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("fQuality: %.3f"), vf.fQuality);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
else if(formattype == FORMAT_VorbisFormat2)
|
||||
{
|
||||
fmtsize = sizeof(VORBISFORMAT2);
|
||||
|
||||
VORBISFORMAT2& vf = *(VORBISFORMAT2*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("VORBISFORMAT:"));
|
||||
str.Format(_T("Channels: %d"), vf.Channels);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("SamplesPerSec: %d"), vf.SamplesPerSec);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("BitsPerSample: %d"), vf.BitsPerSample);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("HeaderSize: {%d, %d, %d}"), vf.HeaderSize[0], vf.HeaderSize[1], vf.HeaderSize[2]);
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
else if(formattype == FORMAT_SubtitleInfo)
|
||||
{
|
||||
fmtsize = sizeof(SUBTITLEINFO);
|
||||
|
||||
SUBTITLEINFO& si = *(SUBTITLEINFO*)pbFormat;
|
||||
|
||||
sl.AddTail(_T("SUBTITLEINFO:"));
|
||||
str.Format(_T("dwOffset: %d"), si.dwOffset);
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("IsoLang: %s"), CString(CStringA(si.IsoLang, sizeof(si.IsoLang)-1)));
|
||||
sl.AddTail(str);
|
||||
str.Format(_T("TrackName: %s"), CString(CStringW(si.TrackName, sizeof(si.TrackName)-1)));
|
||||
sl.AddTail(str);
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
|
||||
if(cbFormat > 0)
|
||||
{
|
||||
sl.AddTail(_T("pbFormat:"));
|
||||
|
||||
for(int i = 0, j = (cbFormat + 15) & ~15; i < j; i += 16)
|
||||
{
|
||||
str.Format(_T("%04x:"), i);
|
||||
|
||||
for(int k = i, l = min(i + 16, cbFormat); k < l; k++)
|
||||
{
|
||||
CString byte;
|
||||
byte.Format(_T("%c%02x"), fmtsize > 0 && fmtsize == k ? '|' : ' ', pbFormat[k]);
|
||||
str += byte;
|
||||
}
|
||||
|
||||
for(int k = min(i + 16, cbFormat), l = i + 16; k < l; k++)
|
||||
{
|
||||
str += _T(" ");
|
||||
}
|
||||
|
||||
str += ' ';
|
||||
|
||||
for(int k = i, l = min(i + 16, cbFormat); k < l; k++)
|
||||
{
|
||||
unsigned char c = (unsigned char)pbFormat[k];
|
||||
CStringA ch;
|
||||
ch.Format("%c", c >= 0x20 ? c : '.');
|
||||
str += ch;
|
||||
}
|
||||
|
||||
sl.AddTail(str);
|
||||
}
|
||||
|
||||
sl.AddTail(_T(""));
|
||||
}
|
||||
}
|
16
vsfilter/dsutil/MediaTypeEx.h
Normal file
16
vsfilter/dsutil/MediaTypeEx.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
class CMediaTypeEx : public CMediaType
|
||||
{
|
||||
public:
|
||||
CMediaTypeEx();
|
||||
CMediaTypeEx(const CMediaType& mt) {CMediaType::operator = (mt);}
|
||||
|
||||
CString ToString(IPin* pPin = NULL);
|
||||
|
||||
static CString GetVideoCodecName(const GUID& subtype, DWORD biCompression);
|
||||
static CString GetAudioCodecName(const GUID& subtype, WORD wFormatTag);
|
||||
static CString GetSubtitleCodecName(const GUID& subtype);
|
||||
|
||||
void Dump(CAtlList<CString>& sl);
|
||||
};
|
381
vsfilter/dsutil/MediaTypes.cpp
Normal file
381
vsfilter/dsutil/MediaTypes.cpp
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <initguid.h>
|
||||
#include "../include/moreuuids.h"
|
||||
#include "MediaTypes.h"
|
||||
#include "DSUtil.h"
|
||||
|
||||
#define VIH_NORMAL (sizeof(VIDEOINFOHEADER))
|
||||
#define VIH_BITFIELDS (sizeof(VIDEOINFOHEADER)+3*sizeof(RGBQUAD))
|
||||
#define VIH2_NORMAL (sizeof(VIDEOINFOHEADER2))
|
||||
#define VIH2_BITFIELDS (sizeof(VIDEOINFOHEADER2)+3*sizeof(RGBQUAD))
|
||||
#define BIH_SIZE (sizeof(BITMAPINFOHEADER))
|
||||
|
||||
VIH vihs[] =
|
||||
{
|
||||
// YUY2
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, mmioFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_YUY2 // subtype
|
||||
},
|
||||
// YV12
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('Y','V','1','2'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_YV12 // subtype
|
||||
},
|
||||
// I420
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('I','4','2','0'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_I420 // subtype
|
||||
},
|
||||
// IYUV
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('I','Y','U','V'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_IYUV // subtype
|
||||
},
|
||||
// 8888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB32 // subtype
|
||||
},
|
||||
// 8888 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB32 // subtype
|
||||
},
|
||||
// A888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_ARGB32 // subtype
|
||||
},
|
||||
// A888 bitf (I'm not sure if this exist...)
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_ARGB32 // subtype
|
||||
},
|
||||
// 888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 24, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB24 // subtype
|
||||
},
|
||||
// 888 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 24, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB24 // subtype
|
||||
},
|
||||
// 565 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB565 // subtype
|
||||
},
|
||||
// 565 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xF800, 0x07E0, 0x001F}, // mask[3]
|
||||
VIH_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB565 // subtype
|
||||
},
|
||||
// 555 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB555 // subtype
|
||||
},
|
||||
// 555 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0x7C00, 0x03E0, 0x001F}, // mask[3]
|
||||
VIH_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB555 // subtype
|
||||
},
|
||||
};
|
||||
|
||||
VIH2 vih2s[] =
|
||||
{
|
||||
// YUY2
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, mmioFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_YUY2 // subtype
|
||||
},
|
||||
// YV12
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('Y','V','1','2'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_YV12 // subtype
|
||||
},
|
||||
// I420
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('I','4','2','0'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_I420 // subtype
|
||||
},
|
||||
// IYUV
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 12, mmioFOURCC('I','Y','U','V'), 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_IYUV // subtype
|
||||
},
|
||||
// 8888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB32 // subtype
|
||||
},
|
||||
// 8888 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH2_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB32 // subtype
|
||||
},
|
||||
// A888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_ARGB32 // subtype
|
||||
},
|
||||
// A888 bitf (I'm not sure if this exist...)
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 32, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH2_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_ARGB32 // subtype
|
||||
},
|
||||
// 888 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 24, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB24 // subtype
|
||||
},
|
||||
// 888 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 24, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xFF0000, 0x00FF00, 0x0000FF}, // mask[3]
|
||||
VIH2_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB24 // subtype
|
||||
},
|
||||
// 565 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB565 // subtype
|
||||
},
|
||||
// 565 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0xF800, 0x07E0, 0x001F}, // mask[3]
|
||||
VIH2_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB565 // subtype
|
||||
},
|
||||
// 555 normal
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_RGB, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0, 0, 0}, // mask[3]
|
||||
VIH2_NORMAL, // size
|
||||
&MEDIASUBTYPE_RGB555 // subtype
|
||||
},
|
||||
// 555 bitf
|
||||
{
|
||||
{
|
||||
{0, 0, 0, 0}, {0, 0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
{BIH_SIZE, 0, 0, 1, 16, BI_BITFIELDS, 0, 0, 0, 0, 0} // bmiHeader
|
||||
},
|
||||
{0x7C00, 0x03E0, 0x001F}, // mask[3]
|
||||
VIH2_BITFIELDS, // size
|
||||
&MEDIASUBTYPE_RGB555 // subtype
|
||||
},
|
||||
};
|
||||
|
||||
int VIHSIZE = countof(vihs);
|
||||
|
||||
CString VIH2String(int i)
|
||||
{
|
||||
CString ret = CString(GuidNames[*vihs[i].subtype]);
|
||||
if(!ret.Left(13).CompareNoCase(_T("MEDIASUBTYPE_"))) ret = ret.Mid(13);
|
||||
if(vihs[i].vih.bmiHeader.biCompression == 3) ret += _T(" BITF");
|
||||
if(*vihs[i].subtype == MEDIASUBTYPE_I420) ret = _T("I420"); // FIXME
|
||||
return(ret);
|
||||
}
|
||||
|
||||
CString Subtype2String(const GUID& subtype)
|
||||
{
|
||||
CString ret = CString(GuidNames[subtype]);
|
||||
if(!ret.Left(13).CompareNoCase(_T("MEDIASUBTYPE_"))) ret = ret.Mid(13);
|
||||
if(subtype == MEDIASUBTYPE_I420) ret = _T("I420"); // FIXME
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void CorrectMediaType(AM_MEDIA_TYPE* pmt)
|
||||
{
|
||||
if(!pmt) return;
|
||||
|
||||
CMediaType mt(*pmt);
|
||||
|
||||
if(mt.formattype == FORMAT_VideoInfo)
|
||||
{
|
||||
VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
|
||||
|
||||
for(int i = 0; i < VIHSIZE; i++)
|
||||
{
|
||||
if(mt.subtype == *vihs[i].subtype
|
||||
&& vih->bmiHeader.biCompression == vihs[i].vih.bmiHeader.biCompression)
|
||||
{
|
||||
mt.AllocFormatBuffer(vihs[i].size);
|
||||
memcpy(mt.pbFormat, &vihs[i], vihs[i].size);
|
||||
memcpy(mt.pbFormat, pmt->pbFormat, sizeof(VIDEOINFOHEADER));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mt.formattype == FORMAT_VideoInfo2)
|
||||
{
|
||||
VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mt.pbFormat;
|
||||
|
||||
for(int i = 0; i < VIHSIZE; i++)
|
||||
{
|
||||
if(mt.subtype == *vih2s[i].subtype
|
||||
&& vih2->bmiHeader.biCompression == vih2s[i].vih.bmiHeader.biCompression)
|
||||
{
|
||||
mt.AllocFormatBuffer(vih2s[i].size);
|
||||
memcpy(mt.pbFormat, &vih2s[i], vih2s[i].size);
|
||||
memcpy(mt.pbFormat, pmt->pbFormat, sizeof(VIDEOINFOHEADER2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CopyMediaType(pmt, &mt);
|
||||
}
|
47
vsfilter/dsutil/MediaTypes.h
Normal file
47
vsfilter/dsutil/MediaTypes.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#pragma pack(1)
|
||||
struct VIH
|
||||
{
|
||||
VIDEOINFOHEADER vih;
|
||||
UINT mask[3];
|
||||
int size;
|
||||
const GUID* subtype;
|
||||
};
|
||||
struct VIH2
|
||||
{
|
||||
VIDEOINFOHEADER2 vih;
|
||||
UINT mask[3];
|
||||
int size;
|
||||
const GUID* subtype;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
extern VIH vihs[];
|
||||
extern VIH2 vih2s[];
|
||||
|
||||
extern int VIHSIZE;
|
||||
|
||||
extern CString VIH2String(int i), Subtype2String(const GUID& subtype);
|
||||
extern void CorrectMediaType(AM_MEDIA_TYPE* pmt);
|
158
vsfilter/dsutil/NullRenderers.cpp
Normal file
158
vsfilter/dsutil/NullRenderers.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "NullRenderers.h"
|
||||
#include "../include/moreuuids.h"
|
||||
|
||||
//
|
||||
// CNullRenderer
|
||||
//
|
||||
|
||||
CNullRenderer::CNullRenderer(REFCLSID clsid, TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CBaseRenderer(clsid, pName, pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// CNullVideoRenderer
|
||||
//
|
||||
|
||||
CNullVideoRenderer::CNullVideoRenderer(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CNullRenderer(__uuidof(this), NAME("Null Video Renderer"), pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CNullVideoRenderer::CheckMediaType(const CMediaType* pmt)
|
||||
{
|
||||
return pmt->majortype == MEDIATYPE_Video
|
||||
|| pmt->subtype == MEDIASUBTYPE_MPEG2_VIDEO
|
||||
? S_OK
|
||||
: E_FAIL;
|
||||
}
|
||||
|
||||
//
|
||||
// CNullUVideoRenderer
|
||||
//
|
||||
|
||||
CNullUVideoRenderer::CNullUVideoRenderer(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CNullRenderer(__uuidof(this), NAME("Null Video Renderer (Uncompressed)"), pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CNullUVideoRenderer::CheckMediaType(const CMediaType* pmt)
|
||||
{
|
||||
return pmt->majortype == MEDIATYPE_Video
|
||||
&& (pmt->subtype == MEDIASUBTYPE_YV12
|
||||
|| pmt->subtype == MEDIASUBTYPE_I420
|
||||
|| pmt->subtype == MEDIASUBTYPE_YUYV
|
||||
|| pmt->subtype == MEDIASUBTYPE_IYUV
|
||||
|| pmt->subtype == MEDIASUBTYPE_YVU9
|
||||
|| pmt->subtype == MEDIASUBTYPE_Y411
|
||||
|| pmt->subtype == MEDIASUBTYPE_Y41P
|
||||
|| pmt->subtype == MEDIASUBTYPE_YUY2
|
||||
|| pmt->subtype == MEDIASUBTYPE_YVYU
|
||||
|| pmt->subtype == MEDIASUBTYPE_UYVY
|
||||
|| pmt->subtype == MEDIASUBTYPE_Y211
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB1
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB4
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB8
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB565
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB555
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB24
|
||||
|| pmt->subtype == MEDIASUBTYPE_RGB32
|
||||
|| pmt->subtype == MEDIASUBTYPE_ARGB1555
|
||||
|| pmt->subtype == MEDIASUBTYPE_ARGB4444
|
||||
|| pmt->subtype == MEDIASUBTYPE_ARGB32
|
||||
|| pmt->subtype == MEDIASUBTYPE_A2R10G10B10
|
||||
|| pmt->subtype == MEDIASUBTYPE_A2B10G10R10)
|
||||
? S_OK
|
||||
: E_FAIL;
|
||||
}
|
||||
|
||||
//
|
||||
// CNullAudioRenderer
|
||||
//
|
||||
|
||||
CNullAudioRenderer::CNullAudioRenderer(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CNullRenderer(__uuidof(this), NAME("Null Audio Renderer"), pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CNullAudioRenderer::CheckMediaType(const CMediaType* pmt)
|
||||
{
|
||||
return pmt->majortype == MEDIATYPE_Audio
|
||||
|| pmt->majortype == MEDIATYPE_Midi
|
||||
|| pmt->subtype == MEDIASUBTYPE_MPEG2_AUDIO
|
||||
|| pmt->subtype == MEDIASUBTYPE_DOLBY_AC3
|
||||
|| pmt->subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO
|
||||
|| pmt->subtype == MEDIASUBTYPE_DTS
|
||||
|| pmt->subtype == MEDIASUBTYPE_SDDS
|
||||
|| pmt->subtype == MEDIASUBTYPE_MPEG1AudioPayload
|
||||
|| pmt->subtype == MEDIASUBTYPE_MPEG1Audio
|
||||
|| pmt->subtype == MEDIASUBTYPE_MPEG1Audio
|
||||
? S_OK
|
||||
: E_FAIL;
|
||||
}
|
||||
|
||||
//
|
||||
// CNullUAudioRenderer
|
||||
//
|
||||
|
||||
CNullUAudioRenderer::CNullUAudioRenderer(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CNullRenderer(__uuidof(this), NAME("Null Audio Renderer (Uncompressed)"), pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CNullUAudioRenderer::CheckMediaType(const CMediaType* pmt)
|
||||
{
|
||||
return pmt->majortype == MEDIATYPE_Audio
|
||||
&& (pmt->subtype == MEDIASUBTYPE_PCM
|
||||
|| pmt->subtype == MEDIASUBTYPE_IEEE_FLOAT
|
||||
|| pmt->subtype == MEDIASUBTYPE_DRM_Audio
|
||||
|| pmt->subtype == MEDIASUBTYPE_DOLBY_AC3_SPDIF
|
||||
|| pmt->subtype == MEDIASUBTYPE_RAW_SPORT
|
||||
|| pmt->subtype == MEDIASUBTYPE_SPDIF_TAG_241h)
|
||||
? S_OK
|
||||
: E_FAIL;
|
||||
}
|
||||
|
||||
//
|
||||
// CNullTextRenderer
|
||||
//
|
||||
|
||||
HRESULT CNullTextRenderer::CTextInputPin::CheckMediaType(const CMediaType* pmt)
|
||||
{
|
||||
return pmt->majortype == MEDIATYPE_Text
|
||||
|| pmt->majortype == MEDIATYPE_ScriptCommand
|
||||
|| pmt->majortype == MEDIATYPE_Subtitle
|
||||
|| pmt->subtype == MEDIASUBTYPE_DVD_SUBPICTURE
|
||||
|| pmt->subtype == MEDIASUBTYPE_CVD_SUBPICTURE
|
||||
|| pmt->subtype == MEDIASUBTYPE_SVCD_SUBPICTURE
|
||||
? S_OK
|
||||
: E_FAIL;
|
||||
}
|
||||
|
||||
CNullTextRenderer::CNullTextRenderer(LPUNKNOWN pUnk, HRESULT* phr)
|
||||
: CBaseFilter(NAME("CNullTextRenderer"), pUnk, this, __uuidof(this), phr)
|
||||
{
|
||||
m_pInput.Attach(new CTextInputPin(this, this, phr));
|
||||
}
|
93
vsfilter/dsutil/NullRenderers.h
Normal file
93
vsfilter/dsutil/NullRenderers.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
|
||||
class CNullRenderer : public CBaseRenderer
|
||||
{
|
||||
protected:
|
||||
HRESULT DoRenderSample(IMediaSample* pSample) {return S_OK;}
|
||||
|
||||
public:
|
||||
CNullRenderer(REFCLSID clsid, TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("579883A0-4E2D-481F-9436-467AAFAB7DE8")]
|
||||
class CNullVideoRenderer : public CNullRenderer
|
||||
{
|
||||
protected:
|
||||
HRESULT CheckMediaType(const CMediaType* pmt);
|
||||
|
||||
public:
|
||||
CNullVideoRenderer(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("DD9ED57D-6ABF-42E8-89A2-11D04798DC58")]
|
||||
class CNullUVideoRenderer : public CNullRenderer
|
||||
{
|
||||
protected:
|
||||
HRESULT CheckMediaType(const CMediaType* pmt);
|
||||
|
||||
public:
|
||||
CNullUVideoRenderer(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("0C38BDFD-8C17-4E00-A344-F89397D3E22A")]
|
||||
class CNullAudioRenderer : public CNullRenderer
|
||||
{
|
||||
protected:
|
||||
HRESULT CheckMediaType(const CMediaType* pmt);
|
||||
|
||||
public:
|
||||
CNullAudioRenderer(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("64A45125-7343-4772-9DA4-179FAC9D462C")]
|
||||
class CNullUAudioRenderer : public CNullRenderer
|
||||
{
|
||||
protected:
|
||||
HRESULT CheckMediaType(const CMediaType* pmt);
|
||||
|
||||
public:
|
||||
CNullUAudioRenderer(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
};
|
||||
|
||||
[uuid("655D7613-C26C-4A25-BBBD-3C9C516122CC")]
|
||||
class CNullTextRenderer : public CBaseFilter, public CCritSec
|
||||
{
|
||||
class CTextInputPin : public CBaseInputPin
|
||||
{
|
||||
public:
|
||||
CTextInputPin(CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
|
||||
: CBaseInputPin(NAME("CTextInputPin"), pFilter, pLock, phr, L"In") {}
|
||||
HRESULT CheckMediaType(const CMediaType* pmt);
|
||||
};
|
||||
|
||||
CAutoPtr<CTextInputPin> m_pInput;
|
||||
|
||||
public:
|
||||
CNullTextRenderer(LPUNKNOWN pUnk, HRESULT* phr);
|
||||
int GetPinCount() {return (int)!!m_pInput;}
|
||||
CBasePin* GetPin(int n) {return n == 0 ? (CBasePin*)m_pInput : NULL;}
|
||||
};
|
||||
|
1910
vsfilter/dsutil/a_yuv2rgb.asm
Normal file
1910
vsfilter/dsutil/a_yuv2rgb.asm
Normal file
File diff suppressed because it is too large
Load diff
612
vsfilter/dsutil/a_yuvtable.asm
Normal file
612
vsfilter/dsutil/a_yuvtable.asm
Normal file
|
@ -0,0 +1,612 @@
|
|||
; VirtualDub - Video processing and capture application
|
||||
; Copyright (C) 1998-2001 Avery Lee
|
||||
;
|
||||
; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
.486
|
||||
.model flat
|
||||
.const
|
||||
|
||||
public _YUV_Y_table
|
||||
public _YUV_U_table
|
||||
public _YUV_V_table
|
||||
public _YUV_clip_table
|
||||
public _YUV_clip_table16
|
||||
|
||||
_YUV_Y_table dd 1FED1FEDh, 1FEF1FEFh, 1FF01FF0h, 1FF11FF1h
|
||||
dd 1FF21FF2h, 1FF31FF3h, 1FF41FF4h, 1FF61FF6h
|
||||
dd 1FF71FF7h, 1FF81FF8h, 1FF91FF9h, 1FFA1FFAh
|
||||
dd 1FFB1FFBh, 1FFD1FFDh, 1FFE1FFEh, 1FFF1FFFh
|
||||
dd 20002000h, 20012001h, 20022002h, 20032003h
|
||||
dd 20052005h, 20062006h, 20072007h, 20082008h
|
||||
dd 20092009h, 200A200Ah, 200C200Ch, 200D200Dh
|
||||
dd 200E200Eh, 200F200Fh, 20102010h, 20112011h
|
||||
dd 20132013h, 20142014h, 20152015h, 20162016h
|
||||
dd 20172017h, 20182018h, 201A201Ah, 201B201Bh
|
||||
dd 201C201Ch, 201D201Dh, 201E201Eh, 201F201Fh
|
||||
dd 20212021h, 20222022h, 20232023h, 20242024h
|
||||
dd 20252025h, 20262026h, 20282028h, 20292029h
|
||||
dd 202A202Ah, 202B202Bh, 202C202Ch, 202D202Dh
|
||||
dd 202F202Fh, 20302030h, 20312031h, 20322032h
|
||||
dd 20332033h, 20342034h, 20362036h, 20372037h
|
||||
dd 20382038h, 20392039h, 203A203Ah, 203B203Bh
|
||||
dd 203D203Dh, 203E203Eh, 203F203Fh, 20402040h
|
||||
dd 20412041h, 20422042h, 20442044h, 20452045h
|
||||
dd 20462046h, 20472047h, 20482048h, 20492049h
|
||||
dd 204A204Ah, 204C204Ch, 204D204Dh, 204E204Eh
|
||||
dd 204F204Fh, 20502050h, 20512051h, 20532053h
|
||||
dd 20542054h, 20552055h, 20562056h, 20572057h
|
||||
dd 20582058h, 205A205Ah, 205B205Bh, 205C205Ch
|
||||
dd 205D205Dh, 205E205Eh, 205F205Fh, 20612061h
|
||||
dd 20622062h, 20632063h, 20642064h, 20652065h
|
||||
dd 20662066h, 20682068h, 20692069h, 206A206Ah
|
||||
dd 206B206Bh, 206C206Ch, 206D206Dh, 206F206Fh
|
||||
dd 20702070h, 20712071h, 20722072h, 20732073h
|
||||
dd 20742074h, 20762076h, 20772077h, 20782078h
|
||||
dd 20792079h, 207A207Ah, 207B207Bh, 207D207Dh
|
||||
dd 207E207Eh, 207F207Fh, 20802080h, 20812081h
|
||||
dd 20822082h, 20842084h, 20852085h, 20862086h
|
||||
dd 20872087h, 20882088h, 20892089h, 208B208Bh
|
||||
dd 208C208Ch, 208D208Dh, 208E208Eh, 208F208Fh
|
||||
dd 20902090h, 20922092h, 20932093h, 20942094h
|
||||
dd 20952095h, 20962096h, 20972097h, 20982098h
|
||||
dd 209A209Ah, 209B209Bh, 209C209Ch, 209D209Dh
|
||||
dd 209E209Eh, 209F209Fh, 20A120A1h, 20A220A2h
|
||||
dd 20A320A3h, 20A420A4h, 20A520A5h, 20A620A6h
|
||||
dd 20A820A8h, 20A920A9h, 20AA20AAh, 20AB20ABh
|
||||
dd 20AC20ACh, 20AD20ADh, 20AF20AFh, 20B020B0h
|
||||
dd 20B120B1h, 20B220B2h, 20B320B3h, 20B420B4h
|
||||
dd 20B620B6h, 20B720B7h, 20B820B8h, 20B920B9h
|
||||
dd 20BA20BAh, 20BB20BBh, 20BD20BDh, 20BE20BEh
|
||||
dd 20BF20BFh, 20C020C0h, 20C120C1h, 20C220C2h
|
||||
dd 20C420C4h, 20C520C5h, 20C620C6h, 20C720C7h
|
||||
dd 20C820C8h, 20C920C9h, 20CB20CBh, 20CC20CCh
|
||||
dd 20CD20CDh, 20CE20CEh, 20CF20CFh, 20D020D0h
|
||||
dd 20D220D2h, 20D320D3h, 20D420D4h, 20D520D5h
|
||||
dd 20D620D6h, 20D720D7h, 20D920D9h, 20DA20DAh
|
||||
dd 20DB20DBh, 20DC20DCh, 20DD20DDh, 20DE20DEh
|
||||
dd 20DF20DFh, 20E120E1h, 20E220E2h, 20E320E3h
|
||||
dd 20E420E4h, 20E520E5h, 20E620E6h, 20E820E8h
|
||||
dd 20E920E9h, 20EA20EAh, 20EB20EBh, 20EC20ECh
|
||||
dd 20ED20EDh, 20EF20EFh, 20F020F0h, 20F120F1h
|
||||
dd 20F220F2h, 20F320F3h, 20F420F4h, 20F620F6h
|
||||
dd 20F720F7h, 20F820F8h, 20F920F9h, 20FA20FAh
|
||||
dd 20FB20FBh, 20FD20FDh, 20FE20FEh, 20FF20FFh
|
||||
dd 21002100h, 21012101h, 21022102h, 21042104h
|
||||
dd 21052105h, 21062106h, 21072107h, 21082108h
|
||||
dd 21092109h, 210B210Bh, 210C210Ch, 210D210Dh
|
||||
dd 210E210Eh, 210F210Fh, 21102110h, 21122112h
|
||||
dd 21132113h, 21142114h, 21152115h, 21162116h
|
||||
|
||||
_YUV_U_table dd 1EFE1032h, 1F001032h, 1F021031h, 1F041031h
|
||||
dd 1F061030h, 1F081030h, 1F0A1030h, 1F0C102Fh
|
||||
dd 1F0E102Fh, 1F10102Fh, 1F12102Eh, 1F14102Eh
|
||||
dd 1F16102Dh, 1F18102Dh, 1F1A102Dh, 1F1C102Ch
|
||||
dd 1F1E102Ch, 1F20102Bh, 1F22102Bh, 1F24102Bh
|
||||
dd 1F26102Ah, 1F28102Ah, 1F2A1029h, 1F2C1029h
|
||||
dd 1F2E1029h, 1F301028h, 1F321028h, 1F341027h
|
||||
dd 1F361027h, 1F381027h, 1F3A1026h, 1F3C1026h
|
||||
dd 1F3E1026h, 1F401025h, 1F421025h, 1F441024h
|
||||
dd 1F461024h, 1F481024h, 1F4A1023h, 1F4C1023h
|
||||
dd 1F4E1022h, 1F501022h, 1F521022h, 1F541021h
|
||||
dd 1F561021h, 1F591020h, 1F5B1020h, 1F5D1020h
|
||||
dd 1F5F101Fh, 1F61101Fh, 1F63101Eh, 1F65101Eh
|
||||
dd 1F67101Eh, 1F69101Dh, 1F6B101Dh, 1F6D101Dh
|
||||
dd 1F6F101Ch, 1F71101Ch, 1F73101Bh, 1F75101Bh
|
||||
dd 1F77101Bh, 1F79101Ah, 1F7B101Ah, 1F7D1019h
|
||||
dd 1F7F1019h, 1F811019h, 1F831018h, 1F851018h
|
||||
dd 1F871017h, 1F891017h, 1F8B1017h, 1F8D1016h
|
||||
dd 1F8F1016h, 1F911016h, 1F931015h, 1F951015h
|
||||
dd 1F971014h, 1F991014h, 1F9B1014h, 1F9D1013h
|
||||
dd 1F9F1013h, 1FA11012h, 1FA31012h, 1FA51012h
|
||||
dd 1FA71011h, 1FA91011h, 1FAB1010h, 1FAD1010h
|
||||
dd 1FAF1010h, 1FB1100Fh, 1FB3100Fh, 1FB5100Eh
|
||||
dd 1FB7100Eh, 1FB9100Eh, 1FBB100Dh, 1FBD100Dh
|
||||
dd 1FBF100Dh, 1FC1100Ch, 1FC3100Ch, 1FC5100Bh
|
||||
dd 1FC7100Bh, 1FCA100Bh, 1FCC100Ah, 1FCE100Ah
|
||||
dd 1FD01009h, 1FD21009h, 1FD41009h, 1FD61008h
|
||||
dd 1FD81008h, 1FDA1007h, 1FDC1007h, 1FDE1007h
|
||||
dd 1FE01006h, 1FE21006h, 1FE41005h, 1FE61005h
|
||||
dd 1FE81005h, 1FEA1004h, 1FEC1004h, 1FEE1004h
|
||||
dd 1FF01003h, 1FF21003h, 1FF41002h, 1FF61002h
|
||||
dd 1FF81002h, 1FFA1001h, 1FFC1001h, 1FFE1000h
|
||||
dd 20001000h, 20021000h, 20040FFFh, 20060FFFh
|
||||
dd 20080FFEh, 200A0FFEh, 200C0FFEh, 200E0FFDh
|
||||
dd 20100FFDh, 20120FFCh, 20140FFCh, 20160FFCh
|
||||
dd 20180FFBh, 201A0FFBh, 201C0FFBh, 201E0FFAh
|
||||
dd 20200FFAh, 20220FF9h, 20240FF9h, 20260FF9h
|
||||
dd 20280FF8h, 202A0FF8h, 202C0FF7h, 202E0FF7h
|
||||
dd 20300FF7h, 20320FF6h, 20340FF6h, 20360FF5h
|
||||
dd 20390FF5h, 203B0FF5h, 203D0FF4h, 203F0FF4h
|
||||
dd 20410FF3h, 20430FF3h, 20450FF3h, 20470FF2h
|
||||
dd 20490FF2h, 204B0FF2h, 204D0FF1h, 204F0FF1h
|
||||
dd 20510FF0h, 20530FF0h, 20550FF0h, 20570FEFh
|
||||
dd 20590FEFh, 205B0FEEh, 205D0FEEh, 205F0FEEh
|
||||
dd 20610FEDh, 20630FEDh, 20650FECh, 20670FECh
|
||||
dd 20690FECh, 206B0FEBh, 206D0FEBh, 206F0FEAh
|
||||
dd 20710FEAh, 20730FEAh, 20750FE9h, 20770FE9h
|
||||
dd 20790FE9h, 207B0FE8h, 207D0FE8h, 207F0FE7h
|
||||
dd 20810FE7h, 20830FE7h, 20850FE6h, 20870FE6h
|
||||
dd 20890FE5h, 208B0FE5h, 208D0FE5h, 208F0FE4h
|
||||
dd 20910FE4h, 20930FE3h, 20950FE3h, 20970FE3h
|
||||
dd 20990FE2h, 209B0FE2h, 209D0FE2h, 209F0FE1h
|
||||
dd 20A10FE1h, 20A30FE0h, 20A50FE0h, 20A70FE0h
|
||||
dd 20AA0FDFh, 20AC0FDFh, 20AE0FDEh, 20B00FDEh
|
||||
dd 20B20FDEh, 20B40FDDh, 20B60FDDh, 20B80FDCh
|
||||
dd 20BA0FDCh, 20BC0FDCh, 20BE0FDBh, 20C00FDBh
|
||||
dd 20C20FDAh, 20C40FDAh, 20C60FDAh, 20C80FD9h
|
||||
dd 20CA0FD9h, 20CC0FD9h, 20CE0FD8h, 20D00FD8h
|
||||
dd 20D20FD7h, 20D40FD7h, 20D60FD7h, 20D80FD6h
|
||||
dd 20DA0FD6h, 20DC0FD5h, 20DE0FD5h, 20E00FD5h
|
||||
dd 20E20FD4h, 20E40FD4h, 20E60FD3h, 20E80FD3h
|
||||
dd 20EA0FD3h, 20EC0FD2h, 20EE0FD2h, 20F00FD1h
|
||||
dd 20F20FD1h, 20F40FD1h, 20F60FD0h, 20F80FD0h
|
||||
dd 20FA0FD0h, 20FC0FCFh, 20FE0FCFh, 21000FCEh
|
||||
|
||||
_YUV_V_table dd 1F341068h, 1F351067h, 1F371066h, 1F391066h
|
||||
dd 1F3A1065h, 1F3C1064h, 1F3D1063h, 1F3F1062h
|
||||
dd 1F401062h, 1F421061h, 1F441060h, 1F45105Fh
|
||||
dd 1F47105Eh, 1F48105Dh, 1F4A105Dh, 1F4C105Ch
|
||||
dd 1F4D105Bh, 1F4F105Ah, 1F501059h, 1F521059h
|
||||
dd 1F541058h, 1F551057h, 1F571056h, 1F581055h
|
||||
dd 1F5A1055h, 1F5C1054h, 1F5D1053h, 1F5F1052h
|
||||
dd 1F601051h, 1F621050h, 1F641050h, 1F65104Fh
|
||||
dd 1F67104Eh, 1F68104Dh, 1F6A104Ch, 1F6C104Ch
|
||||
dd 1F6D104Bh, 1F6F104Ah, 1F701049h, 1F721048h
|
||||
dd 1F741048h, 1F751047h, 1F771046h, 1F781045h
|
||||
dd 1F7A1044h, 1F7C1043h, 1F7D1043h, 1F7F1042h
|
||||
dd 1F801041h, 1F821040h, 1F84103Fh, 1F85103Fh
|
||||
dd 1F87103Eh, 1F88103Dh, 1F8A103Ch, 1F8B103Bh
|
||||
dd 1F8D103Bh, 1F8F103Ah, 1F901039h, 1F921038h
|
||||
dd 1F931037h, 1F951036h, 1F971036h, 1F981035h
|
||||
dd 1F9A1034h, 1F9B1033h, 1F9D1032h, 1F9F1032h
|
||||
dd 1FA01031h, 1FA21030h, 1FA3102Fh, 1FA5102Eh
|
||||
dd 1FA7102Eh, 1FA8102Dh, 1FAA102Ch, 1FAB102Bh
|
||||
dd 1FAD102Ah, 1FAF1029h, 1FB01029h, 1FB21028h
|
||||
dd 1FB31027h, 1FB51026h, 1FB71025h, 1FB81025h
|
||||
dd 1FBA1024h, 1FBB1023h, 1FBD1022h, 1FBF1021h
|
||||
dd 1FC01021h, 1FC21020h, 1FC3101Fh, 1FC5101Eh
|
||||
dd 1FC7101Dh, 1FC8101Ch, 1FCA101Ch, 1FCB101Bh
|
||||
dd 1FCD101Ah, 1FCF1019h, 1FD01018h, 1FD21018h
|
||||
dd 1FD31017h, 1FD51016h, 1FD71015h, 1FD81014h
|
||||
dd 1FDA1014h, 1FDB1013h, 1FDD1012h, 1FDE1011h
|
||||
dd 1FE01010h, 1FE2100Fh, 1FE3100Fh, 1FE5100Eh
|
||||
dd 1FE6100Dh, 1FE8100Ch, 1FEA100Bh, 1FEB100Bh
|
||||
dd 1FED100Ah, 1FEE1009h, 1FF01008h, 1FF21007h
|
||||
dd 1FF31007h, 1FF51006h, 1FF61005h, 1FF81004h
|
||||
dd 1FFA1003h, 1FFB1002h, 1FFD1002h, 1FFE1001h
|
||||
dd 20001000h, 20020FFFh, 20030FFEh, 20050FFEh
|
||||
dd 20060FFDh, 20080FFCh, 200A0FFBh, 200B0FFAh
|
||||
dd 200D0FF9h, 200E0FF9h, 20100FF8h, 20120FF7h
|
||||
dd 20130FF6h, 20150FF5h, 20160FF5h, 20180FF4h
|
||||
dd 201A0FF3h, 201B0FF2h, 201D0FF1h, 201E0FF1h
|
||||
dd 20200FF0h, 20220FEFh, 20230FEEh, 20250FEDh
|
||||
dd 20260FECh, 20280FECh, 20290FEBh, 202B0FEAh
|
||||
dd 202D0FE9h, 202E0FE8h, 20300FE8h, 20310FE7h
|
||||
dd 20330FE6h, 20350FE5h, 20360FE4h, 20380FE4h
|
||||
dd 20390FE3h, 203B0FE2h, 203D0FE1h, 203E0FE0h
|
||||
dd 20400FDFh, 20410FDFh, 20430FDEh, 20450FDDh
|
||||
dd 20460FDCh, 20480FDBh, 20490FDBh, 204B0FDAh
|
||||
dd 204D0FD9h, 204E0FD8h, 20500FD7h, 20510FD7h
|
||||
dd 20530FD6h, 20550FD5h, 20560FD4h, 20580FD3h
|
||||
dd 20590FD2h, 205B0FD2h, 205D0FD1h, 205E0FD0h
|
||||
dd 20600FCFh, 20610FCEh, 20630FCEh, 20650FCDh
|
||||
dd 20660FCCh, 20680FCBh, 20690FCAh, 206B0FCAh
|
||||
dd 206D0FC9h, 206E0FC8h, 20700FC7h, 20710FC6h
|
||||
dd 20730FC5h, 20750FC5h, 20760FC4h, 20780FC3h
|
||||
dd 20790FC2h, 207B0FC1h, 207C0FC1h, 207E0FC0h
|
||||
dd 20800FBFh, 20810FBEh, 20830FBDh, 20840FBDh
|
||||
dd 20860FBCh, 20880FBBh, 20890FBAh, 208B0FB9h
|
||||
dd 208C0FB8h, 208E0FB8h, 20900FB7h, 20910FB6h
|
||||
dd 20930FB5h, 20940FB4h, 20960FB4h, 20980FB3h
|
||||
dd 20990FB2h, 209B0FB1h, 209C0FB0h, 209E0FB0h
|
||||
dd 20A00FAFh, 20A10FAEh, 20A30FADh, 20A40FACh
|
||||
dd 20A60FABh, 20A80FABh, 20A90FAAh, 20AB0FA9h
|
||||
dd 20AC0FA8h, 20AE0FA7h, 20B00FA7h, 20B10FA6h
|
||||
dd 20B30FA5h, 20B40FA4h, 20B60FA3h, 20B80FA3h
|
||||
dd 20B90FA2h, 20BB0FA1h, 20BC0FA0h, 20BE0F9Fh
|
||||
dd 20C00F9Eh, 20C10F9Eh, 20C30F9Dh, 20C40F9Ch
|
||||
dd 20C60F9Bh, 20C70F9Ah, 20C90F9Ah, 20CB0F99h
|
||||
|
||||
_YUV_clip_table db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 1, 2, 3
|
||||
db 4, 5, 6, 7
|
||||
db 8, 9, 10, 11
|
||||
db 12, 13, 14, 15
|
||||
db 16, 17, 18, 19
|
||||
db 20, 21, 22, 23
|
||||
db 24, 25, 26, 27
|
||||
db 28, 29, 30, 31
|
||||
db 32, 33, 34, 35
|
||||
db 36, 37, 38, 39
|
||||
db 40, 41, 42, 43
|
||||
db 44, 45, 46, 47
|
||||
db 48, 49, 50, 51
|
||||
db 52, 53, 54, 55
|
||||
db 56, 57, 58, 59
|
||||
db 60, 61, 62, 63
|
||||
db 64, 65, 66, 67
|
||||
db 68, 69, 70, 71
|
||||
db 72, 73, 74, 75
|
||||
db 76, 77, 78, 79
|
||||
db 80, 81, 82, 83
|
||||
db 84, 85, 86, 87
|
||||
db 88, 89, 90, 91
|
||||
db 92, 93, 94, 95
|
||||
db 96, 97, 98, 99
|
||||
db 100, 101, 102, 103
|
||||
db 104, 105, 106, 107
|
||||
db 108, 109, 110, 111
|
||||
db 112, 113, 114, 115
|
||||
db 116, 117, 118, 119
|
||||
db 120, 121, 122, 123
|
||||
db 124, 125, 126, 127
|
||||
db 128, 129, 130, 131
|
||||
db 132, 133, 134, 135
|
||||
db 136, 137, 138, 139
|
||||
db 140, 141, 142, 143
|
||||
db 144, 145, 146, 147
|
||||
db 148, 149, 150, 151
|
||||
db 152, 153, 154, 155
|
||||
db 156, 157, 158, 159
|
||||
db 160, 161, 162, 163
|
||||
db 164, 165, 166, 167
|
||||
db 168, 169, 170, 171
|
||||
db 172, 173, 174, 175
|
||||
db 176, 177, 178, 179
|
||||
db 180, 181, 182, 183
|
||||
db 184, 185, 186, 187
|
||||
db 188, 189, 190, 191
|
||||
db 192, 193, 194, 195
|
||||
db 196, 197, 198, 199
|
||||
db 200, 201, 202, 203
|
||||
db 204, 205, 206, 207
|
||||
db 208, 209, 210, 211
|
||||
db 212, 213, 214, 215
|
||||
db 216, 217, 218, 219
|
||||
db 220, 221, 222, 223
|
||||
db 224, 225, 226, 227
|
||||
db 228, 229, 230, 231
|
||||
db 232, 233, 234, 235
|
||||
db 236, 237, 238, 239
|
||||
db 240, 241, 242, 243
|
||||
db 244, 245, 246, 247
|
||||
db 248, 249, 250, 251
|
||||
db 252, 253, 254, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
db 255, 255, 255, 255
|
||||
|
||||
|
||||
_YUV_clip_table16 db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 0, 0, 0, 0
|
||||
db 1, 1, 1, 1
|
||||
db 1, 1, 1, 1
|
||||
db 2, 2, 2, 2
|
||||
db 2, 2, 2, 2
|
||||
db 3, 3, 3, 3
|
||||
db 3, 3, 3, 3
|
||||
db 4, 4, 4, 4
|
||||
db 4, 4, 4, 4
|
||||
db 5, 5, 5, 5
|
||||
db 5, 5, 5, 5
|
||||
db 6, 6, 6, 6
|
||||
db 6, 6, 6, 6
|
||||
db 7, 7, 7, 7
|
||||
db 7, 7, 7, 7
|
||||
db 8, 8, 8, 8
|
||||
db 8, 8, 8, 8
|
||||
db 9, 9, 9, 9
|
||||
db 9, 9, 9, 9
|
||||
db 10, 10, 10, 10
|
||||
db 10, 10, 10, 10
|
||||
db 11, 11, 11, 11
|
||||
db 11, 11, 11, 11
|
||||
db 12, 12, 12, 12
|
||||
db 12, 12, 12, 12
|
||||
db 13, 13, 13, 13
|
||||
db 13, 13, 13, 13
|
||||
db 14, 14, 14, 14
|
||||
db 14, 14, 14, 14
|
||||
db 15, 15, 15, 15
|
||||
db 15, 15, 15, 15
|
||||
db 16, 16, 16, 16
|
||||
db 16, 16, 16, 16
|
||||
db 17, 17, 17, 17
|
||||
db 17, 17, 17, 17
|
||||
db 18, 18, 18, 18
|
||||
db 18, 18, 18, 18
|
||||
db 19, 19, 19, 19
|
||||
db 19, 19, 19, 19
|
||||
db 20, 20, 20, 20
|
||||
db 20, 20, 20, 20
|
||||
db 21, 21, 21, 21
|
||||
db 21, 21, 21, 21
|
||||
db 22, 22, 22, 22
|
||||
db 22, 22, 22, 22
|
||||
db 23, 23, 23, 23
|
||||
db 23, 23, 23, 23
|
||||
db 24, 24, 24, 24
|
||||
db 24, 24, 24, 24
|
||||
db 25, 25, 25, 25
|
||||
db 25, 25, 25, 25
|
||||
db 26, 26, 26, 26
|
||||
db 26, 26, 26, 26
|
||||
db 27, 27, 27, 27
|
||||
db 27, 27, 27, 27
|
||||
db 28, 28, 28, 28
|
||||
db 28, 28, 28, 28
|
||||
db 29, 29, 29, 29
|
||||
db 29, 29, 29, 29
|
||||
db 30, 30, 30, 30
|
||||
db 30, 30, 30, 30
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
db 31, 31, 31, 31
|
||||
|
||||
|
||||
end
|
||||
|
263
vsfilter/dsutil/convert_a.asm
Normal file
263
vsfilter/dsutil/convert_a.asm
Normal file
|
@ -0,0 +1,263 @@
|
|||
; Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
|
||||
; http://www.avisynth.org
|
||||
;
|
||||
; 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., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
|
||||
; http://www.gnu.org/copyleft/gpl.html .
|
||||
;
|
||||
; Linking Avisynth statically or dynamically with other modules is making a
|
||||
; combined work based on Avisynth. Thus, the terms and conditions of the GNU
|
||||
; General Public License cover the whole combination.
|
||||
;
|
||||
; As a special exception, the copyright holders of Avisynth give you
|
||||
; permission to link Avisynth with independent modules that communicate with
|
||||
; Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
|
||||
; terms of these independent modules, and to copy and distribute the
|
||||
; resulting combined work under terms of your choice, provided that
|
||||
; every copy of the combined work is accompanied by a complete copy of
|
||||
; the source code of Avisynth (the version of Avisynth used to produce the
|
||||
; combined work), being distributed under the terms of the GNU General
|
||||
; Public License plus this exception. An independent module is a module
|
||||
; which is not derived from or based on Avisynth, such as 3rd-party filters,
|
||||
; import and export plugins, or graphical user interfaces.
|
||||
|
||||
.586
|
||||
.mmx
|
||||
.model flat
|
||||
|
||||
; alignment has to be 'page' so that I can use 'align 32' below
|
||||
|
||||
_TEXT64 segment page public use32 'CODE'
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 8
|
||||
|
||||
yuv2rgb_constants:
|
||||
|
||||
x0000_0000_0010_0010 dq 00000000000100010h
|
||||
x0080_0080_0080_0080 dq 00080008000800080h
|
||||
x00FF_00FF_00FF_00FF dq 000FF00FF00FF00FFh
|
||||
x00002000_00002000 dq 00000200000002000h
|
||||
xFF000000_FF000000 dq 0FF000000FF000000h
|
||||
cy dq 000004A8500004A85h
|
||||
crv dq 03313000033130000h
|
||||
cgu_cgv dq 0E5FCF377E5FCF377h
|
||||
cbu dq 00000408D0000408Dh
|
||||
|
||||
yuv2rgb_constants_rec709:
|
||||
|
||||
dq 00000000000100010h
|
||||
dq 00080008000800080h
|
||||
dq 000FF00FF00FF00FFh
|
||||
dq 00000200000002000h
|
||||
dq 0FF000000FF000000h
|
||||
dq 000004A8500004A85h
|
||||
dq 03960000039600000h
|
||||
dq 0EEF5F930EEF5F930h
|
||||
dq 00000439B0000439Bh
|
||||
|
||||
ofs_x0000_0000_0010_0010 = 0
|
||||
ofs_x0080_0080_0080_0080 = 8
|
||||
ofs_x00FF_00FF_00FF_00FF = 16
|
||||
ofs_x00002000_00002000 = 24
|
||||
ofs_xFF000000_FF000000 = 32
|
||||
ofs_cy = 40
|
||||
ofs_crv = 48
|
||||
ofs_cgu_cgv = 56
|
||||
ofs_cbu = 64
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
GET_Y MACRO mma,uyvy
|
||||
IF &uyvy
|
||||
psrlw mma,8
|
||||
ELSE
|
||||
pand mma,[edx+ofs_x00FF_00FF_00FF_00FF]
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
GET_UV MACRO mma,uyvy
|
||||
GET_Y mma,1-uyvy
|
||||
ENDM
|
||||
|
||||
YUV2RGB_INNER_LOOP MACRO uyvy,rgb32,no_next_pixel
|
||||
|
||||
;; This YUV422->RGB conversion code uses only four MMX registers per
|
||||
;; source dword, so I convert two dwords in parallel. Lines corresponding
|
||||
;; to the "second pipe" are indented an extra space. There's almost no
|
||||
;; overlap, except at the end and in the three lines marked ***.
|
||||
;; revised 4july,2002 to properly set alpha in rgb32 to default "on" & other small memory optimizations
|
||||
|
||||
movd mm0, dword ptr [esi]
|
||||
movd mm5, dword ptr [esi+4]
|
||||
movq mm1,mm0
|
||||
GET_Y mm0,&uyvy ; mm0 = __________Y1__Y0
|
||||
movq mm4,mm5
|
||||
GET_UV mm1,&uyvy ; mm1 = __________V0__U0
|
||||
GET_Y mm4,&uyvy
|
||||
movq mm2,mm5 ; *** avoid reload from [esi+4]
|
||||
GET_UV mm5,&uyvy
|
||||
psubw mm0, qword ptr [edx+ofs_x0000_0000_0010_0010]
|
||||
movd mm6, dword ptr [esi+8-4*(no_next_pixel)]
|
||||
GET_UV mm2,&uyvy ; mm2 = __________V2__U2
|
||||
psubw mm4, qword ptr [edx+ofs_x0000_0000_0010_0010]
|
||||
paddw mm2,mm1
|
||||
GET_UV mm6,&uyvy
|
||||
psubw mm1, qword ptr [edx+ofs_x0080_0080_0080_0080]
|
||||
paddw mm6,mm5
|
||||
psllq mm2,32
|
||||
psubw mm5, qword ptr [edx+ofs_x0080_0080_0080_0080]
|
||||
punpcklwd mm0,mm2 ; mm0 = ______Y1______Y0
|
||||
psllq mm6,32
|
||||
pmaddwd mm0, qword ptr [edx+ofs_cy]
|
||||
punpcklwd mm4,mm6
|
||||
paddw mm1,mm1
|
||||
pmaddwd mm4, qword ptr [edx+ofs_cy]
|
||||
paddw mm5,mm5
|
||||
paddw mm1,mm2 ; mm1 = __V1__U1__V0__U0 * 2
|
||||
paddd mm0,[edx+ofs_x00002000_00002000]
|
||||
paddw mm5,mm6
|
||||
movq mm2,mm1
|
||||
paddd mm4,[edx+ofs_x00002000_00002000]
|
||||
movq mm3,mm1
|
||||
movq mm6,mm5
|
||||
pmaddwd mm1,[edx+ofs_crv]
|
||||
movq mm7,mm5
|
||||
paddd mm1,mm0
|
||||
pmaddwd mm5,[edx+ofs_crv]
|
||||
psrad mm1,14 ; mm1 = RRRRRRRRrrrrrrrr
|
||||
paddd mm5,mm4
|
||||
pmaddwd mm2,[edx+ofs_cgu_cgv]
|
||||
psrad mm5,14
|
||||
paddd mm2,mm0
|
||||
pmaddwd mm6,[edx+ofs_cgu_cgv]
|
||||
psrad mm2,14 ; mm2 = GGGGGGGGgggggggg
|
||||
paddd mm6,mm4
|
||||
pmaddwd mm3,[edx+ofs_cbu]
|
||||
psrad mm6,14
|
||||
paddd mm3,mm0
|
||||
pmaddwd mm7,[edx+ofs_cbu]
|
||||
add esi,8
|
||||
add edi,12+4*rgb32
|
||||
IFE &no_next_pixel
|
||||
cmp esi,ecx
|
||||
ENDIF
|
||||
psrad mm3,14 ; mm3 = BBBBBBBBbbbbbbbb
|
||||
paddd mm7,mm4
|
||||
pxor mm0,mm0
|
||||
psrad mm7,14
|
||||
packssdw mm3,mm2 ; mm3 = GGGGggggBBBBbbbb
|
||||
packssdw mm7,mm6
|
||||
packssdw mm1,mm0 ; mm1 = ________RRRRrrrr
|
||||
packssdw mm5,mm0 ; *** avoid pxor mm4,mm4
|
||||
movq mm2,mm3
|
||||
movq mm6,mm7
|
||||
punpcklwd mm2,mm1 ; mm2 = RRRRBBBBrrrrbbbb
|
||||
punpcklwd mm6,mm5
|
||||
punpckhwd mm3,mm1 ; mm3 = ____GGGG____gggg
|
||||
punpckhwd mm7,mm5
|
||||
movq mm0,mm2
|
||||
movq mm4,mm6
|
||||
punpcklwd mm0,mm3 ; mm0 = ____rrrrggggbbbb
|
||||
punpcklwd mm4,mm7
|
||||
IFE &rgb32
|
||||
psllq mm0,16
|
||||
psllq mm4,16
|
||||
ENDIF
|
||||
punpckhwd mm2,mm3 ; mm2 = ____RRRRGGGGBBBB
|
||||
punpckhwd mm6,mm7
|
||||
packuswb mm0,mm2 ; mm0 = __RRGGBB__rrggbb <- ta dah!
|
||||
packuswb mm4,mm6
|
||||
|
||||
IF &rgb32
|
||||
por mm0, [edx+ofs_xFF000000_FF000000] ; set alpha channels "on"
|
||||
por mm4, [edx+ofs_xFF000000_FF000000]
|
||||
movq [edi-16],mm0 ; store the quadwords independently
|
||||
movq [edi-8],mm4
|
||||
ELSE
|
||||
psrlq mm0,8 ; pack the two quadwords into 12 bytes
|
||||
psllq mm4,8 ; (note: the two shifts above leave
|
||||
movd dword ptr [edi-12],mm0 ; mm0,4 = __RRGGBBrrggbb__)
|
||||
psrlq mm0,32
|
||||
por mm4,mm0
|
||||
movd dword ptr [edi-8],mm4
|
||||
psrlq mm4,32
|
||||
movd dword ptr [edi-4],mm4
|
||||
ENDIF
|
||||
|
||||
ENDM
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
YUV2RGB_PROC MACRO procname,uyvy,rgb32
|
||||
|
||||
PUBLIC C _&procname
|
||||
|
||||
;;void __cdecl procname(
|
||||
;; [esp+ 4] const BYTE* src,
|
||||
;; [esp+ 8] BYTE* dst,
|
||||
;; [esp+12] const BYTE* src_end,
|
||||
;; [esp+16] int src_pitch,
|
||||
;; [esp+20] int row_size,
|
||||
;; [esp+24] bool rec709);
|
||||
|
||||
_&procname PROC
|
||||
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov eax,[esp+16+12]
|
||||
mov esi,[esp+12+12] ; read source bottom-up
|
||||
mov edi,[esp+8+12]
|
||||
mov ebx,[esp+20+12]
|
||||
mov edx,offset yuv2rgb_constants
|
||||
test byte ptr [esp+24+12],1
|
||||
jz loop0
|
||||
mov edx,offset yuv2rgb_constants_rec709
|
||||
|
||||
loop0:
|
||||
sub esi,eax
|
||||
lea ecx,[esi+ebx-8]
|
||||
|
||||
align 32
|
||||
loop1:
|
||||
YUV2RGB_INNER_LOOP uyvy,rgb32,0
|
||||
jb loop1
|
||||
|
||||
YUV2RGB_INNER_LOOP uyvy,rgb32,1
|
||||
|
||||
sub esi,ebx
|
||||
cmp esi,[esp+4+12]
|
||||
ja loop0
|
||||
|
||||
emms
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
retn
|
||||
|
||||
_&procname ENDP
|
||||
|
||||
ENDM
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
YUV2RGB_PROC mmx_YUY2toRGB24,0,0
|
||||
YUV2RGB_PROC mmx_YUY2toRGB32,0,1
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
END
|
323
vsfilter/dsutil/dsutil.vcproj
Normal file
323
vsfilter/dsutil/dsutil.vcproj
Normal file
|
@ -0,0 +1,323 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="dsutil"
|
||||
ProjectGUID="{5F6E4984-0E0A-468D-8EF5-AE52AE8CBBF6}"
|
||||
RootNamespace="dsutil"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalDependencies="vfw32.lib Version.lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
AdditionalDependencies="vfw32.lib Version.lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\a_yuv2rgb.asm"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\a_yuvtable.asm"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\convert_a.asm"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="ml /c /coff /Cx /nologo /Fo"$(OutDir)\$(InputName).obj" "$(InputPath)"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DSMPropertyBag.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DSUtil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\FontInstaller.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaTypeEx.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaTypes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NullRenderers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\text.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vd.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\DSMPropertyBag.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DSUtil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\FontInstaller.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaTypeEx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaTypes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NullRenderers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\text.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vd.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
29
vsfilter/dsutil/stdafx.cpp
Normal file
29
vsfilter/dsutil/stdafx.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// dsutil.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
47
vsfilter/dsutil/stdafx.h
Normal file
47
vsfilter/dsutil/stdafx.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
#endif
|
||||
|
||||
#include <afx.h>
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include <atlcoll.h>
|
||||
#include <atlpath.h>
|
||||
|
||||
#include <streams.h>
|
||||
#include <dvdmedia.h>
|
220
vsfilter/dsutil/text.cpp
Normal file
220
vsfilter/dsutil/text.cpp
Normal file
|
@ -0,0 +1,220 @@
|
|||
#include "stdafx.h"
|
||||
#include "text.h"
|
||||
|
||||
/*
|
||||
CString Explode(CString str, CAtlList<CString>& sl, TCHAR sep, int limit)
|
||||
{
|
||||
sl.RemoveAll();
|
||||
|
||||
if(limit == 1) {sl.AddTail(str); return _T("");}
|
||||
|
||||
if(!str.IsEmpty() && str[str.GetLength()-1] != sep)
|
||||
str += sep;
|
||||
|
||||
for(int i = 0, j = 0; (j = str.Find(sep, i)) >= 0; i = j+1)
|
||||
{
|
||||
CString tmp = str.Mid(i, j-i);
|
||||
tmp.TrimLeft(sep); tmp.TrimRight(sep);
|
||||
tmp.TrimLeft(); tmp.TrimRight();
|
||||
sl.AddTail(tmp);
|
||||
if(limit > 0 && sl.GetCount() == limit-1)
|
||||
{
|
||||
if(j+1 < str.GetLength())
|
||||
{
|
||||
CString tmp = str.Mid(j+1);
|
||||
tmp.TrimLeft(sep); tmp.TrimRight(sep);
|
||||
tmp.TrimLeft(); tmp.TrimRight();
|
||||
sl.AddTail(tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.IsEmpty())
|
||||
{
|
||||
str.TrimLeft(sep); str.TrimRight(sep);
|
||||
str.TrimLeft(); str.TrimRight();
|
||||
sl.AddTail(str);
|
||||
}
|
||||
|
||||
return sl.GetHead();
|
||||
}
|
||||
|
||||
CString ExplodeMin(CString str, CAtlList<CString>& sl, TCHAR sep, int limit)
|
||||
{
|
||||
Explode(str, sl, sep, limit);
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION tmp = pos;
|
||||
if(sl.GetNext(pos).IsEmpty())
|
||||
sl.RemoveAt(tmp);
|
||||
}
|
||||
if(sl.IsEmpty()) sl.AddTail(CString()); // eh
|
||||
|
||||
return sl.GetHead();
|
||||
}
|
||||
|
||||
CString Implode(CAtlList<CString>& sl, TCHAR sep)
|
||||
{
|
||||
CString ret;
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
ret += sl.GetNext(pos);
|
||||
if(pos) ret += sep;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
*/
|
||||
|
||||
DWORD CharSetToCodePage(DWORD dwCharSet)
|
||||
{
|
||||
if(dwCharSet == CP_UTF8) return CP_UTF8;
|
||||
if(dwCharSet == CP_UTF7) return CP_UTF7;
|
||||
CHARSETINFO cs={0};
|
||||
::TranslateCharsetInfo((DWORD *)dwCharSet, &cs, TCI_SRCCHARSET);
|
||||
return cs.ciACP;
|
||||
}
|
||||
|
||||
CStringA ConvertMBCS(CStringA str, DWORD SrcCharSet, DWORD DstCharSet)
|
||||
{
|
||||
WCHAR* utf16 = new WCHAR[str.GetLength()+1];
|
||||
memset(utf16, 0, (str.GetLength()+1)*sizeof(WCHAR));
|
||||
|
||||
CHAR* mbcs = new CHAR[str.GetLength()*6+1];
|
||||
memset(mbcs, 0, str.GetLength()*6+1);
|
||||
|
||||
int len = MultiByteToWideChar(
|
||||
CharSetToCodePage(SrcCharSet), 0,
|
||||
str.GetBuffer(str.GetLength()), str.GetLength(),
|
||||
utf16, (str.GetLength()+1)*sizeof(WCHAR));
|
||||
|
||||
len = WideCharToMultiByte(
|
||||
CharSetToCodePage(DstCharSet), 0,
|
||||
utf16, len,
|
||||
mbcs, str.GetLength()*6,
|
||||
NULL, NULL);
|
||||
|
||||
str = mbcs;
|
||||
|
||||
delete [] utf16;
|
||||
delete [] mbcs;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
CStringA UrlEncode(CStringA str, bool fRaw)
|
||||
{
|
||||
CStringA urlstr;
|
||||
|
||||
for(int i = 0; i < str.GetLength(); i++)
|
||||
{
|
||||
CHAR c = str[i];
|
||||
if(fRaw && c == '+') urlstr += "%2B";
|
||||
else if(c > 0x20 && c < 0x7f && c != '&') urlstr += c;
|
||||
else if(c == 0x20) urlstr += fRaw ? ' ' : '+';
|
||||
else {CStringA tmp; tmp.Format("%%%02x", (BYTE)c); urlstr += tmp;}
|
||||
}
|
||||
|
||||
return urlstr;
|
||||
}
|
||||
|
||||
CStringA UrlDecode(CStringA str, bool fRaw)
|
||||
{
|
||||
str.Replace("&", "&");
|
||||
|
||||
CHAR* s = str.GetBuffer(str.GetLength());
|
||||
CHAR* e = s + str.GetLength();
|
||||
CHAR* s1 = s;
|
||||
CHAR* s2 = s;
|
||||
while(s1 < e)
|
||||
{
|
||||
CHAR s11 = (s1 < e-1) ? (__isascii(s1[1]) && isupper(s1[1]) ? tolower(s1[1]) : s1[1]) : 0;
|
||||
CHAR s12 = (s1 < e-2) ? (__isascii(s1[2]) && isupper(s1[2]) ? tolower(s1[2]) : s1[2]) : 0;
|
||||
|
||||
if(*s1 == '%' && s1 < e-2
|
||||
&& (s1[1] >= '0' && s1[1] <= '9' || s11 >= 'a' && s11 <= 'f')
|
||||
&& (s1[2] >= '0' && s1[2] <= '9' || s12 >= 'a' && s12 <= 'f'))
|
||||
{
|
||||
s1[1] = s11;
|
||||
s1[2] = s12;
|
||||
*s2 = 0;
|
||||
if(s1[1] >= '0' && s1[1] <= '9') *s2 |= s1[1]-'0';
|
||||
else if(s1[1] >= 'a' && s1[1] <= 'f') *s2 |= s1[1]-'a'+10;
|
||||
*s2 <<= 4;
|
||||
if(s1[2] >= '0' && s1[2] <= '9') *s2 |= s1[2]-'0';
|
||||
else if(s1[2] >= 'a' && s1[2] <= 'f') *s2 |= s1[2]-'a'+10;
|
||||
s1 += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*s2 = *s1 == '+' && !fRaw ? ' ' : *s1;
|
||||
}
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
str.ReleaseBuffer(s2 - s);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
CString ExtractTag(CString tag, CMapStringToString& attribs, bool& fClosing)
|
||||
{
|
||||
tag.Trim();
|
||||
attribs.RemoveAll();
|
||||
|
||||
fClosing = !tag.IsEmpty() ? tag[0] == '/' : false;
|
||||
tag.TrimLeft('/');
|
||||
|
||||
int i = tag.Find(' ');
|
||||
if(i < 0) i = tag.GetLength();
|
||||
CString type = tag.Left(i).MakeLower();
|
||||
tag = tag.Mid(i).Trim();
|
||||
|
||||
while((i = tag.Find('=')) > 0)
|
||||
{
|
||||
CString attrib = tag.Left(i).Trim().MakeLower();
|
||||
tag = tag.Mid(i+1);
|
||||
for(i = 0; i < tag.GetLength() && _istspace(tag[i]); i++);
|
||||
tag = i < tag.GetLength() ? tag.Mid(i) : _T("");
|
||||
if(!tag.IsEmpty() && tag[0] == '\"') {tag = tag.Mid(1); i = tag.Find('\"');}
|
||||
else i = tag.Find(' ');
|
||||
if(i < 0) i = tag.GetLength();
|
||||
CString param = tag.Left(i).Trim();
|
||||
if(!param.IsEmpty())
|
||||
attribs[attrib] = param;
|
||||
tag = i+1 < tag.GetLength() ? tag.Mid(i+1) : _T("");
|
||||
}
|
||||
|
||||
return(type);
|
||||
}
|
||||
|
||||
CAtlList<CString>& MakeLower(CAtlList<CString>& sl)
|
||||
{
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos) sl.GetNext(pos).MakeLower();
|
||||
return sl;
|
||||
}
|
||||
|
||||
CAtlList<CString>& MakeUpper(CAtlList<CString>& sl)
|
||||
{
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos) sl.GetNext(pos).MakeUpper();
|
||||
return sl;
|
||||
}
|
||||
|
||||
CAtlList<CString>& RemoveStrings(CAtlList<CString>& sl, int minlen, int maxlen)
|
||||
{
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION tmp = pos;
|
||||
CString& str = sl.GetNext(pos);
|
||||
int len = str.GetLength();
|
||||
if(len < minlen || len > maxlen) sl.RemoveAt(tmp);
|
||||
}
|
||||
return sl;
|
||||
}
|
69
vsfilter/dsutil/text.h
Normal file
69
vsfilter/dsutil/text.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
|
||||
// extern CString ExplodeMin(CString str, CAtlList<CString>& sl, TCHAR sep, int limit = 0);
|
||||
// extern CString Explode(CString str, CAtlList<CString>& sl, TCHAR sep, int limit = 0);
|
||||
// extern CString Implode(CAtlList<CString>& sl, TCHAR sep);
|
||||
|
||||
template<class T, typename SEP>
|
||||
T Explode(T str, CAtlList<T>& sl, SEP sep, int limit = 0)
|
||||
{
|
||||
sl.RemoveAll();
|
||||
|
||||
for(int i = 0, j = 0; ; i = j+1)
|
||||
{
|
||||
j = str.Find(sep, i);
|
||||
|
||||
if(j < 0 || sl.GetCount() == limit-1)
|
||||
{
|
||||
sl.AddTail(str.Mid(i).Trim());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl.AddTail(str.Mid(i, j-i).Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return sl.GetHead();
|
||||
}
|
||||
|
||||
template<class T, typename SEP>
|
||||
T ExplodeMin(T str, CAtlList<T>& sl, SEP sep, int limit = 0)
|
||||
{
|
||||
Explode(str, sl, sep, limit);
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION tmp = pos;
|
||||
if(sl.GetNext(pos).IsEmpty())
|
||||
sl.RemoveAt(tmp);
|
||||
}
|
||||
if(sl.IsEmpty()) sl.AddTail(T()); // eh
|
||||
|
||||
return sl.GetHead();
|
||||
}
|
||||
|
||||
template<class T, typename SEP>
|
||||
T Implode(CAtlList<T>& sl, SEP sep)
|
||||
{
|
||||
T ret;
|
||||
POSITION pos = sl.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
ret += sl.GetNext(pos);
|
||||
if(pos) ret += sep;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
extern CString ExtractTag(CString tag, CMapStringToString& attribs, bool& fClosing);
|
||||
extern CStringA ConvertMBCS(CStringA str, DWORD SrcCharSet, DWORD DstCharSet);
|
||||
extern CStringA UrlEncode(CStringA str, bool fRaw = false);
|
||||
extern CStringA UrlDecode(CStringA str, bool fRaw = false);
|
||||
extern DWORD CharSetToCodePage(DWORD dwCharSet);
|
||||
extern CAtlList<CString>& MakeLower(CAtlList<CString>& sl);
|
||||
extern CAtlList<CString>& MakeUpper(CAtlList<CString>& sl);
|
||||
extern CAtlList<CString>& RemoveStrings(CAtlList<CString>& sl, int minlen, int maxlen);
|
||||
|
1509
vsfilter/dsutil/vd.cpp
Normal file
1509
vsfilter/dsutil/vd.cpp
Normal file
File diff suppressed because it is too large
Load diff
42
vsfilter/dsutil/vd.h
Normal file
42
vsfilter/dsutil/vd.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// VirtualDub - Video processing and capture application
|
||||
// Copyright (C) 1998-2001 Avery Lee
|
||||
//
|
||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// Notes:
|
||||
// - BitBltFromI420ToRGB is from VirtualDub
|
||||
// - BitBltFromYUY2ToRGB is from AviSynth 2.52
|
||||
// - The core assembly function of CCpuID is from DVD2AVI
|
||||
// (- vd.cpp/h should be renamed to something more sensible already :)
|
||||
|
||||
#pragma once
|
||||
|
||||
class CCpuID {public: CCpuID(); enum flag_t {mmx=1, ssemmx=2, ssefpu=4, sse2=8, _3dnow=16} m_flags;};
|
||||
extern CCpuID g_cpuid;
|
||||
|
||||
extern bool BitBltFromI420ToI420(int w, int h, BYTE* dsty, BYTE* dstu, BYTE* dstv, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch);
|
||||
extern bool BitBltFromI420ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch, bool fInterlaced = false);
|
||||
extern bool BitBltFromI420ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch /* TODO: , bool fInterlaced = false */);
|
||||
extern bool BitBltFromYUY2ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* src, int srcpitch);
|
||||
extern bool BitBltFromYUY2ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch);
|
||||
extern bool BitBltFromRGBToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch, int sbpp);
|
||||
|
||||
extern void DeinterlaceBlend(BYTE* dst, BYTE* src, DWORD rowbytes, DWORD h, DWORD dstpitch, DWORD srcpitch);
|
||||
extern void DeinterlaceBob(BYTE* dst, BYTE* src, DWORD rowbytes, DWORD h, DWORD dstpitch, DWORD srcpitch, bool topfield);
|
||||
|
||||
extern void AvgLines8(BYTE* dst, DWORD h, DWORD pitch);
|
||||
extern void AvgLines555(BYTE* dst, DWORD h, DWORD pitch);
|
||||
extern void AvgLines565(BYTE* dst, DWORD h, DWORD pitch);
|
||||
|
28
vsfilter/include/IFilterVersion.h
Normal file
28
vsfilter/include/IFilterVersion.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
[uuid("A0DD28E1-61C0-4539-A7E6-14544AFF092E")]
|
||||
interface IFilterVersion : public IUnknown
|
||||
{
|
||||
STDMETHOD_(DWORD, GetFilterVersion) () = 0;
|
||||
};
|
406
vsfilter/include/avisynth/avisynth1.h
Normal file
406
vsfilter/include/avisynth/avisynth1.h
Normal file
|
@ -0,0 +1,406 @@
|
|||
// Avisynth v1.0 beta. Copyright 2000 Ben Rudiak-Gould.
|
||||
// http://www.math.berkeley.edu/~benrg/avisynth.html
|
||||
|
||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
|
||||
// http://www.gnu.org/copyleft/gpl.html .
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#define _ASSERTE(x) assert(x)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
enum { AVISYNTH_INTERFACE_VERSION = 1 };
|
||||
|
||||
|
||||
// I had problems with Premiere wanting 1-byte alignment for its structures,
|
||||
// so I now set the Avisynth struct alignment explicitly here.
|
||||
#pragma pack(push,8)
|
||||
|
||||
|
||||
// The VideoInfo struct holds global information about a clip (i.e.
|
||||
// information that does not depend on the frame number). The GetVideoInfo
|
||||
// method in IClip returns this struct.
|
||||
|
||||
struct VideoInfo {
|
||||
int width, height; // width=0 means no video
|
||||
unsigned fps_numerator, fps_denominator;
|
||||
int num_frames;
|
||||
enum { UNKNOWN=0, BGR24=0x13, BGR32=0x14, YUY2=0x22 };
|
||||
unsigned char pixel_type;
|
||||
bool field_based;
|
||||
|
||||
int audio_samples_per_second; // 0 means no audio
|
||||
int num_audio_samples;
|
||||
bool stereo, sixteen_bit;
|
||||
|
||||
// useful functions of the above
|
||||
bool HasVideo() const { return !!width; }
|
||||
bool HasAudio() const { return !!audio_samples_per_second; }
|
||||
bool IsRGB() const { return !!(pixel_type&0x10); }
|
||||
bool IsRGB24() const { return pixel_type == BGR24; }
|
||||
bool IsRGB32() const { return pixel_type == BGR32; }
|
||||
bool IsYUV() const { return !!(pixel_type&0x20); }
|
||||
bool IsYUY2() const { return pixel_type == YUY2; }
|
||||
int BytesFromPixels(int pixels) const { return pixels * (pixel_type&7); }
|
||||
int RowSize() const { return BytesFromPixels(width); }
|
||||
int BitsPerPixel() const { return (pixel_type&7) * 8; }
|
||||
int BMPSize() const { return height * ((RowSize()+3) & -4); }
|
||||
int AudioSamplesFromFrames(int frames) const { return int(__int64(frames) * audio_samples_per_second * fps_denominator / fps_numerator); }
|
||||
int FramesFromAudioSamples(int samples) const { return int(__int64(samples) * fps_numerator / fps_denominator / audio_samples_per_second); }
|
||||
int AudioSamplesFromBytes(int bytes) const { return bytes >> (stereo + sixteen_bit); }
|
||||
int BytesFromAudioSamples(int samples) const { return samples << (stereo + sixteen_bit); }
|
||||
int BytesPerAudioSample() const { return BytesFromAudioSamples(1); }
|
||||
|
||||
// useful mutator
|
||||
void SetFPS(unsigned numerator, unsigned denominator) {
|
||||
unsigned x=numerator, y=denominator;
|
||||
while (y) { // find gcd
|
||||
unsigned t = x%y; x = y; y = t;
|
||||
}
|
||||
fps_numerator = numerator/x;
|
||||
fps_denominator = denominator/x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// VideoFrameBuffer holds information about a memory block which is used
|
||||
// for video data. For efficiency, instances of this class are not deleted
|
||||
// when the refcount reaches zero; instead they're stored in a linked list
|
||||
// to be reused. The instances are deleted when the corresponding AVS
|
||||
// file is closed.
|
||||
|
||||
class VideoFrameBuffer {
|
||||
unsigned char* const data;
|
||||
const int data_size;
|
||||
// sequence_number is incremented every time the buffer is changed, so
|
||||
// that stale views can tell they're no longer valid.
|
||||
long sequence_number;
|
||||
|
||||
friend class VideoFrame;
|
||||
friend class Cache;
|
||||
long refcount;
|
||||
|
||||
public:
|
||||
VideoFrameBuffer(int size);
|
||||
VideoFrameBuffer();
|
||||
~VideoFrameBuffer();
|
||||
|
||||
const unsigned char* GetReadPtr() const { return data; }
|
||||
unsigned char* GetWritePtr() { ++sequence_number; return data; }
|
||||
int GetDataSize() { return data_size; }
|
||||
int GetSequenceNumber() { return sequence_number; }
|
||||
int GetRefcount() { return refcount; }
|
||||
};
|
||||
|
||||
|
||||
class IClip;
|
||||
class PClip;
|
||||
class PVideoFrame;
|
||||
class IScriptEnvironment;
|
||||
class AVSValue;
|
||||
|
||||
|
||||
// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new
|
||||
// is overloaded to recycle class instances.
|
||||
|
||||
class VideoFrame {
|
||||
int refcount;
|
||||
VideoFrameBuffer* const vfb;
|
||||
const int offset, pitch, row_size, height;
|
||||
|
||||
friend class PVideoFrame;
|
||||
void AddRef() { ++refcount; }
|
||||
void Release() { if (refcount==1) --vfb->refcount; --refcount; }
|
||||
|
||||
friend class ScriptEnvironment;
|
||||
friend class Cache;
|
||||
|
||||
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height);
|
||||
|
||||
void* operator new(unsigned size);
|
||||
|
||||
public:
|
||||
int GetPitch() const { return pitch; }
|
||||
int GetRowSize() const { return row_size; }
|
||||
int GetHeight() const { return height; }
|
||||
|
||||
// generally you shouldn't use these two
|
||||
VideoFrameBuffer* GetFrameBuffer() const { return vfb; }
|
||||
int GetOffset() const { return offset; }
|
||||
|
||||
// in plugins use env->SubFrame()
|
||||
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const;
|
||||
|
||||
const unsigned char* GetReadPtr() const { return vfb->GetReadPtr() + offset; }
|
||||
|
||||
bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); }
|
||||
|
||||
unsigned char* GetWritePtr() const {
|
||||
return IsWritable() ? (vfb->GetWritePtr() + offset) : 0;
|
||||
}
|
||||
|
||||
~VideoFrame() { --vfb->refcount; }
|
||||
};
|
||||
|
||||
|
||||
// Base class for all filters.
|
||||
class IClip {
|
||||
friend class PClip;
|
||||
friend class AVSValue;
|
||||
int refcnt;
|
||||
void AddRef() { ++refcnt; }
|
||||
void Release() { if (!--refcnt) delete this; }
|
||||
public:
|
||||
IClip() : refcnt(0) {}
|
||||
|
||||
virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; }
|
||||
|
||||
virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0;
|
||||
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame
|
||||
virtual void __stdcall GetAudio(void* buf, int start, int count, IScriptEnvironment* env) = 0; // start and count are in samples
|
||||
virtual const VideoInfo& __stdcall GetVideoInfo() = 0;
|
||||
virtual __stdcall ~IClip() {}
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to IClip
|
||||
class PClip {
|
||||
|
||||
IClip* p;
|
||||
|
||||
IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; }
|
||||
friend class AVSValue;
|
||||
friend class VideoFrame;
|
||||
|
||||
void Init(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PClip() { p = 0; }
|
||||
PClip(const PClip& x) { Init(x.p); }
|
||||
PClip(IClip* x) { Init(x); }
|
||||
void operator=(IClip* x) { Set(x); }
|
||||
void operator=(const PClip& x) { Set(x.p); }
|
||||
|
||||
IClip* operator->() const { return p; }
|
||||
|
||||
// useful in conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PClip() { if (p) p->Release(); }
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to VideoFrame
|
||||
class PVideoFrame {
|
||||
|
||||
VideoFrame* p;
|
||||
|
||||
void Init(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PVideoFrame() { p = 0; }
|
||||
PVideoFrame(const PVideoFrame& x) { Init(x.p); }
|
||||
PVideoFrame(VideoFrame* x) { Init(x); }
|
||||
void operator=(VideoFrame* x) { Set(x); }
|
||||
void operator=(const PVideoFrame& x) { Set(x.p); }
|
||||
|
||||
VideoFrame* operator->() const { return p; }
|
||||
|
||||
// for conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PVideoFrame() { if (p) p->Release(); }
|
||||
};
|
||||
|
||||
|
||||
class AVSValue {
|
||||
public:
|
||||
|
||||
AVSValue() { type = 'v'; }
|
||||
AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); }
|
||||
AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); }
|
||||
AVSValue(bool b) { type = 'b'; boolean = b; }
|
||||
AVSValue(int i) { type = 'i'; integer = i; }
|
||||
AVSValue(float f) { type = 'f'; floating_pt = f; }
|
||||
AVSValue(double f) { type = 'f'; floating_pt = float(f); }
|
||||
AVSValue(const char* s) { type = 's'; string = s; }
|
||||
AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; }
|
||||
AVSValue(const AVSValue& v) { Assign(&v, true); }
|
||||
|
||||
~AVSValue() { if (IsClip() && clip) clip->Release(); }
|
||||
AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; }
|
||||
|
||||
// Note that we transparently allow 'int' to be treated as 'float'.
|
||||
// There are no int<->bool conversions, though.
|
||||
|
||||
bool Defined() const { return type != 'v'; }
|
||||
bool IsClip() const { return type == 'c'; }
|
||||
bool IsBool() const { return type == 'b'; }
|
||||
bool IsInt() const { return type == 'i'; }
|
||||
bool IsFloat() const { return type == 'f' || type == 'i'; }
|
||||
bool IsString() const { return type == 's'; }
|
||||
bool IsArray() const { return type == 'a'; }
|
||||
|
||||
PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; }
|
||||
bool AsBool() const { _ASSERTE(IsBool()); return boolean; }
|
||||
int AsInt() const { _ASSERTE(IsInt()); return integer; }
|
||||
const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; }
|
||||
double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; }
|
||||
|
||||
bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; }
|
||||
int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; }
|
||||
double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; }
|
||||
const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; }
|
||||
|
||||
int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; }
|
||||
const AVSValue& operator[](int index) const {
|
||||
_ASSERTE(IsArray() && index>=0 && index<array_size);
|
||||
return (IsArray() && index>=0 && index<array_size) ? array[index] : *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, or 'v'oid
|
||||
short array_size;
|
||||
union {
|
||||
IClip* clip;
|
||||
bool boolean;
|
||||
int integer;
|
||||
float floating_pt;
|
||||
const char* string;
|
||||
const AVSValue* array;
|
||||
};
|
||||
|
||||
void Assign(const AVSValue* src, bool init) {
|
||||
if (src->IsClip() && src->clip)
|
||||
src->clip->AddRef();
|
||||
if (!init && IsClip() && clip)
|
||||
clip->Release();
|
||||
// make sure this copies the whole struct!
|
||||
((__int32*)this)[0] = ((__int32*)src)[0];
|
||||
((__int32*)this)[1] = ((__int32*)src)[1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// instantiable null filter
|
||||
class GenericVideoFilter : public IClip {
|
||||
protected:
|
||||
PClip child;
|
||||
VideoInfo vi;
|
||||
public:
|
||||
GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); }
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); }
|
||||
void __stdcall GetAudio(void* buf, int start, int count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); }
|
||||
const VideoInfo& __stdcall GetVideoInfo() { return vi; }
|
||||
bool __stdcall GetParity(int n) { return child->GetParity(n); }
|
||||
};
|
||||
|
||||
|
||||
class AvisynthError /* exception */ {
|
||||
public:
|
||||
const char* const msg;
|
||||
AvisynthError(const char* _msg) : msg(_msg) {}
|
||||
};
|
||||
|
||||
|
||||
// For GetCPUFlags. These are the same as in VirtualDub.
|
||||
enum {
|
||||
CPUF_FORCE = 0x01,
|
||||
CPUF_FPU = 0x02,
|
||||
CPUF_MMX = 0x04,
|
||||
CPUF_INTEGER_SSE = 0x08, // Athlon MMX extensions or Intel SSE
|
||||
CPUF_SSE = 0x10, // Full SSE (PIII)
|
||||
CPUF_SSE2 = 0x20, // (PIV)
|
||||
CPUF_3DNOW = 0x40,
|
||||
CPUF_3DNOW_EXT = 0x80, // Athlon 3DNow! extensions
|
||||
};
|
||||
|
||||
|
||||
class IScriptEnvironment {
|
||||
public:
|
||||
virtual __stdcall ~IScriptEnvironment() {}
|
||||
|
||||
virtual /*static*/ long __stdcall GetCPUFlags() = 0;
|
||||
|
||||
virtual char* __stdcall SaveString(const char* s, int length = -1) = 0;
|
||||
virtual char* __stdcall Sprintf(const char* fmt, ...) = 0;
|
||||
// note: val is really a va_list; I hope everyone typedefs va_list to a pointer
|
||||
virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0;
|
||||
|
||||
__declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0;
|
||||
|
||||
class NotFound /*exception*/ {}; // thrown by Invoke and GetVar
|
||||
|
||||
typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env);
|
||||
|
||||
virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0;
|
||||
virtual bool __stdcall FunctionExists(const char* name) = 0;
|
||||
virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0;
|
||||
|
||||
virtual AVSValue __stdcall GetVar(const char* name) = 0;
|
||||
virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0;
|
||||
virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0;
|
||||
|
||||
virtual void __stdcall PushContext(int level=0) = 0;
|
||||
virtual void __stdcall PopContext() = 0;
|
||||
|
||||
// align should be 4 or 8
|
||||
virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=8) = 0;
|
||||
|
||||
virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0;
|
||||
|
||||
virtual /*static*/ void __stdcall BitBlt(unsigned char* dstp, int dst_pitch, const unsigned char* srcp, int src_pitch, int row_size, int height) = 0;
|
||||
|
||||
typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env);
|
||||
virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0;
|
||||
|
||||
virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0;
|
||||
|
||||
virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0;
|
||||
};
|
||||
|
||||
|
||||
// avisynth.dll exports this; it's a way to use it as a library, without
|
||||
// writing an AVS script or without going through AVIFile.
|
||||
IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION);
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
670
vsfilter/include/avisynth/avisynth25.h
Normal file
670
vsfilter/include/avisynth/avisynth25.h
Normal file
|
@ -0,0 +1,670 @@
|
|||
// Avisynth v2.5 alpha. Copyright 2002 Ben Rudiak-Gould et al.
|
||||
// http://www.avisynth.org
|
||||
|
||||
// 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., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
|
||||
// http://www.gnu.org/copyleft/gpl.html .
|
||||
//
|
||||
// Linking Avisynth statically or dynamically with other modules is making a
|
||||
// combined work based on Avisynth. Thus, the terms and conditions of the GNU
|
||||
// General Public License cover the whole combination.
|
||||
//
|
||||
// As a special exception, the copyright holders of Avisynth give you
|
||||
// permission to link Avisynth with independent modules that communicate with
|
||||
// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
|
||||
// terms of these independent modules, and to copy and distribute the
|
||||
// resulting combined work under terms of your choice, provided that
|
||||
// every copy of the combined work is accompanied by a complete copy of
|
||||
// the source code of Avisynth (the version of Avisynth used to produce the
|
||||
// combined work), being distributed under the terms of the GNU General
|
||||
// Public License plus this exception. An independent module is a module
|
||||
// which is not derived from or based on Avisynth, such as 3rd-party filters,
|
||||
// import and export plugins, or graphical user interfaces.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
enum { AVISYNTH_INTERFACE_VERSION = 2 };
|
||||
|
||||
|
||||
/* Define all types necessary for interfacing with avisynth.dll
|
||||
Moved from internal.h */
|
||||
|
||||
// Win32 API macros, notably the types BYTE, DWORD, ULONG, etc.
|
||||
#include <windef.h>
|
||||
|
||||
// COM interface macros
|
||||
#include <objbase.h>
|
||||
|
||||
// Raster types used by VirtualDub & Avisynth
|
||||
#define in64 (__int64)(unsigned short)
|
||||
typedef unsigned long Pixel; // this will break on 64-bit machines!
|
||||
typedef unsigned long Pixel32;
|
||||
typedef unsigned char Pixel8;
|
||||
typedef long PixCoord;
|
||||
typedef long PixDim;
|
||||
typedef long PixOffset;
|
||||
|
||||
|
||||
/* Compiler-specific crap */
|
||||
|
||||
// Tell MSVC to stop precompiling here
|
||||
#ifdef _MSC_VER
|
||||
// #pragma hdrstop
|
||||
#endif
|
||||
|
||||
// Set up debugging macros for MS compilers; for others, step down to the
|
||||
// standard <assert.h> interface
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#define _RPT0(a,b) ((void)0)
|
||||
#define _RPT1(a,b,c) ((void)0)
|
||||
#define _RPT2(a,b,c,d) ((void)0)
|
||||
#define _RPT3(a,b,c,d,e) ((void)0)
|
||||
#define _RPT4(a,b,c,d,e,f) ((void)0)
|
||||
|
||||
#define _ASSERTE(x) assert(x)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// I had problems with Premiere wanting 1-byte alignment for its structures,
|
||||
// so I now set the Avisynth struct alignment explicitly here.
|
||||
#pragma pack(push,8)
|
||||
|
||||
#define FRAME_ALIGN 16
|
||||
// Default frame alignment is 16 bytes, to help P4, when using SSE2
|
||||
|
||||
// The VideoInfo struct holds global information about a clip (i.e.
|
||||
// information that does not depend on the frame number). The GetVideoInfo
|
||||
// method in IClip returns this struct.
|
||||
|
||||
// Audio Sample information
|
||||
typedef float SFLOAT;
|
||||
|
||||
enum {SAMPLE_INT8 = 1<<0,
|
||||
SAMPLE_INT16 = 1<<1,
|
||||
SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware.
|
||||
SAMPLE_INT32 = 1<<3,
|
||||
SAMPLE_FLOAT = 1<<4};
|
||||
|
||||
enum {
|
||||
PLANAR_Y=1<<0,
|
||||
PLANAR_U=1<<1,
|
||||
PLANAR_V=1<<2,
|
||||
PLANAR_ALIGNED=1<<3,
|
||||
PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED,
|
||||
PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED,
|
||||
PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED,
|
||||
};
|
||||
|
||||
struct VideoInfo {
|
||||
int width, height; // width=0 means no video
|
||||
unsigned fps_numerator, fps_denominator;
|
||||
int num_frames;
|
||||
// This is more extensible than previous versions. More properties can be added seeminglesly.
|
||||
|
||||
// Colorspace properties.
|
||||
enum {
|
||||
CS_BGR = 1<<28,
|
||||
CS_YUV = 1<<29,
|
||||
CS_INTERLEAVED = 1<<30,
|
||||
CS_PLANAR = 1<<31
|
||||
};
|
||||
|
||||
// Specific colorformats
|
||||
enum { CS_UNKNOWN = 0,
|
||||
CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED,
|
||||
CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED,
|
||||
CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED,
|
||||
CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, planar
|
||||
CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, planar
|
||||
CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR // same as above
|
||||
};
|
||||
int pixel_type; // changed to int as of 2.5
|
||||
|
||||
|
||||
int audio_samples_per_second; // 0 means no audio
|
||||
int sample_type; // as of 2.5
|
||||
__int64 num_audio_samples; // changed as of 2.5
|
||||
int nchannels; // as of 2.5
|
||||
|
||||
// Imagetype properties
|
||||
|
||||
int image_type;
|
||||
|
||||
enum {
|
||||
IT_BFF = 1<<0,
|
||||
IT_TFF = 1<<1,
|
||||
IT_FIELDBASED = 1<<2
|
||||
};
|
||||
|
||||
// useful functions of the above
|
||||
bool HasVideo() const { return (width!=0); }
|
||||
bool HasAudio() const { return (audio_samples_per_second!=0); }
|
||||
bool IsRGB() const { return !!(pixel_type&CS_BGR); }
|
||||
bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties
|
||||
bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; }
|
||||
bool IsYUV() const { return !!(pixel_type&CS_YUV ); }
|
||||
bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; }
|
||||
bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); }
|
||||
bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); }
|
||||
bool Is(int property) const { return ((pixel_type & property)==property ); }
|
||||
bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); }
|
||||
bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
|
||||
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF||IT_TFF))); }
|
||||
bool IsBFF() const { return !!(pixel_type & IT_BFF); }
|
||||
bool IsTFF() const { return !!(pixel_type & IT_TFF); }
|
||||
|
||||
bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this
|
||||
int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes
|
||||
int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images
|
||||
int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); }
|
||||
__int64 AudioSamplesFromFrames(__int64 frames) const { return (__int64(frames) * audio_samples_per_second * fps_denominator / fps_numerator); }
|
||||
int FramesFromAudioSamples(__int64 samples) const { return (int)(samples * (__int64)fps_numerator / (__int64)fps_denominator / (__int64)audio_samples_per_second); }
|
||||
__int64 AudioSamplesFromBytes(__int64 bytes) const { return bytes / BytesPerAudioSample(); }
|
||||
__int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); }
|
||||
int AudioChannels() const { return nchannels; }
|
||||
int SampleType() const{ return sample_type;}
|
||||
int SamplesPerSecond() const { return audio_samples_per_second; }
|
||||
int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();}
|
||||
void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; }
|
||||
void Set(int property) { image_type|=property; }
|
||||
void Clear(int property) { image_type&=~property; }
|
||||
|
||||
int BitsPerPixel() const {
|
||||
switch (pixel_type) {
|
||||
case CS_BGR24:
|
||||
return 24;
|
||||
case CS_BGR32:
|
||||
return 32;
|
||||
case CS_YUY2:
|
||||
return 16;
|
||||
case CS_YV12:
|
||||
case CS_I420:
|
||||
return 12;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int BytesPerChannelSample() const {
|
||||
switch (sample_type) {
|
||||
case SAMPLE_INT8:
|
||||
return sizeof(signed char);
|
||||
case SAMPLE_INT16:
|
||||
return sizeof(signed short);
|
||||
case SAMPLE_INT24:
|
||||
return 3;
|
||||
case SAMPLE_INT32:
|
||||
return sizeof(signed int);
|
||||
case SAMPLE_FLOAT:
|
||||
return sizeof(SFLOAT);
|
||||
default:
|
||||
_ASSERTE("Sample type not recognized!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// useful mutator
|
||||
void SetFPS(unsigned numerator, unsigned denominator) {
|
||||
unsigned x=numerator, y=denominator;
|
||||
while (y) { // find gcd
|
||||
unsigned t = x%y; x = y; y = t;
|
||||
}
|
||||
fps_numerator = numerator/x;
|
||||
fps_denominator = denominator/x;
|
||||
}
|
||||
};
|
||||
|
||||
enum {
|
||||
FILTER_TYPE=1,
|
||||
FILTER_INPUT_COLORSPACE=2,
|
||||
FILTER_OUTPUT_TYPE=9,
|
||||
FILTER_NAME=4,
|
||||
FILTER_AUTHOR=5,
|
||||
FILTER_VERSION=6,
|
||||
FILTER_ARGS=7,
|
||||
FILTER_ARGS_INFO=8,
|
||||
FILTER_ARGS_DESCRIPTION=10,
|
||||
FILTER_DESCRIPTION=11,
|
||||
};
|
||||
enum { //SUBTYPES
|
||||
FILTER_TYPE_AUDIO=1,
|
||||
FILTER_TYPE_VIDEO=2,
|
||||
FILTER_OUTPUT_TYPE_SAME=3,
|
||||
FILTER_OUTPUT_TYPE_DIFFERENT=4,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// VideoFrameBuffer holds information about a memory block which is used
|
||||
// for video data. For efficiency, instances of this class are not deleted
|
||||
// when the refcount reaches zero; instead they're stored in a linked list
|
||||
// to be reused. The instances are deleted when the corresponding AVS
|
||||
// file is closed.
|
||||
|
||||
class VideoFrameBuffer {
|
||||
BYTE* const data;
|
||||
const int data_size;
|
||||
// sequence_number is incremented every time the buffer is changed, so
|
||||
// that stale views can tell they're no longer valid.
|
||||
long sequence_number;
|
||||
|
||||
friend class VideoFrame;
|
||||
friend class Cache;
|
||||
long refcount;
|
||||
|
||||
public:
|
||||
VideoFrameBuffer(int size);
|
||||
VideoFrameBuffer();
|
||||
~VideoFrameBuffer();
|
||||
|
||||
const BYTE* GetReadPtr() const { return data; }
|
||||
BYTE* GetWritePtr() { ++sequence_number; return data; }
|
||||
int GetDataSize() { return data_size; }
|
||||
int GetSequenceNumber() { return sequence_number; }
|
||||
int GetRefcount() { return refcount; }
|
||||
};
|
||||
|
||||
|
||||
class IClip;
|
||||
class PClip;
|
||||
class PVideoFrame;
|
||||
class IScriptEnvironment;
|
||||
class AVSValue;
|
||||
|
||||
|
||||
// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new
|
||||
// is overloaded to recycle class instances.
|
||||
|
||||
class VideoFrame {
|
||||
int refcount;
|
||||
VideoFrameBuffer* const vfb;
|
||||
const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture.
|
||||
|
||||
friend class PVideoFrame;
|
||||
void AddRef() { ++refcount; }
|
||||
void Release() { if (refcount==1) --vfb->refcount; --refcount; }
|
||||
|
||||
friend class ScriptEnvironment;
|
||||
friend class Cache;
|
||||
|
||||
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height);
|
||||
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV);
|
||||
|
||||
void* operator new(unsigned size);
|
||||
// TESTME: OFFSET U/V may be switched to what could be expected from AVI standard!
|
||||
public:
|
||||
int GetPitch() const { return pitch; }
|
||||
int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; }
|
||||
int GetRowSize() const { return row_size; }
|
||||
int GetRowSize(int plane) const {
|
||||
switch (plane) {
|
||||
case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0;
|
||||
case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED:
|
||||
if (pitchUV) {
|
||||
int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize
|
||||
if (r<=pitchUV)
|
||||
return r;
|
||||
return row_size>>1;
|
||||
} else return 0;
|
||||
case PLANAR_Y_ALIGNED:
|
||||
int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize
|
||||
if (r<=pitch)
|
||||
return r;
|
||||
return row_size;
|
||||
}
|
||||
return row_size; }
|
||||
int GetHeight() const { return height; }
|
||||
int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; }
|
||||
|
||||
// generally you shouldn't use these three
|
||||
VideoFrameBuffer* GetFrameBuffer() const { return vfb; }
|
||||
int GetOffset() const { return offset; }
|
||||
int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; }
|
||||
|
||||
// in plugins use env->SubFrame()
|
||||
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const;
|
||||
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const;
|
||||
|
||||
|
||||
const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; }
|
||||
const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); }
|
||||
|
||||
bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); }
|
||||
|
||||
BYTE* GetWritePtr() const {
|
||||
return IsWritable() ? (vfb->GetWritePtr() + offset) : 0;
|
||||
}
|
||||
|
||||
BYTE* GetWritePtr(int plane) const {
|
||||
if (plane==PLANAR_Y)
|
||||
return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0;
|
||||
return vfb->data + GetOffset(plane);
|
||||
}
|
||||
|
||||
~VideoFrame() { --vfb->refcount; }
|
||||
};
|
||||
|
||||
enum {
|
||||
CACHE_NOTHING=0,
|
||||
CACHE_RANGE=1 };
|
||||
|
||||
// Base class for all filters.
|
||||
class IClip {
|
||||
friend class PClip;
|
||||
friend class AVSValue;
|
||||
int refcnt;
|
||||
void AddRef() { ++refcnt; }
|
||||
void Release() { if (!--refcnt) delete this; }
|
||||
public:
|
||||
IClip() : refcnt(0) {}
|
||||
|
||||
virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; }
|
||||
|
||||
virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0;
|
||||
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame
|
||||
virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples
|
||||
virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter.
|
||||
virtual const VideoInfo& __stdcall GetVideoInfo() = 0;
|
||||
virtual __stdcall ~IClip() {}
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to IClip
|
||||
class PClip {
|
||||
|
||||
IClip* p;
|
||||
|
||||
IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; }
|
||||
friend class AVSValue;
|
||||
friend class VideoFrame;
|
||||
|
||||
void Init(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(IClip* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PClip() { p = 0; }
|
||||
PClip(const PClip& x) { Init(x.p); }
|
||||
PClip(IClip* x) { Init(x); }
|
||||
void operator=(IClip* x) { Set(x); }
|
||||
void operator=(const PClip& x) { Set(x.p); }
|
||||
|
||||
IClip* operator->() const { return p; }
|
||||
|
||||
// useful in conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PClip() { if (p) p->Release(); }
|
||||
};
|
||||
|
||||
|
||||
// smart pointer to VideoFrame
|
||||
class PVideoFrame {
|
||||
|
||||
VideoFrame* p;
|
||||
|
||||
void Init(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
p=x;
|
||||
}
|
||||
void Set(VideoFrame* x) {
|
||||
if (x) x->AddRef();
|
||||
if (p) p->Release();
|
||||
p=x;
|
||||
}
|
||||
|
||||
public:
|
||||
PVideoFrame() { p = 0; }
|
||||
PVideoFrame(const PVideoFrame& x) { Init(x.p); }
|
||||
PVideoFrame(VideoFrame* x) { Init(x); }
|
||||
void operator=(VideoFrame* x) { Set(x); }
|
||||
void operator=(const PVideoFrame& x) { Set(x.p); }
|
||||
|
||||
VideoFrame* operator->() const { return p; }
|
||||
|
||||
// for conditional expressions
|
||||
operator void*() const { return p; }
|
||||
bool operator!() const { return !p; }
|
||||
|
||||
~PVideoFrame() { if (p) p->Release(); }
|
||||
};
|
||||
|
||||
|
||||
class AVSValue {
|
||||
public:
|
||||
|
||||
AVSValue() { type = 'v'; }
|
||||
AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); }
|
||||
AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); }
|
||||
AVSValue(bool b) { type = 'b'; boolean = b; }
|
||||
AVSValue(int i) { type = 'i'; integer = i; }
|
||||
// AVSValue(__int64 l) { type = 'l'; longlong = l; }
|
||||
AVSValue(float f) { type = 'f'; floating_pt = f; }
|
||||
AVSValue(double f) { type = 'f'; floating_pt = float(f); }
|
||||
AVSValue(const char* s) { type = 's'; string = s; }
|
||||
AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; }
|
||||
AVSValue(const AVSValue& v) { Assign(&v, true); }
|
||||
|
||||
~AVSValue() { if (IsClip() && clip) clip->Release(); }
|
||||
AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; }
|
||||
|
||||
// Note that we transparently allow 'int' to be treated as 'float'.
|
||||
// There are no int<->bool conversions, though.
|
||||
|
||||
bool Defined() const { return type != 'v'; }
|
||||
bool IsClip() const { return type == 'c'; }
|
||||
bool IsBool() const { return type == 'b'; }
|
||||
bool IsInt() const { return type == 'i'; }
|
||||
// bool IsLong() const { return (type == 'l'|| type == 'i'); }
|
||||
bool IsFloat() const { return type == 'f' || type == 'i'; }
|
||||
bool IsString() const { return type == 's'; }
|
||||
bool IsArray() const { return type == 'a'; }
|
||||
|
||||
PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; }
|
||||
bool AsBool() const { _ASSERTE(IsBool()); return boolean; }
|
||||
int AsInt() const { _ASSERTE(IsInt()); return integer; }
|
||||
// int AsLong() const { _ASSERTE(IsLong()); return longlong; }
|
||||
const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; }
|
||||
double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; }
|
||||
|
||||
bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; }
|
||||
int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; }
|
||||
double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; }
|
||||
const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; }
|
||||
|
||||
int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; }
|
||||
const AVSValue& operator[](int index) const {
|
||||
_ASSERTE(IsArray() && index>=0 && index<array_size);
|
||||
return (IsArray() && index>=0 && index<array_size) ? array[index] : *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong
|
||||
short array_size;
|
||||
union {
|
||||
IClip* clip;
|
||||
bool boolean;
|
||||
int integer;
|
||||
float floating_pt;
|
||||
const char* string;
|
||||
const AVSValue* array;
|
||||
// __int64 longlong;
|
||||
};
|
||||
|
||||
void Assign(const AVSValue* src, bool init) {
|
||||
if (src->IsClip() && src->clip)
|
||||
src->clip->AddRef();
|
||||
if (!init && IsClip() && clip)
|
||||
clip->Release();
|
||||
// make sure this copies the whole struct!
|
||||
((__int32*)this)[0] = ((__int32*)src)[0];
|
||||
((__int32*)this)[1] = ((__int32*)src)[1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// instantiable null filter
|
||||
class GenericVideoFilter : public IClip {
|
||||
protected:
|
||||
PClip child;
|
||||
VideoInfo vi;
|
||||
public:
|
||||
GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); }
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); }
|
||||
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); }
|
||||
const VideoInfo& __stdcall GetVideoInfo() { return vi; }
|
||||
bool __stdcall GetParity(int n) { return child->GetParity(n); }
|
||||
void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter.
|
||||
};
|
||||
|
||||
|
||||
class AvisynthError /* exception */ {
|
||||
public:
|
||||
const char* const msg;
|
||||
AvisynthError(const char* _msg) : msg(_msg) {}
|
||||
};
|
||||
|
||||
|
||||
// For GetCPUFlags. These are backwards-compatible with those in VirtualDub.
|
||||
enum {
|
||||
/* slowest CPU to support extension */
|
||||
CPUF_FORCE = 0x01, // N/A
|
||||
CPUF_FPU = 0x02, // 386/486DX
|
||||
CPUF_MMX = 0x04, // P55C, K6, PII
|
||||
CPUF_INTEGER_SSE = 0x08, // PIII, Athlon
|
||||
CPUF_SSE = 0x10, // PIII, Athlon XP/MP
|
||||
CPUF_SSE2 = 0x20, // PIV, Hammer
|
||||
CPUF_3DNOW = 0x40, // K6-2
|
||||
CPUF_3DNOW_EXT = 0x80, // Athlon
|
||||
CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which only Hammer
|
||||
// will have anyway)
|
||||
};
|
||||
#define MAX_INT 0x7fffffff
|
||||
#define MIN_INT 0x80000000
|
||||
|
||||
|
||||
class ConvertAudio : public GenericVideoFilter
|
||||
/**
|
||||
* Helper class to convert audio to any format
|
||||
**/
|
||||
{
|
||||
public:
|
||||
ConvertAudio(PClip _clip, int prefered_format);
|
||||
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
|
||||
|
||||
static PClip Create(PClip clip, int sample_type, int prefered_type);
|
||||
static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
static AVSValue __cdecl Create_8bit(AVSValue args, void*, IScriptEnvironment*);
|
||||
virtual ~ConvertAudio()
|
||||
{if (tempbuffer_size) {delete[] tempbuffer;tempbuffer_size=0;}}
|
||||
private:
|
||||
void ConvertAudio::convertToFloat(char* inbuf, float* outbuf, char sample_type, int count);
|
||||
void ConvertAudio::convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count);
|
||||
|
||||
__inline int Saturate_int8(float n);
|
||||
__inline short Saturate_int16(float n);
|
||||
__inline int Saturate_int24(float n);
|
||||
__inline int Saturate_int32(float n);
|
||||
|
||||
char src_format;
|
||||
char dst_format;
|
||||
int src_bps;
|
||||
char *tempbuffer;
|
||||
SFLOAT *floatbuffer;
|
||||
int tempbuffer_size;
|
||||
};
|
||||
|
||||
class AlignPlanar : public GenericVideoFilter {
|
||||
public:
|
||||
AlignPlanar(PClip _clip);
|
||||
static PClip Create(PClip clip);
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
|
||||
};
|
||||
|
||||
class FillBorder : public GenericVideoFilter {
|
||||
public:
|
||||
FillBorder(PClip _clip);
|
||||
static PClip Create(PClip clip);
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
|
||||
};
|
||||
|
||||
class IScriptEnvironment {
|
||||
public:
|
||||
virtual __stdcall ~IScriptEnvironment() {}
|
||||
|
||||
virtual /*static*/ long __stdcall GetCPUFlags() = 0;
|
||||
|
||||
virtual char* __stdcall SaveString(const char* s, int length = -1) = 0;
|
||||
virtual char* __stdcall Sprintf(const char* fmt, ...) = 0;
|
||||
// note: val is really a va_list; I hope everyone typedefs va_list to a pointer
|
||||
virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0;
|
||||
|
||||
__declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0;
|
||||
|
||||
class NotFound /*exception*/ {}; // thrown by Invoke and GetVar
|
||||
|
||||
typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env);
|
||||
|
||||
virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0;
|
||||
virtual bool __stdcall FunctionExists(const char* name) = 0;
|
||||
virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0;
|
||||
|
||||
virtual AVSValue __stdcall GetVar(const char* name) = 0;
|
||||
virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0;
|
||||
virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0;
|
||||
|
||||
virtual void __stdcall PushContext(int level=0) = 0;
|
||||
virtual void __stdcall PopContext() = 0;
|
||||
|
||||
// align should be 4 or 8
|
||||
virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0;
|
||||
|
||||
virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0;
|
||||
|
||||
virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0;
|
||||
|
||||
typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env);
|
||||
virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0;
|
||||
|
||||
virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0;
|
||||
|
||||
virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0;
|
||||
|
||||
virtual int __stdcall SetMemoryMax(int mem) = 0;
|
||||
|
||||
virtual int __stdcall SetWorkingDir(const char * newdir) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// avisynth.dll exports this; it's a way to use it as a library, without
|
||||
// writing an AVS script or without going through AVIFile.
|
||||
IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION);
|
||||
|
||||
|
||||
#pragma pack(pop)
|
21
vsfilter/include/decss/VobDec.h
Normal file
21
vsfilter/include/decss/VobDec.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
class CVobDec
|
||||
{
|
||||
int m_lfsr0, m_lfsr1;
|
||||
|
||||
void ClockLfsr0Forward(int& lfsr0);
|
||||
void ClockLfsr1Forward(int& lfsr1);
|
||||
void ClockBackward(int& lfsr0, int& lfsr1);
|
||||
void Salt(const BYTE salt[5], int& lfsr0, int& lfsr1);
|
||||
int FindLfsr(const BYTE* crypt, int offset, const BYTE* plain);
|
||||
|
||||
public:
|
||||
CVobDec();
|
||||
virtual ~CVobDec();
|
||||
|
||||
bool m_fFoundKey;
|
||||
|
||||
bool FindKey(BYTE* buff);
|
||||
void Decrypt(BYTE* buff);
|
||||
};
|
87
vsfilter/include/decss/vobfile.h
Normal file
87
vsfilter/include/decss/vobfile.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#pragma warning(disable : 4200)
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <atlcoll.h>
|
||||
//#include <winioctl.h> // platform sdk
|
||||
#include "../winddk/ntddcdvd.h"
|
||||
|
||||
class CDVDSession
|
||||
{
|
||||
protected:
|
||||
HANDLE m_hDrive;
|
||||
|
||||
DVD_SESSION_ID m_session;
|
||||
bool BeginSession();
|
||||
void EndSession();
|
||||
|
||||
BYTE m_SessionKey[5];
|
||||
bool Authenticate();
|
||||
|
||||
BYTE m_DiscKey[6], m_TitleKey[6];
|
||||
bool GetDiscKey();
|
||||
bool GetTitleKey(int lba, BYTE* pKey);
|
||||
|
||||
public:
|
||||
CDVDSession();
|
||||
virtual ~CDVDSession();
|
||||
|
||||
bool Open(LPCTSTR path);
|
||||
void Close();
|
||||
|
||||
operator HANDLE() {return m_hDrive;}
|
||||
operator DVD_SESSION_ID() {return m_session;}
|
||||
|
||||
bool SendKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData);
|
||||
bool ReadKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData, int lba = 0);
|
||||
};
|
||||
|
||||
class CLBAFile : private CFile
|
||||
{
|
||||
public:
|
||||
CLBAFile();
|
||||
virtual ~CLBAFile();
|
||||
|
||||
bool IsOpen();
|
||||
|
||||
bool Open(LPCTSTR path);
|
||||
void Close();
|
||||
|
||||
int GetLength();
|
||||
int GetPosition();
|
||||
int Seek(int lba);
|
||||
bool Read(BYTE* buff);
|
||||
};
|
||||
|
||||
class CVobFile : public CDVDSession
|
||||
{
|
||||
// all files
|
||||
typedef struct {CString fn; int size;} file_t;
|
||||
CAtlArray<file_t> m_files;
|
||||
int m_iFile;
|
||||
int m_pos, m_size, m_offset;
|
||||
|
||||
// currently opened file
|
||||
CLBAFile m_file;
|
||||
|
||||
// attribs
|
||||
bool m_fDVD, m_fHasDiscKey, m_fHasTitleKey;
|
||||
|
||||
public:
|
||||
CVobFile();
|
||||
virtual ~CVobFile();
|
||||
|
||||
bool IsDVD();
|
||||
bool HasDiscKey(BYTE* key);
|
||||
bool HasTitleKey(BYTE* key);
|
||||
|
||||
bool Open(CString fn, CAtlList<CString>& files /* out */); // vts ifo
|
||||
bool Open(CAtlList<CString>& files, int offset = -1); // vts vobs, video vob offset in lba
|
||||
void Close();
|
||||
|
||||
int GetLength();
|
||||
int GetPosition();
|
||||
int Seek(int pos);
|
||||
bool Read(BYTE* buff);
|
||||
};
|
449
vsfilter/include/moreuuids.h
Normal file
449
vsfilter/include/moreuuids.h
Normal file
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Note: This interface was defined for the matroska container format
|
||||
* originally, but can be implemented for other formats as well.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dvdmedia.h>
|
||||
|
||||
// 30323449-0000-0010-8000-00AA00389B71 'I420' == MEDIASUBTYPE_I420
|
||||
DEFINE_GUID(MEDIASUBTYPE_I420,
|
||||
0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_DOLBY_AC3 0x2000
|
||||
// {00002000-0000-0010-8000-00aa00389b71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_WAVE_DOLBY_AC3,
|
||||
WAVE_FORMAT_DOLBY_AC3, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_DVD_DTS 0x2001
|
||||
// {00002001-0000-0010-8000-00aa00389b71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_WAVE_DTS,
|
||||
WAVE_FORMAT_DVD_DTS, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// Be compatible with 3ivx
|
||||
#define WAVE_FORMAT_AAC 0x00FF
|
||||
// {000000FF-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_AAC,
|
||||
WAVE_FORMAT_AAC, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// ... and also compatible with nero
|
||||
// btw, older nero parsers use a lower-case fourcc, newer upper-case (why can't it just offer both?)
|
||||
// {4134504D-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_MP4A,
|
||||
0x4134504D, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// {6134706D-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_mp4a,
|
||||
0x6134706D, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_MP3 0x0055
|
||||
// 00000055-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_MP3,
|
||||
WAVE_FORMAT_MP3, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_FLAC 0xF1AC
|
||||
// 0000F1AC-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_FLAC,
|
||||
WAVE_FORMAT_FLAC, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// {1541C5C0-CDDF-477d-BC0A-86F8AE7F8354}
|
||||
DEFINE_GUID(MEDIASUBTYPE_FLAC_FRAMED,
|
||||
0x1541c5c0, 0xcddf, 0x477d, 0xbc, 0xa, 0x86, 0xf8, 0xae, 0x7f, 0x83, 0x54);
|
||||
|
||||
#define WAVE_FORMAT_TTA1 0x77A1
|
||||
// {000077A1-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_TTA1,
|
||||
WAVE_FORMAT_TTA1, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_WAVPACK4 0x5756
|
||||
// {00005756-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_WAVPACK4,
|
||||
WAVE_FORMAT_WAVPACK4, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// {DA5B82EE-6BD2-426f-BF1E-30112DA78AE1}
|
||||
DEFINE_GUID(MEDIASUBTYPE_SVCD_SUBPICTURE,
|
||||
0xda5b82ee, 0x6bd2, 0x426f, 0xbf, 0x1e, 0x30, 0x11, 0x2d, 0xa7, 0x8a, 0xe1);
|
||||
|
||||
// {7B57308F-5154-4c36-B903-52FE76E184FC}
|
||||
DEFINE_GUID(MEDIASUBTYPE_CVD_SUBPICTURE,
|
||||
0x7b57308f, 0x5154, 0x4c36, 0xb9, 0x3, 0x52, 0xfe, 0x76, 0xe1, 0x84, 0xfc);
|
||||
|
||||
// {0E3A2342-F6E2-4c91-BDAE-87C71EAD0D63}
|
||||
DEFINE_GUID(MEDIASUBTYPE_MPEG2_PVA,
|
||||
0xe3a2342, 0xf6e2, 0x4c91, 0xbd, 0xae, 0x87, 0xc7, 0x1e, 0xad, 0xd, 0x63);
|
||||
|
||||
// {6B6D0800-9ADA-11d0-A520-00A0D10129C0}
|
||||
DEFINE_GUID(CLSID_NetShowSource,
|
||||
0x6b6d0800, 0x9ada, 0x11d0, 0xa5, 0x20, 0x0, 0xa0, 0xd1, 0x1, 0x29, 0xc0);
|
||||
|
||||
// DirectShowMedia
|
||||
|
||||
// {5E9C9EE0-2E4A-4f22-9906-7BBBB75AA2B6}
|
||||
DEFINE_GUID(MEDIASUBTYPE_DirectShowMedia,
|
||||
0x5e9c9ee0, 0x2e4a, 0x4f22, 0x99, 0x6, 0x7b, 0xbb, 0xb7, 0x5a, 0xa2, 0xb6);
|
||||
|
||||
// Dirac
|
||||
|
||||
// {A29DA00F-A22B-40ea-98DE-2F7FECADA5DE}
|
||||
DEFINE_GUID(MEDIASUBTYPE_Dirac,
|
||||
0xa29da00f, 0xa22b, 0x40ea, 0x98, 0xde, 0x2f, 0x7f, 0xec, 0xad, 0xa5, 0xde);
|
||||
|
||||
// {64726376-0000-0010-8000-00AA00389B71}
|
||||
DEFINE_GUID(MEDIASUBTYPE_DiracVideo,
|
||||
0x64726376, 0x000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
// {D2667A7E-4055-4244-A65F-DDDDF2B74BD7}
|
||||
DEFINE_GUID(FORMAT_DiracVideoInfo,
|
||||
0xd2667a7e, 0x4055, 0x4244, 0xa6, 0x5f, 0xdd, 0xdd, 0xf2, 0xb7, 0x4b, 0xd7);
|
||||
|
||||
struct DIRACINFOHEADER
|
||||
{
|
||||
VIDEOINFOHEADER2 hdr;
|
||||
DWORD cbSequenceHeader;
|
||||
DWORD dwSequenceHeader[1];
|
||||
};
|
||||
|
||||
// MP4
|
||||
|
||||
// {08E22ADA-B715-45ed-9D20-7B87750301D4}
|
||||
DEFINE_GUID(MEDIASUBTYPE_MP4,
|
||||
0x8e22ada, 0xb715, 0x45ed, 0x9d, 0x20, 0x7b, 0x87, 0x75, 0x3, 0x1, 0xd4);
|
||||
|
||||
// FLV
|
||||
|
||||
// {F2FAC0F1-3852-4670-AAC0-9051D400AC54}
|
||||
DEFINE_GUID(MEDIASUBTYPE_FLV,
|
||||
0xf2fac0f1, 0x3852, 0x4670, 0xaa, 0xc0, 0x90, 0x51, 0xd4, 0x0, 0xac, 0x54);
|
||||
|
||||
// 34564c46-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_FLV4,
|
||||
0x34564c46, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 30365056-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_VP60,
|
||||
0x30365056, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 31365056-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_VP61,
|
||||
0x31365056, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 32365056-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_VP62,
|
||||
0x32365056, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
//
|
||||
// RealMedia
|
||||
//
|
||||
|
||||
// {57428EC6-C2B2-44a2-AA9C-28F0B6A5C48E}
|
||||
DEFINE_GUID(MEDIASUBTYPE_RealMedia,
|
||||
0x57428ec6, 0xc2b2, 0x44a2, 0xaa, 0x9c, 0x28, 0xf0, 0xb6, 0xa5, 0xc4, 0x8e);
|
||||
|
||||
// 30315652-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RV10,
|
||||
0x30315652, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 30325652-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RV20,
|
||||
0x30325652, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 30335652-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RV30,
|
||||
0x30335652, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 30345652-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RV40,
|
||||
0x30345652, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 31345652-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RV41,
|
||||
0x31345652, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 345f3431-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_14_4,
|
||||
0x345f3431, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 385f3832-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_28_8,
|
||||
0x385f3832, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 43525441-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_ATRC,
|
||||
0x43525441, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 4b4f4f43-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_COOK,
|
||||
0x4b4f4f43, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 54454e44-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_DNET,
|
||||
0x54454e44, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 52504953-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_SIPR,
|
||||
0x52504953, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 43414152-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RAAC,
|
||||
0x43414152, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
// 50434152-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_RACP,
|
||||
0x50434152, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
enum
|
||||
{
|
||||
WAVE_FORMAT_14_4 = 0x2002,
|
||||
WAVE_FORMAT_28_8 = 0x2003,
|
||||
WAVE_FORMAT_ATRC = 0x0270, //WAVE_FORMAT_SONY_SCX,
|
||||
WAVE_FORMAT_COOK = 0x2004,
|
||||
WAVE_FORMAT_DNET = 0x2005,
|
||||
WAVE_FORMAT_RAAC = 0x2006,
|
||||
WAVE_FORMAT_RACP = 0x2007,
|
||||
WAVE_FORMAT_SIPR = 0x0130, //WAVE_FORMAT_SIPROLAB_ACEPLNET,
|
||||
};
|
||||
|
||||
//
|
||||
// PS2
|
||||
//
|
||||
|
||||
#define WAVE_FORMAT_PS2_PCM 0xF521
|
||||
// 0000F521-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_PS2_PCM,
|
||||
WAVE_FORMAT_PS2_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
#define WAVE_FORMAT_PS2_ADPCM 0xF522
|
||||
// 0000F522-0000-0010-8000-00AA00389B71
|
||||
DEFINE_GUID(MEDIASUBTYPE_PS2_ADPCM,
|
||||
WAVE_FORMAT_PS2_ADPCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
struct WAVEFORMATEXPS2 : public WAVEFORMATEX
|
||||
{
|
||||
DWORD dwInterleave;
|
||||
|
||||
struct WAVEFORMATEXPS2()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
cbSize = sizeof(WAVEFORMATEXPS2) - sizeof(WAVEFORMATEX);
|
||||
}
|
||||
};
|
||||
|
||||
// {4F3D3D21-6D7C-4f73-AA05-E397B5EAE0AA}
|
||||
DEFINE_GUID(MEDIASUBTYPE_PS2_SUB,
|
||||
0x4f3d3d21, 0x6d7c, 0x4f73, 0xaa, 0x5, 0xe3, 0x97, 0xb5, 0xea, 0xe0, 0xaa);
|
||||
|
||||
// Haali's video renderer
|
||||
|
||||
// {760A8F35-97E7-479d-AAF5-DA9EFF95D751}
|
||||
DEFINE_GUID(CLSID_DXR,
|
||||
0x760a8f35, 0x97e7, 0x479d, 0xaa, 0xf5, 0xda, 0x9e, 0xff, 0x95, 0xd7, 0x51);
|
||||
|
||||
//
|
||||
// Ogg
|
||||
//
|
||||
|
||||
// f07e245f-5a1f-4d1e-8bff-dc31d84a55ab
|
||||
DEFINE_GUID(CLSID_OggSplitter,
|
||||
0xf07e245f, 0x5a1f, 0x4d1e, 0x8b, 0xff, 0xdc, 0x31, 0xd8, 0x4a, 0x55, 0xab);
|
||||
|
||||
// {078C3DAA-9E58-4d42-9E1C-7C8EE79539C5}
|
||||
DEFINE_GUID(CLSID_OggSplitPropPage,
|
||||
0x78c3daa, 0x9e58, 0x4d42, 0x9e, 0x1c, 0x7c, 0x8e, 0xe7, 0x95, 0x39, 0xc5);
|
||||
|
||||
// 8cae96b7-85b1-4605-b23c-17ff5262b296
|
||||
DEFINE_GUID(CLSID_OggMux,
|
||||
0x8cae96b7, 0x85b1, 0x4605, 0xb2, 0x3c, 0x17, 0xff, 0x52, 0x62, 0xb2, 0x96);
|
||||
|
||||
// {AB97AFC3-D08E-4e2d-98E0-AEE6D4634BA4}
|
||||
DEFINE_GUID(CLSID_OggMuxPropPage,
|
||||
0xab97afc3, 0xd08e, 0x4e2d, 0x98, 0xe0, 0xae, 0xe6, 0xd4, 0x63, 0x4b, 0xa4);
|
||||
|
||||
// {889EF574-0656-4B52-9091-072E52BB1B80}
|
||||
DEFINE_GUID(CLSID_VorbisEnc,
|
||||
0x889ef574, 0x0656, 0x4b52, 0x90, 0x91, 0x07, 0x2e, 0x52, 0xbb, 0x1b, 0x80);
|
||||
|
||||
// {c5379125-fd36-4277-a7cd-fab469ef3a2f}
|
||||
DEFINE_GUID(CLSID_VorbisEncPropPage,
|
||||
0xc5379125, 0xfd36, 0x4277, 0xa7, 0xcd, 0xfa, 0xb4, 0x69, 0xef, 0x3a, 0x2f);
|
||||
|
||||
// 02391f44-2767-4e6a-a484-9b47b506f3a4
|
||||
DEFINE_GUID(CLSID_VorbisDec,
|
||||
0x02391f44, 0x2767, 0x4e6a, 0xa4, 0x84, 0x9b, 0x47, 0xb5, 0x06, 0xf3, 0xa4);
|
||||
|
||||
// 77983549-ffda-4a88-b48f-b924e8d1f01c
|
||||
DEFINE_GUID(CLSID_OggDSAboutPage,
|
||||
0x77983549, 0xffda, 0x4a88, 0xb4, 0x8f, 0xb9, 0x24, 0xe8, 0xd1, 0xf0, 0x1c);
|
||||
|
||||
// {D2855FA9-61A7-4db0-B979-71F297C17A04}
|
||||
DEFINE_GUID(MEDIASUBTYPE_Ogg,
|
||||
0xd2855fa9, 0x61a7, 0x4db0, 0xb9, 0x79, 0x71, 0xf2, 0x97, 0xc1, 0x7a, 0x4);
|
||||
|
||||
// cddca2d5-6d75-4f98-840e-737bedd5c63b
|
||||
DEFINE_GUID(MEDIASUBTYPE_Vorbis,
|
||||
0xcddca2d5, 0x6d75, 0x4f98, 0x84, 0x0e, 0x73, 0x7b, 0xed, 0xd5, 0xc6, 0x3b);
|
||||
|
||||
// 6bddfa7e-9f22-46a9-ab5e-884eff294d9f
|
||||
DEFINE_GUID(FORMAT_VorbisFormat,
|
||||
0x6bddfa7e, 0x9f22, 0x46a9, 0xab, 0x5e, 0x88, 0x4e, 0xff, 0x29, 0x4d, 0x9f);
|
||||
|
||||
typedef struct tagVORBISFORMAT
|
||||
{
|
||||
WORD nChannels;
|
||||
DWORD nSamplesPerSec;
|
||||
DWORD nMinBitsPerSec;
|
||||
DWORD nAvgBitsPerSec;
|
||||
DWORD nMaxBitsPerSec;
|
||||
float fQuality;
|
||||
} VORBISFORMAT, *PVORBISFORMAT, FAR *LPVORBISFORMAT;
|
||||
|
||||
// {8D2FD10B-5841-4a6b-8905-588FEC1ADED9}
|
||||
DEFINE_GUID(MEDIASUBTYPE_Vorbis2,
|
||||
0x8d2fd10b, 0x5841, 0x4a6b, 0x89, 0x5, 0x58, 0x8f, 0xec, 0x1a, 0xde, 0xd9);
|
||||
|
||||
// {B36E107F-A938-4387-93C7-55E966757473}
|
||||
DEFINE_GUID(FORMAT_VorbisFormat2,
|
||||
0xb36e107f, 0xa938, 0x4387, 0x93, 0xc7, 0x55, 0xe9, 0x66, 0x75, 0x74, 0x73);
|
||||
|
||||
typedef struct tagVORBISFORMAT2
|
||||
{
|
||||
DWORD Channels;
|
||||
DWORD SamplesPerSec;
|
||||
DWORD BitsPerSample;
|
||||
DWORD HeaderSize[3]; // 0: Identification, 1: Comment, 2: Setup
|
||||
} VORBISFORMAT2, *PVORBISFORMAT2, FAR *LPVORBISFORMAT2;
|
||||
|
||||
//
|
||||
// Matroska
|
||||
//
|
||||
|
||||
// {1AC0BEBD-4D2B-45ad-BCEB-F2C41C5E3788}
|
||||
DEFINE_GUID(MEDIASUBTYPE_Matroska,
|
||||
0x1ac0bebd, 0x4d2b, 0x45ad, 0xbc, 0xeb, 0xf2, 0xc4, 0x1c, 0x5e, 0x37, 0x88);
|
||||
|
||||
// {E487EB08-6B26-4be9-9DD3-993434D313FD}
|
||||
DEFINE_GUID(MEDIATYPE_Subtitle,
|
||||
0xe487eb08, 0x6b26, 0x4be9, 0x9d, 0xd3, 0x99, 0x34, 0x34, 0xd3, 0x13, 0xfd);
|
||||
|
||||
// {87C0B230-03A8-4fdf-8010-B27A5848200D}
|
||||
DEFINE_GUID(MEDIASUBTYPE_UTF8,
|
||||
0x87c0b230, 0x3a8, 0x4fdf, 0x80, 0x10, 0xb2, 0x7a, 0x58, 0x48, 0x20, 0xd);
|
||||
|
||||
// {3020560F-255A-4ddc-806E-6C5CC6DCD70A}
|
||||
DEFINE_GUID(MEDIASUBTYPE_SSA,
|
||||
0x3020560f, 0x255a, 0x4ddc, 0x80, 0x6e, 0x6c, 0x5c, 0xc6, 0xdc, 0xd7, 0xa);
|
||||
|
||||
// {326444F7-686F-47ff-A4B2-C8C96307B4C2}
|
||||
DEFINE_GUID(MEDIASUBTYPE_ASS,
|
||||
0x326444f7, 0x686f, 0x47ff, 0xa4, 0xb2, 0xc8, 0xc9, 0x63, 0x7, 0xb4, 0xc2);
|
||||
|
||||
// {370689E7-B226-4f67-978D-F10BC1A9C6AE}
|
||||
DEFINE_GUID(MEDIASUBTYPE_ASS2,
|
||||
0x370689e7, 0xb226, 0x4f67, 0x97, 0x8d, 0xf1, 0xb, 0xc1, 0xa9, 0xc6, 0xae);
|
||||
|
||||
// {76C421C4-DB89-42ec-936E-A9FBC1794714}
|
||||
DEFINE_GUID(MEDIASUBTYPE_SSF,
|
||||
0x76c421c4, 0xdb89, 0x42ec, 0x93, 0x6e, 0xa9, 0xfb, 0xc1, 0x79, 0x47, 0x14);
|
||||
|
||||
// {B753B29A-0A96-45be-985F-68351D9CAB90}
|
||||
DEFINE_GUID(MEDIASUBTYPE_USF,
|
||||
0xb753b29a, 0xa96, 0x45be, 0x98, 0x5f, 0x68, 0x35, 0x1d, 0x9c, 0xab, 0x90);
|
||||
|
||||
// {F7239E31-9599-4e43-8DD5-FBAF75CF37F1}
|
||||
DEFINE_GUID(MEDIASUBTYPE_VOBSUB,
|
||||
0xf7239e31, 0x9599, 0x4e43, 0x8d, 0xd5, 0xfb, 0xaf, 0x75, 0xcf, 0x37, 0xf1);
|
||||
|
||||
// {A33D2F7D-96BC-4337-B23B-A8B9FBC295E9}
|
||||
DEFINE_GUID(FORMAT_SubtitleInfo,
|
||||
0xa33d2f7d, 0x96bc, 0x4337, 0xb2, 0x3b, 0xa8, 0xb9, 0xfb, 0xc2, 0x95, 0xe9);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
DWORD dwOffset;
|
||||
CHAR IsoLang[4]; // three letter lang code + terminating zero
|
||||
WCHAR TrackName[256]; // 256 chars ought to be enough for everyone :)
|
||||
} SUBTITLEINFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
// SUBTITLEINFO structure content starting at dwOffset (also the content of CodecPrivate)
|
||||
// --------------------------------------------------------------------------------------
|
||||
//
|
||||
// Here the text should start with the Byte Order Mark, even though
|
||||
// UTF-8 is prefered, it also helps identifying the encoding type.
|
||||
//
|
||||
// MEDIASUBTYPE_USF:
|
||||
//
|
||||
// <?xml version="1.0" encoding="UTF-8"?>
|
||||
// <!-- DOCTYPE USFSubtitles SYSTEM "USFV100.dtd" -->
|
||||
// <?xml-stylesheet type="text/xsl" href="USFV100.xsl"?>
|
||||
//
|
||||
// <USFSubtitles version="1.0">
|
||||
// ... every element excluding <subtitles></subtitles> ...
|
||||
// </USFSubtitles>
|
||||
//
|
||||
// MEDIASUBTYPE_SSA/ASS:
|
||||
//
|
||||
// The file header and all sub-sections except [Events]
|
||||
//
|
||||
// MEDIATYPE_VOBSUB:
|
||||
//
|
||||
// TODO
|
||||
//
|
||||
|
||||
// Data description of the media samples (everything is UTF-8 encoded here)
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// MEDIASUBTYPE_USF:
|
||||
//
|
||||
// The text _inside_ the <subtitle>..</subtitle> element.
|
||||
//
|
||||
// Since timing is set on the sample, there is no need to put
|
||||
// <subtitle start=".." stop=".." duration=".."> into the data.
|
||||
//
|
||||
// MEDIASUBTYPE_SSA/ASS:
|
||||
//
|
||||
// Comma separated values similar to the "Dialogue: ..." line with these fields:
|
||||
// ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
//
|
||||
// With the exception of ReadOrder every field can be found in ASS files. The
|
||||
// ReadOrder field is needed for the decoder to be able to reorder the streamed
|
||||
// samples as they were placed originally in the file.
|
||||
//
|
||||
// If the source is only SSA, the Layer field can be left empty.
|
||||
//
|
||||
// MEDIATYPE_VOBSUB:
|
||||
//
|
||||
// Standard dvd subpic data, without the stream id at the beginning.
|
||||
//
|
||||
|
||||
// Matroska CodecID mappings
|
||||
// ------------------------
|
||||
//
|
||||
// S_TEXT/ASCII <-> MEDIATYPE_Text MEDIASUBTYPE_NULL FORMAT_None
|
||||
// S_TEXT/UTF8 <-> MEDIATYPE_Subtitle MEDIASUBTYPE_UTF8 FORMAT_SubtitleInfo
|
||||
// S_TEXT/SSA <-> MEDIATYPE_Subtitle MEDIASUBTYPE_SSA FORMAT_SubtitleInfo
|
||||
// S_TEXT/ASS <-> MEDIATYPE_Subtitle MEDIASUBTYPE_ASS FORMAT_SubtitleInfo
|
||||
// S_TEXT/USF <-> MEDIATYPE_Subtitle MEDIASUBTYPE_USF FORMAT_SubtitleInfo
|
||||
// S_VOBSUB <-> MEDIATYPE_Subtitle MEDIASUBTYPE_VOBSUB FORMAT_SubtitleInfo
|
||||
// S_VOBSUB/ZLIB<-> MEDIATYPE_Subtitle MEDIASUBTYPE_VOBSUB FORMAT_SubtitleInfo
|
||||
//
|
||||
|
129
vsfilter/include/unrar/UNRAR.H
Normal file
129
vsfilter/include/unrar/UNRAR.H
Normal file
|
@ -0,0 +1,129 @@
|
|||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#define ERAR_END_ARCHIVE 10
|
||||
#define ERAR_NO_MEMORY 11
|
||||
#define ERAR_BAD_DATA 12
|
||||
#define ERAR_BAD_ARCHIVE 13
|
||||
#define ERAR_UNKNOWN_FORMAT 14
|
||||
#define ERAR_EOPEN 15
|
||||
#define ERAR_ECREATE 16
|
||||
#define ERAR_ECLOSE 17
|
||||
#define ERAR_EREAD 18
|
||||
#define ERAR_EWRITE 19
|
||||
#define ERAR_SMALL_BUF 20
|
||||
#define ERAR_UNKNOWN 21
|
||||
|
||||
#define RAR_OM_LIST 0
|
||||
#define RAR_OM_EXTRACT 1
|
||||
|
||||
#define RAR_SKIP 0
|
||||
#define RAR_TEST 1
|
||||
#define RAR_EXTRACT 2
|
||||
|
||||
#define RAR_VOL_ASK 0
|
||||
#define RAR_VOL_NOTIFY 1
|
||||
|
||||
#define RAR_DLL_VERSION 3
|
||||
|
||||
struct RARHeaderData
|
||||
{
|
||||
char ArcName[260];
|
||||
char FileName[260];
|
||||
unsigned int Flags;
|
||||
unsigned int PackSize;
|
||||
unsigned int UnpSize;
|
||||
unsigned int HostOS;
|
||||
unsigned int FileCRC;
|
||||
unsigned int FileTime;
|
||||
unsigned int UnpVer;
|
||||
unsigned int Method;
|
||||
unsigned int FileAttr;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
};
|
||||
|
||||
|
||||
struct RARHeaderDataEx
|
||||
{
|
||||
char ArcName[1024];
|
||||
wchar_t ArcNameW[1024];
|
||||
char FileName[1024];
|
||||
wchar_t FileNameW[1024];
|
||||
unsigned int Flags;
|
||||
unsigned int PackSize;
|
||||
unsigned int PackSizeHigh;
|
||||
unsigned int UnpSize;
|
||||
unsigned int UnpSizeHigh;
|
||||
unsigned int HostOS;
|
||||
unsigned int FileCRC;
|
||||
unsigned int FileTime;
|
||||
unsigned int UnpVer;
|
||||
unsigned int Method;
|
||||
unsigned int FileAttr;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
unsigned int Reserved[1024];
|
||||
};
|
||||
|
||||
|
||||
struct RAROpenArchiveData
|
||||
{
|
||||
char *ArcName;
|
||||
unsigned int OpenMode;
|
||||
unsigned int OpenResult;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
};
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
wchar_t *ArcNameW;
|
||||
unsigned int OpenMode;
|
||||
unsigned int OpenResult;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
unsigned int Flags;
|
||||
unsigned int Reserved[32];
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
|
||||
};
|
||||
|
||||
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2);
|
||||
|
||||
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
|
||||
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef HANDLE (PASCAL * RAROpenArchive)(struct RAROpenArchiveData *ArchiveData);
|
||||
typedef HANDLE (PASCAL * RAROpenArchiveEx)(struct RAROpenArchiveDataEx *ArchiveData);
|
||||
typedef int (PASCAL * RARCloseArchive)(HANDLE hArcData);
|
||||
typedef int (PASCAL * RARReadHeader)(HANDLE hArcData,struct RARHeaderData *HeaderData);
|
||||
typedef int (PASCAL * RARReadHeaderEx)(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
|
||||
typedef int (PASCAL * RARProcessFile)(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
|
||||
typedef void (PASCAL * RARSetCallback)(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData);
|
||||
typedef void (PASCAL * RARSetChangeVolProc)(HANDLE hArcData, CHANGEVOLPROC);
|
||||
typedef void (PASCAL * RARSetProcessDataProc)(HANDLE hArcData, PROCESSDATAPROC);
|
||||
typedef void (PASCAL * RARSetPassword)(HANDLE hArcData,char *Password);
|
||||
typedef int (PASCAL * RARGetDllVersion)();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
566
vsfilter/include/unrar/UNRARDLL.TXT
Normal file
566
vsfilter/include/unrar/UNRARDLL.TXT
Normal file
|
@ -0,0 +1,566 @@
|
|||
|
||||
unRAR.dll Manual
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
UNRAR.DLL is a 32-bit Windows dynamic-link library which provides
|
||||
file extraction from RAR archives.
|
||||
|
||||
|
||||
Exported functions
|
||||
|
||||
====================================================================
|
||||
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData)
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Open RAR archive and allocate memory structures
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
ArchiveData Points to RAROpenArchiveData structure
|
||||
|
||||
struct RAROpenArchiveData
|
||||
{
|
||||
char *ArcName;
|
||||
UINT OpenMode;
|
||||
UINT OpenResult;
|
||||
char *CmtBuf;
|
||||
UINT CmtBufSize;
|
||||
UINT CmtSize;
|
||||
UINT CmtState;
|
||||
};
|
||||
|
||||
Structure fields:
|
||||
|
||||
ArcName
|
||||
Input parameter which should point to zero terminated string
|
||||
containing the archive name.
|
||||
|
||||
OpenMode
|
||||
Input parameter.
|
||||
|
||||
Possible values
|
||||
|
||||
RAR_OM_LIST Open archive for reading file headers only
|
||||
RAR_OM_EXTRACT Open archive for testing and extracting files
|
||||
|
||||
OpenResult
|
||||
Output parameter.
|
||||
|
||||
Possible values
|
||||
|
||||
0 Success
|
||||
ERAR_NO_MEMORY Not enough memory to initialize data structures
|
||||
ERAR_BAD_DATA Archive header broken
|
||||
ERAR_BAD_ARCHIVE File is not valid RAR archive
|
||||
ERAR_EOPEN File open error
|
||||
|
||||
CmtBuf
|
||||
Input parameter which should point to the buffer for archive
|
||||
comments. Maximum comment size is limited to 64Kb. Comment text is
|
||||
zero terminated. If the comment text is larger than the buffer
|
||||
size, the comment text will be truncated. If CmtBuf is set to
|
||||
NULL, comments will not be read.
|
||||
|
||||
CmtBufSize
|
||||
Input parameter which should contain size of buffer for archive
|
||||
comments.
|
||||
|
||||
CmtSize
|
||||
Output parameter containing size of comments actually read into the
|
||||
buffer, cannot exceed CmtBufSize.
|
||||
|
||||
CmtState
|
||||
Output parameter.
|
||||
|
||||
Possible values
|
||||
|
||||
0 comments not present
|
||||
1 Comments read completely
|
||||
ERAR_NO_MEMORY Not enough memory to extract comments
|
||||
ERAR_BAD_DATA Broken comment
|
||||
ERAR_UNKNOWN_FORMAT Unknown comment format
|
||||
ERAR_SMALL_BUF Buffer too small, comments not completely read
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
Archive handle or NULL in case of error
|
||||
|
||||
|
||||
========================================================================
|
||||
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData)
|
||||
========================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Similar to RAROpenArchive, but uses RAROpenArchiveDataEx structure
|
||||
allowing to specify Unicode archive name and returning information
|
||||
about archive flags.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
ArchiveData Points to RAROpenArchiveDataEx structure
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
wchar_t *ArcNameW;
|
||||
unsigned int OpenMode;
|
||||
unsigned int OpenResult;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
unsigned int Flags;
|
||||
unsigned int Reserved[32];
|
||||
};
|
||||
|
||||
Structure fields:
|
||||
|
||||
ArcNameW
|
||||
Input parameter which should point to zero terminated Unicode string
|
||||
containing the archive name or NULL if Unicode name is not specified.
|
||||
|
||||
Flags
|
||||
Output parameter. Combination of bit flags.
|
||||
|
||||
Possible values
|
||||
|
||||
0x0001 - Volume attribute (archive volume)
|
||||
0x0002 - Archive comment present
|
||||
0x0004 - Archive lock attribute
|
||||
0x0008 - Solid attribute (solid archive)
|
||||
0x0010 - New volume naming scheme ('volname.partN.rar')
|
||||
0x0020 - Authenticity information present
|
||||
0x0040 - Recovery record present
|
||||
0x0080 - Block headers are encrypted
|
||||
0x0100 - First volume (set only by RAR 3.0 and later)
|
||||
|
||||
Reserved[32]
|
||||
Reserved for future use. Must be zero.
|
||||
|
||||
Information on other structure fields and function return values
|
||||
is available above, in RAROpenArchive function description.
|
||||
|
||||
|
||||
====================================================================
|
||||
int PASCAL RARCloseArchive(HANDLE hArcData)
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Close RAR archive and release allocated memory. It must be called when
|
||||
archive processing is finished, even if the archive processing was stopped
|
||||
due to an error.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
hArcData
|
||||
This parameter should contain the archive handle obtained from the
|
||||
RAROpenArchive function call.
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
0 Success
|
||||
ERAR_ECLOSE Archive close error
|
||||
|
||||
|
||||
====================================================================
|
||||
int PASCAL RARReadHeader(HANDLE hArcData,
|
||||
struct RARHeaderData *HeaderData)
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Read header of file in archive.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
hArcData
|
||||
This parameter should contain the archive handle obtained from the
|
||||
RAROpenArchive function call.
|
||||
|
||||
HeaderData
|
||||
It should point to RARHeaderData structure:
|
||||
|
||||
struct RARHeaderData
|
||||
{
|
||||
char ArcName[260];
|
||||
char FileName[260];
|
||||
UINT Flags;
|
||||
UINT PackSize;
|
||||
UINT UnpSize;
|
||||
UINT HostOS;
|
||||
UINT FileCRC;
|
||||
UINT FileTime;
|
||||
UINT UnpVer;
|
||||
UINT Method;
|
||||
UINT FileAttr;
|
||||
char *CmtBuf;
|
||||
UINT CmtBufSize;
|
||||
UINT CmtSize;
|
||||
UINT CmtState;
|
||||
};
|
||||
|
||||
Structure fields:
|
||||
|
||||
ArcName
|
||||
Output parameter which contains a zero terminated string of the
|
||||
current archive name. May be used to determine the current volume
|
||||
name.
|
||||
|
||||
FileName
|
||||
Output parameter which contains a zero terminated string of the
|
||||
file name in OEM (DOS) encoding.
|
||||
|
||||
Flags
|
||||
Output parameter which contains file flags:
|
||||
|
||||
0x01 - file continued from previous volume
|
||||
0x02 - file continued on next volume
|
||||
0x04 - file encrypted with password
|
||||
0x08 - file comment present
|
||||
0x10 - compression of previous files is used (solid flag)
|
||||
|
||||
bits 7 6 5
|
||||
|
||||
0 0 0 - dictionary size 64 Kb
|
||||
0 0 1 - dictionary size 128 Kb
|
||||
0 1 0 - dictionary size 256 Kb
|
||||
0 1 1 - dictionary size 512 Kb
|
||||
1 0 0 - dictionary size 1024 Kb
|
||||
1 0 1 - reserved
|
||||
1 1 0 - reserved
|
||||
1 1 1 - file is directory
|
||||
|
||||
Other bits are reserved.
|
||||
|
||||
PackSize
|
||||
Output parameter means packed file size or size of the
|
||||
file part if file was split between volumes.
|
||||
|
||||
UnpSize
|
||||
Output parameter - unpacked file size.
|
||||
|
||||
HostOS
|
||||
Output parameter - operating system used for archiving:
|
||||
|
||||
0 - MS DOS;
|
||||
1 - OS/2.
|
||||
2 - Win32
|
||||
3 - Unix
|
||||
|
||||
FileCRC
|
||||
Output parameter which contains unpacked file CRC. It should not be
|
||||
used for file parts which were split between volumes.
|
||||
|
||||
FileTime
|
||||
Output parameter - contains date and time in standard MS DOS format.
|
||||
|
||||
UnpVer
|
||||
Output parameter - RAR version needed to extract file.
|
||||
It is encoded as 10 * Major version + minor version.
|
||||
|
||||
Method
|
||||
Output parameter - packing method.
|
||||
|
||||
FileAttr
|
||||
Output parameter - file attributes.
|
||||
|
||||
CmtBuf
|
||||
File comments support is not implemented in the new DLL version yet.
|
||||
Now CmtState is always 0.
|
||||
|
||||
/*
|
||||
* Input parameter which should point to the buffer for file
|
||||
* comments. Maximum comment size is limited to 64Kb. Comment text is
|
||||
* a zero terminated string in OEM encoding. If the comment text is
|
||||
* larger than the buffer size, the comment text will be truncated.
|
||||
* If CmtBuf is set to NULL, comments will not be read.
|
||||
*/
|
||||
|
||||
CmtBufSize
|
||||
Input parameter which should contain size of buffer for archive
|
||||
comments.
|
||||
|
||||
CmtSize
|
||||
Output parameter containing size of comments actually read into the
|
||||
buffer, should not exceed CmtBufSize.
|
||||
|
||||
CmtState
|
||||
Output parameter.
|
||||
|
||||
Possible values
|
||||
|
||||
0 Absent comments
|
||||
1 Comments read completely
|
||||
ERAR_NO_MEMORY Not enough memory to extract comments
|
||||
ERAR_BAD_DATA Broken comment
|
||||
ERAR_UNKNOWN_FORMAT Unknown comment format
|
||||
ERAR_SMALL_BUF Buffer too small, comments not completely read
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
0 Success
|
||||
ERAR_END_ARCHIVE End of archive
|
||||
ERAR_BAD_DATA File header broken
|
||||
|
||||
|
||||
====================================================================
|
||||
int PASCAL RARReadHeaderEx(HANDLE hArcData,
|
||||
struct RARHeaderDataEx *HeaderData)
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Similar to RARReadHeader, but uses RARHeaderDataEx structure,
|
||||
containing information about Unicode file names and 64 bit file sizes.
|
||||
|
||||
struct RARHeaderDataEx
|
||||
{
|
||||
char ArcName[1024];
|
||||
wchar_t ArcNameW[1024];
|
||||
char FileName[1024];
|
||||
wchar_t FileNameW[1024];
|
||||
unsigned int Flags;
|
||||
unsigned int PackSize;
|
||||
unsigned int PackSizeHigh;
|
||||
unsigned int UnpSize;
|
||||
unsigned int UnpSizeHigh;
|
||||
unsigned int HostOS;
|
||||
unsigned int FileCRC;
|
||||
unsigned int FileTime;
|
||||
unsigned int UnpVer;
|
||||
unsigned int Method;
|
||||
unsigned int FileAttr;
|
||||
char *CmtBuf;
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
unsigned int Reserved[1024];
|
||||
};
|
||||
|
||||
|
||||
====================================================================
|
||||
int PASCAL RARProcessFile(HANDLE hArcData,
|
||||
int Operation,
|
||||
char *DestPath,
|
||||
char *DestName)
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Performs action and moves the current position in the archive to
|
||||
the next file. Extract or test the current file from the archive
|
||||
opened in RAR_OM_EXTRACT mode. If the mode RAR_OM_LIST is set,
|
||||
then a call to this function will simply skip the archive position
|
||||
to the next file.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
hArcData
|
||||
This parameter should contain the archive handle obtained from the
|
||||
RAROpenArchive function call.
|
||||
|
||||
Operation
|
||||
File operation.
|
||||
|
||||
Possible values
|
||||
|
||||
RAR_SKIP Move to the next file in the archive. If the
|
||||
archive is solid and RAR_OM_EXTRACT mode was set
|
||||
when the archive was opened, the current file will
|
||||
be processed - the operation will be performed
|
||||
slower than a simple seek.
|
||||
|
||||
RAR_TEST Test the current file and move to the next file in
|
||||
the archive. If the archive was opened with
|
||||
RAR_OM_LIST mode, the operation is equal to
|
||||
RAR_SKIP.
|
||||
|
||||
RAR_EXTRACT Extract the current file and move to the next file.
|
||||
If the archive was opened with RAR_OM_LIST mode,
|
||||
the operation is equal to RAR_SKIP.
|
||||
|
||||
|
||||
DestPath
|
||||
This parameter should point to a zero terminated string containing the
|
||||
destination directory to which to extract files to. If DestPath is equal
|
||||
to NULL it means extract to the current directory. This parameter has
|
||||
meaning only if DestName is NULL.
|
||||
|
||||
DestName
|
||||
This parameter should point to a string containing the full path and name
|
||||
of the file to be extracted or NULL as default. If DestName is defined
|
||||
(not NULL) it overrides the original file name saved in the archive and
|
||||
DestPath setting.
|
||||
|
||||
Both DestPath and DestName must be in OEM encoding. If necessary,
|
||||
use CharToOem to convert text to OEM before passing to this function.
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
0 Success
|
||||
ERAR_BAD_DATA File CRC error
|
||||
ERAR_BAD_ARCHIVE Volume is not valid RAR archive
|
||||
ERAR_UNKNOWN_FORMAT Unknown archive format
|
||||
ERAR_EOPEN Volume open error
|
||||
ERAR_ECREATE File create error
|
||||
ERAR_ECLOSE File close error
|
||||
ERAR_EREAD Read error
|
||||
ERAR_EWRITE Write error
|
||||
|
||||
|
||||
====================================================================
|
||||
void PASCAL RARSetCallback(HANDLE hArcData,
|
||||
int PASCAL (*CallbackProc)(UINT msg,LONG UserData,LONG P1,LONG P2),
|
||||
LONG UserData);
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Set a user-defined callback function to process Unrar events.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
hArcData
|
||||
This parameter should contain the archive handle obtained from the
|
||||
RAROpenArchive function call.
|
||||
|
||||
CallbackProc
|
||||
It should point to a user-defined callback function.
|
||||
|
||||
The function will be passed four parameters:
|
||||
|
||||
|
||||
msg Type of event. Described below.
|
||||
|
||||
UserData User defined value passed to RARSetCallback.
|
||||
|
||||
P1 and P2 Event dependent parameters. Described below.
|
||||
|
||||
|
||||
Possible events
|
||||
|
||||
UCM_CHANGEVOLUME Process volume change.
|
||||
|
||||
P1 Points to the zero terminated name
|
||||
of the next volume.
|
||||
|
||||
P2 The function call mode:
|
||||
|
||||
RAR_VOL_ASK Required volume is absent. The function should
|
||||
prompt user and return a non-zero value
|
||||
to retry or return -1 value to terminate
|
||||
operation. The function may also specify a new
|
||||
volume name, placing it to the address specified
|
||||
by P1 parameter.
|
||||
|
||||
RAR_VOL_NOTIFY Required volume is successfully opened.
|
||||
This is a notification call and volume name
|
||||
modification is not allowed. The function should
|
||||
return a non-zero value to continue or -1
|
||||
to terminate operation.
|
||||
|
||||
UCM_PROCESSDATA Process unpacked data. It may be used to read
|
||||
a file while it is being extracted or tested
|
||||
without actual extracting file to disk.
|
||||
Return a non-zero value to continue process
|
||||
or -1 to cancel the archive operation
|
||||
|
||||
P1 Address pointing to the unpacked data.
|
||||
Function may refer to the data but must not
|
||||
change it.
|
||||
|
||||
P2 Size of the unpacked data. It is guaranteed
|
||||
only that the size will not exceed the maximum
|
||||
dictionary size (4 Mb in RAR 3.0).
|
||||
|
||||
UCM_NEEDPASSWORD DLL needs a password to process archive.
|
||||
This message must be processed if you wish
|
||||
to be able to handle archives with encrypted
|
||||
file names. It can be also used as replacement
|
||||
of RARSetPassword function even for usual
|
||||
encrypted files with non-encrypted names.
|
||||
|
||||
P1 Address pointing to the buffer for a password.
|
||||
You need to copy a password here.
|
||||
|
||||
P2 Size of the password buffer.
|
||||
|
||||
|
||||
UserData
|
||||
User data passed to callback function.
|
||||
|
||||
Other functions of UNRAR.DLL should not be called from the callback
|
||||
function.
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
None
|
||||
|
||||
|
||||
|
||||
====================================================================
|
||||
void PASCAL RARSetChangeVolProc(HANDLE hArcData,
|
||||
int PASCAL (*ChangeVolProc)(char *ArcName,int Mode));
|
||||
====================================================================
|
||||
|
||||
Obsoleted, use RARSetCallback instead.
|
||||
|
||||
|
||||
|
||||
====================================================================
|
||||
void PASCAL RARSetProcessDataProc(HANDLE hArcData,
|
||||
int PASCAL (*ProcessDataProc)(unsigned char *Addr,int Size))
|
||||
====================================================================
|
||||
|
||||
Obsoleted, use RARSetCallback instead.
|
||||
|
||||
|
||||
====================================================================
|
||||
void PASCAL RARSetPassword(HANDLE hArcData,
|
||||
char *Password);
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Set a password to decrypt files.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
hArcData
|
||||
This parameter should contain the archive handle obtained from the
|
||||
RAROpenArchive function call.
|
||||
|
||||
Password
|
||||
It should point to a string containing a zero terminated password.
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
None
|
||||
|
||||
|
||||
====================================================================
|
||||
void PASCAL RARGetDllVersion();
|
||||
====================================================================
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
Returns unrar.dll version.
|
||||
|
||||
Parameters
|
||||
~~~~~~~~~~
|
||||
None.
|
||||
|
||||
Return values
|
||||
~~~~~~~~~~~~~
|
||||
Returns an integer value denoting DLL version. It is increased in case
|
||||
of changes in DLL API. The current version value is defined in unrar.h
|
||||
as RAR_DLL_VERSION
|
||||
|
||||
This function is absent in old versions of unrar.dll, so it may be wise
|
||||
to use LoadLibrary and GetProcAddress to access this function.
|
||||
|
167
vsfilter/include/virtualdub/Filter.h
Normal file
167
vsfilter/include/virtualdub/Filter.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
#ifndef f_FILTER_H
|
||||
#define f_FILTER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// This is really dumb, but necessary to support VTbls in C++.
|
||||
|
||||
struct FilterVTbls {
|
||||
void *pvtblVBitmap;
|
||||
};
|
||||
|
||||
#ifdef VDEXT_MAIN
|
||||
struct FilterVTbls g_vtbls;
|
||||
#elif defined(VDEXT_NOTMAIN)
|
||||
extern struct FilterVTbls g_vtbls;
|
||||
#endif
|
||||
|
||||
#define INITIALIZE_VTBLS ff->InitVTables(&g_vtbls)
|
||||
|
||||
#include "VBitmap.h"
|
||||
|
||||
//////////////////
|
||||
|
||||
struct CScriptObject;
|
||||
|
||||
//////////////////
|
||||
|
||||
enum {
|
||||
FILTERPARAM_SWAP_BUFFERS = 0x00000001L,
|
||||
FILTERPARAM_NEEDS_LAST = 0x00000002L,
|
||||
};
|
||||
|
||||
///////////////////
|
||||
|
||||
class VFBitmap;
|
||||
class FilterActivation;
|
||||
struct FilterFunctions;
|
||||
|
||||
typedef int (*FilterInitProc )(FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef void (*FilterDeinitProc )(FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef int (*FilterRunProc )(const FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef long (*FilterParamProc )(FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef int (*FilterConfigProc )(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd);
|
||||
typedef int (*FilterConfig2Proc )(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd);
|
||||
typedef void (*FilterStringProc )(const FilterActivation *fa, const FilterFunctions *ff, char *buf);
|
||||
typedef int (*FilterStartProc )(FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef int (*FilterEndProc )(FilterActivation *fa, const FilterFunctions *ff);
|
||||
typedef bool (*FilterScriptStrProc)(FilterActivation *fa, const FilterFunctions *, char *, int);
|
||||
|
||||
typedef int (__cdecl *FilterModuleInitProc)(struct FilterModule *fm, const FilterFunctions *ff, int& vdfd_ver, int& vdfd_compat);
|
||||
typedef void (__cdecl *FilterModuleDeinitProc)(struct FilterModule *fm, const FilterFunctions *ff);
|
||||
|
||||
//////////
|
||||
|
||||
typedef void (__cdecl *FilterPreviewButtonCallback)(bool fNewState, void *pData);
|
||||
typedef void (__cdecl *FilterPreviewSampleCallback)(VFBitmap *, long lFrame, long lCount, void *pData);
|
||||
|
||||
class IFilterPreview {
|
||||
public:
|
||||
virtual void SetButtonCallback(FilterPreviewButtonCallback, void *)=0;
|
||||
virtual void SetSampleCallback(FilterPreviewSampleCallback, void *)=0;
|
||||
|
||||
virtual bool isPreviewEnabled()=0;
|
||||
virtual void Toggle(HWND)=0;
|
||||
virtual void Display(HWND, bool)=0;
|
||||
virtual void RedoFrame()=0;
|
||||
virtual void RedoSystem()=0;
|
||||
virtual void UndoSystem()=0;
|
||||
virtual void InitButton(HWND)=0;
|
||||
virtual void Close()=0;
|
||||
virtual bool SampleCurrentFrame()=0;
|
||||
virtual long SampleFrames()=0;
|
||||
};
|
||||
|
||||
//////////
|
||||
|
||||
#define VIRTUALDUB_FILTERDEF_VERSION (4)
|
||||
#define VIRTUALDUB_FILTERDEF_COMPATIBLE (4)
|
||||
|
||||
// v3: added lCurrentSourceFrame to FrameStateInfo
|
||||
// v4: lots of additions (VirtualDub 1.2)
|
||||
|
||||
typedef struct FilterModule {
|
||||
struct FilterModule *next, *prev;
|
||||
HINSTANCE hInstModule;
|
||||
FilterModuleInitProc initProc;
|
||||
FilterModuleDeinitProc deinitProc;
|
||||
} FilterModule;
|
||||
|
||||
typedef struct FilterDefinition {
|
||||
|
||||
struct FilterDefinition *next, *prev;
|
||||
FilterModule *module;
|
||||
|
||||
char * name;
|
||||
char * desc;
|
||||
char * maker;
|
||||
void * private_data;
|
||||
int inst_data_size;
|
||||
|
||||
FilterInitProc initProc;
|
||||
FilterDeinitProc deinitProc;
|
||||
FilterRunProc runProc;
|
||||
FilterParamProc paramProc;
|
||||
FilterConfigProc configProc;
|
||||
FilterStringProc stringProc;
|
||||
FilterStartProc startProc;
|
||||
FilterEndProc endProc;
|
||||
|
||||
CScriptObject *script_obj;
|
||||
|
||||
FilterScriptStrProc fssProc;
|
||||
|
||||
} FilterDefinition;
|
||||
|
||||
//////////
|
||||
|
||||
// FilterStateInfo: contains dynamic info about file being processed
|
||||
|
||||
class FilterStateInfo {
|
||||
public:
|
||||
long lCurrentFrame; // current output frame
|
||||
long lMicrosecsPerFrame; // microseconds per output frame
|
||||
long lCurrentSourceFrame; // current source frame
|
||||
long lMicrosecsPerSrcFrame; // microseconds per source frame
|
||||
long lSourceFrameMS; // source frame timestamp
|
||||
long lDestFrameMS; // output frame timestamp
|
||||
};
|
||||
|
||||
// VFBitmap: VBitmap extended to hold filter-specific information
|
||||
|
||||
class VFBitmap : public VBitmap {
|
||||
public:
|
||||
enum {
|
||||
NEEDS_HDC = 0x00000001L,
|
||||
};
|
||||
|
||||
DWORD dwFlags;
|
||||
HDC hdc;
|
||||
};
|
||||
|
||||
// FilterActivation: This is what is actually passed to filters at runtime.
|
||||
|
||||
class FilterActivation {
|
||||
public:
|
||||
FilterDefinition *filter;
|
||||
void *filter_data;
|
||||
VFBitmap &dst, &src;
|
||||
VFBitmap *rsrc, *last;
|
||||
unsigned long x1, y1, x2, y2;
|
||||
|
||||
FilterStateInfo *pfsi;
|
||||
IFilterPreview *ifp;
|
||||
|
||||
FilterActivation(VFBitmap& _dst, VFBitmap& _src) : dst(_dst), src(_src) {}
|
||||
FilterActivation(const FilterActivation& fa, VFBitmap& _dst, VFBitmap& _src);
|
||||
};
|
||||
|
||||
struct FilterFunctions {
|
||||
FilterDefinition *(*addFilter)(FilterModule *, FilterDefinition *, int fd_len);
|
||||
void (*removeFilter)(FilterDefinition *);
|
||||
bool (*isFPUEnabled)();
|
||||
bool (*isMMXEnabled)();
|
||||
void (*InitVTables)(struct FilterVTbls *);
|
||||
};
|
||||
|
||||
#endif
|
55
vsfilter/include/virtualdub/ScriptError.h
Normal file
55
vsfilter/include/virtualdub/ScriptError.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef f_SYLIA_SCRIPTERROR_H
|
||||
#define f_SYLIA_SCRIPTERROR_H
|
||||
|
||||
class CScriptError {
|
||||
public:
|
||||
int err;
|
||||
|
||||
enum {
|
||||
PARSE_ERROR=1,
|
||||
SEMICOLON_EXPECTED,
|
||||
IDENTIFIER_EXPECTED,
|
||||
|
||||
TYPE_INT_REQUIRED,
|
||||
TYPE_ARRAY_REQUIRED,
|
||||
TYPE_FUNCTION_REQUIRED,
|
||||
TYPE_OBJECT_REQUIRED,
|
||||
|
||||
OBJECT_MEMBER_NAME_REQUIRED,
|
||||
FUNCCALLEND_EXPECTED,
|
||||
TOO_MANY_PARAMS,
|
||||
DIVIDE_BY_ZERO,
|
||||
VAR_NOT_FOUND,
|
||||
MEMBER_NOT_FOUND,
|
||||
OVERLOADED_FUNCTION_NOT_FOUND,
|
||||
IDENT_TOO_LONG,
|
||||
OPERATOR_EXPECTED,
|
||||
CLOSEPARENS_EXPECTED,
|
||||
CLOSEBRACKET_EXPECTED,
|
||||
|
||||
VAR_UNDEFINED,
|
||||
|
||||
OUT_OF_STRING_SPACE,
|
||||
OUT_OF_MEMORY,
|
||||
INTERNAL_ERROR,
|
||||
EXTERNAL_ERROR,
|
||||
|
||||
FCALL_OUT_OF_RANGE,
|
||||
FCALL_INVALID_PTYPE,
|
||||
FCALL_UNKNOWN_STR,
|
||||
};
|
||||
|
||||
CScriptError(int err_num) : err(err_num) { }
|
||||
|
||||
int getErr() { return err; }
|
||||
};
|
||||
|
||||
#define SCRIPT_ERROR(x) throw CScriptError(CScriptError::##x)
|
||||
|
||||
extern "C" __declspec(dllexport) char * __stdcall TranslateScriptError(int);
|
||||
|
||||
char inline *TranslateScriptError(CScriptError cse) {
|
||||
return TranslateScriptError(cse.getErr());
|
||||
}
|
||||
|
||||
#endif
|
32
vsfilter/include/virtualdub/ScriptInterpreter.h
Normal file
32
vsfilter/include/virtualdub/ScriptInterpreter.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef f_SYLIA_SCRIPTINTERPRETER_H
|
||||
#define f_SYLIA_SCRIPTINTERPRETER_H
|
||||
|
||||
class CScriptValue;
|
||||
class CScriptError;
|
||||
struct CScriptObject;
|
||||
class IScriptInterpreter;
|
||||
|
||||
typedef CScriptValue (*ScriptRootHandlerPtr)(IScriptInterpreter *,char *,void *);
|
||||
|
||||
class IScriptInterpreter {
|
||||
public:
|
||||
virtual void Destroy() =0;
|
||||
|
||||
virtual void SetRootHandler(ScriptRootHandlerPtr, void *) =0;
|
||||
|
||||
virtual void ExecuteLine(char *s) =0;
|
||||
|
||||
virtual void ScriptError(int e) =0;
|
||||
virtual char* TranslateScriptError(CScriptError& cse) =0;
|
||||
virtual char** AllocTempString(long l) =0;
|
||||
|
||||
virtual CScriptValue LookupObjectMember(CScriptObject *obj, void *, char *szIdent) = 0;
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) IScriptInterpreter * __stdcall CreateScriptInterpreter();
|
||||
|
||||
#define GETPROC_CREATESCRIPTINTERPRETER(hInst) ((IScriptInterpreter *(__stdcall *)())GetProcAddress(hInst, "_CreateScriptInterpreter@0"))
|
||||
|
||||
#define EXT_SCRIPT_ERROR(x) (isi->ScriptError((CScriptError::x)))
|
||||
|
||||
#endif
|
88
vsfilter/include/virtualdub/ScriptValue.h
Normal file
88
vsfilter/include/virtualdub/ScriptValue.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
#ifndef f_SYLIA_SCRIPTVALUE_H
|
||||
#define f_SYLIA_SCRIPTVALUE_H
|
||||
|
||||
class CScriptArray;
|
||||
struct CScriptObject;
|
||||
class CScriptValue;
|
||||
class IScriptInterpreter;
|
||||
class VariableTableEntry;
|
||||
|
||||
typedef CScriptValue (*ScriptObjectLookupFuncPtr)(IScriptInterpreter *, CScriptObject *, void *lpVoid, char *szName);
|
||||
typedef CScriptValue (*ScriptFunctionPtr)(IScriptInterpreter *, void *, CScriptValue *, int);
|
||||
typedef void (*ScriptVoidFunctionPtr)(IScriptInterpreter *, void *, CScriptValue *, int);
|
||||
typedef int (*ScriptIntFunctionPtr)(IScriptInterpreter *, void *, CScriptValue *, int);
|
||||
typedef CScriptValue (*ScriptArrayFunctionPtr)(IScriptInterpreter *, void *, int);
|
||||
|
||||
typedef struct ScriptFunctionDef {
|
||||
ScriptFunctionPtr func_ptr;
|
||||
char *name;
|
||||
char *arg_list;
|
||||
} ScriptFunctionDef;
|
||||
|
||||
typedef struct ScriptObjectDef {
|
||||
char *name;
|
||||
CScriptObject *obj;
|
||||
} ScriptObjectDef;
|
||||
|
||||
typedef struct CScriptObject {
|
||||
ScriptObjectLookupFuncPtr Lookup;
|
||||
ScriptFunctionDef *func_list;
|
||||
ScriptObjectDef *obj_list;
|
||||
} CScriptObject;
|
||||
|
||||
class CScriptValue {
|
||||
public:
|
||||
enum { T_VOID, T_INT, T_PINT, T_STR, T_ARRAY, T_OBJECT, T_FNAME, T_FUNCTION, T_VARLV } type;
|
||||
CScriptObject *thisPtr;
|
||||
union {
|
||||
int i;
|
||||
int *pi;
|
||||
char **s;
|
||||
ScriptArrayFunctionPtr ary;
|
||||
CScriptObject *obj;
|
||||
ScriptFunctionPtr func;
|
||||
ScriptFunctionDef *fname;
|
||||
VariableTableEntry *vte;
|
||||
} u;
|
||||
void *lpVoid;
|
||||
|
||||
CScriptValue() { type = T_VOID; }
|
||||
CScriptValue(int i) { type = T_INT; u.i = i; }
|
||||
CScriptValue(int *pi) { type = T_PINT; u.pi = pi; }
|
||||
CScriptValue(char **s) { type = T_STR; u.s = s; }
|
||||
CScriptValue(CScriptObject *obj) { type = T_OBJECT; u.obj = obj; }
|
||||
CScriptValue(CScriptObject *_thisPtr, ScriptArrayFunctionPtr csa) {
|
||||
type = T_ARRAY;
|
||||
u.ary = csa;
|
||||
thisPtr = _thisPtr;
|
||||
}
|
||||
CScriptValue(CScriptObject *_thisPtr, ScriptFunctionDef *sfd) {
|
||||
type = T_FNAME;
|
||||
u.fname = sfd;
|
||||
thisPtr = _thisPtr;
|
||||
}
|
||||
CScriptValue(CScriptObject *_thisPtr, ScriptFunctionPtr fn) {
|
||||
type = T_FUNCTION;
|
||||
u.func = fn;
|
||||
thisPtr = _thisPtr;
|
||||
}
|
||||
CScriptValue(VariableTableEntry *vte) { type = T_VARLV; u.vte = vte; }
|
||||
|
||||
bool isVoid() { return type == T_VOID; }
|
||||
bool isInt() { return type == T_INT; }
|
||||
bool isString() { return type == T_STR; }
|
||||
bool isArray() { return type == T_ARRAY; }
|
||||
bool isObject() { return type == T_OBJECT; }
|
||||
bool isFName() { return type == T_FNAME; }
|
||||
bool isFunction() { return type == T_FUNCTION; }
|
||||
bool isVarLV() { return type == T_VARLV; }
|
||||
|
||||
int asInt() { return u.i; }
|
||||
char ** asString() { return u.s; }
|
||||
ScriptArrayFunctionPtr asArray() { return u.ary; }
|
||||
CScriptObject * asObject() { return u.obj; }
|
||||
ScriptFunctionPtr asFunction() { return u.func; }
|
||||
VariableTableEntry* asVarLV() { return u.vte; }
|
||||
};
|
||||
|
||||
#endif
|
113
vsfilter/include/virtualdub/VBitmap.h
Normal file
113
vsfilter/include/virtualdub/VBitmap.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
#ifndef f_VIRTUALDUB_VBITMAP_H
|
||||
#define f_VIRTUALDUB_VBITMAP_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef unsigned long Pixel;
|
||||
typedef unsigned long Pixel32;
|
||||
typedef unsigned char Pixel8;
|
||||
typedef long PixCoord;
|
||||
typedef long PixDim;
|
||||
typedef long PixOffset;
|
||||
|
||||
#ifdef VDEXT_VIDEO_FILTER
|
||||
#define NOVTABLE __declspec(novtable)
|
||||
#else
|
||||
#define NOVTABLE
|
||||
#endif
|
||||
|
||||
class NOVTABLE VBitmap {
|
||||
public:
|
||||
Pixel * data;
|
||||
Pixel * palette;
|
||||
int depth;
|
||||
PixCoord w, h;
|
||||
PixOffset pitch;
|
||||
PixOffset modulo;
|
||||
PixOffset size;
|
||||
PixOffset offset;
|
||||
|
||||
Pixel *Address(PixCoord x, PixCoord y) const {
|
||||
return Addressi(x, h-y-1);
|
||||
}
|
||||
|
||||
Pixel *Addressi(PixCoord x, PixCoord y) const {
|
||||
return (Pixel *)((char *)data + y*pitch + x*(depth>>3));
|
||||
}
|
||||
|
||||
Pixel *Address32(PixCoord x, PixCoord y) const {
|
||||
return Address32i(x, h-y-1);
|
||||
}
|
||||
|
||||
Pixel *Address32i(PixCoord x, PixCoord y) const {
|
||||
return (Pixel *)((char *)data + y*pitch + x*sizeof(Pixel));
|
||||
}
|
||||
|
||||
PixOffset PitchAlign4() {
|
||||
return ((w * depth + 31)/32)*4;
|
||||
}
|
||||
|
||||
PixOffset PitchAlign8() {
|
||||
return ((w * depth + 63)/64)*8;
|
||||
}
|
||||
|
||||
PixOffset Modulo() {
|
||||
return pitch - (w*depth+7)/8;
|
||||
}
|
||||
|
||||
PixOffset Size() {
|
||||
return pitch*h;
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
VBitmap() throw() {
|
||||
#ifdef VDEXT_VIDEO_FILTER
|
||||
init();
|
||||
#endif
|
||||
}
|
||||
VBitmap(void *data, PixDim w, PixDim h, int depth) throw();
|
||||
VBitmap(void *data, BITMAPINFOHEADER *) throw();
|
||||
|
||||
#ifdef VDEXT_VIDEO_FILTER
|
||||
void init() throw() { *(void **)this = g_vtbls.pvtblVBitmap; }
|
||||
#endif
|
||||
|
||||
virtual VBitmap& init(void *data, PixDim w, PixDim h, int depth) throw();
|
||||
virtual VBitmap& init(void *data, BITMAPINFOHEADER *) throw();
|
||||
|
||||
virtual void MakeBitmapHeader(BITMAPINFOHEADER *bih) const throw();
|
||||
|
||||
virtual void AlignTo4() throw();
|
||||
virtual void AlignTo8() throw();
|
||||
|
||||
virtual void BitBlt(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1, PixCoord y1, PixDim dx, PixDim dy) const throw();
|
||||
virtual void BitBltDither(PixCoord x2, PixCoord y2, const VBitmap *src, PixDim x1, PixDim y1, PixDim dx, PixDim dy, bool to565) const throw();
|
||||
virtual void BitBlt565(PixCoord x2, PixCoord y2, const VBitmap *src, PixDim x1, PixDim y1, PixDim dx, PixDim dy) const throw();
|
||||
|
||||
virtual bool BitBltXlat1(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, const Pixel8 *tbl) const throw();
|
||||
virtual bool BitBltXlat3(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, const Pixel32 *tbl) const throw();
|
||||
|
||||
virtual bool StretchBltNearestFast(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, const VBitmap *src, double x2, double y2, double dx1, double dy1) const throw();
|
||||
|
||||
virtual bool StretchBltBilinearFast(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, const VBitmap *src, double x2, double y2, double dx1, double dy1) const throw();
|
||||
|
||||
virtual bool RectFill(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, Pixel32 c) const throw();
|
||||
|
||||
enum {
|
||||
HISTO_LUMA,
|
||||
HISTO_GRAY,
|
||||
HISTO_RED,
|
||||
HISTO_GREEN,
|
||||
HISTO_BLUE,
|
||||
};
|
||||
|
||||
virtual bool Histogram(PixCoord x, PixCoord y, PixCoord dx, PixCoord dy, long *pHisto, int iHistoType) const throw();
|
||||
|
||||
private:
|
||||
bool dualrectclip(PixCoord& x2, PixCoord& y2, const VBitmap *src, PixCoord& x1, PixCoord& y1, PixDim& dx, PixDim& dy) const throw();
|
||||
};
|
||||
|
||||
#undef NOVTABLE
|
||||
|
||||
#endif
|
7
vsfilter/include/virtualdub/VirtualDub.h
Normal file
7
vsfilter/include/virtualdub/VirtualDub.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Filter.h"
|
||||
#include "ScriptInterpreter.h"
|
||||
#include "ScriptError.h"
|
||||
#include "ScriptValue.h"
|
||||
#include "VBitmap.h"
|
145
vsfilter/include/winddk/devioctl.h
Normal file
145
vsfilter/include/winddk/devioctl.h
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*++ BUILD Version: 0004 // Increment this if a change has global effects
|
||||
|
||||
Copyright (c) 1992-1999 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
devioctl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains
|
||||
|
||||
Author:
|
||||
|
||||
Andre Vachon (andreva) 21-Feb-1992
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
#ifndef _DEVIOCTL_
|
||||
#define _DEVIOCTL_
|
||||
|
||||
// begin_ntddk begin_wdm begin_nthal begin_ntifs
|
||||
//
|
||||
// Define the various device type values. Note that values used by Microsoft
|
||||
// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
|
||||
// by customers.
|
||||
//
|
||||
|
||||
#define DEVICE_TYPE ULONG
|
||||
|
||||
#define FILE_DEVICE_BEEP 0x00000001
|
||||
#define FILE_DEVICE_CD_ROM 0x00000002
|
||||
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
|
||||
#define FILE_DEVICE_CONTROLLER 0x00000004
|
||||
#define FILE_DEVICE_DATALINK 0x00000005
|
||||
#define FILE_DEVICE_DFS 0x00000006
|
||||
#define FILE_DEVICE_DISK 0x00000007
|
||||
#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
|
||||
#define FILE_DEVICE_FILE_SYSTEM 0x00000009
|
||||
#define FILE_DEVICE_INPORT_PORT 0x0000000a
|
||||
#define FILE_DEVICE_KEYBOARD 0x0000000b
|
||||
#define FILE_DEVICE_MAILSLOT 0x0000000c
|
||||
#define FILE_DEVICE_MIDI_IN 0x0000000d
|
||||
#define FILE_DEVICE_MIDI_OUT 0x0000000e
|
||||
#define FILE_DEVICE_MOUSE 0x0000000f
|
||||
#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
|
||||
#define FILE_DEVICE_NAMED_PIPE 0x00000011
|
||||
#define FILE_DEVICE_NETWORK 0x00000012
|
||||
#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
|
||||
#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
|
||||
#define FILE_DEVICE_NULL 0x00000015
|
||||
#define FILE_DEVICE_PARALLEL_PORT 0x00000016
|
||||
#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
|
||||
#define FILE_DEVICE_PRINTER 0x00000018
|
||||
#define FILE_DEVICE_SCANNER 0x00000019
|
||||
#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
|
||||
#define FILE_DEVICE_SERIAL_PORT 0x0000001b
|
||||
#define FILE_DEVICE_SCREEN 0x0000001c
|
||||
#define FILE_DEVICE_SOUND 0x0000001d
|
||||
#define FILE_DEVICE_STREAMS 0x0000001e
|
||||
#define FILE_DEVICE_TAPE 0x0000001f
|
||||
#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
|
||||
#define FILE_DEVICE_TRANSPORT 0x00000021
|
||||
#define FILE_DEVICE_UNKNOWN 0x00000022
|
||||
#define FILE_DEVICE_VIDEO 0x00000023
|
||||
#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
|
||||
#define FILE_DEVICE_WAVE_IN 0x00000025
|
||||
#define FILE_DEVICE_WAVE_OUT 0x00000026
|
||||
#define FILE_DEVICE_8042_PORT 0x00000027
|
||||
#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
|
||||
#define FILE_DEVICE_BATTERY 0x00000029
|
||||
#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
|
||||
#define FILE_DEVICE_MODEM 0x0000002b
|
||||
#define FILE_DEVICE_VDM 0x0000002c
|
||||
#define FILE_DEVICE_MASS_STORAGE 0x0000002d
|
||||
#define FILE_DEVICE_SMB 0x0000002e
|
||||
#define FILE_DEVICE_KS 0x0000002f
|
||||
#define FILE_DEVICE_CHANGER 0x00000030
|
||||
#define FILE_DEVICE_SMARTCARD 0x00000031
|
||||
#define FILE_DEVICE_ACPI 0x00000032
|
||||
#define FILE_DEVICE_DVD 0x00000033
|
||||
#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
|
||||
#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
|
||||
#define FILE_DEVICE_DFS_VOLUME 0x00000036
|
||||
#define FILE_DEVICE_SERENUM 0x00000037
|
||||
#define FILE_DEVICE_TERMSRV 0x00000038
|
||||
#define FILE_DEVICE_KSEC 0x00000039
|
||||
#define FILE_DEVICE_FIPS 0x0000003A
|
||||
|
||||
//
|
||||
// Macro definition for defining IOCTL and FSCTL function control codes. Note
|
||||
// that function codes 0-2047 are reserved for Microsoft Corporation, and
|
||||
// 2048-4095 are reserved for customers.
|
||||
//
|
||||
|
||||
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
|
||||
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
|
||||
)
|
||||
|
||||
//
|
||||
// Macro to extract device type out of the device io control code
|
||||
//
|
||||
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
|
||||
|
||||
//
|
||||
// Define the method codes for how buffers are passed for I/O and FS controls
|
||||
//
|
||||
|
||||
#define METHOD_BUFFERED 0
|
||||
#define METHOD_IN_DIRECT 1
|
||||
#define METHOD_OUT_DIRECT 2
|
||||
#define METHOD_NEITHER 3
|
||||
|
||||
//
|
||||
// Define the access check value for any access
|
||||
//
|
||||
//
|
||||
// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
|
||||
// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
|
||||
// constants *MUST* always be in sync.
|
||||
//
|
||||
//
|
||||
// FILE_SPECIAL_ACCESS is checked by the NT I/O system the same as FILE_ANY_ACCESS.
|
||||
// The file systems, however, may add additional access checks for I/O and FS controls
|
||||
// that use this value.
|
||||
//
|
||||
|
||||
|
||||
#define FILE_ANY_ACCESS 0
|
||||
#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)
|
||||
#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
|
||||
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
|
||||
|
||||
// end_ntddk end_wdm end_nthal end_ntifs
|
||||
|
||||
#endif // _DEVIOCTL_
|
||||
|
||||
// end_winioctl
|
||||
|
548
vsfilter/include/winddk/ntddcdrm.h
Normal file
548
vsfilter/include/winddk/ntddcdrm.h
Normal file
|
@ -0,0 +1,548 @@
|
|||
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
ntddcdrm.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains structures and definitions
|
||||
associated with CDROM IOCTls.
|
||||
|
||||
Author:
|
||||
|
||||
Mike Glass
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
#ifndef _NTDDCDRM_
|
||||
#define _NTDDCDRM_
|
||||
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(push)
|
||||
#endif
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// remove some level 4 warnings for this header file:
|
||||
#pragma warning(disable:4200) // array[0]
|
||||
#pragma warning(disable:4201) // nameless struct/unions
|
||||
#pragma warning(disable:4214) // bit fields other than int
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// NtDeviceIoControlFile IoControlCode values for this device.
|
||||
//
|
||||
// Warning: Remember that the low two bits of the code specify how the
|
||||
// buffers are passed to the driver!
|
||||
//
|
||||
|
||||
#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
||||
|
||||
#define IOCTL_CDROM_UNLOAD_DRIVER CTL_CODE(IOCTL_CDROM_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
//
|
||||
// CDROM Audio Device Control Functions
|
||||
//
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_STOP_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_PAUSE_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_RESUME_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_GET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_PLAY_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_SET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_GET_CONTROL CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_DISK_TYPE CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0014, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_GET_CONFIGURATION CTL_CODE(IOCTL_CDROM_BASE, 0x0016, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
// end_winioctl
|
||||
|
||||
//
|
||||
// The following device control codes are common for all class drivers. The
|
||||
// functions codes defined here must match all of the other class drivers.
|
||||
//
|
||||
// Warning: these codes will be replaced in the future with the IOCTL_STORAGE
|
||||
// codes included below
|
||||
//
|
||||
|
||||
#define IOCTL_CDROM_CHECK_VERIFY CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_EJECT_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_LOAD_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_RESERVE CTL_CODE(IOCTL_CDROM_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_RELEASE CTL_CODE(IOCTL_CDROM_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_CDROM_FIND_NEW_DEVICES CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
//
|
||||
// The following file contains the IOCTL_STORAGE class ioctl definitions
|
||||
//
|
||||
|
||||
#include "ntddstor.h"
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
//
|
||||
// The following device control code is for the SIMBAD simulated bad
|
||||
// sector facility. See SIMBAD.H in this directory for related structures.
|
||||
//
|
||||
|
||||
#define IOCTL_CDROM_SIMBAD CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
//
|
||||
// Maximum CD Rom size
|
||||
//
|
||||
|
||||
#define MAXIMUM_NUMBER_TRACKS 100
|
||||
#define MAXIMUM_CDROM_SIZE 804
|
||||
#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 // two bytes min transferred
|
||||
|
||||
//
|
||||
// READ_TOC_EX structure
|
||||
//
|
||||
typedef struct _CDROM_READ_TOC_EX {
|
||||
UCHAR Format : 4;
|
||||
UCHAR Reserved1 : 3; // future expansion
|
||||
UCHAR Msf : 1;
|
||||
UCHAR SessionTrack;
|
||||
UCHAR Reserved2; // future expansion
|
||||
UCHAR Reserved3; // future expansion
|
||||
} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX;
|
||||
|
||||
#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00
|
||||
#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01
|
||||
#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02
|
||||
#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03
|
||||
#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04
|
||||
#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents (TOC)
|
||||
// Format 0 - Get table of contents
|
||||
//
|
||||
|
||||
typedef struct _TRACK_DATA {
|
||||
UCHAR Reserved;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Address[4];
|
||||
} TRACK_DATA, *PTRACK_DATA;
|
||||
|
||||
typedef struct _CDROM_TOC {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR FirstTrack;
|
||||
UCHAR LastTrack;
|
||||
|
||||
//
|
||||
// Track data
|
||||
//
|
||||
|
||||
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
|
||||
} CDROM_TOC, *PCDROM_TOC;
|
||||
|
||||
#define CDROM_TOC_SIZE sizeof(CDROM_TOC)
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents
|
||||
// Format 1 - Session Information
|
||||
//
|
||||
|
||||
typedef struct _CDROM_TOC_SESSION_DATA {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR FirstCompleteSession;
|
||||
UCHAR LastCompleteSession;
|
||||
|
||||
//
|
||||
// One track, representing the first track
|
||||
// of the last finished session
|
||||
//
|
||||
|
||||
TRACK_DATA TrackData[1];
|
||||
|
||||
} CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA;
|
||||
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents
|
||||
// Format 2 - Full TOC
|
||||
//
|
||||
|
||||
typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK {
|
||||
UCHAR SessionNumber;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Point;
|
||||
UCHAR MsfExtra[3];
|
||||
UCHAR Zero;
|
||||
UCHAR Msf[3];
|
||||
} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK;
|
||||
|
||||
typedef struct _CDROM_TOC_FULL_TOC_DATA {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR FirstCompleteSession;
|
||||
UCHAR LastCompleteSession;
|
||||
|
||||
//
|
||||
// one to N descriptors included
|
||||
//
|
||||
|
||||
CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0];
|
||||
|
||||
} CDROM_TOC_FULL_TOC_DATA, *PCDROM_TOC_FULL_TOC_DATA;
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents
|
||||
// Format 3 - Program Memory Area
|
||||
//
|
||||
typedef struct _CDROM_TOC_PMA_DATA {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
|
||||
//
|
||||
// one to N descriptors included
|
||||
//
|
||||
|
||||
CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0];
|
||||
|
||||
} CDROM_TOC_PMA_DATA, *PCDROM_TOC_PMA_DATA;
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents
|
||||
// Format 4 - Absolute Time In Pregroove
|
||||
//
|
||||
|
||||
typedef struct _CDROM_TOC_ATIP_DATA_BLOCK {
|
||||
|
||||
UCHAR CdrwReferenceSpeed : 3;
|
||||
UCHAR Reserved3 : 1;
|
||||
UCHAR WritePower : 3;
|
||||
UCHAR True1 : 1;
|
||||
UCHAR Reserved4 : 6;
|
||||
UCHAR UnrestrictedUse : 1;
|
||||
UCHAR Reserved5 : 1;
|
||||
UCHAR A3Valid : 1;
|
||||
UCHAR A2Valid : 1;
|
||||
UCHAR A1Valid : 1;
|
||||
UCHAR DiscSubType : 3;
|
||||
UCHAR IsCdrw : 1;
|
||||
UCHAR True2 : 1;
|
||||
UCHAR Reserved7;
|
||||
|
||||
UCHAR LeadInMsf[3];
|
||||
UCHAR Reserved8;
|
||||
|
||||
UCHAR LeadOutMsf[3];
|
||||
UCHAR Reserved9;
|
||||
|
||||
UCHAR A1Values[3];
|
||||
UCHAR Reserved10;
|
||||
|
||||
UCHAR A2Values[3];
|
||||
UCHAR Reserved11;
|
||||
|
||||
UCHAR A3Values[3];
|
||||
UCHAR Reserved12;
|
||||
|
||||
} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK;
|
||||
|
||||
typedef struct _CDROM_TOC_ATIP_DATA {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
|
||||
//
|
||||
// zero? to N descriptors included.
|
||||
//
|
||||
|
||||
CDROM_TOC_ATIP_DATA_BLOCK Descriptors[0];
|
||||
|
||||
} CDROM_TOC_ATIP_DATA, *PCDROM_TOC_ATIP_DATA;
|
||||
|
||||
//
|
||||
// CD ROM Table OF Contents
|
||||
// Format 5 - CD Text Info
|
||||
//
|
||||
typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK {
|
||||
UCHAR PackType;
|
||||
UCHAR TrackNumber : 7;
|
||||
UCHAR ExtensionFlag : 1; // should be zero!
|
||||
UCHAR SequenceNumber;
|
||||
UCHAR CharacterPosition : 4;
|
||||
UCHAR BlockNumber : 3;
|
||||
UCHAR Unicode : 1;
|
||||
union {
|
||||
UCHAR Text[12];
|
||||
WCHAR WText[6];
|
||||
};
|
||||
UCHAR CRC[2];
|
||||
} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK;
|
||||
|
||||
typedef struct _CDROM_TOC_CD_TEXT_DATA {
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
|
||||
UCHAR Length[2]; // add two bytes for this field
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
|
||||
//
|
||||
// the text info comes in discrete blocks of
|
||||
// a heavily-overloaded structure
|
||||
//
|
||||
|
||||
CDROM_TOC_CD_TEXT_DATA_BLOCK Descriptors[0];
|
||||
|
||||
} CDROM_TOC_CD_TEXT_DATA, *PCDROM_TOC_CD_TEXT_DATA;
|
||||
|
||||
//
|
||||
// These are the types used for PackType field in CDROM_TOC_CD_TEXT_DATA_BLOCK
|
||||
// and also for requesting specific info from IOCTL_CDROM_READ_CD_TEXT
|
||||
//
|
||||
#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80
|
||||
#define CDROM_CD_TEXT_PACK_PERFORMER 0x81
|
||||
#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82
|
||||
#define CDROM_CD_TEXT_PACK_COMPOSER 0x83
|
||||
#define CDROM_CD_TEXT_PACK_ARRANGER 0x84
|
||||
#define CDROM_CD_TEXT_PACK_MESSAGES 0x85
|
||||
#define CDROM_CD_TEXT_PACK_DISC_ID 0x86
|
||||
#define CDROM_CD_TEXT_PACK_GENRE 0x87
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89
|
||||
// 0x8a - 0x8d are reserved....
|
||||
#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e
|
||||
#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f
|
||||
|
||||
//
|
||||
// Play audio starting at MSF and ending at MSF
|
||||
//
|
||||
|
||||
typedef struct _CDROM_PLAY_AUDIO_MSF {
|
||||
UCHAR StartingM;
|
||||
UCHAR StartingS;
|
||||
UCHAR StartingF;
|
||||
UCHAR EndingM;
|
||||
UCHAR EndingS;
|
||||
UCHAR EndingF;
|
||||
} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF;
|
||||
|
||||
//
|
||||
// Seek to MSF
|
||||
//
|
||||
|
||||
typedef struct _CDROM_SEEK_AUDIO_MSF {
|
||||
UCHAR M;
|
||||
UCHAR S;
|
||||
UCHAR F;
|
||||
} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF;
|
||||
|
||||
|
||||
//
|
||||
// Flags for the disk type
|
||||
//
|
||||
|
||||
typedef struct _CDROM_DISK_DATA {
|
||||
|
||||
ULONG DiskData;
|
||||
|
||||
} CDROM_DISK_DATA, *PCDROM_DISK_DATA;
|
||||
|
||||
#define CDROM_DISK_AUDIO_TRACK (0x00000001)
|
||||
#define CDROM_DISK_DATA_TRACK (0x00000002)
|
||||
|
||||
//
|
||||
// CD ROM Data Mode Codes, used with IOCTL_CDROM_READ_Q_CHANNEL
|
||||
//
|
||||
|
||||
#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00
|
||||
#define IOCTL_CDROM_CURRENT_POSITION 0x01
|
||||
#define IOCTL_CDROM_MEDIA_CATALOG 0x02
|
||||
#define IOCTL_CDROM_TRACK_ISRC 0x03
|
||||
|
||||
typedef struct _CDROM_SUB_Q_DATA_FORMAT {
|
||||
UCHAR Format;
|
||||
UCHAR Track;
|
||||
} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT;
|
||||
|
||||
|
||||
//
|
||||
// CD ROM Sub-Q Channel Data Format
|
||||
//
|
||||
|
||||
typedef struct _SUB_Q_HEADER {
|
||||
UCHAR Reserved;
|
||||
UCHAR AudioStatus;
|
||||
UCHAR DataLength[2];
|
||||
} SUB_Q_HEADER, *PSUB_Q_HEADER;
|
||||
|
||||
typedef struct _SUB_Q_CURRENT_POSITION {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Control : 4;
|
||||
UCHAR ADR : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR IndexNumber;
|
||||
UCHAR AbsoluteAddress[4];
|
||||
UCHAR TrackRelativeAddress[4];
|
||||
} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION;
|
||||
|
||||
typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved[3];
|
||||
UCHAR Reserved1 : 7;
|
||||
UCHAR Mcval : 1;
|
||||
UCHAR MediaCatalog[15];
|
||||
} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER;
|
||||
|
||||
typedef struct _SUB_Q_TRACK_ISRC {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved0;
|
||||
UCHAR Track;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2 : 7;
|
||||
UCHAR Tcval : 1;
|
||||
UCHAR TrackIsrc[15];
|
||||
} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC;
|
||||
|
||||
typedef union _SUB_Q_CHANNEL_DATA {
|
||||
SUB_Q_CURRENT_POSITION CurrentPosition;
|
||||
SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog;
|
||||
SUB_Q_TRACK_ISRC TrackIsrc;
|
||||
} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA;
|
||||
|
||||
//
|
||||
// Audio Status Codes
|
||||
//
|
||||
|
||||
#define AUDIO_STATUS_NOT_SUPPORTED 0x00
|
||||
#define AUDIO_STATUS_IN_PROGRESS 0x11
|
||||
#define AUDIO_STATUS_PAUSED 0x12
|
||||
#define AUDIO_STATUS_PLAY_COMPLETE 0x13
|
||||
#define AUDIO_STATUS_PLAY_ERROR 0x14
|
||||
#define AUDIO_STATUS_NO_STATUS 0x15
|
||||
|
||||
//
|
||||
// ADR Sub-channel Q Field
|
||||
//
|
||||
|
||||
#define ADR_NO_MODE_INFORMATION 0x0
|
||||
#define ADR_ENCODES_CURRENT_POSITION 0x1
|
||||
#define ADR_ENCODES_MEDIA_CATALOG 0x2
|
||||
#define ADR_ENCODES_ISRC 0x3
|
||||
|
||||
//
|
||||
// Sub-channel Q Control Bits
|
||||
//
|
||||
|
||||
#define AUDIO_WITH_PREEMPHASIS 0x1
|
||||
#define DIGITAL_COPY_PERMITTED 0x2
|
||||
#define AUDIO_DATA_TRACK 0x4
|
||||
#define TWO_FOUR_CHANNEL_AUDIO 0x8
|
||||
|
||||
//
|
||||
// Get Audio control parameters
|
||||
//
|
||||
|
||||
typedef struct _CDROM_AUDIO_CONTROL {
|
||||
UCHAR LbaFormat;
|
||||
USHORT LogicalBlocksPerSecond;
|
||||
} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL;
|
||||
|
||||
//
|
||||
// Volume control - Volume takes a value between 1 and 0xFF.
|
||||
// SCSI-II CDROM audio suppports up to 4 audio ports with
|
||||
// Independent volume control.
|
||||
//
|
||||
|
||||
typedef struct _VOLUME_CONTROL {
|
||||
UCHAR PortVolume[4];
|
||||
} VOLUME_CONTROL, *PVOLUME_CONTROL;
|
||||
|
||||
typedef enum _TRACK_MODE_TYPE {
|
||||
YellowMode2,
|
||||
XAForm2,
|
||||
CDDA
|
||||
} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
|
||||
|
||||
//
|
||||
// Passed to cdrom to describe the raw read, ie. Mode 2, Form 2, CDDA...
|
||||
//
|
||||
|
||||
typedef struct __RAW_READ_INFO {
|
||||
LARGE_INTEGER DiskOffset;
|
||||
ULONG SectorCount;
|
||||
TRACK_MODE_TYPE TrackMode;
|
||||
} RAW_READ_INFO, *PRAW_READ_INFO;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(pop) // un-sets any local warning changes
|
||||
#else
|
||||
#pragma warning(default:4200) // array[0] is not a warning for this file
|
||||
#pragma warning(default:4201) // nameless struct/unions
|
||||
#pragma warning(default:4214) // bit fields other than int
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _NTDDCDRM_
|
||||
|
||||
// end_winioctl
|
||||
|
||||
|
294
vsfilter/include/winddk/ntddcdvd.h
Normal file
294
vsfilter/include/winddk/ntddcdvd.h
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
ntddcdvd.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains structures and definitions
|
||||
associated with DVD ioctls.
|
||||
|
||||
This module is used in conjunction with ntddcdrm.h which contains the
|
||||
cdrom specific ioctls which will work on CDVD drives
|
||||
|
||||
Author:
|
||||
|
||||
Peter Wieland
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
#ifndef _NTDDCDVD_
|
||||
#define _NTDDCDVD_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
|
||||
//
|
||||
// NtDeviceIoControlFile IoControlCode values for this device.
|
||||
//
|
||||
// Warning: Remember that the low two bits of the code specify how the
|
||||
// buffers are passed to the driver!
|
||||
//
|
||||
|
||||
#define IOCTL_DVD_BASE FILE_DEVICE_DVD
|
||||
|
||||
//
|
||||
// CDVD Device Control Functions
|
||||
//
|
||||
// Warning: Ioctls from 200 through 300 are used for the old common class
|
||||
// driver ioctls and should not be used for device specific functionality
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright ioctls
|
||||
//
|
||||
|
||||
#define IOCTL_DVD_START_SESSION CTL_CODE(IOCTL_DVD_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_READ_KEY CTL_CODE(IOCTL_DVD_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_SEND_KEY CTL_CODE(IOCTL_DVD_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_END_SESSION CTL_CODE(IOCTL_DVD_BASE, 0x0403, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_SET_READ_AHEAD CTL_CODE(IOCTL_DVD_BASE, 0x0404, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_GET_REGION CTL_CODE(IOCTL_DVD_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_DVD_SEND_KEY2 CTL_CODE(IOCTL_DVD_BASE, 0x0406, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
//
|
||||
// DVD Structure queries
|
||||
//
|
||||
|
||||
#define IOCTL_DVD_READ_STRUCTURE CTL_CODE(IOCTL_DVD_BASE, 0x0450, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
//
|
||||
// The following file contains the IOCTL_STORAGE class ioctl definitions
|
||||
//
|
||||
|
||||
#define IOCTL_STORAGE_SET_READ_AHEAD CTL_CODE(IOCTL_STORAGE_BASE, 0x0100, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
// end_winioctl
|
||||
|
||||
//#include <ntddstor.h>
|
||||
#include "ntddstor.h"
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DvdChallengeKey = 0x01,
|
||||
DvdBusKey1,
|
||||
DvdBusKey2,
|
||||
DvdTitleKey,
|
||||
DvdAsf,
|
||||
DvdSetRpcKey = 0x6,
|
||||
DvdGetRpcKey = 0x8,
|
||||
DvdDiskKey = 0x80,
|
||||
DvdInvalidateAGID = 0x3f
|
||||
} DVD_KEY_TYPE;
|
||||
|
||||
typedef ULONG DVD_SESSION_ID, *PDVD_SESSION_ID;
|
||||
|
||||
typedef struct _DVD_COPY_PROTECT_KEY {
|
||||
ULONG KeyLength;
|
||||
DVD_SESSION_ID SessionId;
|
||||
DVD_KEY_TYPE KeyType;
|
||||
ULONG KeyFlags;
|
||||
union {
|
||||
HANDLE FileHandle;
|
||||
LARGE_INTEGER TitleOffset;
|
||||
} Parameters;
|
||||
UCHAR KeyData[0];
|
||||
} DVD_COPY_PROTECT_KEY, *PDVD_COPY_PROTECT_KEY;
|
||||
|
||||
//
|
||||
// Predefined (Mt. Fuji) key sizes
|
||||
// Add sizeof(DVD_COPY_PROTECT_KEY) to get allocation size for
|
||||
// the full key structure
|
||||
//
|
||||
|
||||
#define DVD_CHALLENGE_KEY_LENGTH (12 + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_BUS_KEY_LENGTH (8 + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_TITLE_KEY_LENGTH (8 + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_DISK_KEY_LENGTH (2048 + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_RPC_KEY_LENGTH (sizeof(DVD_RPC_KEY) + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_SET_RPC_KEY_LENGTH (sizeof(DVD_SET_RPC_KEY) + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
#define DVD_ASF_LENGTH (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
|
||||
|
||||
//
|
||||
// Used with IOCTL_DVD_END_SESSION to end all DVD sessions at once
|
||||
//
|
||||
|
||||
#define DVD_END_ALL_SESSIONS ((DVD_SESSION_ID) 0xffffffff)
|
||||
|
||||
//
|
||||
// CGMS Copy Protection Flags
|
||||
//
|
||||
|
||||
#define DVD_CGMS_RESERVED_MASK 0x00000078
|
||||
|
||||
#define DVD_CGMS_COPY_PROTECT_MASK 0x00000018
|
||||
#define DVD_CGMS_COPY_PERMITTED 0x00000000
|
||||
#define DVD_CGMS_COPY_ONCE 0x00000010
|
||||
#define DVD_CGMS_NO_COPY 0x00000018
|
||||
|
||||
#define DVD_COPYRIGHT_MASK 0x00000040
|
||||
#define DVD_NOT_COPYRIGHTED 0x00000000
|
||||
#define DVD_COPYRIGHTED 0x00000040
|
||||
|
||||
#define DVD_SECTOR_PROTECT_MASK 0x00000020
|
||||
#define DVD_SECTOR_NOT_PROTECTED 0x00000000
|
||||
#define DVD_SECTOR_PROTECTED 0x00000020
|
||||
|
||||
/*++
|
||||
|
||||
IOCTL_STORAGE_SET_READ_AHEAD
|
||||
|
||||
Requests that the storage device skip to TargetAddress once it has run across
|
||||
TriggerAddress during the course of it's read-ahead caching operations.
|
||||
|
||||
Input:
|
||||
|
||||
a STORAGE_SET_READ_AHEAD structure which contains:
|
||||
* the trigger address
|
||||
* the target address
|
||||
|
||||
Output:
|
||||
|
||||
none
|
||||
|
||||
--*/
|
||||
|
||||
typedef struct _STORAGE_SET_READ_AHEAD {
|
||||
LARGE_INTEGER TriggerAddress;
|
||||
LARGE_INTEGER TargetAddress;
|
||||
} STORAGE_SET_READ_AHEAD, *PSTORAGE_SET_READ_AHEAD;
|
||||
|
||||
/*++
|
||||
|
||||
IOCTL_DVD_READ_STRUCTURE
|
||||
|
||||
Issues a READ_DVD_STRUCTURE command to the drive.
|
||||
|
||||
Input:
|
||||
|
||||
a DVD_READ_STRUCTURE describing what information is requested
|
||||
|
||||
Output:
|
||||
|
||||
a DVD Layer Descriptor as defined below
|
||||
|
||||
--*/
|
||||
|
||||
typedef enum DVD_STRUCTURE_FORMAT {
|
||||
DvdPhysicalDescriptor,
|
||||
DvdCopyrightDescriptor,
|
||||
DvdDiskKeyDescriptor,
|
||||
DvdBCADescriptor,
|
||||
DvdManufacturerDescriptor,
|
||||
DvdMaxDescriptor
|
||||
} DVD_STRUCTURE_FORMAT, *PDVD_STRUCTURE_FORMAT;
|
||||
|
||||
typedef struct DVD_READ_STRUCTURE {
|
||||
LARGE_INTEGER BlockByteOffset;
|
||||
DVD_STRUCTURE_FORMAT Format;
|
||||
DVD_SESSION_ID SessionId;
|
||||
UCHAR LayerNumber;
|
||||
} DVD_READ_STRUCTURE, *PDVD_READ_STRUCTURE;
|
||||
|
||||
typedef struct _DVD_DESCRIPTOR_HEADER {
|
||||
USHORT Length;
|
||||
UCHAR Reserved[2];
|
||||
UCHAR Data[0];
|
||||
} DVD_DESCRIPTOR_HEADER, *PDVD_DESCRIPTOR_HEADER;
|
||||
|
||||
typedef struct _DVD_LAYER_DESCRIPTOR {
|
||||
UCHAR BookVersion : 4;
|
||||
UCHAR BookType : 4;
|
||||
UCHAR MinimumRate : 4;
|
||||
UCHAR DiskSize : 4;
|
||||
UCHAR LayerType : 4;
|
||||
UCHAR TrackPath : 1;
|
||||
UCHAR NumberOfLayers : 2;
|
||||
UCHAR Reserved1 : 1;
|
||||
UCHAR TrackDensity : 4;
|
||||
UCHAR LinearDensity : 4;
|
||||
ULONG StartingDataSector;
|
||||
ULONG EndDataSector;
|
||||
ULONG EndLayerZeroSector;
|
||||
UCHAR Reserved5 : 7;
|
||||
UCHAR BCAFlag : 1;
|
||||
UCHAR Reserved6;
|
||||
} DVD_LAYER_DESCRIPTOR, *PDVD_LAYER_DESCRIPTOR;
|
||||
|
||||
typedef struct _DVD_COPYRIGHT_DESCRIPTOR {
|
||||
UCHAR CopyrightProtectionType;
|
||||
UCHAR RegionManagementInformation;
|
||||
USHORT Reserved;
|
||||
} DVD_COPYRIGHT_DESCRIPTOR, *PDVD_COPYRIGHT_DESCRIPTOR;
|
||||
|
||||
typedef struct _DVD_DISK_KEY_DESCRIPTOR {
|
||||
UCHAR DiskKeyData[2048];
|
||||
} DVD_DISK_KEY_DESCRIPTOR, *PDVD_DISK_KEY_DESCRIPTOR;
|
||||
|
||||
typedef struct _DVD_BCA_DESCRIPTOR {
|
||||
UCHAR BCAInformation[0];
|
||||
} DVD_BCA_DESCRIPTOR, *PDVD_BCA_DESCRIPTOR;
|
||||
|
||||
typedef struct _DVD_MANUFACTURER_DESCRIPTOR {
|
||||
UCHAR ManufacturingInformation[2048];
|
||||
} DVD_MANUFACTURER_DESCRIPTOR, *PDVD_MANUFACTURER_DESCRIPTOR;
|
||||
|
||||
typedef struct _DVD_RPC_KEY {
|
||||
UCHAR UserResetsAvailable:3;
|
||||
UCHAR ManufacturerResetsAvailable:3;
|
||||
UCHAR TypeCode:2;
|
||||
UCHAR RegionMask;
|
||||
UCHAR RpcScheme;
|
||||
UCHAR Reserved2[1];
|
||||
} DVD_RPC_KEY, * PDVD_RPC_KEY;
|
||||
|
||||
typedef struct _DVD_SET_RPC_KEY {
|
||||
UCHAR PreferredDriveRegionCode;
|
||||
UCHAR Reserved[3];
|
||||
} DVD_SET_RPC_KEY, * PDVD_SET_RPC_KEY;
|
||||
|
||||
typedef struct _DVD_ASF {
|
||||
UCHAR Reserved0[3];
|
||||
UCHAR SuccessFlag:1;
|
||||
UCHAR Reserved1:7;
|
||||
} DVD_ASF, * PDVD_ASF;
|
||||
|
||||
#if 0
|
||||
typedef struct _DVD_REGION {
|
||||
UCHAR CopySystem;
|
||||
UCHAR RegionData; // current media region (not playable when set)
|
||||
UCHAR SystemRegion; // current drive region (playable when set)
|
||||
UCHAR ResetCount; // number of resets available
|
||||
} DVD_REGION, *PDVD_REGION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
|
||||
#endif // _NTDDCDVD_
|
||||
|
||||
// end_winioctl
|
||||
|
||||
|
748
vsfilter/include/winddk/ntddstor.h
Normal file
748
vsfilter/include/winddk/ntddstor.h
Normal file
|
@ -0,0 +1,748 @@
|
|||
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
ntddstor.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This is the include file that defines all common constants and types
|
||||
accessing the storage class drivers
|
||||
|
||||
Author:
|
||||
|
||||
Peter Wieland 19-Jun-1996
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "devioctl.h"
|
||||
|
||||
//
|
||||
// Interface GUIDs
|
||||
//
|
||||
// need these GUIDs outside conditional includes so that user can
|
||||
// #include <ntddstor.h> in precompiled header
|
||||
// #include <initguid.h> in a single source file
|
||||
// #include <ntddstor.h> in that source file a second time to instantiate the GUIDs
|
||||
//
|
||||
#ifdef DEFINE_GUID
|
||||
//
|
||||
// Make sure FAR is defined...
|
||||
//
|
||||
#ifndef FAR
|
||||
#ifdef _WIN32
|
||||
#define FAR
|
||||
#else
|
||||
#define FAR _far
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// begin_wioctlguids
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_CDROM, 0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_PARTITION, 0x53f5630aL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_TAPE, 0x53f5630bL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_WRITEONCEDISK, 0x53f5630cL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_MEDIUMCHANGER, 0x53f56310L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_FLOPPY, 0x53f56311L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_CDCHANGER, 0x53f56312L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
// end_wioctlguids
|
||||
|
||||
// begin_wioctlobsoleteguids
|
||||
#define DiskClassGuid GUID_DEVINTERFACE_DISK
|
||||
#define CdRomClassGuid GUID_DEVINTERFACE_CDROM
|
||||
#define PartitionClassGuid GUID_DEVINTERFACE_PARTITION
|
||||
#define TapeClassGuid GUID_DEVINTERFACE_TAPE
|
||||
#define WriteOnceDiskClassGuid GUID_DEVINTERFACE_WRITEONCEDISK
|
||||
#define VolumeClassGuid GUID_DEVINTERFACE_VOLUME
|
||||
#define MediumChangerClassGuid GUID_DEVINTERFACE_MEDIUMCHANGER
|
||||
#define FloppyClassGuid GUID_DEVINTERFACE_FLOPPY
|
||||
#define CdChangerClassGuid GUID_DEVINTERFACE_CDCHANGER
|
||||
#define StoragePortClassGuid GUID_DEVINTERFACE_STORAGEPORT
|
||||
// end_wioctlobsoleteguids
|
||||
#endif
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
#ifndef _NTDDSTOR_H_
|
||||
#define _NTDDSTOR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// IoControlCode values for storage devices
|
||||
//
|
||||
|
||||
#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE
|
||||
|
||||
//
|
||||
// The following device control codes are common for all class drivers. They
|
||||
// should be used in place of the older IOCTL_DISK, IOCTL_CDROM and IOCTL_TAPE
|
||||
// common codes
|
||||
//
|
||||
|
||||
#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_STORAGE_EJECTION_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0250, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_MCN_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0251, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_STORAGE_GET_MEDIA_TYPES CTL_CODE(IOCTL_STORAGE_BASE, 0x0300, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_GET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0305, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_SET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0306, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
#define IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_STORAGE_BREAK_RESERVATION CTL_CODE(IOCTL_STORAGE_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_STORAGE_GET_DEVICE_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_STORAGE_PREDICT_FAILURE CTL_CODE(IOCTL_STORAGE_BASE, 0x0440, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
// end_winioctl
|
||||
|
||||
|
||||
#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
//
|
||||
// These ioctl codes are obsolete. They are defined here to avoid resuing them
|
||||
// and to allow class drivers to respond to them more easily.
|
||||
//
|
||||
|
||||
#define OBSOLETE_IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
#define OBSOLETE_IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_GET_HOTPLUG_INFO
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_HOTPLUG_INFO {
|
||||
ULONG Size; // version
|
||||
BOOLEAN MediaRemovable; // ie. zip, jaz, cdrom, mo, etc. vs hdd
|
||||
BOOLEAN MediaHotplug; // ie. does the device succeed a lock even though its not lockable media?
|
||||
BOOLEAN DeviceHotplug; // ie. 1394, USB, etc.
|
||||
BOOLEAN WriteCacheEnableOverride; // This field should not be relied upon because it is no longer used
|
||||
} STORAGE_HOTPLUG_INFO, *PSTORAGE_HOTPLUG_INFO;
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_GET_DEVICE_NUMBER
|
||||
//
|
||||
// input - none
|
||||
//
|
||||
// output - STORAGE_DEVICE_NUMBER structure
|
||||
// The values in the STORAGE_DEVICE_NUMBER structure are guaranteed
|
||||
// to remain unchanged until the system is rebooted. They are not
|
||||
// guaranteed to be persistant across boots.
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_DEVICE_NUMBER {
|
||||
|
||||
//
|
||||
// The FILE_DEVICE_XXX type for this device.
|
||||
//
|
||||
|
||||
DEVICE_TYPE DeviceType;
|
||||
|
||||
//
|
||||
// The number of this device
|
||||
//
|
||||
|
||||
ULONG DeviceNumber;
|
||||
|
||||
//
|
||||
// If the device is partitionable, the partition number of the device.
|
||||
// Otherwise -1
|
||||
//
|
||||
|
||||
ULONG PartitionNumber;
|
||||
} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
|
||||
|
||||
//
|
||||
// Define the structures for scsi resets
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_BUS_RESET_REQUEST {
|
||||
UCHAR PathId;
|
||||
} STORAGE_BUS_RESET_REQUEST, *PSTORAGE_BUS_RESET_REQUEST;
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_MEDIA_REMOVAL disables the mechanism
|
||||
// on a storage device that ejects media. This function
|
||||
// may or may not be supported on storage devices that
|
||||
// support removable media.
|
||||
//
|
||||
// TRUE means prevent media from being removed.
|
||||
// FALSE means allow media removal.
|
||||
//
|
||||
|
||||
typedef struct _PREVENT_MEDIA_REMOVAL {
|
||||
BOOLEAN PreventMediaRemoval;
|
||||
} PREVENT_MEDIA_REMOVAL, *PPREVENT_MEDIA_REMOVAL;
|
||||
|
||||
// begin_ntminitape
|
||||
|
||||
|
||||
typedef struct _TAPE_STATISTICS {
|
||||
ULONG Version;
|
||||
ULONG Flags;
|
||||
LARGE_INTEGER RecoveredWrites;
|
||||
LARGE_INTEGER UnrecoveredWrites;
|
||||
LARGE_INTEGER RecoveredReads;
|
||||
LARGE_INTEGER UnrecoveredReads;
|
||||
UCHAR CompressionRatioReads;
|
||||
UCHAR CompressionRatioWrites;
|
||||
} TAPE_STATISTICS, *PTAPE_STATISTICS;
|
||||
|
||||
#define RECOVERED_WRITES_VALID 0x00000001
|
||||
#define UNRECOVERED_WRITES_VALID 0x00000002
|
||||
#define RECOVERED_READS_VALID 0x00000004
|
||||
#define UNRECOVERED_READS_VALID 0x00000008
|
||||
#define WRITE_COMPRESSION_INFO_VALID 0x00000010
|
||||
#define READ_COMPRESSION_INFO_VALID 0x00000020
|
||||
|
||||
typedef struct _TAPE_GET_STATISTICS {
|
||||
ULONG Operation;
|
||||
} TAPE_GET_STATISTICS, *PTAPE_GET_STATISTICS;
|
||||
|
||||
#define TAPE_RETURN_STATISTICS 0L
|
||||
#define TAPE_RETURN_ENV_INFO 1L
|
||||
#define TAPE_RESET_STATISTICS 2L
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_GET_MEDIA_TYPES_EX will return an array of DEVICE_MEDIA_INFO
|
||||
// structures, one per supported type, embedded in the GET_MEDIA_TYPES struct.
|
||||
//
|
||||
|
||||
typedef enum _STORAGE_MEDIA_TYPE {
|
||||
//
|
||||
// Following are defined in ntdddisk.h in the MEDIA_TYPE enum
|
||||
//
|
||||
// Unknown, // Format is unknown
|
||||
// F5_1Pt2_512, // 5.25", 1.2MB, 512 bytes/sector
|
||||
// F3_1Pt44_512, // 3.5", 1.44MB, 512 bytes/sector
|
||||
// F3_2Pt88_512, // 3.5", 2.88MB, 512 bytes/sector
|
||||
// F3_20Pt8_512, // 3.5", 20.8MB, 512 bytes/sector
|
||||
// F3_720_512, // 3.5", 720KB, 512 bytes/sector
|
||||
// F5_360_512, // 5.25", 360KB, 512 bytes/sector
|
||||
// F5_320_512, // 5.25", 320KB, 512 bytes/sector
|
||||
// F5_320_1024, // 5.25", 320KB, 1024 bytes/sector
|
||||
// F5_180_512, // 5.25", 180KB, 512 bytes/sector
|
||||
// F5_160_512, // 5.25", 160KB, 512 bytes/sector
|
||||
// RemovableMedia, // Removable media other than floppy
|
||||
// FixedMedia, // Fixed hard disk media
|
||||
// F3_120M_512, // 3.5", 120M Floppy
|
||||
// F3_640_512, // 3.5" , 640KB, 512 bytes/sector
|
||||
// F5_640_512, // 5.25", 640KB, 512 bytes/sector
|
||||
// F5_720_512, // 5.25", 720KB, 512 bytes/sector
|
||||
// F3_1Pt2_512, // 3.5" , 1.2Mb, 512 bytes/sector
|
||||
// F3_1Pt23_1024, // 3.5" , 1.23Mb, 1024 bytes/sector
|
||||
// F5_1Pt23_1024, // 5.25", 1.23MB, 1024 bytes/sector
|
||||
// F3_128Mb_512, // 3.5" MO 128Mb 512 bytes/sector
|
||||
// F3_230Mb_512, // 3.5" MO 230Mb 512 bytes/sector
|
||||
// F8_256_128, // 8", 256KB, 128 bytes/sector
|
||||
// F3_200Mb_512, // 3.5", 200M Floppy (HiFD)
|
||||
//
|
||||
|
||||
DDS_4mm = 0x20, // Tape - DAT DDS1,2,... (all vendors)
|
||||
MiniQic, // Tape - miniQIC Tape
|
||||
Travan, // Tape - Travan TR-1,2,3,...
|
||||
QIC, // Tape - QIC
|
||||
MP_8mm, // Tape - 8mm Exabyte Metal Particle
|
||||
AME_8mm, // Tape - 8mm Exabyte Advanced Metal Evap
|
||||
AIT1_8mm, // Tape - 8mm Sony AIT
|
||||
DLT, // Tape - DLT Compact IIIxt, IV
|
||||
NCTP, // Tape - Philips NCTP
|
||||
IBM_3480, // Tape - IBM 3480
|
||||
IBM_3490E, // Tape - IBM 3490E
|
||||
IBM_Magstar_3590, // Tape - IBM Magstar 3590
|
||||
IBM_Magstar_MP, // Tape - IBM Magstar MP
|
||||
STK_DATA_D3, // Tape - STK Data D3
|
||||
SONY_DTF, // Tape - Sony DTF
|
||||
DV_6mm, // Tape - 6mm Digital Video
|
||||
DMI, // Tape - Exabyte DMI and compatibles
|
||||
SONY_D2, // Tape - Sony D2S and D2L
|
||||
CLEANER_CARTRIDGE, // Cleaner - All Drive types that support Drive Cleaners
|
||||
CD_ROM, // Opt_Disk - CD
|
||||
CD_R, // Opt_Disk - CD-Recordable (Write Once)
|
||||
CD_RW, // Opt_Disk - CD-Rewriteable
|
||||
DVD_ROM, // Opt_Disk - DVD-ROM
|
||||
DVD_R, // Opt_Disk - DVD-Recordable (Write Once)
|
||||
DVD_RW, // Opt_Disk - DVD-Rewriteable
|
||||
MO_3_RW, // Opt_Disk - 3.5" Rewriteable MO Disk
|
||||
MO_5_WO, // Opt_Disk - MO 5.25" Write Once
|
||||
MO_5_RW, // Opt_Disk - MO 5.25" Rewriteable (not LIMDOW)
|
||||
MO_5_LIMDOW, // Opt_Disk - MO 5.25" Rewriteable (LIMDOW)
|
||||
PC_5_WO, // Opt_Disk - Phase Change 5.25" Write Once Optical
|
||||
PC_5_RW, // Opt_Disk - Phase Change 5.25" Rewriteable
|
||||
PD_5_RW, // Opt_Disk - PhaseChange Dual Rewriteable
|
||||
ABL_5_WO, // Opt_Disk - Ablative 5.25" Write Once Optical
|
||||
PINNACLE_APEX_5_RW, // Opt_Disk - Pinnacle Apex 4.6GB Rewriteable Optical
|
||||
SONY_12_WO, // Opt_Disk - Sony 12" Write Once
|
||||
PHILIPS_12_WO, // Opt_Disk - Philips/LMS 12" Write Once
|
||||
HITACHI_12_WO, // Opt_Disk - Hitachi 12" Write Once
|
||||
CYGNET_12_WO, // Opt_Disk - Cygnet/ATG 12" Write Once
|
||||
KODAK_14_WO, // Opt_Disk - Kodak 14" Write Once
|
||||
MO_NFR_525, // Opt_Disk - Near Field Recording (Terastor)
|
||||
NIKON_12_RW, // Opt_Disk - Nikon 12" Rewriteable
|
||||
IOMEGA_ZIP, // Mag_Disk - Iomega Zip
|
||||
IOMEGA_JAZ, // Mag_Disk - Iomega Jaz
|
||||
SYQUEST_EZ135, // Mag_Disk - Syquest EZ135
|
||||
SYQUEST_EZFLYER, // Mag_Disk - Syquest EzFlyer
|
||||
SYQUEST_SYJET, // Mag_Disk - Syquest SyJet
|
||||
AVATAR_F2, // Mag_Disk - 2.5" Floppy
|
||||
MP2_8mm, // Tape - 8mm Hitachi
|
||||
DST_S, // Ampex DST Small Tapes
|
||||
DST_M, // Ampex DST Medium Tapes
|
||||
DST_L, // Ampex DST Large Tapes
|
||||
VXATape_1, // Ecrix 8mm Tape
|
||||
VXATape_2, // Ecrix 8mm Tape
|
||||
STK_9840, // STK 9840
|
||||
LTO_Ultrium, // IBM, HP, Seagate LTO Ultrium
|
||||
LTO_Accelis, // IBM, HP, Seagate LTO Accelis
|
||||
DVD_RAM, // Opt_Disk - DVD-RAM
|
||||
AIT_8mm, // AIT2 or higher
|
||||
ADR_1, // OnStream ADR Mediatypes
|
||||
ADR_2
|
||||
} STORAGE_MEDIA_TYPE, *PSTORAGE_MEDIA_TYPE;
|
||||
|
||||
#define MEDIA_ERASEABLE 0x00000001
|
||||
#define MEDIA_WRITE_ONCE 0x00000002
|
||||
#define MEDIA_READ_ONLY 0x00000004
|
||||
#define MEDIA_READ_WRITE 0x00000008
|
||||
|
||||
#define MEDIA_WRITE_PROTECTED 0x00000100
|
||||
#define MEDIA_CURRENTLY_MOUNTED 0x80000000
|
||||
|
||||
//
|
||||
// Define the different storage bus types
|
||||
// Bus types below 128 (0x80) are reserved for Microsoft use
|
||||
//
|
||||
|
||||
typedef enum _STORAGE_BUS_TYPE {
|
||||
BusTypeUnknown = 0x00,
|
||||
BusTypeScsi,
|
||||
BusTypeAtapi,
|
||||
BusTypeAta,
|
||||
BusType1394,
|
||||
BusTypeSsa,
|
||||
BusTypeFibre,
|
||||
BusTypeUsb,
|
||||
BusTypeRAID,
|
||||
BusTypeMaxReserved = 0x7F
|
||||
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;
|
||||
|
||||
typedef struct _DEVICE_MEDIA_INFO {
|
||||
union {
|
||||
struct {
|
||||
LARGE_INTEGER Cylinders;
|
||||
STORAGE_MEDIA_TYPE MediaType;
|
||||
ULONG TracksPerCylinder;
|
||||
ULONG SectorsPerTrack;
|
||||
ULONG BytesPerSector;
|
||||
ULONG NumberMediaSides;
|
||||
ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values.
|
||||
} DiskInfo;
|
||||
|
||||
struct {
|
||||
LARGE_INTEGER Cylinders;
|
||||
STORAGE_MEDIA_TYPE MediaType;
|
||||
ULONG TracksPerCylinder;
|
||||
ULONG SectorsPerTrack;
|
||||
ULONG BytesPerSector;
|
||||
ULONG NumberMediaSides;
|
||||
ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values.
|
||||
} RemovableDiskInfo;
|
||||
|
||||
struct {
|
||||
STORAGE_MEDIA_TYPE MediaType;
|
||||
ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values.
|
||||
ULONG CurrentBlockSize;
|
||||
STORAGE_BUS_TYPE BusType;
|
||||
|
||||
//
|
||||
// Bus specific information describing the medium supported.
|
||||
//
|
||||
|
||||
union {
|
||||
struct {
|
||||
UCHAR MediumType;
|
||||
UCHAR DensityCode;
|
||||
} ScsiInformation;
|
||||
} BusSpecificData;
|
||||
|
||||
} TapeInfo;
|
||||
} DeviceSpecific;
|
||||
} DEVICE_MEDIA_INFO, *PDEVICE_MEDIA_INFO;
|
||||
|
||||
typedef struct _GET_MEDIA_TYPES {
|
||||
ULONG DeviceType; // FILE_DEVICE_XXX values
|
||||
ULONG MediaInfoCount;
|
||||
DEVICE_MEDIA_INFO MediaInfo[1];
|
||||
} GET_MEDIA_TYPES, *PGET_MEDIA_TYPES;
|
||||
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_PREDICT_FAILURE
|
||||
//
|
||||
// input - none
|
||||
//
|
||||
// output - STORAGE_PREDICT_FAILURE structure
|
||||
// PredictFailure returns zero if no failure predicted and non zero
|
||||
// if a failure is predicted.
|
||||
//
|
||||
// VendorSpecific returns 512 bytes of vendor specific information
|
||||
// if a failure is predicted
|
||||
//
|
||||
typedef struct _STORAGE_PREDICT_FAILURE
|
||||
{
|
||||
ULONG PredictFailure;
|
||||
UCHAR VendorSpecific[512];
|
||||
} STORAGE_PREDICT_FAILURE, *PSTORAGE_PREDICT_FAILURE;
|
||||
|
||||
// end_ntminitape
|
||||
// end_winioctl
|
||||
|
||||
//
|
||||
// Property Query Structures
|
||||
//
|
||||
|
||||
//
|
||||
// IOCTL_STORAGE_QUERY_PROPERTY
|
||||
//
|
||||
// Input Buffer:
|
||||
// a STORAGE_PROPERTY_QUERY structure which describes what type of query
|
||||
// is being done, what property is being queried for, and any additional
|
||||
// parameters which a particular property query requires.
|
||||
//
|
||||
// Output Buffer:
|
||||
// Contains a buffer to place the results of the query into. Since all
|
||||
// property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER,
|
||||
// the IOCTL can be called once with a small buffer then again using
|
||||
// a buffer as large as the header reports is necessary.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Types of queries
|
||||
//
|
||||
|
||||
typedef enum _STORAGE_QUERY_TYPE {
|
||||
PropertyStandardQuery = 0, // Retrieves the descriptor
|
||||
PropertyExistsQuery, // Used to test whether the descriptor is supported
|
||||
PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor
|
||||
PropertyQueryMaxDefined // use to validate the value
|
||||
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
|
||||
|
||||
//
|
||||
// define some initial property id's
|
||||
//
|
||||
|
||||
typedef enum _STORAGE_PROPERTY_ID {
|
||||
StorageDeviceProperty = 0,
|
||||
StorageAdapterProperty,
|
||||
StorageDeviceIdProperty
|
||||
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
|
||||
|
||||
//
|
||||
// Query structure - additional parameters for specific queries can follow
|
||||
// the header
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_PROPERTY_QUERY {
|
||||
|
||||
//
|
||||
// ID of the property being retrieved
|
||||
//
|
||||
|
||||
STORAGE_PROPERTY_ID PropertyId;
|
||||
|
||||
//
|
||||
// Flags indicating the type of query being performed
|
||||
//
|
||||
|
||||
STORAGE_QUERY_TYPE QueryType;
|
||||
|
||||
//
|
||||
// Space for additional parameters if necessary
|
||||
//
|
||||
|
||||
UCHAR AdditionalParameters[1];
|
||||
|
||||
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
|
||||
|
||||
//
|
||||
// Standard property descriptor header. All property pages should use this
|
||||
// as their first element or should contain these two elements
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_DESCRIPTOR_HEADER {
|
||||
|
||||
ULONG Version;
|
||||
|
||||
ULONG Size;
|
||||
|
||||
} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER;
|
||||
|
||||
//
|
||||
// Device property descriptor - this is really just a rehash of the inquiry
|
||||
// data retrieved from a scsi device
|
||||
//
|
||||
// This may only be retrieved from a target device. Sending this to the bus
|
||||
// will result in an error
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
|
||||
|
||||
//
|
||||
// Sizeof(STORAGE_DEVICE_DESCRIPTOR)
|
||||
//
|
||||
|
||||
ULONG Version;
|
||||
|
||||
//
|
||||
// Total size of the descriptor, including the space for additional
|
||||
// data and id strings
|
||||
//
|
||||
|
||||
ULONG Size;
|
||||
|
||||
//
|
||||
// The SCSI-2 device type
|
||||
//
|
||||
|
||||
UCHAR DeviceType;
|
||||
|
||||
//
|
||||
// The SCSI-2 device type modifier (if any) - this may be zero
|
||||
//
|
||||
|
||||
UCHAR DeviceTypeModifier;
|
||||
|
||||
//
|
||||
// Flag indicating whether the device's media (if any) is removable. This
|
||||
// field should be ignored for media-less devices
|
||||
//
|
||||
|
||||
BOOLEAN RemovableMedia;
|
||||
|
||||
//
|
||||
// Flag indicating whether the device can support mulitple outstanding
|
||||
// commands. The actual synchronization in this case is the responsibility
|
||||
// of the port driver.
|
||||
//
|
||||
|
||||
BOOLEAN CommandQueueing;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// vendor id string. For devices with no such ID this will be zero
|
||||
//
|
||||
|
||||
ULONG VendorIdOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// product id string. For devices with no such ID this will be zero
|
||||
//
|
||||
|
||||
ULONG ProductIdOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// product revision string. For devices with no such string this will be
|
||||
// zero
|
||||
//
|
||||
|
||||
ULONG ProductRevisionOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// serial number. For devices with no serial number this will be zero
|
||||
//
|
||||
|
||||
ULONG SerialNumberOffset;
|
||||
|
||||
//
|
||||
// Contains the bus type (as defined above) of the device. It should be
|
||||
// used to interpret the raw device properties at the end of this structure
|
||||
// (if any)
|
||||
//
|
||||
|
||||
STORAGE_BUS_TYPE BusType;
|
||||
|
||||
//
|
||||
// The number of bytes of bus-specific data which have been appended to
|
||||
// this descriptor
|
||||
//
|
||||
|
||||
ULONG RawPropertiesLength;
|
||||
|
||||
//
|
||||
// Place holder for the first byte of the bus specific property data
|
||||
//
|
||||
|
||||
UCHAR RawDeviceProperties[1];
|
||||
|
||||
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
|
||||
|
||||
|
||||
//
|
||||
// Adapter properties
|
||||
//
|
||||
// This descriptor can be retrieved from a target device object of from the
|
||||
// device object for the bus. Retrieving from the target device object will
|
||||
// forward the request to the underlying bus
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_ADAPTER_DESCRIPTOR {
|
||||
|
||||
ULONG Version;
|
||||
|
||||
ULONG Size;
|
||||
|
||||
ULONG MaximumTransferLength;
|
||||
|
||||
ULONG MaximumPhysicalPages;
|
||||
|
||||
ULONG AlignmentMask;
|
||||
|
||||
BOOLEAN AdapterUsesPio;
|
||||
|
||||
BOOLEAN AdapterScansDown;
|
||||
|
||||
BOOLEAN CommandQueueing;
|
||||
|
||||
BOOLEAN AcceleratedTransfer;
|
||||
|
||||
UCHAR BusType;
|
||||
|
||||
USHORT BusMajorVersion;
|
||||
|
||||
USHORT BusMinorVersion;
|
||||
|
||||
} STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR;
|
||||
|
||||
//
|
||||
// Storage identification descriptor.
|
||||
// The definitions here are based on the SCSI/SBP vital product data
|
||||
// device identifier page.
|
||||
//
|
||||
|
||||
typedef enum _STORAGE_IDENTIFIER_CODE_SET {
|
||||
StorageIdCodeSetReserved = 0,
|
||||
StorageIdCodeSetBinary = 1,
|
||||
StorageIdCodeSetAscii = 2
|
||||
} STORAGE_IDENTIFIER_CODE_SET, *PSTORAGE_IDENTIFIER_CODE_SET;
|
||||
|
||||
typedef enum _STORAGE_IDENTIFIER_TYPE {
|
||||
StorageIdTypeVendorSpecific = 0,
|
||||
StorageIdTypeVendorId = 1,
|
||||
StorageIdTypeEUI64 = 2,
|
||||
StorageIdTypeFCPHName = 3,
|
||||
StorageIdTypePortRelative = 4
|
||||
} STORAGE_IDENTIFIER_TYPE, *PSTORAGE_IDENTIFIER_TYPE;
|
||||
|
||||
typedef enum _STORAGE_ASSOCIATION_TYPE {
|
||||
StorageIdAssocDevice = 0,
|
||||
StorageIdAssocPort = 1
|
||||
} STORAGE_ASSOCIATION_TYPE, *PSTORAGE_ASSOCIATION_TYPE;
|
||||
|
||||
typedef struct _STORAGE_IDENTIFIER {
|
||||
STORAGE_IDENTIFIER_CODE_SET CodeSet;
|
||||
STORAGE_IDENTIFIER_TYPE Type;
|
||||
USHORT IdentifierSize;
|
||||
USHORT NextOffset;
|
||||
|
||||
//
|
||||
// Add new fields here since existing code depends on
|
||||
// the above layout not changing.
|
||||
//
|
||||
|
||||
STORAGE_ASSOCIATION_TYPE Association;
|
||||
|
||||
//
|
||||
// The identifier is a variable length array of bytes.
|
||||
//
|
||||
|
||||
UCHAR Identifier[1];
|
||||
} STORAGE_IDENTIFIER, *PSTORAGE_IDENTIFIER;
|
||||
|
||||
typedef struct _STORAGE_DEVICE_ID_DESCRIPTOR {
|
||||
|
||||
ULONG Version;
|
||||
|
||||
ULONG Size;
|
||||
|
||||
//
|
||||
// The number of identifiers reported by the device.
|
||||
//
|
||||
|
||||
ULONG NumberOfIdentifiers;
|
||||
|
||||
//
|
||||
// The following field is actually a variable length array of identification
|
||||
// descriptors. Unfortunately there's no C notation for an array of
|
||||
// variable length structures so we're forced to just pretend.
|
||||
//
|
||||
|
||||
UCHAR Identifiers[1];
|
||||
} STORAGE_DEVICE_ID_DESCRIPTOR, *PSTORAGE_DEVICE_ID_DESCRIPTOR;
|
||||
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200)
|
||||
typedef struct _STORAGE_MEDIA_SERIAL_NUMBER_DATA {
|
||||
|
||||
USHORT Reserved;
|
||||
|
||||
//
|
||||
// the SerialNumberLength will be set to zero
|
||||
// if the command is supported and the media
|
||||
// does not have a valid serial number.
|
||||
//
|
||||
|
||||
USHORT SerialNumberLength;
|
||||
|
||||
//
|
||||
// the following data is binary, and is not guaranteed
|
||||
// to be NULL terminated. this is an excercise for the
|
||||
// caller.
|
||||
//
|
||||
|
||||
UCHAR SerialNumber[0];
|
||||
|
||||
} STORAGE_MEDIA_SERIAL_NUMBER_DATA, *PSTORAGE_MEDIA_SERIAL_NUMBER_DATA;
|
||||
#pragma warning(push)
|
||||
|
||||
|
||||
// begin_winioctl
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _NTDDSTOR_H_
|
||||
// end_winioctl
|
||||
|
327
vsfilter/libssf/Arabic.cpp
Normal file
327
vsfilter/libssf/Arabic.cpp
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* The "ArabicForms" table originates from fontforge
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Arabic.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
static const struct arabicforms
|
||||
{
|
||||
unsigned short initial, medial, final, isolated;
|
||||
unsigned int isletter: 1;
|
||||
unsigned int joindual: 1;
|
||||
unsigned int required_lig_with_alef: 1;
|
||||
}
|
||||
ArabicForms[256] =
|
||||
{
|
||||
{ 0x0600, 0x0600, 0x0600, 0x0600, 0, 0, 0 },
|
||||
{ 0x0601, 0x0601, 0x0601, 0x0601, 0, 0, 0 },
|
||||
{ 0x0602, 0x0602, 0x0602, 0x0602, 0, 0, 0 },
|
||||
{ 0x0603, 0x0603, 0x0603, 0x0603, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x060b, 0x060b, 0x060b, 0x060b, 0, 0, 0 },
|
||||
{ 0x060c, 0x060c, 0x060c, 0x060c, 0, 0, 0 },
|
||||
{ 0x060d, 0x060d, 0x060d, 0x060d, 0, 0, 0 },
|
||||
{ 0x060e, 0x060e, 0x060e, 0x060e, 0, 0, 0 },
|
||||
{ 0x060f, 0x060f, 0x060f, 0x060f, 0, 0, 0 },
|
||||
{ 0x0610, 0x0610, 0x0610, 0x0610, 0, 0, 0 },
|
||||
{ 0x0611, 0x0611, 0x0611, 0x0611, 0, 0, 0 },
|
||||
{ 0x0612, 0x0612, 0x0612, 0x0612, 0, 0, 0 },
|
||||
{ 0x0613, 0x0613, 0x0613, 0x0613, 0, 0, 0 },
|
||||
{ 0x0614, 0x0614, 0x0614, 0x0614, 0, 0, 0 },
|
||||
{ 0x0615, 0x0615, 0x0615, 0x0615, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x061b, 0x061b, 0x061b, 0x061b, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x061e, 0x061e, 0x061e, 0x061e, 0, 0, 0 },
|
||||
{ 0x061f, 0x061f, 0x061f, 0x061f, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0621, 0x0621, 0x0621, 0xfe80, 1, 0, 0 },
|
||||
{ 0x0622, 0x0622, 0xfe82, 0xfe81, 1, 0, 0 },
|
||||
{ 0x0623, 0x0623, 0xfe84, 0xfe83, 1, 0, 0 },
|
||||
{ 0x0624, 0x0624, 0xfe86, 0xfe85, 1, 0, 0 },
|
||||
{ 0x0625, 0x0625, 0xfe88, 0xfe87, 1, 0, 0 },
|
||||
{ 0xfe8b, 0xfe8c, 0xfe8a, 0xfe89, 1, 1, 0 },
|
||||
{ 0x0627, 0x0627, 0xfe8e, 0xfe8d, 1, 0, 0 },
|
||||
{ 0xfe91, 0xfe92, 0xfe90, 0xfe8f, 1, 1, 0 },
|
||||
{ 0x0629, 0x0629, 0xfe94, 0xfe93, 1, 0, 0 },
|
||||
{ 0xfe97, 0xfe98, 0xfe96, 0xfe95, 1, 1, 0 },
|
||||
{ 0xfe9b, 0xfe9c, 0xfe9a, 0xfe99, 1, 1, 0 },
|
||||
{ 0xfe9f, 0xfea0, 0xfe9e, 0xfe9d, 1, 1, 0 },
|
||||
{ 0xfea3, 0xfea4, 0xfea2, 0xfea1, 1, 1, 0 },
|
||||
{ 0xfea7, 0xfea8, 0xfea6, 0xfea5, 1, 1, 0 },
|
||||
{ 0x062f, 0x062f, 0xfeaa, 0xfea9, 1, 0, 0 },
|
||||
{ 0x0630, 0x0630, 0xfeac, 0xfeab, 1, 0, 0 },
|
||||
{ 0x0631, 0x0631, 0xfeae, 0xfead, 1, 0, 0 },
|
||||
{ 0x0632, 0x0632, 0xfeb0, 0xfeaf, 1, 0, 0 },
|
||||
{ 0xfeb3, 0xfeb4, 0xfeb2, 0xfeb1, 1, 1, 0 },
|
||||
{ 0xfeb7, 0xfeb8, 0xfeb6, 0xfeb5, 1, 1, 0 },
|
||||
{ 0xfebb, 0xfebc, 0xfeba, 0xfeb9, 1, 1, 0 },
|
||||
{ 0xfebf, 0xfec0, 0xfebe, 0xfebd, 1, 1, 0 },
|
||||
{ 0xfec3, 0xfec4, 0xfec2, 0xfec1, 1, 1, 0 },
|
||||
{ 0xfec7, 0xfec8, 0xfec6, 0xfec5, 1, 1, 0 },
|
||||
{ 0xfecb, 0xfecc, 0xfeca, 0xfec9, 1, 1, 0 },
|
||||
{ 0xfecf, 0xfed0, 0xfece, 0xfecd, 1, 1, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0640, 0x0640, 0x0640, 0x0640, 0, 0, 0 },
|
||||
{ 0xfed3, 0xfed4, 0xfed2, 0xfed1, 1, 1, 0 },
|
||||
{ 0xfed7, 0xfed8, 0xfed6, 0xfed5, 1, 1, 0 },
|
||||
{ 0xfedb, 0xfedc, 0xfeda, 0xfed9, 1, 1, 0 },
|
||||
{ 0xfedf, 0xfee0, 0xfede, 0xfedd, 1, 1, 1 },
|
||||
{ 0xfee3, 0xfee4, 0xfee2, 0xfee1, 1, 1, 0 },
|
||||
{ 0xfee7, 0xfee8, 0xfee6, 0xfee5, 1, 1, 0 },
|
||||
{ 0xfeeb, 0xfeec, 0xfeea, 0xfee9, 1, 1, 0 },
|
||||
{ 0x0648, 0x0648, 0xfeee, 0xfeed, 1, 0, 0 },
|
||||
{ 0x0649, 0x0649, 0xfef0, 0xfeef, 1, 0, 0 },
|
||||
{ 0xfef3, 0xfef4, 0xfef2, 0xfef1, 1, 1, 0 },
|
||||
{ 0x064b, 0x064b, 0x064b, 0x064b, 0, 0, 0 },
|
||||
{ 0x064c, 0x064c, 0x064c, 0x064c, 0, 0, 0 },
|
||||
{ 0x064d, 0x064d, 0x064d, 0x064d, 0, 0, 0 },
|
||||
{ 0x064e, 0x064e, 0x064e, 0x064e, 0, 0, 0 },
|
||||
{ 0x064f, 0x064f, 0x064f, 0x064f, 0, 0, 0 },
|
||||
{ 0x0650, 0x0650, 0x0650, 0x0650, 0, 0, 0 },
|
||||
{ 0x0651, 0x0651, 0x0651, 0x0651, 0, 0, 0 },
|
||||
{ 0x0652, 0x0652, 0x0652, 0x0652, 0, 0, 0 },
|
||||
{ 0x0653, 0x0653, 0x0653, 0x0653, 0, 0, 0 },
|
||||
{ 0x0654, 0x0654, 0x0654, 0x0654, 0, 0, 0 },
|
||||
{ 0x0655, 0x0655, 0x0655, 0x0655, 0, 0, 0 },
|
||||
{ 0x0656, 0x0656, 0x0656, 0x0656, 0, 0, 0 },
|
||||
{ 0x0657, 0x0657, 0x0657, 0x0657, 0, 0, 0 },
|
||||
{ 0x0658, 0x0658, 0x0658, 0x0658, 0, 0, 0 },
|
||||
{ 0x0659, 0x0659, 0x0659, 0x0659, 0, 0, 0 },
|
||||
{ 0x065a, 0x065a, 0x065a, 0x065a, 0, 0, 0 },
|
||||
{ 0x065b, 0x065b, 0x065b, 0x065b, 0, 0, 0 },
|
||||
{ 0x065c, 0x065c, 0x065c, 0x065c, 0, 0, 0 },
|
||||
{ 0x065d, 0x065d, 0x065d, 0x065d, 0, 0, 0 },
|
||||
{ 0x065e, 0x065e, 0x065e, 0x065e, 0, 0, 0 },
|
||||
{ 0x0000, 0x0000, 0x0000, 0x0000, 0, 0, 0 },
|
||||
{ 0x0660, 0x0660, 0x0660, 0x0660, 0, 0, 0 },
|
||||
{ 0x0661, 0x0661, 0x0661, 0x0661, 0, 0, 0 },
|
||||
{ 0x0662, 0x0662, 0x0662, 0x0662, 0, 0, 0 },
|
||||
{ 0x0663, 0x0663, 0x0663, 0x0663, 0, 0, 0 },
|
||||
{ 0x0664, 0x0664, 0x0664, 0x0664, 0, 0, 0 },
|
||||
{ 0x0665, 0x0665, 0x0665, 0x0665, 0, 0, 0 },
|
||||
{ 0x0666, 0x0666, 0x0666, 0x0666, 0, 0, 0 },
|
||||
{ 0x0667, 0x0667, 0x0667, 0x0667, 0, 0, 0 },
|
||||
{ 0x0668, 0x0668, 0x0668, 0x0668, 0, 0, 0 },
|
||||
{ 0x0669, 0x0669, 0x0669, 0x0669, 0, 0, 0 },
|
||||
{ 0x066a, 0x066a, 0x066a, 0x066a, 0, 0, 0 },
|
||||
{ 0x066b, 0x066b, 0x066b, 0x066b, 0, 0, 0 },
|
||||
{ 0x066c, 0x066c, 0x066c, 0x066c, 0, 0, 0 },
|
||||
{ 0x066d, 0x066d, 0x066d, 0x066d, 0, 0, 0 },
|
||||
{ 0x066e, 0x066e, 0x066e, 0x066e, 1, 0, 0 },
|
||||
{ 0x066f, 0x066f, 0x066f, 0x066f, 1, 0, 0 },
|
||||
{ 0x0670, 0x0670, 0x0670, 0x0670, 1, 0, 0 },
|
||||
{ 0x0671, 0x0671, 0xfb51, 0xfb50, 1, 0, 0 },
|
||||
{ 0x0672, 0x0672, 0x0672, 0x0672, 1, 0, 0 },
|
||||
{ 0x0673, 0x0673, 0x0673, 0x0673, 1, 0, 0 },
|
||||
{ 0x0674, 0x0674, 0x0674, 0x0674, 1, 0, 0 },
|
||||
{ 0x0675, 0x0675, 0x0675, 0x0675, 1, 0, 0 },
|
||||
{ 0x0676, 0x0676, 0x0676, 0x0676, 1, 0, 0 },
|
||||
{ 0x0677, 0x0677, 0x0677, 0xfbdd, 1, 0, 0 },
|
||||
{ 0x0678, 0x0678, 0x0678, 0x0678, 1, 0, 0 },
|
||||
{ 0xfb68, 0xfb69, 0xfb67, 0xfb66, 1, 1, 0 },
|
||||
{ 0xfb60, 0xfb61, 0xfb5f, 0xfb5e, 1, 1, 0 },
|
||||
{ 0xfb54, 0xfb55, 0xfb53, 0xfb52, 1, 1, 0 },
|
||||
{ 0x067c, 0x067c, 0x067c, 0x067c, 1, 0, 0 },
|
||||
{ 0x067d, 0x067d, 0x067d, 0x067d, 1, 0, 0 },
|
||||
{ 0xfb58, 0xfb59, 0xfb57, 0xfb56, 1, 1, 0 },
|
||||
{ 0xfb64, 0xfb65, 0xfb63, 0xfb62, 1, 1, 0 },
|
||||
{ 0xfb5c, 0xfb5d, 0xfb5b, 0xfb5a, 1, 1, 0 },
|
||||
{ 0x0681, 0x0681, 0x0681, 0x0681, 1, 0, 0 },
|
||||
{ 0x0682, 0x0682, 0x0682, 0x0682, 1, 0, 0 },
|
||||
{ 0xfb78, 0xfb79, 0xfb77, 0xfb76, 1, 1, 0 },
|
||||
{ 0xfb74, 0xfb75, 0xfb73, 0xfb72, 1, 1, 0 },
|
||||
{ 0x0685, 0x0685, 0x0685, 0x0685, 1, 0, 0 },
|
||||
{ 0xfb7c, 0xfb7d, 0xfb7b, 0xfb7a, 1, 1, 0 },
|
||||
{ 0xfb80, 0xfb81, 0xfb7f, 0xfb7e, 1, 1, 0 },
|
||||
{ 0x0688, 0x0688, 0xfb89, 0xfb88, 1, 0, 0 },
|
||||
{ 0x0689, 0x0689, 0x0689, 0x0689, 1, 0, 0 },
|
||||
{ 0x068a, 0x068a, 0x068a, 0x068a, 1, 0, 0 },
|
||||
{ 0x068b, 0x068b, 0x068b, 0x068b, 1, 0, 0 },
|
||||
{ 0x068c, 0x068c, 0xfb85, 0xfb84, 1, 0, 0 },
|
||||
{ 0x068d, 0x068d, 0xfb83, 0xfb82, 1, 0, 0 },
|
||||
{ 0x068e, 0x068e, 0xfb87, 0xfb86, 1, 0, 0 },
|
||||
{ 0x068f, 0x068f, 0x068f, 0x068f, 1, 0, 0 },
|
||||
{ 0x0690, 0x0690, 0x0690, 0x0690, 1, 0, 0 },
|
||||
{ 0x0691, 0x0691, 0xfb8d, 0xfb8c, 1, 0, 0 },
|
||||
{ 0x0692, 0x0692, 0x0692, 0x0692, 1, 0, 0 },
|
||||
{ 0x0693, 0x0693, 0x0693, 0x0693, 1, 0, 0 },
|
||||
{ 0x0694, 0x0694, 0x0694, 0x0694, 1, 0, 0 },
|
||||
{ 0x0695, 0x0695, 0x0695, 0x0695, 1, 0, 0 },
|
||||
{ 0x0696, 0x0696, 0x0696, 0x0696, 1, 0, 0 },
|
||||
{ 0x0697, 0x0697, 0x0697, 0x0697, 1, 0, 0 },
|
||||
{ 0x0698, 0x0698, 0xfb8b, 0xfb8a, 1, 0, 0 },
|
||||
{ 0x0699, 0x0699, 0x0699, 0x0699, 1, 0, 0 },
|
||||
{ 0x069a, 0x069a, 0x069a, 0x069a, 1, 0, 0 },
|
||||
{ 0x069b, 0x069b, 0x069b, 0x069b, 1, 0, 0 },
|
||||
{ 0x069c, 0x069c, 0x069c, 0x069c, 1, 0, 0 },
|
||||
{ 0x069d, 0x069d, 0x069d, 0x069d, 1, 0, 0 },
|
||||
{ 0x069e, 0x069e, 0x069e, 0x069e, 1, 0, 0 },
|
||||
{ 0x069f, 0x069f, 0x069f, 0x069f, 1, 0, 0 },
|
||||
{ 0x06a0, 0x06a0, 0x06a0, 0x06a0, 1, 0, 0 },
|
||||
{ 0x06a1, 0x06a1, 0x06a1, 0x06a1, 1, 0, 0 },
|
||||
{ 0x06a2, 0x06a2, 0x06a2, 0x06a2, 1, 0, 0 },
|
||||
{ 0x06a3, 0x06a3, 0x06a3, 0x06a3, 1, 0, 0 },
|
||||
{ 0xfb6c, 0xfb6d, 0xfb6b, 0xfb6a, 1, 1, 0 },
|
||||
{ 0x06a5, 0x06a5, 0x06a5, 0x06a5, 1, 0, 0 },
|
||||
{ 0xfb70, 0xfb71, 0xfb6f, 0xfb6e, 1, 1, 0 },
|
||||
{ 0x06a7, 0x06a7, 0x06a7, 0x06a7, 1, 0, 0 },
|
||||
{ 0x06a8, 0x06a8, 0x06a8, 0x06a8, 1, 0, 0 },
|
||||
{ 0xfb90, 0xfb91, 0xfb8f, 0xfb8e, 1, 1, 0 },
|
||||
{ 0x06aa, 0x06aa, 0x06aa, 0x06aa, 1, 0, 0 },
|
||||
{ 0x06ab, 0x06ab, 0x06ab, 0x06ab, 1, 0, 0 },
|
||||
{ 0x06ac, 0x06ac, 0x06ac, 0x06ac, 1, 0, 0 },
|
||||
{ 0xfbd5, 0xfbd6, 0xfbd4, 0xfbd3, 1, 1, 0 },
|
||||
{ 0x06ae, 0x06ae, 0x06ae, 0x06ae, 1, 0, 0 },
|
||||
{ 0xfb94, 0xfb95, 0xfb93, 0xfb92, 1, 1, 0 },
|
||||
{ 0x06b0, 0x06b0, 0x06b0, 0x06b0, 1, 0, 0 },
|
||||
{ 0xfb9c, 0xfb9d, 0xfb9b, 0xfb9a, 1, 1, 0 },
|
||||
{ 0x06b2, 0x06b2, 0x06b2, 0x06b2, 1, 0, 0 },
|
||||
{ 0xfb98, 0xfb99, 0xfb97, 0xfb96, 1, 1, 0 },
|
||||
{ 0x06b4, 0x06b4, 0x06b4, 0x06b4, 1, 0, 0 },
|
||||
{ 0x06b5, 0x06b5, 0x06b5, 0x06b5, 1, 0, 0 },
|
||||
{ 0x06b6, 0x06b6, 0x06b6, 0x06b6, 1, 0, 0 },
|
||||
{ 0x06b7, 0x06b7, 0x06b7, 0x06b7, 1, 0, 0 },
|
||||
{ 0x06b8, 0x06b8, 0x06b8, 0x06b8, 1, 0, 0 },
|
||||
{ 0x06b9, 0x06b9, 0x06b9, 0x06b9, 1, 0, 0 },
|
||||
{ 0x06ba, 0x06ba, 0xfb9f, 0xfb9e, 1, 0, 0 },
|
||||
{ 0xfba2, 0xfba3, 0xfba1, 0xfba0, 1, 1, 0 },
|
||||
{ 0x06bc, 0x06bc, 0x06bc, 0x06bc, 1, 0, 0 },
|
||||
{ 0x06bd, 0x06bd, 0x06bd, 0x06bd, 1, 0, 0 },
|
||||
{ 0xfbac, 0xfbad, 0xfbab, 0xfbaa, 1, 1, 0 },
|
||||
{ 0x06bf, 0x06bf, 0x06bf, 0x06bf, 1, 0, 0 },
|
||||
{ 0x06c0, 0x06c0, 0xfba5, 0xfba4, 1, 0, 0 },
|
||||
{ 0xfba8, 0xfba9, 0xfba7, 0xfba6, 1, 1, 0 },
|
||||
{ 0x06c2, 0x06c2, 0x06c2, 0x06c2, 1, 0, 0 },
|
||||
{ 0x06c3, 0x06c3, 0x06c3, 0x06c3, 1, 0, 0 },
|
||||
{ 0x06c4, 0x06c4, 0x06c4, 0x06c4, 1, 0, 0 },
|
||||
{ 0x06c5, 0x06c5, 0xfbe1, 0xfbe0, 1, 0, 0 },
|
||||
{ 0x06c6, 0x06c6, 0xfbda, 0xfbd9, 1, 0, 0 },
|
||||
{ 0x06c7, 0x06c7, 0xfbd8, 0xfbd7, 1, 0, 0 },
|
||||
{ 0x06c8, 0x06c8, 0xfbdc, 0xfbdb, 1, 0, 0 },
|
||||
{ 0x06c9, 0x06c9, 0xfbe3, 0xfbe2, 1, 0, 0 },
|
||||
{ 0x06ca, 0x06ca, 0x06ca, 0x06ca, 1, 0, 0 },
|
||||
{ 0x06cb, 0x06cb, 0xfbdf, 0xfbde, 1, 0, 0 },
|
||||
{ 0xfbfe, 0xfbff, 0xfbfd, 0xfbfc, 1, 1, 0 },
|
||||
{ 0x06cd, 0x06cd, 0x06cd, 0x06cd, 1, 0, 0 },
|
||||
{ 0x06ce, 0x06ce, 0x06ce, 0x06ce, 1, 0, 0 },
|
||||
{ 0x06cf, 0x06cf, 0x06cf, 0x06cf, 1, 0, 0 },
|
||||
{ 0xfbe6, 0xfbe7, 0xfbe5, 0xfbe4, 1, 1, 0 },
|
||||
{ 0x06d1, 0x06d1, 0x06d1, 0x06d1, 1, 0, 0 },
|
||||
{ 0x06d2, 0x06d2, 0xfbaf, 0xfbae, 1, 0, 0 },
|
||||
{ 0x06d3, 0x06d3, 0xfbb1, 0xfbb0, 1, 0, 0 },
|
||||
{ 0x06d4, 0x06d4, 0x06d4, 0x06d4, 0, 0, 0 },
|
||||
{ 0x06d5, 0x06d5, 0x06d5, 0x06d5, 1, 0, 0 },
|
||||
{ 0x06d6, 0x06d6, 0x06d6, 0x06d6, 0, 0, 0 },
|
||||
{ 0x06d7, 0x06d7, 0x06d7, 0x06d7, 0, 0, 0 },
|
||||
{ 0x06d8, 0x06d8, 0x06d8, 0x06d8, 0, 0, 0 },
|
||||
{ 0x06d9, 0x06d9, 0x06d9, 0x06d9, 0, 0, 0 },
|
||||
{ 0x06da, 0x06da, 0x06da, 0x06da, 0, 0, 0 },
|
||||
{ 0x06db, 0x06db, 0x06db, 0x06db, 0, 0, 0 },
|
||||
{ 0x06dc, 0x06dc, 0x06dc, 0x06dc, 0, 0, 0 },
|
||||
{ 0x06dd, 0x06dd, 0x06dd, 0x06dd, 0, 0, 0 },
|
||||
{ 0x06de, 0x06de, 0x06de, 0x06de, 0, 0, 0 },
|
||||
{ 0x06df, 0x06df, 0x06df, 0x06df, 0, 0, 0 },
|
||||
{ 0x06e0, 0x06e0, 0x06e0, 0x06e0, 0, 0, 0 },
|
||||
{ 0x06e1, 0x06e1, 0x06e1, 0x06e1, 0, 0, 0 },
|
||||
{ 0x06e2, 0x06e2, 0x06e2, 0x06e2, 0, 0, 0 },
|
||||
{ 0x06e3, 0x06e3, 0x06e3, 0x06e3, 0, 0, 0 },
|
||||
{ 0x06e4, 0x06e4, 0x06e4, 0x06e4, 0, 0, 0 },
|
||||
{ 0x06e5, 0x06e5, 0x06e5, 0x06e5, 0, 0, 0 },
|
||||
{ 0x06e6, 0x06e6, 0x06e6, 0x06e6, 0, 0, 0 },
|
||||
{ 0x06e7, 0x06e7, 0x06e7, 0x06e7, 0, 0, 0 },
|
||||
{ 0x06e8, 0x06e8, 0x06e8, 0x06e8, 0, 0, 0 },
|
||||
{ 0x06e9, 0x06e9, 0x06e9, 0x06e9, 0, 0, 0 },
|
||||
{ 0x06ea, 0x06ea, 0x06ea, 0x06ea, 0, 0, 0 },
|
||||
{ 0x06eb, 0x06eb, 0x06eb, 0x06eb, 0, 0, 0 },
|
||||
{ 0x06ec, 0x06ec, 0x06ec, 0x06ec, 0, 0, 0 },
|
||||
{ 0x06ed, 0x06ed, 0x06ed, 0x06ed, 0, 0, 0 },
|
||||
{ 0x06ee, 0x06ee, 0x06ee, 0x06ee, 1, 0, 0 },
|
||||
{ 0x06ef, 0x06ef, 0x06ef, 0x06ef, 1, 0, 0 },
|
||||
{ 0x06f0, 0x06f0, 0x06f0, 0x06f0, 0, 0, 0 },
|
||||
{ 0x06f1, 0x06f1, 0x06f1, 0x06f1, 0, 0, 0 },
|
||||
{ 0x06f2, 0x06f2, 0x06f2, 0x06f2, 0, 0, 0 },
|
||||
{ 0x06f3, 0x06f3, 0x06f3, 0x06f3, 0, 0, 0 },
|
||||
{ 0x06f4, 0x06f4, 0x06f4, 0x06f4, 0, 0, 0 },
|
||||
{ 0x06f5, 0x06f5, 0x06f5, 0x06f5, 0, 0, 0 },
|
||||
{ 0x06f6, 0x06f6, 0x06f6, 0x06f6, 0, 0, 0 },
|
||||
{ 0x06f7, 0x06f7, 0x06f7, 0x06f7, 0, 0, 0 },
|
||||
{ 0x06f8, 0x06f8, 0x06f8, 0x06f8, 0, 0, 0 },
|
||||
{ 0x06f9, 0x06f9, 0x06f9, 0x06f9, 0, 0, 0 },
|
||||
{ 0x06fa, 0x06fa, 0x06fa, 0x06fa, 1, 0, 0 },
|
||||
{ 0x06fb, 0x06fb, 0x06fb, 0x06fb, 1, 0, 0 },
|
||||
{ 0x06fc, 0x06fc, 0x06fc, 0x06fc, 1, 0, 0 },
|
||||
{ 0x06fd, 0x06fd, 0x06fd, 0x06fd, 0, 0, 0 },
|
||||
{ 0x06fe, 0x06fe, 0x06fe, 0x06fe, 0, 0, 0 },
|
||||
{ 0x06ff, 0x06ff, 0x06ff, 0x06ff, 1, 0, 0 }
|
||||
};
|
||||
|
||||
bool Arabic::IsArabic(WCHAR c)
|
||||
{
|
||||
return c >= 0x600 && c <= 0x6ff;
|
||||
}
|
||||
|
||||
bool Arabic::Replace(WCHAR& c, pres_form_t pf)
|
||||
{
|
||||
if(!IsArabic(c)) return false;
|
||||
|
||||
const arabicforms& af = ArabicForms[c - 0x600];
|
||||
|
||||
switch(pf)
|
||||
{
|
||||
case isol: c = af.isolated; break;
|
||||
case init: c = af.initial; break;
|
||||
case medi: c = af.medial; break;
|
||||
case fina: c = af.final; break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Arabic::Replace(WCHAR& c, WCHAR prev, WCHAR next)
|
||||
{
|
||||
if(!IsArabic(c)) return false;
|
||||
|
||||
bool p = IsArabic(prev);
|
||||
bool n = IsArabic(next);
|
||||
|
||||
return Replace(c, p ? (n ? medi : fina) : (n ? init : isol));
|
||||
}
|
||||
}
|
34
vsfilter/libssf/Arabic.h
Normal file
34
vsfilter/libssf/Arabic.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Arabic
|
||||
{
|
||||
public:
|
||||
enum pres_form_t {isol, init, medi, fina};
|
||||
static bool IsArabic(WCHAR c);
|
||||
static bool Replace(WCHAR& c, pres_form_t pf);
|
||||
static bool Replace(WCHAR& c, WCHAR prev, WCHAR next);
|
||||
};
|
||||
}
|
28
vsfilter/libssf/Array.cpp
Normal file
28
vsfilter/libssf/Array.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Array.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
|
||||
}
|
108
vsfilter/libssf/Array.h
Normal file
108
vsfilter/libssf/Array.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
// simple array class for simple types without constructors,
|
||||
// and it doesn't free its reserves on SetCount(0)
|
||||
|
||||
template<class T>
|
||||
class Array
|
||||
{
|
||||
T* m_pData;
|
||||
size_t m_nSize;
|
||||
size_t m_nMaxSize;
|
||||
size_t m_nGrowBy;
|
||||
|
||||
public:
|
||||
Array() {m_pData = NULL; m_nSize = m_nMaxSize = 0; m_nGrowBy = 4096;}
|
||||
virtual ~Array() {if(m_pData) _aligned_free(m_pData);}
|
||||
|
||||
void SetCount(size_t nSize, size_t nGrowBy = 0)
|
||||
{
|
||||
if(nGrowBy > 0)
|
||||
{
|
||||
m_nGrowBy = nGrowBy;
|
||||
}
|
||||
|
||||
if(nSize > m_nMaxSize)
|
||||
{
|
||||
m_nMaxSize = nSize + max(m_nGrowBy, m_nSize);
|
||||
size_t nBytes = m_nMaxSize * sizeof(T);
|
||||
m_pData = m_pData ? (T*)_aligned_realloc(m_pData, nBytes, 16) : (T*)_aligned_malloc(nBytes, 16);
|
||||
}
|
||||
|
||||
m_nSize = nSize;
|
||||
}
|
||||
|
||||
size_t GetCount() const {return m_nSize;}
|
||||
|
||||
void RemoveAll() {m_nSize = 0;}
|
||||
bool IsEmpty() const {return m_nSize == 0;}
|
||||
|
||||
T* GetData() {return m_pData;}
|
||||
|
||||
void Add(const T& t)
|
||||
{
|
||||
size_t nPos = m_nSize;
|
||||
SetCount(m_nSize+1);
|
||||
m_pData[nPos] = t;
|
||||
}
|
||||
|
||||
void Append(const Array& a, size_t nGrowBy = 0)
|
||||
{
|
||||
Append(a.m_pData, a.m_nSize, nGrowBy);
|
||||
}
|
||||
|
||||
void Append(const T* ptr, size_t nSize, size_t nGrowBy = 0)
|
||||
{
|
||||
if(!nSize) return;
|
||||
size_t nOldSize = m_nSize;
|
||||
SetCount(nOldSize + nSize);
|
||||
memcpy(m_pData + nOldSize, ptr, nSize * sizeof(T));
|
||||
}
|
||||
|
||||
const T& operator [] (size_t i) const {return m_pData[i];}
|
||||
T& operator [] (size_t i) {return m_pData[i];}
|
||||
|
||||
void Copy(const Array& v)
|
||||
{
|
||||
SetCount(v.GetCount());
|
||||
memcpy(m_pData, v.m_pData, m_nSize * sizeof(T));
|
||||
}
|
||||
|
||||
void Move(Array& v)
|
||||
{
|
||||
Swap(v);
|
||||
v.SetCount(0);
|
||||
}
|
||||
|
||||
void Swap(Array& v)
|
||||
{
|
||||
T* pData = m_pData; m_pData = v.m_pData; v.m_pData = pData;
|
||||
size_t nSize = m_nSize; m_nSize = v.m_nSize; v.m_nSize = nSize;
|
||||
size_t nMaxSize = m_nMaxSize; m_nMaxSize = v.m_nMaxSize; v.m_nMaxSize = nMaxSize;
|
||||
size_t nGrowBy = m_nGrowBy; m_nGrowBy = v.m_nGrowBy; v.m_nGrowBy = nGrowBy;
|
||||
}
|
||||
};
|
||||
}
|
35
vsfilter/libssf/Exception.cpp
Normal file
35
vsfilter/libssf/Exception.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Exception.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
Exception::Exception(LPCTSTR fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = _vsctprintf(fmt, args) + 1;
|
||||
if(len > 0) _vstprintf_s(m_msg.GetBufferSetLength(len), len, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
35
vsfilter/libssf/Exception.h
Normal file
35
vsfilter/libssf/Exception.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Exception
|
||||
{
|
||||
CString m_msg;
|
||||
|
||||
public:
|
||||
Exception(LPCTSTR fmt, ...);
|
||||
|
||||
CString ToString() {return m_msg;}
|
||||
};
|
||||
}
|
261
vsfilter/libssf/File.cpp
Normal file
261
vsfilter/libssf/File.cpp
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "File.h"
|
||||
|
||||
#ifndef iswcsym
|
||||
#define iswcsym(c) (iswalnum(c) || (c) == '_')
|
||||
#endif
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
File::File()
|
||||
{
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
}
|
||||
|
||||
void File::Parse(InputStream& s, LPCWSTR predef)
|
||||
{
|
||||
Reference* pRef = CreateRootRef();
|
||||
|
||||
SetPredefined(true);
|
||||
|
||||
try {ParseDefs(WCharInputStream(predef), pRef);}
|
||||
catch(Exception& e) {ASSERT(0); TRACE(_T("%s\n"), e.ToString());}
|
||||
|
||||
SetPredefined(false);
|
||||
|
||||
ParseDefs(s, pRef);
|
||||
|
||||
Commit();
|
||||
|
||||
if(s.PeekChar() != Stream::EOS)
|
||||
{
|
||||
TRACE(_T("Warning: parsing ended before EOF!\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void File::ParseDefs(InputStream& s, Reference* pParentRef)
|
||||
{
|
||||
while(s.SkipWhiteSpace(L";") != '}' && s.PeekChar() != Stream::EOS)
|
||||
{
|
||||
NodePriority priority = PNormal;
|
||||
CAtlList<CStringW> types;
|
||||
CStringW name;
|
||||
|
||||
int c = s.SkipWhiteSpace();
|
||||
|
||||
if(c == '*') {s.GetChar(); priority = PLow;}
|
||||
else if(c == '!') {s.GetChar(); priority = PHigh;}
|
||||
|
||||
ParseTypes(s, types);
|
||||
|
||||
if(s.SkipWhiteSpace() == '#')
|
||||
{
|
||||
s.GetChar();
|
||||
ParseName(s, name);
|
||||
}
|
||||
|
||||
if(types.IsEmpty())
|
||||
{
|
||||
if(name.IsEmpty()) s.ThrowError(_T("syntax error"));
|
||||
types.AddTail(L"?");
|
||||
}
|
||||
|
||||
Reference* pRef = pParentRef;
|
||||
|
||||
while(types.GetCount() > 1)
|
||||
pRef = CreateRef(CreateDef(pRef, types.RemoveHead()));
|
||||
|
||||
Definition* pDef = NULL;
|
||||
|
||||
if(!types.IsEmpty())
|
||||
pDef = CreateDef(pRef, types.RemoveHead(), name, priority);
|
||||
|
||||
c = s.SkipWhiteSpace(L":=");
|
||||
|
||||
if(c == '"' || c == '\'') ParseQuotedString(s, pDef);
|
||||
else if(iswdigit(c) || c == '+' || c == '-') ParseNumber(s, pDef);
|
||||
else if(pDef->IsType(L"@")) ParseBlock(s, pDef);
|
||||
else ParseRefs(s, pDef);
|
||||
}
|
||||
|
||||
s.GetChar();
|
||||
}
|
||||
|
||||
void File::ParseTypes(InputStream& s, CAtlList<CStringW>& types)
|
||||
{
|
||||
types.RemoveAll();
|
||||
|
||||
CStringW str;
|
||||
|
||||
for(int c = s.SkipWhiteSpace(); iswcsym(c) || c == '.' || c == '@'; c = s.PeekChar())
|
||||
{
|
||||
c = s.GetChar();
|
||||
|
||||
if(c == '.')
|
||||
{
|
||||
if(str.IsEmpty()) s.ThrowError(_T("'type' cannot be an empty string"));
|
||||
if(!iswcsym(s.PeekChar())) s.ThrowError(_T("unexpected dot after type '%s'"), CString(str));
|
||||
|
||||
types.AddTail(str);
|
||||
str.Empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(str.IsEmpty() && iswdigit(c)) s.ThrowError(_T("'type' cannot start with a number"));
|
||||
if((!str.IsEmpty() || !types.IsEmpty()) && c == '@') s.ThrowError(_T("unexpected @ in 'type'"));
|
||||
|
||||
str += (WCHAR)c;
|
||||
}
|
||||
}
|
||||
|
||||
if(!str.IsEmpty())
|
||||
{
|
||||
types.AddTail(str);
|
||||
}
|
||||
}
|
||||
|
||||
void File::ParseName(InputStream& s, CStringW& name)
|
||||
{
|
||||
name.Empty();
|
||||
|
||||
for(int c = s.SkipWhiteSpace(); iswcsym(c); c = s.PeekChar())
|
||||
{
|
||||
if(name.IsEmpty() && iswdigit(c)) s.ThrowError(_T("'name' cannot start with a number"));
|
||||
name += (WCHAR)s.GetChar();
|
||||
}
|
||||
}
|
||||
|
||||
void File::ParseQuotedString(InputStream& s, Definition* pDef)
|
||||
{
|
||||
CStringW v;
|
||||
|
||||
int quote = s.SkipWhiteSpace();
|
||||
if(quote != '"' && quote != '\'') s.ThrowError(_T("expected qouted string"));
|
||||
s.GetChar();
|
||||
|
||||
for(int c = s.PeekChar(); c != Stream::EOS; c = s.PeekChar())
|
||||
{
|
||||
c = s.GetChar();
|
||||
if(c == quote) {pDef->SetAsValue(Definition::string, v); return;}
|
||||
if(c == '\n') s.ThrowError(_T("qouted string terminated unexpectedly by a new-line character"));
|
||||
if(c == '\\') c = s.GetChar();
|
||||
if(c == Stream::EOS) s.ThrowError(_T("qouted string terminated unexpectedly by EOS"));
|
||||
v += (WCHAR)c;
|
||||
}
|
||||
|
||||
s.ThrowError(_T("unterminated quoted string"));
|
||||
}
|
||||
|
||||
void File::ParseNumber(InputStream& s, Definition* pDef)
|
||||
{
|
||||
CStringW v, u;
|
||||
|
||||
for(int c = s.SkipWhiteSpace(); iswxdigit(c) || wcschr(L"+-.x:", c); c = s.PeekChar())
|
||||
{
|
||||
if((c == '+' || c == '-') && !v.IsEmpty()
|
||||
|| (c == '.' && (v.IsEmpty() || v.Find('.') >= 0 || v.Find('x') >= 0))
|
||||
|| (c == 'x' && v != '0')
|
||||
|| (c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') && v.Find(L"0x") != 0
|
||||
|| (c == ':' && v.IsEmpty()))
|
||||
{
|
||||
s.ThrowError(_T("unexpected character '%c' in number"), (TCHAR)c);
|
||||
}
|
||||
|
||||
v += (WCHAR)s.GetChar();
|
||||
}
|
||||
|
||||
if(v.IsEmpty()) s.ThrowError(_T("invalid number"));
|
||||
|
||||
for(int c = s.SkipWhiteSpace(); iswcsym(c); c = s.PeekChar())
|
||||
{
|
||||
u += (WCHAR)s.GetChar();
|
||||
}
|
||||
|
||||
pDef->SetAsNumber(v, u);
|
||||
}
|
||||
|
||||
void File::ParseBlock(InputStream& s, Definition* pDef)
|
||||
{
|
||||
CStringW v;
|
||||
|
||||
int c = s.SkipWhiteSpace(L":=");
|
||||
if(c != '{') s.ThrowError(_T("expected '{'"));
|
||||
s.GetChar();
|
||||
|
||||
int depth = 0;
|
||||
|
||||
for(int c = s.PeekChar(); c != Stream::EOS; c = s.PeekChar())
|
||||
{
|
||||
c = s.GetChar();
|
||||
if(c == '}' && depth == 0) {pDef->SetAsValue(Definition::block, v); return;}
|
||||
if(c == '\\') {v += (WCHAR)c; c = s.GetChar();}
|
||||
else if(c == '{') depth++;
|
||||
else if(c == '}') depth--;
|
||||
if(c == Stream::EOS) s.ThrowError(_T("block terminated unexpectedly by EOS"));
|
||||
v += (WCHAR)c;
|
||||
}
|
||||
|
||||
s.ThrowError(_T("unterminated block"));
|
||||
}
|
||||
|
||||
void File::ParseRefs(InputStream& s, Definition* pParentDef, LPCWSTR term)
|
||||
{
|
||||
int c = s.SkipWhiteSpace();
|
||||
|
||||
do
|
||||
{
|
||||
if(pParentDef->IsValue()) s.ThrowError(_T("cannot mix references with other values"));
|
||||
|
||||
if(c == '{')
|
||||
{
|
||||
s.GetChar();
|
||||
ParseDefs(s, CreateRef(pParentDef));
|
||||
}
|
||||
else if(iswcsym(c))
|
||||
{
|
||||
CStringW str;
|
||||
ParseName(s, str);
|
||||
|
||||
// TODO: allow spec references: parent.<type>, self.<type>, child.<type>
|
||||
|
||||
Definition* pDef = GetDefByName(str);
|
||||
if(!pDef) s.ThrowError(_T("cannot find definition of '%s'"), CString(str));
|
||||
|
||||
if(!pParentDef->IsVisible(pDef)) s.ThrowError(_T("cannot access '%s' from here"), CString(str));
|
||||
|
||||
pParentDef->AddTail(pDef);
|
||||
}
|
||||
else if(!wcschr(term, c) && c != Stream::EOS)
|
||||
{
|
||||
s.ThrowError(_T("unexpected character '%c'"), (TCHAR)c);
|
||||
}
|
||||
|
||||
c = s.SkipWhiteSpace();
|
||||
}
|
||||
while(!wcschr(term, c) && c != Stream::EOS);
|
||||
}
|
||||
}
|
45
vsfilter/libssf/File.h
Normal file
45
vsfilter/libssf/File.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "NodeFactory.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class File : public NodeFactory
|
||||
{
|
||||
public:
|
||||
File();
|
||||
virtual ~File();
|
||||
|
||||
void Parse(InputStream& s, LPCWSTR predef = NULL);
|
||||
|
||||
void ParseDefs(InputStream& s, Reference* pParentRef);
|
||||
void ParseTypes(InputStream& s, CAtlList<CStringW>& types);
|
||||
void ParseName(InputStream& s, CStringW& name);
|
||||
void ParseQuotedString(InputStream& s, Definition* pDef);
|
||||
void ParseNumber(InputStream& s, Definition* pDef);
|
||||
void ParseBlock(InputStream& s, Definition* pDef);
|
||||
void ParseRefs(InputStream& s, Definition* pParentDef, LPCWSTR term = L";}]");
|
||||
};
|
||||
}
|
57
vsfilter/libssf/FontWrapper.cpp
Normal file
57
vsfilter/libssf/FontWrapper.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "FontWrapper.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
FontWrapper::FontWrapper(HDC hDC, HFONT hFont, const CStringW& key)
|
||||
: m_hFont(hFont)
|
||||
, m_key(key)
|
||||
{
|
||||
HFONT hFontOld = SelectFont(hDC, hFont);
|
||||
|
||||
GetTextMetrics(hDC, &m_tm);
|
||||
|
||||
if(DWORD nNumPairs = GetKerningPairs(hDC, 0, NULL))
|
||||
{
|
||||
KERNINGPAIR* kp = new KERNINGPAIR[nNumPairs];
|
||||
GetKerningPairs(hDC, nNumPairs, kp);
|
||||
for(DWORD i = 0; i < nNumPairs; i++)
|
||||
m_kerning[(kp[i].wFirst<<16)|kp[i].wSecond] = kp[i].iKernAmount;
|
||||
delete [] kp;
|
||||
}
|
||||
|
||||
SelectFont(hDC, hFontOld);
|
||||
}
|
||||
|
||||
FontWrapper::~FontWrapper()
|
||||
{
|
||||
DeleteFont(m_hFont);
|
||||
}
|
||||
|
||||
int FontWrapper::GetKernAmount(WCHAR c1, WCHAR c2)
|
||||
{
|
||||
int size = 0;
|
||||
return m_kerning.Lookup((c1<<16)|c2, size) ? size : 0;
|
||||
}
|
||||
}
|
41
vsfilter/libssf/FontWrapper.h
Normal file
41
vsfilter/libssf/FontWrapper.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class FontWrapper
|
||||
{
|
||||
HFONT m_hFont;
|
||||
CStringW m_key;
|
||||
TEXTMETRIC m_tm;
|
||||
CAtlMap<DWORD, int> m_kerning;
|
||||
|
||||
public:
|
||||
FontWrapper(HDC hDC, HFONT hFont, const CStringW& key);
|
||||
virtual ~FontWrapper();
|
||||
operator HFONT() const {return m_hFont;}
|
||||
operator LPCWSTR() const {return m_key;}
|
||||
const TEXTMETRIC& GetTextMetric() {return m_tm;}
|
||||
int GetKernAmount(WCHAR c1, WCHAR c2);
|
||||
};
|
||||
}
|
306
vsfilter/libssf/Glyph.cpp
Normal file
306
vsfilter/libssf/Glyph.cpp
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Glyph.h"
|
||||
#include "Split.h"
|
||||
|
||||
#define deg2rad(d) (float)(M_PI/180*(d))
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
Glyph::Glyph()
|
||||
{
|
||||
c = 0;
|
||||
font = NULL;
|
||||
ascent = descent = width = spacing = fill = 0;
|
||||
tl.x = tl.y = tls.x = tls.y = 0;
|
||||
}
|
||||
|
||||
float Glyph::GetBackgroundSize() const
|
||||
{
|
||||
return style.background.size * (scale.cx + scale.cy) / 2;
|
||||
}
|
||||
|
||||
float Glyph::GetShadowDepth() const
|
||||
{
|
||||
return style.shadow.depth * (scale.cx + scale.cy) / 2;
|
||||
}
|
||||
|
||||
CRect Glyph::GetClipRect() const
|
||||
{
|
||||
CRect r = bbox + tl;
|
||||
|
||||
int size = (int)(GetBackgroundSize() + 0.5);
|
||||
int depth = (int)(GetShadowDepth() + 0.5);
|
||||
|
||||
r.InflateRect(size, size);
|
||||
r.InflateRect(depth, depth);
|
||||
|
||||
r.left >>= 6;
|
||||
r.top >>= 6;
|
||||
r.right = (r.right + 32) >> 6;
|
||||
r.bottom = (r.bottom + 32) >> 6;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void Glyph::CreateBkg()
|
||||
{
|
||||
path_bkg.RemoveAll();
|
||||
|
||||
if(style.background.type == L"enlarge" && style.background.size > 0)
|
||||
{
|
||||
path_bkg.Enlarge(path, GetBackgroundSize());
|
||||
}
|
||||
else if(style.background.type == L"box" && style.background.size >= 0)
|
||||
{
|
||||
if(c != ssf::Text::LSEP)
|
||||
{
|
||||
int s = (int)(GetBackgroundSize() + 0.5);
|
||||
int x0 = (!vertical ? -spacing/2 : ascent - row_ascent);
|
||||
int y0 = (!vertical ? ascent - row_ascent : -spacing/2);
|
||||
int x1 = x0 + (!vertical ? width + spacing : row_ascent + row_descent);
|
||||
int y1 = y0 + (!vertical ? row_ascent + row_descent : width + spacing);
|
||||
path_bkg.types.SetCount(4);
|
||||
path_bkg.types[0] = PT_MOVETO;
|
||||
path_bkg.types[1] = PT_LINETO;
|
||||
path_bkg.types[2] = PT_LINETO;
|
||||
path_bkg.types[3] = PT_LINETO;
|
||||
path_bkg.points.SetCount(4);
|
||||
path_bkg.points[0] = CPoint(x0-s, y0-s);
|
||||
path_bkg.points[1] = CPoint(x1+s, y0-s);
|
||||
path_bkg.points[2] = CPoint(x1+s, y1+s);
|
||||
path_bkg.points[3] = CPoint(x0-s, y1+s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Glyph::CreateSplineCoeffs(const CRect& spdrc)
|
||||
{
|
||||
spline.RemoveAll();
|
||||
|
||||
if(style.placement.path.IsEmpty())
|
||||
return;
|
||||
|
||||
size_t i = 0, j = style.placement.path.GetCount();
|
||||
|
||||
CAtlArray<Point> pts;
|
||||
pts.SetCount(j + 2);
|
||||
|
||||
Point p;
|
||||
|
||||
while(i < j)
|
||||
{
|
||||
p.x = style.placement.path[i].x * scale.cx + spdrc.left * 64;
|
||||
p.y = style.placement.path[i].y * scale.cy + spdrc.top * 64;
|
||||
pts[++i] = p;
|
||||
}
|
||||
|
||||
if(pts.GetCount() >= 4)
|
||||
{
|
||||
if(pts[1].x == pts[j].x && pts[1].y == pts[j].y)
|
||||
{
|
||||
pts.SetAt(0, pts[j-1]);
|
||||
pts.SetAt(j+1, pts[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.x = pts[1].x*2 - pts[2].x;
|
||||
p.y = pts[1].y*2 - pts[2].y;
|
||||
pts.SetAt(0, p);
|
||||
|
||||
p.x = pts[j].x*2 - pts[j-1].x;
|
||||
p.y = pts[j].y*2 - pts[j-1].y;
|
||||
pts.SetAt(j+1, p);
|
||||
}
|
||||
|
||||
spline.SetCount(pts.GetCount()-3);
|
||||
|
||||
for(size_t i = 0, j = pts.GetCount()-4; i <= j; i++)
|
||||
{
|
||||
static const float _1div6 = 1.0f / 6;
|
||||
|
||||
SplineCoeffs sc;
|
||||
|
||||
sc.cx[3] = _1div6*(- pts[i+0].x + 3*pts[i+1].x - 3*pts[i+2].x + pts[i+3].x);
|
||||
sc.cx[2] = _1div6*( 3*pts[i+0].x - 6*pts[i+1].x + 3*pts[i+2].x);
|
||||
sc.cx[1] = _1div6*(-3*pts[i+0].x + 3*pts[i+2].x);
|
||||
sc.cx[0] = _1div6*( pts[i+0].x + 4*pts[i+1].x + 1*pts[i+2].x);
|
||||
|
||||
sc.cy[3] = _1div6*(- pts[i+0].y + 3*pts[i+1].y - 3*pts[i+2].y + pts[i+3].y);
|
||||
sc.cy[2] = _1div6*( 3*pts[i+0].y - 6*pts[i+1].y + 3*pts[i+2].y);
|
||||
sc.cy[1] = _1div6*(-3*pts[i+0].y + 3*pts[i+2].y);
|
||||
sc.cy[0] = _1div6*( pts[i+0].y + 4*pts[i+1].y + 1*pts[i+2].y);
|
||||
|
||||
spline.SetAt(i, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Glyph::Transform(GlyphPath& path, CPoint org, const CRect& subrect)
|
||||
{
|
||||
// TODO: add sse code path
|
||||
|
||||
float sx = style.font.scale.cx;
|
||||
float sy = style.font.scale.cy;
|
||||
|
||||
bool brotate = style.placement.angle.x || style.placement.angle.y || style.placement.angle.z;
|
||||
bool bspline = !spline.IsEmpty();
|
||||
bool bscale = brotate || bspline || sx != 1 || sy != 1;
|
||||
|
||||
float caz = cos(deg2rad(style.placement.angle.z));
|
||||
float saz = sin(deg2rad(style.placement.angle.z));
|
||||
float cax = cos(deg2rad(style.placement.angle.x));
|
||||
float sax = sin(deg2rad(style.placement.angle.x));
|
||||
float cay = cos(deg2rad(style.placement.angle.y));
|
||||
float say = sin(deg2rad(style.placement.angle.y));
|
||||
|
||||
for(size_t i = 0, j = path.types.GetCount(); i < j; i++)
|
||||
{
|
||||
CPoint p = path.points[i];
|
||||
|
||||
if(bscale)
|
||||
{
|
||||
float x, y, z, xx, yy, zz;
|
||||
|
||||
x = sx * (p.x - org.x);
|
||||
y = sy * (p.y - org.y);
|
||||
z = 0;
|
||||
|
||||
if(bspline)
|
||||
{
|
||||
float pos = vertical ? y + org.y + tl.y - subrect.top : x + org.x + tl.x - subrect.left;
|
||||
float size = vertical ? subrect.Size().cy : subrect.Size().cx;
|
||||
float dist = vertical ? x : y;
|
||||
|
||||
const SplineCoeffs* sc;
|
||||
float t;
|
||||
|
||||
if(pos >= size)
|
||||
{
|
||||
sc = &spline[spline.GetCount() - 1];
|
||||
t = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
float u = size / spline.GetCount();
|
||||
sc = &spline[max((int)(pos / u), 0)];
|
||||
t = fmod(pos, u) / u;
|
||||
}
|
||||
|
||||
float nx = sc->cx[1] + 2*t*sc->cx[2] + 3*t*t*sc->cx[3];
|
||||
float ny = sc->cy[1] + 2*t*sc->cy[2] + 3*t*t*sc->cy[3];
|
||||
float nl = 1.0f / sqrt(nx*nx + ny*ny);
|
||||
|
||||
nx *= nl;
|
||||
ny *= nl;
|
||||
|
||||
x = sc->cx[0] + t*(sc->cx[1] + t*(sc->cx[2] + t*sc->cx[3])) - ny * dist - org.x - tl.x;
|
||||
y = sc->cy[0] + t*(sc->cy[1] + t*(sc->cy[2] + t*sc->cy[3])) + nx * dist - org.y - tl.y;
|
||||
}
|
||||
|
||||
if(brotate)
|
||||
{
|
||||
xx = x*caz + y*saz;
|
||||
yy = -(x*saz - y*caz);
|
||||
zz = z;
|
||||
|
||||
x = xx;
|
||||
y = yy*cax + zz*sax;
|
||||
z = yy*sax - zz*cax;
|
||||
|
||||
xx = x*cay + z*say;
|
||||
yy = y;
|
||||
zz = x*say - z*cay;
|
||||
|
||||
zz = 1.0f / (max(zz, -19000) + 20000);
|
||||
|
||||
x = (xx * 20000) * zz;
|
||||
y = (yy * 20000) * zz;
|
||||
}
|
||||
|
||||
p.x = (int)(x + org.x + 0.5);
|
||||
p.y = (int)(y + org.y + 0.5);
|
||||
|
||||
path.points[i] = p;
|
||||
}
|
||||
|
||||
if(p.x < bbox.left) bbox.left = p.x;
|
||||
if(p.x > bbox.right) bbox.right = p.x;
|
||||
if(p.y < bbox.top) bbox.top = p.y;
|
||||
if(p.y > bbox.bottom) bbox.bottom = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
void Glyph::Transform(CPoint org, const CRect& subrect)
|
||||
{
|
||||
if(!style.placement.org.auto_x) org.x = style.placement.org.x * scale.cx;
|
||||
if(!style.placement.org.auto_y) org.y = style.placement.org.y * scale.cy;
|
||||
|
||||
org -= tl;
|
||||
|
||||
bbox.SetRect(INT_MAX, INT_MAX, INT_MIN, INT_MIN);
|
||||
|
||||
Transform(path_bkg, org, subrect);
|
||||
Transform(path, org, subrect);
|
||||
|
||||
bbox |= CRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Glyph::Rasterize()
|
||||
{
|
||||
if(!path_bkg.IsEmpty())
|
||||
{
|
||||
ras_bkg.ScanConvert(path_bkg, bbox);
|
||||
ras_bkg.Rasterize(tl.x, tl.y);
|
||||
}
|
||||
|
||||
ras.ScanConvert(path, bbox);
|
||||
|
||||
if(style.background.type == L"outline" && style.background.size > 0)
|
||||
{
|
||||
ras.CreateWidenedRegion((int)(GetBackgroundSize() + 0.5));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Rasterizer* r = path_bkg.IsEmpty() ? &ras : &ras_bkg;
|
||||
int plane = path_bkg.IsEmpty() ? (style.font.color.a < 255 ? 2 : 1) : 0;
|
||||
|
||||
ras.Rasterize(tl.x, tl.y);
|
||||
r->Blur(style.background.blur, plane);
|
||||
|
||||
if(style.shadow.depth > 0)
|
||||
{
|
||||
ras_shadow.Reuse(*r);
|
||||
|
||||
float depth = GetShadowDepth();
|
||||
|
||||
tls.x = tl.x + (int)(depth * cos(deg2rad(style.shadow.angle)) + 0.5);
|
||||
tls.y = tl.y + (int)(depth * -sin(deg2rad(style.shadow.angle)) + 0.5);
|
||||
|
||||
ras_shadow.Rasterize(tls.x, tls.y);
|
||||
ras_shadow.Blur(style.shadow.blur, plane ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
63
vsfilter/libssf/Glyph.h
Normal file
63
vsfilter/libssf/Glyph.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
#include "GlyphPath.h"
|
||||
#include "FontWrapper.h"
|
||||
#include "Rasterizer.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Glyph
|
||||
{
|
||||
void Transform(GlyphPath& path, CPoint org, const CRect& subrect);
|
||||
|
||||
struct SplineCoeffs {float cx[4], cy[4];};
|
||||
|
||||
public:
|
||||
WCHAR c;
|
||||
Style style;
|
||||
CAtlArray<SplineCoeffs> spline;
|
||||
Size scale;
|
||||
bool vertical;
|
||||
FontWrapper* font;
|
||||
int ascent, descent, width, spacing, fill;
|
||||
int row_ascent, row_descent;
|
||||
GlyphPath path, path_bkg;
|
||||
CRect bbox;
|
||||
CPoint tl, tls;
|
||||
Rasterizer ras, ras_bkg, ras_shadow;
|
||||
|
||||
public:
|
||||
Glyph();
|
||||
|
||||
void CreateBkg();
|
||||
void CreateSplineCoeffs(const CRect& spdrc);
|
||||
void Transform(CPoint org, const CRect& subrect);
|
||||
void Rasterize();
|
||||
|
||||
float GetBackgroundSize() const;
|
||||
float GetShadowDepth() const;
|
||||
CRect GetClipRect() const;
|
||||
};
|
||||
}
|
164
vsfilter/libssf/GlyphPath.cpp
Normal file
164
vsfilter/libssf/GlyphPath.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GlyphPath.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
GlyphPath::GlyphPath(const GlyphPath& path)
|
||||
{
|
||||
*this = path;
|
||||
}
|
||||
|
||||
void GlyphPath::operator = (const GlyphPath& path)
|
||||
{
|
||||
types.Copy(path.types);
|
||||
points.Copy(path.points);
|
||||
}
|
||||
|
||||
bool GlyphPath::IsEmpty()
|
||||
{
|
||||
return types.IsEmpty() || points.IsEmpty();
|
||||
}
|
||||
|
||||
void GlyphPath::RemoveAll()
|
||||
{
|
||||
types.RemoveAll();
|
||||
points.RemoveAll();
|
||||
}
|
||||
|
||||
void GlyphPath::MovePoints(const CPoint& o)
|
||||
{
|
||||
size_t n = points.GetCount();
|
||||
POINT* p = points.GetData();
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
if(!!(g_cpuid.m_flags & CCpuID::sse2) && !((DWORD_PTR)p & 7))
|
||||
{
|
||||
for( ; i < n && ((DWORD_PTR)&p[i] & 15); i++)
|
||||
{
|
||||
p[i].x += o.x;
|
||||
p[i].y += o.y;
|
||||
}
|
||||
|
||||
__m128i oo = _mm_set_epi32(o.y, o.x, o.y, o.x);
|
||||
|
||||
for(unsigned int j = i + ((n - i) & ~7); i < j; i += 8)
|
||||
{
|
||||
__m128i r0 = _mm_load_si128((__m128i*)&p[i+0]);
|
||||
__m128i r1 = _mm_load_si128((__m128i*)&p[i+2]);
|
||||
__m128i r2 = _mm_load_si128((__m128i*)&p[i+4]);
|
||||
__m128i r3 = _mm_load_si128((__m128i*)&p[i+6]);
|
||||
_mm_store_si128((__m128i*)&p[i+0], _mm_add_epi32(r0, oo));
|
||||
_mm_store_si128((__m128i*)&p[i+2], _mm_add_epi32(r1, oo));
|
||||
_mm_store_si128((__m128i*)&p[i+4], _mm_add_epi32(r2, oo));
|
||||
_mm_store_si128((__m128i*)&p[i+6], _mm_add_epi32(r3, oo));
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < n; i++)
|
||||
{
|
||||
p[i].x += o.x;
|
||||
p[i].y += o.y;
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphPath::Enlarge(const GlyphPath& src, float size)
|
||||
{
|
||||
types.SetCount(src.types.GetCount());
|
||||
points.SetCount(src.points.GetCount());
|
||||
|
||||
memcpy(types.GetData(), src.types.GetData(), types.GetCount());
|
||||
|
||||
size_t start = 0, end = 0;
|
||||
|
||||
for(size_t i = 0, j = src.types.GetCount(); i <= j; i++)
|
||||
{
|
||||
if(i > 0 && (i == j || (src.types[i] & ~PT_CLOSEFIGURE) == PT_MOVETO))
|
||||
{
|
||||
end = i-1;
|
||||
|
||||
bool cw = true; // TODO: determine orientation (ttf is always cw and we are sill before Transform)
|
||||
float rotate = cw ? -M_PI_2 : M_PI_2;
|
||||
|
||||
CPoint prev = src.points[end];
|
||||
CPoint cur = src.points[start];
|
||||
|
||||
for(size_t k = start; k <= end; k++)
|
||||
{
|
||||
CPoint next = k < end ? src.points[k+1] : src.points[start];
|
||||
|
||||
for(int l = k-1; prev == cur; l--)
|
||||
{
|
||||
if(l < (int)start) l = end;
|
||||
prev = src.points[l];
|
||||
}
|
||||
|
||||
for(int l = k+1; next == cur; l++)
|
||||
{
|
||||
if(l > (int)end) l = start;
|
||||
next = src.points[l];
|
||||
}
|
||||
|
||||
CPoint in = cur - prev;
|
||||
CPoint out = next - cur;
|
||||
|
||||
float angle_in = atan2((float)in.y, (float)in.x);
|
||||
float angle_out = atan2((float)out.y, (float)out.x);
|
||||
float angle_diff = angle_out - angle_in;
|
||||
if(angle_diff < 0) angle_diff += M_PI*2;
|
||||
if(angle_diff > M_PI) angle_diff -= M_PI*2;
|
||||
float scale = cos(angle_diff / 2);
|
||||
|
||||
CPoint p;
|
||||
|
||||
if(angle_diff < 0)
|
||||
{
|
||||
if(angle_diff > -M_PI/8) {if(scale < 1) scale = 1;}
|
||||
else {if(scale < 0.50) scale = 0.50;}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(angle_diff < M_PI/8) {if(scale < 0.75) scale = 0.75;}
|
||||
else {if(scale < 0.25) scale = 0.25;}
|
||||
}
|
||||
|
||||
if(scale < 0.1) scale = 0.1;
|
||||
|
||||
float angle = angle_in + angle_diff / 2 - rotate;
|
||||
float radius = -size / scale; // FIXME
|
||||
|
||||
p.x = (int)(radius * cos(angle) + 0.5);
|
||||
p.y = (int)(radius * sin(angle) + 0.5);
|
||||
|
||||
points[k] = cur + p;
|
||||
|
||||
prev = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
start = end+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
vsfilter/libssf/GlyphPath.h
Normal file
45
vsfilter/libssf/GlyphPath.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class GlyphPath
|
||||
{
|
||||
public:
|
||||
GlyphPath() {}
|
||||
virtual ~GlyphPath() {}
|
||||
|
||||
GlyphPath(const GlyphPath& path);
|
||||
void operator = (const GlyphPath& path);
|
||||
|
||||
bool IsEmpty();
|
||||
void RemoveAll();
|
||||
void MovePoints(const CPoint& o);
|
||||
void Enlarge(const GlyphPath& src, float size);
|
||||
|
||||
CAtlArray<BYTE> types;
|
||||
CAtlArray<POINT> points;
|
||||
};
|
||||
}
|
551
vsfilter/libssf/Node.cpp
Normal file
551
vsfilter/libssf/Node.cpp
Normal file
|
@ -0,0 +1,551 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Node.h"
|
||||
#include "NodeFactory.h"
|
||||
#include "Exception.h"
|
||||
#include "Split.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
Node::Node(NodeFactory* pnf, CStringW name)
|
||||
: m_pnf(pnf)
|
||||
, m_type('?')
|
||||
, m_name(name)
|
||||
, m_priority(PNormal)
|
||||
, m_predefined(false)
|
||||
, m_parent(NULL)
|
||||
{
|
||||
ASSERT(m_pnf);
|
||||
}
|
||||
|
||||
void Node::AddTail(Node* pNode)
|
||||
{
|
||||
if(POSITION pos = m_nodes.Find(pNode)) // TODO: slow
|
||||
{
|
||||
m_nodes.MoveToTail(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
m_nodes.AddTail(pNode);
|
||||
m_name2node[pNode->m_name] = pNode;
|
||||
}
|
||||
|
||||
bool Node::IsNameUnknown()
|
||||
{
|
||||
return m_name.IsEmpty() || !!iswdigit(m_name[0]);
|
||||
}
|
||||
|
||||
bool Node::IsTypeUnknown()
|
||||
{
|
||||
return m_type.IsEmpty() || m_type == '?';
|
||||
}
|
||||
|
||||
bool Node::IsType(CStringW type)
|
||||
{
|
||||
return m_type == type;
|
||||
}
|
||||
|
||||
void Node::GetChildDefs(CAtlList<Definition*>& l, LPCWSTR type, bool fFirst)
|
||||
{
|
||||
CAtlList<Definition*> rdl[3];
|
||||
|
||||
if(fFirst)
|
||||
{
|
||||
if(Definition* pDef = m_pnf->GetDefByName(m_type))
|
||||
{
|
||||
pDef->GetChildDefs(rdl[pDef->m_priority], type, false);
|
||||
}
|
||||
}
|
||||
|
||||
POSITION pos = m_nodes.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
if(Node* pNode = m_nodes.GetNext(pos))
|
||||
{
|
||||
pNode->GetChildDefs(rdl[pNode->m_priority], type, false);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < sizeof(rdl)/sizeof(rdl[0]); i++)
|
||||
{
|
||||
l.AddTailList(&rdl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Reference
|
||||
|
||||
Reference::Reference(NodeFactory* pnf, CStringW name)
|
||||
: Node(pnf, name)
|
||||
{
|
||||
}
|
||||
|
||||
Reference::~Reference()
|
||||
{
|
||||
}
|
||||
|
||||
void Reference::GetChildDefs(CAtlList<Definition*>& l, LPCWSTR type, bool fFirst)
|
||||
{
|
||||
CAtlList<Definition*> rdl[3];
|
||||
|
||||
POSITION pos = m_nodes.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
if(Definition* pDef = dynamic_cast<Definition*>(m_nodes.GetNext(pos)))
|
||||
{
|
||||
if(!type || pDef->m_type == type) // TODO: faster lookup
|
||||
{
|
||||
rdl[pDef->m_priority].AddTail(pDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < sizeof(rdl)/sizeof(rdl[0]); i++)
|
||||
{
|
||||
l.AddTailList(&rdl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Reference::Dump(OutputStream& s, int level, bool fLast)
|
||||
{
|
||||
if(m_predefined) return;
|
||||
|
||||
CStringW tabs(' ', level*4);
|
||||
|
||||
// s.PutString(tabs + '\n' + tabs + L" {\n");
|
||||
s.PutString(L" {\n");
|
||||
|
||||
POSITION pos = m_nodes.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Node* pNode = m_nodes.GetNext(pos);
|
||||
|
||||
if(Definition* pDef = dynamic_cast<Definition*>(pNode))
|
||||
{
|
||||
pDef->Dump(s, level + 1, pos == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
s.PutString(tabs + '}');
|
||||
}
|
||||
|
||||
// Definition
|
||||
|
||||
Definition::Definition(NodeFactory* pnf, CStringW name)
|
||||
: Node(pnf, name)
|
||||
, m_status(node)
|
||||
, m_autotype(false)
|
||||
{
|
||||
}
|
||||
|
||||
Definition::~Definition()
|
||||
{
|
||||
RemoveFromCache();
|
||||
}
|
||||
|
||||
bool Definition::IsVisible(Definition* pDef)
|
||||
{
|
||||
Node* pNode = m_parent;
|
||||
|
||||
while(pNode)
|
||||
{
|
||||
if(pNode->m_name2node.Lookup(pDef->m_name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
pNode = pNode->m_parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Definition::AddTail(Node* pNode)
|
||||
{
|
||||
// if(Reference* pRef = dynamic_cast<Reference*>(pNode))
|
||||
{
|
||||
ASSERT(m_status == node);
|
||||
|
||||
m_status = node;
|
||||
|
||||
if(IsTypeUnknown() && !pNode->IsTypeUnknown())
|
||||
{
|
||||
m_type = pNode->m_type;
|
||||
m_autotype = true;
|
||||
}
|
||||
|
||||
RemoveFromCache(pNode->m_type);
|
||||
}
|
||||
|
||||
__super::AddTail(pNode);
|
||||
}
|
||||
|
||||
Definition& Definition::operator[] (LPCWSTR type)
|
||||
{
|
||||
Definition* pRetDef = NULL;
|
||||
if(m_type2def.Lookup(type, pRetDef))
|
||||
return *pRetDef;
|
||||
|
||||
pRetDef = new Definition(m_pnf, L"");
|
||||
pRetDef->m_priority = PLow;
|
||||
pRetDef->m_type = type;
|
||||
m_type2def[type] = pRetDef;
|
||||
|
||||
CAtlList<Definition*> l;
|
||||
GetChildDefs(l, type);
|
||||
|
||||
while(!l.IsEmpty())
|
||||
{
|
||||
Definition* pDef = l.RemoveHead();
|
||||
|
||||
pRetDef->m_priority = pDef->m_priority;
|
||||
pRetDef->m_parent = pDef->m_parent;
|
||||
|
||||
if(pDef->IsValue())
|
||||
{
|
||||
pRetDef->SetAsValue(pDef->m_status, pDef->m_value, pDef->m_unit);
|
||||
}
|
||||
else
|
||||
{
|
||||
pRetDef->m_status = node;
|
||||
pRetDef->m_nodes.AddTailList(&pDef->m_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
return *pRetDef;
|
||||
}
|
||||
|
||||
void Definition::RemoveFromCache(LPCWSTR type)
|
||||
{
|
||||
if(!type)
|
||||
{
|
||||
POSITION pos = m_type2def.GetStartPosition();
|
||||
while(pos) delete m_type2def.GetNextValue(pos);
|
||||
}
|
||||
else if(StringMapW<Definition*>::CPair* p = m_type2def.Lookup(type))
|
||||
{
|
||||
delete p->m_value;
|
||||
m_type2def.RemoveKey(type);
|
||||
}
|
||||
}
|
||||
|
||||
bool Definition::IsValue(status_t s)
|
||||
{
|
||||
return s ? m_status == s : m_status != node;
|
||||
}
|
||||
|
||||
void Definition::SetAsValue(status_t s, CStringW v, CStringW u)
|
||||
{
|
||||
ASSERT(s != node);
|
||||
|
||||
m_nodes.RemoveAll();
|
||||
m_name2node.RemoveAll();
|
||||
|
||||
m_status = s;
|
||||
|
||||
m_value = v;
|
||||
m_unit = u;
|
||||
}
|
||||
|
||||
void Definition::SetAsNumber(CStringW v, CStringW u)
|
||||
{
|
||||
SetAsValue(number, v, u);
|
||||
|
||||
Number<float> n;
|
||||
GetAsNumber(n); // will throw an exception if not a number
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Definition::GetAsNumber(Number<T>& n, StringMapW<T>* n2n)
|
||||
{
|
||||
CStringW str = m_value;
|
||||
str.Replace(L" ", L"");
|
||||
|
||||
n.value = 0;
|
||||
n.unit = m_unit;
|
||||
n.sign = 0;
|
||||
|
||||
if(n2n)
|
||||
{
|
||||
if(m_status == node) throw Exception(_T("expected value type"));
|
||||
|
||||
if(StringMapW<T>::CPair* p = n2n->Lookup(str))
|
||||
{
|
||||
n.value = p->m_value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_status != number) throw Exception(_T("expected number"));
|
||||
|
||||
n.sign = str.Find('+') == 0 ? 1 : str.Find('-') == 0 ? -1 : 0;
|
||||
str.TrimLeft(L"+-");
|
||||
|
||||
if(str.Find(L"0x") == 0)
|
||||
{
|
||||
if(n.sign) throw Exception(_T("hex values must be unsigned"));
|
||||
|
||||
n.value = (T)wcstoul(str.Mid(2), NULL, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
CStringW num_string = m_value + m_unit;
|
||||
|
||||
if(m_num_string != num_string)
|
||||
{
|
||||
Split sa(':', str);
|
||||
Split sa2('.', sa ? sa[sa-1] : L"");
|
||||
|
||||
if(sa == 0 || sa2 == 0 || sa2 > 2) throw Exception(_T("invalid number"));
|
||||
|
||||
float f = 0;
|
||||
for(size_t i = 0; i < sa; i++) {f *= 60; f += wcstoul(sa[i], NULL, 10);}
|
||||
if(sa2 > 1) f += (float)wcstoul(sa2[1], NULL, 10) / pow((float)10, sa2[1].GetLength());
|
||||
|
||||
if(n.unit == L"ms") {f /= 1000; n.unit = L"s";}
|
||||
else if(n.unit == L"m") {f *= 60; n.unit = L"s";}
|
||||
else if(n.unit == L"h") {f *= 3600; n.unit = L"s";}
|
||||
|
||||
m_num.value = f;
|
||||
m_num.unit = n.unit;
|
||||
m_num_string = num_string;
|
||||
|
||||
n.value = (T)f;
|
||||
}
|
||||
else
|
||||
{
|
||||
n.value = (T)m_num.value;
|
||||
n.unit = m_num.unit;
|
||||
}
|
||||
|
||||
if(n.sign) n.value *= n.sign;
|
||||
}
|
||||
}
|
||||
|
||||
void Definition::GetAsString(CStringW& str)
|
||||
{
|
||||
if(m_status == node) throw Exception(_T("expected value type"));
|
||||
|
||||
str = m_value;
|
||||
}
|
||||
|
||||
void Definition::GetAsNumber(Number<int>& n, StringMapW<int>* n2n) {return GetAsNumber<int>(n, n2n);}
|
||||
void Definition::GetAsNumber(Number<DWORD>& n, StringMapW<DWORD>* n2n) {return GetAsNumber<DWORD>(n, n2n);}
|
||||
void Definition::GetAsNumber(Number<float>& n, StringMapW<float>* n2n) {return GetAsNumber<float>(n, n2n);}
|
||||
|
||||
void Definition::GetAsBoolean(bool& b)
|
||||
{
|
||||
static StringMapW<bool> s2b;
|
||||
|
||||
if(s2b.IsEmpty())
|
||||
{
|
||||
s2b[L"true"] = true;
|
||||
s2b[L"on"] = true;
|
||||
s2b[L"yes"] = true;
|
||||
s2b[L"1"] = true;
|
||||
s2b[L"false"] = false;
|
||||
s2b[L"off"] = false;
|
||||
s2b[L"no"] = false;
|
||||
s2b[L"0"] = false;
|
||||
}
|
||||
|
||||
if(!s2b.Lookup(m_value, b)) // m_status != boolean && m_status != number ||
|
||||
{
|
||||
throw Exception(_T("expected boolean"));
|
||||
}
|
||||
}
|
||||
|
||||
bool Definition::GetAsTime(Time& t, StringMapW<float>& offset, StringMapW<float>* n2n, int default_id)
|
||||
{
|
||||
Definition& time = (*this)[L"time"];
|
||||
|
||||
CStringW id;
|
||||
if(time[L"id"].IsValue()) id = time[L"id"];
|
||||
else id.Format(L"%d", default_id);
|
||||
|
||||
float scale = time[L"scale"].IsValue() ? time[L"scale"] : 1.0f;
|
||||
|
||||
if(time[L"start"].IsValue() && time[L"stop"].IsValue())
|
||||
{
|
||||
time[L"start"].GetAsNumber(t.start, n2n);
|
||||
time[L"stop"].GetAsNumber(t.stop, n2n);
|
||||
|
||||
if(t.start.unit.IsEmpty()) t.start.value *= scale;
|
||||
if(t.stop.unit.IsEmpty()) t.stop.value *= scale;
|
||||
|
||||
float o = 0;
|
||||
offset.Lookup(id, o);
|
||||
|
||||
if(t.start.sign != 0) t.start.value = o + t.start.value;
|
||||
if(t.stop.sign != 0) t.stop.value = t.start.value + t.stop.value;
|
||||
|
||||
offset[id] = t.stop.value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Definition::operator LPCWSTR()
|
||||
{
|
||||
CStringW str;
|
||||
GetAsString(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
Definition::operator float()
|
||||
{
|
||||
float d;
|
||||
GetAsNumber(d);
|
||||
return d;
|
||||
}
|
||||
|
||||
Definition::operator bool()
|
||||
{
|
||||
bool b;
|
||||
GetAsBoolean(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
Definition* Definition::SetChildAsValue(CStringW path, status_t s, CStringW v, CStringW u)
|
||||
{
|
||||
Definition* pDef = this;
|
||||
|
||||
Split split('.', path);
|
||||
|
||||
for(size_t i = 0, j = split-1; i <= j; i++)
|
||||
{
|
||||
CStringW type = split[i];
|
||||
|
||||
if(pDef->m_nodes.IsEmpty() || !dynamic_cast<Reference*>(pDef->m_nodes.GetTail()))
|
||||
{
|
||||
EXECUTE_ASSERT(m_pnf->CreateRef(pDef) != NULL);
|
||||
}
|
||||
|
||||
if(Reference* pRef = dynamic_cast<Reference*>(pDef->m_nodes.GetTail()))
|
||||
{
|
||||
pDef = NULL;
|
||||
|
||||
POSITION pos = pRef->m_nodes.GetTailPosition();
|
||||
while(pos)
|
||||
{
|
||||
Definition* pChildDef = dynamic_cast<Definition*>(pRef->m_nodes.GetPrev(pos));
|
||||
|
||||
if(pChildDef->IsType(type))
|
||||
{
|
||||
if(pChildDef->IsNameUnknown()) pDef = pChildDef;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pDef)
|
||||
{
|
||||
pDef = m_pnf->CreateDef(pRef, type);
|
||||
}
|
||||
|
||||
if(i == j)
|
||||
{
|
||||
pDef->SetAsValue(s, v, u);
|
||||
return pDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Definition* Definition::SetChildAsNumber(CStringW path, CStringW v, CStringW u)
|
||||
{
|
||||
Definition* pDef = SetChildAsValue(path, number, v, u);
|
||||
|
||||
Number<float> n;
|
||||
pDef->GetAsNumber(n); // will throw an exception if not a number
|
||||
|
||||
return pDef;
|
||||
}
|
||||
|
||||
void Definition::Dump(OutputStream& s, int level, bool fLast)
|
||||
{
|
||||
if(m_predefined) return;
|
||||
|
||||
CStringW tabs(' ', level*4);
|
||||
|
||||
CStringW str = tabs;
|
||||
if(m_predefined) str += '?';
|
||||
if(m_priority == PLow) str += '*';
|
||||
else if(m_priority == PHigh) str += '!';
|
||||
if(!IsTypeUnknown() && !m_autotype) str += m_type;
|
||||
if(!IsNameUnknown()) str += '#' + m_name;
|
||||
str += ':';
|
||||
s.PutString(L"%s", str);
|
||||
|
||||
if(!m_nodes.IsEmpty())
|
||||
{
|
||||
POSITION pos = m_nodes.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Node* pNode = m_nodes.GetNext(pos);
|
||||
|
||||
if(Reference* pRef = dynamic_cast<Reference*>(pNode))
|
||||
{
|
||||
pRef->Dump(s, level, fLast);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(!pNode->IsNameUnknown());
|
||||
s.PutString(L" %s", pNode->m_name);
|
||||
}
|
||||
}
|
||||
|
||||
s.PutString(L";\n");
|
||||
|
||||
if(!fLast && (!m_nodes.IsEmpty() || level == 0)) s.PutString(L"\n");
|
||||
}
|
||||
else if(m_status == string)
|
||||
{
|
||||
CStringW str = m_value;
|
||||
str.Replace(L"\"", L"\\\"");
|
||||
s.PutString(L" \"%s\";\n", str);
|
||||
}
|
||||
else if(m_status == number)
|
||||
{
|
||||
CStringW str = m_value;
|
||||
if(!m_unit.IsEmpty()) str += m_unit;
|
||||
s.PutString(L" %s;\n", str);
|
||||
}
|
||||
else if(m_status == boolean)
|
||||
{
|
||||
s.PutString(L" %s;\n", m_value);
|
||||
}
|
||||
else if(m_status == block)
|
||||
{
|
||||
s.PutString(L" {%s};\n", m_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.PutString(L" null;\n");
|
||||
}
|
||||
}
|
||||
}
|
122
vsfilter/libssf/Node.h
Normal file
122
vsfilter/libssf/Node.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "StringMap.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Definition;
|
||||
class NodeFactory;
|
||||
|
||||
enum NodePriority {PLow, PNormal, PHigh};
|
||||
|
||||
class Node
|
||||
{
|
||||
protected:
|
||||
NodeFactory* m_pnf;
|
||||
|
||||
public:
|
||||
Node* m_parent;
|
||||
CAtlList<Node*> m_nodes;
|
||||
StringMapW<Node*> m_name2node;
|
||||
CStringW m_type, m_name;
|
||||
NodePriority m_priority;
|
||||
bool m_predefined;
|
||||
|
||||
Node(NodeFactory* pnf, CStringW name);
|
||||
virtual ~Node() {}
|
||||
|
||||
bool IsNameUnknown();
|
||||
bool IsTypeUnknown();
|
||||
bool IsType(CStringW type);
|
||||
|
||||
virtual void AddTail(Node* pNode);
|
||||
virtual void GetChildDefs(CAtlList<Definition*>& l, LPCWSTR type = NULL, bool fFirst = true);
|
||||
virtual void Dump(OutputStream& s, int level = 0, bool fLast = false) = 0;
|
||||
};
|
||||
|
||||
class Reference : public Node
|
||||
{
|
||||
public:
|
||||
Reference(NodeFactory* pnf, CStringW name);
|
||||
virtual ~Reference();
|
||||
|
||||
void GetChildDefs(CAtlList<Definition*>& l, LPCWSTR type = NULL, bool fFirst = true);
|
||||
void Dump(OutputStream& s, int level = 0, bool fLast = false);
|
||||
};
|
||||
|
||||
class Definition : public Node
|
||||
{
|
||||
public:
|
||||
template<typename T> struct Number {T value; int sign; CStringW unit;};
|
||||
struct Time {Number<float> start, stop;};
|
||||
|
||||
enum status_t {node, string, number, boolean, block};
|
||||
|
||||
private:
|
||||
status_t m_status;
|
||||
bool m_autotype;
|
||||
CStringW m_value, m_unit;
|
||||
Number<float> m_num;
|
||||
CStringW m_num_string;
|
||||
|
||||
StringMapW<Definition*> m_type2def;
|
||||
void RemoveFromCache(LPCWSTR type = NULL);
|
||||
|
||||
template<typename T>
|
||||
void GetAsNumber(Number<T>& n, StringMapW<T>* n2n = NULL);
|
||||
|
||||
public:
|
||||
Definition(NodeFactory* pnf, CStringW name);
|
||||
virtual ~Definition();
|
||||
|
||||
bool IsVisible(Definition* pDef);
|
||||
|
||||
void AddTail(Node* pNode);
|
||||
void Dump(OutputStream& s, int level = 0, bool fLast = false);
|
||||
|
||||
Definition& operator[] (LPCWSTR type);
|
||||
|
||||
bool IsValue(status_t s = (status_t)0);
|
||||
|
||||
void SetAsValue(status_t s, CStringW v, CStringW u = L"");
|
||||
void SetAsNumber(CStringW v, CStringW u = L"");
|
||||
|
||||
void GetAsString(CStringW& str);
|
||||
void GetAsNumber(Number<int>& n, StringMapW<int>* n2n = NULL);
|
||||
void GetAsNumber(Number<DWORD>& n, StringMapW<DWORD>* n2n = NULL);
|
||||
void GetAsNumber(Number<float>& n, StringMapW<float>* n2n = NULL);
|
||||
template<typename T>
|
||||
void GetAsNumber(T& t, StringMapW<T>* n2n = NULL) {Number<T> n; GetAsNumber(n, n2n); t = n.value;}
|
||||
void GetAsBoolean(bool& b);
|
||||
bool GetAsTime(Time& t, StringMapW<float>& offset, StringMapW<float>* n2n = NULL, int default_id = 0);
|
||||
|
||||
operator LPCWSTR();
|
||||
operator float();
|
||||
operator bool();
|
||||
|
||||
Definition* SetChildAsValue(CStringW path, status_t s, CStringW v, CStringW u = L"");
|
||||
Definition* SetChildAsNumber(CStringW path, CStringW v, CStringW u = L"");
|
||||
};
|
||||
}
|
182
vsfilter/libssf/NodeFactory.cpp
Normal file
182
vsfilter/libssf/NodeFactory.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "NodeFactory.h"
|
||||
#include "Exception.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
NodeFactory::NodeFactory()
|
||||
: m_counter(0)
|
||||
, m_root(NULL)
|
||||
, m_predefined(false)
|
||||
{
|
||||
}
|
||||
|
||||
NodeFactory::~NodeFactory()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
CStringW NodeFactory::GenName()
|
||||
{
|
||||
CStringW name;
|
||||
name.Format(L"%I64d", m_counter++);
|
||||
return name;
|
||||
}
|
||||
|
||||
void NodeFactory::RemoveAll()
|
||||
{
|
||||
m_root = NULL;
|
||||
|
||||
POSITION pos = m_nodes.GetStartPosition();
|
||||
while(pos) delete m_nodes.GetNextValue(pos);
|
||||
m_nodes.RemoveAll();
|
||||
|
||||
m_newnodes.RemoveAll();
|
||||
}
|
||||
|
||||
void NodeFactory::Commit()
|
||||
{
|
||||
m_newnodes.RemoveAll();
|
||||
}
|
||||
|
||||
void NodeFactory::Rollback()
|
||||
{
|
||||
POSITION pos = m_newnodes.GetTailPosition();
|
||||
while(pos)
|
||||
{
|
||||
if(StringMap<Node*, CStringW>::CPair* p = m_nodes.Lookup(m_newnodes.GetPrev(pos)))
|
||||
{
|
||||
delete p->m_value; // TODO: remove it from "parent"->m_nodes too
|
||||
m_nodes.RemoveKey(p->m_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference* NodeFactory::CreateRootRef()
|
||||
{
|
||||
RemoveAll();
|
||||
m_root = CreateRef(NULL);
|
||||
return m_root;
|
||||
}
|
||||
|
||||
Reference* NodeFactory::GetRootRef() const
|
||||
{
|
||||
ASSERT(m_root);
|
||||
return m_root;
|
||||
}
|
||||
|
||||
Reference* NodeFactory::CreateRef(Definition* pParentDef)
|
||||
{
|
||||
CStringW name = GenName();
|
||||
|
||||
Reference* pRef = new Reference(this, name);
|
||||
|
||||
m_nodes.SetAt(name, pRef);
|
||||
m_newnodes.AddTail(name);
|
||||
|
||||
if(pParentDef)
|
||||
{
|
||||
pParentDef->AddTail(pRef);
|
||||
pRef->m_parent = pParentDef;
|
||||
}
|
||||
|
||||
return pRef;
|
||||
}
|
||||
|
||||
Definition* NodeFactory::CreateDef(Reference* pParentRef, CStringW type, CStringW name, NodePriority priority)
|
||||
{
|
||||
Definition* pDef = NULL;
|
||||
|
||||
if(name.IsEmpty())
|
||||
{
|
||||
name = GenName();
|
||||
}
|
||||
else
|
||||
{
|
||||
pDef = GetDefByName(name);
|
||||
|
||||
if(pDef)
|
||||
{
|
||||
if(!pDef->m_predefined)
|
||||
{
|
||||
throw Exception(_T("redefinition of '%s' is not allowed"), CString(name));
|
||||
}
|
||||
|
||||
if(!pDef->IsTypeUnknown() && !pDef->IsType(type))
|
||||
{
|
||||
throw Exception(_T("cannot redefine type of %s to %s"), CString(name), CString(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!pDef)
|
||||
{
|
||||
pDef = new Definition(this, name);
|
||||
|
||||
m_nodes.SetAt(name, pDef);
|
||||
m_newnodes.AddTail(name);
|
||||
|
||||
if(pParentRef)
|
||||
{
|
||||
pParentRef->AddTail(pDef);
|
||||
pDef->m_parent = pParentRef;
|
||||
}
|
||||
}
|
||||
|
||||
pDef->m_type = type;
|
||||
pDef->m_priority = priority;
|
||||
pDef->m_predefined = m_predefined;
|
||||
|
||||
return pDef;
|
||||
}
|
||||
|
||||
Definition* NodeFactory::GetDefByName(CStringW name) const
|
||||
{
|
||||
Node* pNode = NULL;
|
||||
m_nodes.Lookup(name, pNode);
|
||||
return dynamic_cast<Definition*>(pNode);
|
||||
}
|
||||
|
||||
void NodeFactory::GetNewDefs(CAtlList<Definition*>& defs)
|
||||
{
|
||||
defs.RemoveAll();
|
||||
|
||||
POSITION pos = m_newnodes.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
if(Definition* pDef = GetDefByName(m_newnodes.GetNext(pos)))
|
||||
{
|
||||
defs.AddTail(pDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeFactory::Dump(OutputStream& s) const
|
||||
{
|
||||
if(!m_root) return;
|
||||
|
||||
POSITION pos = m_root->m_nodes.GetHeadPosition();
|
||||
while(pos) m_root->m_nodes.GetNext(pos)->Dump(s);
|
||||
}
|
||||
}
|
58
vsfilter/libssf/NodeFactory.h
Normal file
58
vsfilter/libssf/NodeFactory.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Node.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class NodeFactory
|
||||
{
|
||||
Reference* m_root;
|
||||
StringMapW<Node*> m_nodes;
|
||||
CAtlList<CStringW> m_newnodes;
|
||||
bool m_predefined;
|
||||
|
||||
unsigned __int64 m_counter;
|
||||
CStringW GenName();
|
||||
|
||||
public:
|
||||
NodeFactory();
|
||||
virtual ~NodeFactory();
|
||||
|
||||
virtual void RemoveAll();
|
||||
|
||||
void SetPredefined(bool predefined) {m_predefined = predefined;}
|
||||
|
||||
void Commit();
|
||||
void Rollback();
|
||||
|
||||
Reference* CreateRootRef();
|
||||
Reference* GetRootRef() const;
|
||||
Reference* CreateRef(Definition* pParentDef);
|
||||
Definition* CreateDef(Reference* pParentRef = NULL, CStringW type = L"", CStringW name = L"", NodePriority priority = PNormal);
|
||||
Definition* GetDefByName(CStringW name) const;
|
||||
void GetNewDefs(CAtlList<Definition*>& defs);
|
||||
|
||||
void Dump(OutputStream& s) const;
|
||||
};
|
||||
}
|
708
vsfilter/libssf/Rasterizer.cpp
Normal file
708
vsfilter/libssf/Rasterizer.cpp
Normal file
|
@ -0,0 +1,708 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Based on the rasterizer of virtualdub's subtitler plugin
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "Rasterizer.h"
|
||||
#include "Glyph.h"
|
||||
|
||||
#define FONT_AA 3
|
||||
#define FONT_SCALE (6-FONT_AA)
|
||||
|
||||
// FONT_AA: 0 - 3
|
||||
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
template<class T> T mymax(T a, T b) {return a > b ? a : b;}
|
||||
template<class T> T mymin(T a, T b) {return a < b ? a : b;}
|
||||
|
||||
Rasterizer::Rasterizer()
|
||||
{
|
||||
mpOverlayBuffer = NULL;
|
||||
mOverlayWidth = mOverlayHeight = 0;
|
||||
mPathOffsetX = mPathOffsetY = 0;
|
||||
mOffsetX = mOffsetY = 0;
|
||||
}
|
||||
|
||||
Rasterizer::~Rasterizer()
|
||||
{
|
||||
_TrashOverlay();
|
||||
}
|
||||
|
||||
void Rasterizer::_TrashOverlay()
|
||||
{
|
||||
if(mpOverlayBuffer) delete [] mpOverlayBuffer;
|
||||
mpOverlayBuffer = NULL;
|
||||
}
|
||||
|
||||
void Rasterizer::_ReallocEdgeBuffer(int edges)
|
||||
{
|
||||
mEdgeHeapSize = edges;
|
||||
mpEdgeBuffer = (Edge*)realloc(mpEdgeBuffer, sizeof(Edge)*edges);
|
||||
}
|
||||
|
||||
void Rasterizer::_EvaluateBezier(const CPoint& p0, const CPoint& p1, const CPoint& p2, const CPoint& p3)
|
||||
{
|
||||
if(abs(p0.x + p2.x - p1.x*2) +
|
||||
abs(p0.y + p2.y - p1.y*2) +
|
||||
abs(p1.x + p3.x - p2.x*2) +
|
||||
abs(p1.y + p3.y - p2.y*2) <= max(2, 1<<FONT_AA))
|
||||
{
|
||||
_EvaluateLine(p0, p3);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPoint p01, p12, p23, p012, p123, p0123;
|
||||
|
||||
p01.x = (p0.x + p1.x + 1) >> 1;
|
||||
p01.y = (p0.y + p1.y + 1) >> 1;
|
||||
p12.x = (p1.x + p2.x + 1) >> 1;
|
||||
p12.y = (p1.y + p2.y + 1) >> 1;
|
||||
p23.x = (p2.x + p3.x + 1) >> 1;
|
||||
p23.y = (p2.y + p3.y + 1) >> 1;
|
||||
p012.x = (p01.x + p12.x + 1) >> 1;
|
||||
p012.y = (p01.y + p12.y + 1) >> 1;
|
||||
p123.x = (p12.x + p23.x + 1) >> 1;
|
||||
p123.y = (p12.y + p23.y + 1) >> 1;
|
||||
p0123.x = (p012.x + p123.x + 1) >> 1;
|
||||
p0123.y = (p012.y + p123.y + 1) >> 1;
|
||||
|
||||
_EvaluateBezier(p0, p01, p012, p0123);
|
||||
_EvaluateBezier(p0123, p123, p23, p3);
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::_EvaluateLine(CPoint p0, CPoint p1)
|
||||
{
|
||||
if(lastp != p0)
|
||||
{
|
||||
_EvaluateLine(lastp, p0);
|
||||
}
|
||||
|
||||
if(!fFirstSet)
|
||||
{
|
||||
firstp = p0;
|
||||
fFirstSet = true;
|
||||
}
|
||||
|
||||
lastp = p1;
|
||||
|
||||
// TODO: ((1<<FONT_SCALE)/2+-1)
|
||||
|
||||
if(p1.y > p0.y) // down
|
||||
{
|
||||
int xacc = p0.x << (8 - FONT_SCALE);
|
||||
|
||||
// prestep p0.y down
|
||||
|
||||
int dy = p1.y - p0.y;
|
||||
int y = ((p0.y + ((1<<FONT_SCALE)/2-1)) & ~((1<<FONT_SCALE)-1)) + (1<<FONT_SCALE)/2;
|
||||
int iy = y >> FONT_SCALE;
|
||||
|
||||
p1.y = (p1.y - ((1<<FONT_SCALE)/2+1)) >> FONT_SCALE;
|
||||
|
||||
if(iy <= p1.y)
|
||||
{
|
||||
int invslope = ((p1.x - p0.x) << 8) / dy;
|
||||
|
||||
while(mEdgeNext + p1.y + 1 - iy > mEdgeHeapSize)
|
||||
_ReallocEdgeBuffer(mEdgeHeapSize*2);
|
||||
|
||||
xacc += (invslope * (y - p0.y)) >> FONT_SCALE;
|
||||
|
||||
while(iy <= p1.y)
|
||||
{
|
||||
int ix = (xacc + 128) >> 8;
|
||||
|
||||
mpEdgeBuffer[mEdgeNext].next = mpScanBuffer[iy];
|
||||
mpEdgeBuffer[mEdgeNext].posandflag = ix*2 + 1;
|
||||
|
||||
mpScanBuffer[iy] = mEdgeNext++;
|
||||
|
||||
++iy;
|
||||
xacc += invslope;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(p1.y < p0.y) // up
|
||||
{
|
||||
int xacc = p1.x << (8 - FONT_SCALE);
|
||||
|
||||
// prestep p1.y down
|
||||
|
||||
int dy = p0.y - p1.y;
|
||||
int y = ((p1.y + ((1<<FONT_SCALE)/2-1)) & ~((1<<FONT_SCALE)-1)) + (1<<FONT_SCALE)/2;
|
||||
int iy = y >> FONT_SCALE;
|
||||
|
||||
p0.y = (p0.y - ((1<<FONT_SCALE)/2+1)) >> FONT_SCALE;
|
||||
|
||||
if(iy <= p0.y)
|
||||
{
|
||||
int invslope = ((p0.x - p1.x) << 8) / dy;
|
||||
|
||||
while(mEdgeNext + p0.y + 1 - iy > mEdgeHeapSize)
|
||||
_ReallocEdgeBuffer(mEdgeHeapSize*2);
|
||||
|
||||
xacc += (invslope * (y - p1.y)) >> FONT_SCALE;
|
||||
|
||||
while(iy <= p0.y)
|
||||
{
|
||||
int ix = (xacc + 128) >> 8;
|
||||
|
||||
mpEdgeBuffer[mEdgeNext].next = mpScanBuffer[iy];
|
||||
mpEdgeBuffer[mEdgeNext].posandflag = ix*2;
|
||||
|
||||
mpScanBuffer[iy] = mEdgeNext++;
|
||||
|
||||
++iy;
|
||||
xacc += invslope;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Rasterizer::ScanConvert(GlyphPath& path, const CRect& bbox)
|
||||
{
|
||||
// Drop any outlines we may have.
|
||||
|
||||
mOutline.RemoveAll();
|
||||
mWideOutline.RemoveAll();
|
||||
|
||||
if(path.types.IsEmpty() || path.points.IsEmpty() || bbox.IsRectEmpty())
|
||||
{
|
||||
mPathOffsetX = mPathOffsetY = 0;
|
||||
mWidth = mHeight = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int minx = (bbox.left >> FONT_SCALE) & ~((1<<FONT_SCALE)-1);
|
||||
int miny = (bbox.top >> FONT_SCALE) & ~((1<<FONT_SCALE)-1);
|
||||
int maxx = (bbox.right + ((1<<FONT_SCALE)-1)) >> FONT_SCALE;
|
||||
int maxy = (bbox.bottom + ((1<<FONT_SCALE)-1)) >> FONT_SCALE;
|
||||
|
||||
path.MovePoints(CPoint(-minx*(1<<FONT_SCALE), -miny*(1<<FONT_SCALE)));
|
||||
|
||||
if(minx > maxx || miny > maxy)
|
||||
{
|
||||
mWidth = mHeight = 0;
|
||||
mPathOffsetX = mPathOffsetY = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
mWidth = maxx + 1 - minx;
|
||||
mHeight = maxy + 1 - miny;
|
||||
|
||||
mPathOffsetX = minx;
|
||||
mPathOffsetY = miny;
|
||||
|
||||
// Initialize edge buffer. We use edge 0 as a sentinel.
|
||||
|
||||
mEdgeNext = 1;
|
||||
mEdgeHeapSize = 0x10000;
|
||||
mpEdgeBuffer = (Edge*)malloc(sizeof(Edge)*mEdgeHeapSize);
|
||||
|
||||
// Initialize scanline list.
|
||||
|
||||
mpScanBuffer = new unsigned int[mHeight];
|
||||
memset(mpScanBuffer, 0, mHeight*sizeof(unsigned int));
|
||||
|
||||
// Scan convert the outline. Yuck, Bezier curves....
|
||||
|
||||
// Unfortunately, Windows 95/98 GDI has a bad habit of giving us text
|
||||
// paths with all but the first figure left open, so we can't rely
|
||||
// on the PT_CLOSEFIGURE flag being used appropriately.
|
||||
|
||||
fFirstSet = false;
|
||||
firstp.x = firstp.y = 0;
|
||||
lastp.x = lastp.y = 0;
|
||||
|
||||
int lastmoveto = -1;
|
||||
|
||||
BYTE* type = path.types.GetData();
|
||||
POINT* pt = path.points.GetData();
|
||||
|
||||
for(size_t i = 0, j = path.types.GetCount(); i < j; i++)
|
||||
{
|
||||
switch(type[i] & ~PT_CLOSEFIGURE)
|
||||
{
|
||||
case PT_MOVETO:
|
||||
if(lastmoveto >= 0 && firstp != lastp) _EvaluateLine(lastp, firstp);
|
||||
lastmoveto = i;
|
||||
fFirstSet = false;
|
||||
lastp = pt[i];
|
||||
break;
|
||||
case PT_LINETO:
|
||||
if(j - (i-1) >= 2) _EvaluateLine(pt[i-1], pt[i]);
|
||||
break;
|
||||
case PT_BEZIERTO:
|
||||
if(j - (i-1) >= 4) _EvaluateBezier(pt[i-1], pt[i], pt[i+1], pt[i+2]);
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(lastmoveto >= 0 && firstp != lastp) _EvaluateLine(lastp, firstp);
|
||||
|
||||
// Convert the edges to spans. We couldn't do this before because some of
|
||||
// the regions may have winding numbers >+1 and it would have been a pain
|
||||
// to try to adjust the spans on the fly. We use one heap to detangle
|
||||
// a scanline's worth of edges from the singly-linked lists, and another
|
||||
// to collect the actual scans.
|
||||
|
||||
std::vector<int> heap;
|
||||
|
||||
mOutline.SetCount(0, mEdgeNext / 2);
|
||||
|
||||
for(int y = 0; y < mHeight; y++)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
// Detangle scanline into edge heap.
|
||||
|
||||
for(unsigned int ptr = mpScanBuffer[y]; ptr; ptr = mpEdgeBuffer[ptr].next)
|
||||
{
|
||||
heap.push_back(mpEdgeBuffer[ptr].posandflag);
|
||||
}
|
||||
|
||||
// Sort edge heap. Note that we conveniently made the opening edges
|
||||
// one more than closing edges at the same spot, so we won't have any
|
||||
// problems with abutting spans.
|
||||
|
||||
std::sort(heap.begin(), heap.end());
|
||||
|
||||
// Process edges and add spans. Since we only check for a non-zero
|
||||
// winding number, it doesn't matter which way the outlines go!
|
||||
|
||||
std::vector<int>::iterator itX1 = heap.begin();
|
||||
std::vector<int>::iterator itX2 = heap.end();
|
||||
|
||||
int x1, x2;
|
||||
|
||||
for(; itX1 != itX2; ++itX1)
|
||||
{
|
||||
int x = *itX1;
|
||||
|
||||
if(!count)
|
||||
{
|
||||
x1 = x >> 1;
|
||||
}
|
||||
|
||||
if(x&1) ++count;
|
||||
else --count;
|
||||
|
||||
if(!count)
|
||||
{
|
||||
x2 = x >> 1;
|
||||
|
||||
if(x2 > x1)
|
||||
{
|
||||
Span s(x1, y, x2, y);
|
||||
s.first += 0x4000000040000000i64;
|
||||
s.second += 0x4000000040000000i64;
|
||||
mOutline.Add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heap.clear();
|
||||
}
|
||||
|
||||
// Dump the edge and scan buffers, since we no longer need them.
|
||||
|
||||
free(mpEdgeBuffer);
|
||||
delete [] mpScanBuffer;
|
||||
|
||||
// All done!
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Rasterizer::_OverlapRegion(Array<Span>& dst, Array<Span>& src, int dx, int dy)
|
||||
{
|
||||
mWideOutlineTmp.Move(dst);
|
||||
|
||||
Span* a = mWideOutlineTmp.GetData();
|
||||
Span* ae = a + mWideOutlineTmp.GetCount();
|
||||
Span* b = src.GetData();
|
||||
Span* be = b + src.GetCount();
|
||||
|
||||
Span o(0, dy, 0, dy);
|
||||
o.first -= dx;
|
||||
o.second += dx;
|
||||
|
||||
while(a != ae && b != be)
|
||||
{
|
||||
Span x;
|
||||
|
||||
if(b->first + o.first < a->first)
|
||||
{
|
||||
// B span is earlier. Use it.
|
||||
|
||||
x.first = b->first + o.first;
|
||||
x.second = b->second + o.second;
|
||||
|
||||
b++;
|
||||
|
||||
// B spans don't overlap, so begin merge loop with A first.
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// If we run out of A spans or the A span doesn't overlap,
|
||||
// then the next B span can't either (because B spans don't
|
||||
// overlap) and we exit.
|
||||
|
||||
if(a == ae || a->first > x.second)
|
||||
break;
|
||||
|
||||
do {x.second = mymax(x.second, a->second);}
|
||||
while(++a != ae && a->first <= x.second);
|
||||
|
||||
// If we run out of B spans or the B span doesn't overlap,
|
||||
// then the next A span can't either (because A spans don't
|
||||
// overlap) and we exit.
|
||||
|
||||
if(b == be || b->first + o.first > x.second)
|
||||
break;
|
||||
|
||||
do {x.second = mymax(x.second, b->second + o.second);}
|
||||
while(++b != be && b->first + o.first <= x.second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// A span is earlier. Use it.
|
||||
|
||||
x = *a;
|
||||
|
||||
a++;
|
||||
|
||||
// A spans don't overlap, so begin merge loop with B first.
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// If we run out of B spans or the B span doesn't overlap,
|
||||
// then the next A span can't either (because A spans don't
|
||||
// overlap) and we exit.
|
||||
|
||||
if(b == be || b->first + o.first > x.second)
|
||||
break;
|
||||
|
||||
do {x.second = mymax(x.second, b->second + o.second);}
|
||||
while(++b != be && b->first + o.first <= x.second);
|
||||
|
||||
// If we run out of A spans or the A span doesn't overlap,
|
||||
// then the next B span can't either (because B spans don't
|
||||
// overlap) and we exit.
|
||||
|
||||
if(a == ae || a->first > x.second)
|
||||
break;
|
||||
|
||||
do {x.second = mymax(x.second, a->second);}
|
||||
while(++a != ae && a->first <= x.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Flush span.
|
||||
|
||||
dst.Add(x);
|
||||
}
|
||||
|
||||
// Copy over leftover spans.
|
||||
|
||||
dst.Append(a, ae - a);
|
||||
|
||||
for(; b != be; b++)
|
||||
{
|
||||
dst.Add(Span(b->first + o.first, b->second + o.second));
|
||||
}
|
||||
}
|
||||
|
||||
bool Rasterizer::CreateWidenedRegion(int r)
|
||||
{
|
||||
if(r < 0) r = 0;
|
||||
|
||||
r >>= FONT_SCALE;
|
||||
|
||||
for(int y = -r; y <= r; ++y)
|
||||
{
|
||||
int x = (int)(0.5f + sqrt(float(r*r - y*y)));
|
||||
|
||||
_OverlapRegion(mWideOutline, mOutline, x, y);
|
||||
}
|
||||
|
||||
mWideBorder = r;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Rasterizer::Rasterize(int xsub, int ysub)
|
||||
{
|
||||
_TrashOverlay();
|
||||
|
||||
if(!mWidth || !mHeight)
|
||||
{
|
||||
mOverlayWidth = mOverlayHeight = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
xsub >>= FONT_SCALE;
|
||||
ysub >>= FONT_SCALE;
|
||||
|
||||
xsub &= (1<<FONT_AA)-1;
|
||||
ysub &= (1<<FONT_AA)-1;
|
||||
|
||||
int width = mWidth + xsub;
|
||||
int height = mHeight + ysub;
|
||||
|
||||
mOffsetX = mPathOffsetX - xsub;
|
||||
mOffsetY = mPathOffsetY - ysub;
|
||||
|
||||
int border = ((mWideBorder + ((1<<FONT_AA)-1)) & ~((1<<FONT_AA)-1)) + (1<<FONT_AA)*4;
|
||||
|
||||
if(!mWideOutline.IsEmpty())
|
||||
{
|
||||
width += 2*border;
|
||||
height += 2*border;
|
||||
|
||||
xsub += border;
|
||||
ysub += border;
|
||||
|
||||
mOffsetX -= border;
|
||||
mOffsetY -= border;
|
||||
}
|
||||
|
||||
mOverlayWidth = ((width + ((1<<FONT_AA)-1)) >> FONT_AA) + 1;
|
||||
mOverlayHeight = ((height + ((1<<FONT_AA)-1)) >> FONT_AA) + 1;
|
||||
|
||||
mpOverlayBuffer = new BYTE[4 * mOverlayWidth * mOverlayHeight];
|
||||
memset(mpOverlayBuffer, 0, 4 * mOverlayWidth * mOverlayHeight);
|
||||
|
||||
Array<Span>* pOutline[2] = {&mOutline, &mWideOutline};
|
||||
|
||||
for(int i = 0; i < countof(pOutline); i++)
|
||||
{
|
||||
const Span* s = pOutline[i]->GetData();
|
||||
|
||||
for(size_t j = 0, k = pOutline[i]->GetCount(); j < k; j++)
|
||||
{
|
||||
int y = s[j].y1 - 0x40000000 + ysub;
|
||||
int x1 = s[j].x1 - 0x40000000 + xsub;
|
||||
int x2 = s[j].x2 - 0x40000000 + xsub;
|
||||
|
||||
if(x2 > x1)
|
||||
{
|
||||
int first = x1 >> FONT_AA;
|
||||
int last = (x2-1) >> FONT_AA;
|
||||
|
||||
BYTE* dst = mpOverlayBuffer + 4*(mOverlayWidth * (y >> FONT_AA) + first) + i;
|
||||
|
||||
if(first == last)
|
||||
{
|
||||
*dst += x2 - x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst += (((first+1) << FONT_AA) - x1) << (6 - FONT_AA*2);
|
||||
dst += 4;
|
||||
|
||||
while(++first < last)
|
||||
{
|
||||
*dst += (1 << FONT_AA) << (6 - FONT_AA*2);
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
*dst += (x2 - (last << FONT_AA)) << (6 - FONT_AA*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!mWideOutline.IsEmpty())
|
||||
{
|
||||
BYTE* p = mpOverlayBuffer;
|
||||
|
||||
for(int j = 0; j < mOverlayHeight; j++, p += mOverlayWidth*4)
|
||||
{
|
||||
for(int i = 0; i < mOverlayWidth; i++)
|
||||
{
|
||||
p[i*4+2] = min(p[i*4+1], (1<<6) - p[i*4]); // TODO: sse2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Rasterizer::Blur(float n, int plane)
|
||||
{
|
||||
if(n <= 0 || !mOverlayWidth || !mOverlayHeight || !mpOverlayBuffer)
|
||||
return;
|
||||
|
||||
int w = mOverlayWidth;
|
||||
int h = mOverlayHeight;
|
||||
int pitch = w*4;
|
||||
BYTE* q0 = new BYTE[w*h];
|
||||
|
||||
for(int pass = 0, limit = (int)(n + 0.5); pass < n; pass++)
|
||||
{
|
||||
BYTE* p = mpOverlayBuffer + plane;
|
||||
BYTE* q = q0;
|
||||
|
||||
for(int y = 0; y < h; y++, p += pitch, q += w)
|
||||
{
|
||||
q[0] = (2*p[0] + p[4]) >> 2;
|
||||
int x = 0;
|
||||
for(x = 1; x < w-1; x++)
|
||||
q[x] = (p[(x-1)*4] + 2*p[x*4] + p[(x+1)*4]) >> 2;
|
||||
q[x] = (p[(x-1)*4] + 2*p[x*4]) >> 2;
|
||||
}
|
||||
|
||||
p = mpOverlayBuffer + plane;
|
||||
q = q0;
|
||||
|
||||
for(int x = 0; x < w; x++, p += 4, q++)
|
||||
{
|
||||
p[0] = (2*q[0] + q[w]) >> 2;
|
||||
int y = 0, yp, yq;
|
||||
for(y = 1, yp = y*pitch, yq = y*w; y < h-1; y++, yp += pitch, yq += w)
|
||||
p[yp] = (q[yq-w] + 2*q[yq] + q[yq+w]) >> 2;
|
||||
p[yp] = (q[yq-w] + 2*q[yq]) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] q0;
|
||||
}
|
||||
|
||||
void Rasterizer::Reuse(Rasterizer& r)
|
||||
{
|
||||
mWidth = r.mWidth;
|
||||
mHeight = r.mHeight;
|
||||
mPathOffsetX = r.mPathOffsetX;
|
||||
mPathOffsetY = r.mPathOffsetY;
|
||||
mWideBorder = r.mWideBorder;
|
||||
mOutline.Move(r.mOutline);
|
||||
mWideOutline.Move(r.mWideOutline);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline void pixmix_c(DWORD* dst, DWORD color, DWORD alpha)
|
||||
{
|
||||
int a = ((alpha * (color>>24)) >> 6) & 0xff;
|
||||
int ia = 0xff - a;
|
||||
|
||||
*dst = ((((*dst & 0x00ff00ff)*ia + (color & 0x00ff00ff)*a) & 0xff00ff00) >> 8)
|
||||
| ((((*dst>>8) & 0x00ff00ff)*ia + ((color>>8) & 0x000000ff)*a) & 0xff00ff00);
|
||||
}
|
||||
|
||||
static __forceinline void pixmix_sse2(DWORD* dst, DWORD color, DWORD alpha)
|
||||
{
|
||||
alpha = ((alpha * (color>>24)) >> 6) & 0xff;
|
||||
color &= 0xffffff;
|
||||
|
||||
__m128i zero = _mm_setzero_si128();
|
||||
__m128i a = _mm_set1_epi32((alpha << 16) | (0xff - alpha));
|
||||
__m128i d = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*dst), zero);
|
||||
__m128i s = _mm_unpacklo_epi8(_mm_cvtsi32_si128(color), zero);
|
||||
__m128i r = _mm_unpacklo_epi16(d, s);
|
||||
|
||||
r = _mm_madd_epi16(r, a);
|
||||
r = _mm_srli_epi32(r, 8);
|
||||
r = _mm_packs_epi32(r, r);
|
||||
r = _mm_packus_epi16(r, r);
|
||||
|
||||
*dst = (DWORD)_mm_cvtsi128_si32(r);
|
||||
}
|
||||
|
||||
CRect Rasterizer::Draw(const SubPicDesc& spd, const CRect& clip, int xsub, int ysub, const DWORD* switchpts, int plane)
|
||||
{
|
||||
CRect bbox(0, 0, 0, 0);
|
||||
|
||||
if(!switchpts) return bbox;
|
||||
|
||||
// clip
|
||||
|
||||
CRect r(0, 0, spd.w, spd.h);
|
||||
r &= clip;
|
||||
|
||||
xsub >>= FONT_SCALE;
|
||||
ysub >>= FONT_SCALE;
|
||||
|
||||
int x = (xsub + mOffsetX + (1<<FONT_AA)/2) >> FONT_AA;
|
||||
int y = (ysub + mOffsetY + (1<<FONT_AA)/2) >> FONT_AA;
|
||||
int w = mOverlayWidth;
|
||||
int h = mOverlayHeight;
|
||||
int xo = 0, yo = 0;
|
||||
|
||||
if(x < r.left) {xo = r.left - x; w -= r.left - x; x = r.left;}
|
||||
if(y < r.top) {yo = r.top - y; h -= r.top - y; y = r.top;}
|
||||
if(x+w > r.right) w = r.right - x;
|
||||
if(y+h > r.bottom) h = r.bottom - y;
|
||||
|
||||
if(w <= 0 || h <= 0) return bbox;
|
||||
|
||||
bbox.SetRect(x, y, x + w, y + h);
|
||||
bbox &= CRect(0, 0, spd.w, spd.h);
|
||||
|
||||
// draw
|
||||
|
||||
const BYTE* src = mpOverlayBuffer + 4*(mOverlayWidth * yo + xo) + plane;
|
||||
DWORD* dst = (DWORD*)((BYTE*)spd.bits + spd.pitch * y) + x;
|
||||
|
||||
DWORD color = switchpts[0];
|
||||
|
||||
bool fSSE2 = !!(g_cpuid.m_flags & CCpuID::sse2);
|
||||
|
||||
while(h--)
|
||||
{
|
||||
if(switchpts[1] == 0xffffffff)
|
||||
{
|
||||
if(fSSE2) for(int wt=0; wt<w; ++wt) pixmix_sse2(&dst[wt], color, src[wt*4]);
|
||||
else for(int wt=0; wt<w; ++wt) pixmix_c(&dst[wt], color, src[wt*4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const DWORD* sw = switchpts;
|
||||
|
||||
if(fSSE2)
|
||||
for(int wt=0; wt<w; ++wt)
|
||||
{
|
||||
if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];}
|
||||
pixmix_sse2(&dst[wt], color, src[wt*4]);
|
||||
}
|
||||
else
|
||||
for(int wt=0; wt<w; ++wt)
|
||||
{
|
||||
if(wt+xo >= sw[1]) {while(wt+xo >= sw[1]) sw += 2; color = sw[-2];}
|
||||
pixmix_c(&dst[wt], color, src[wt*4]);
|
||||
}
|
||||
}
|
||||
|
||||
src += 4*mOverlayWidth;
|
||||
dst = (DWORD*)((BYTE*)dst + spd.pitch);
|
||||
}
|
||||
|
||||
return bbox;
|
||||
}
|
||||
}
|
82
vsfilter/libssf/Rasterizer.h
Normal file
82
vsfilter/libssf/Rasterizer.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlcoll.h>
|
||||
#include "SubtitleFile.h"
|
||||
#include "Array.h"
|
||||
#include "GlyphPath.h"
|
||||
#include "../SubPic/ISubPic.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Rasterizer
|
||||
{
|
||||
bool fFirstSet;
|
||||
CPoint firstp, lastp;
|
||||
|
||||
private:
|
||||
int mWidth, mHeight;
|
||||
|
||||
union Span
|
||||
{
|
||||
struct {int x1, y1, x2, y2;};
|
||||
struct {unsigned __int64 first, second;};
|
||||
union Span() {}
|
||||
union Span(int _x1, int _y1, int _x2, int _y2) {x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2;}
|
||||
union Span(unsigned __int64 _first, unsigned __int64 _second) {first = _first; second = _second;}
|
||||
};
|
||||
|
||||
Array<Span> mOutline, mWideOutline, mWideOutlineTmp;
|
||||
int mWideBorder;
|
||||
|
||||
struct Edge {int next, posandflag;}* mpEdgeBuffer;
|
||||
unsigned int mEdgeHeapSize;
|
||||
unsigned int mEdgeNext;
|
||||
unsigned int* mpScanBuffer;
|
||||
|
||||
protected:
|
||||
BYTE* mpOverlayBuffer;
|
||||
int mOverlayWidth, mOverlayHeight;
|
||||
int mPathOffsetX, mPathOffsetY;
|
||||
int mOffsetX, mOffsetY;
|
||||
|
||||
private:
|
||||
void _TrashOverlay();
|
||||
void _ReallocEdgeBuffer(int edges);
|
||||
void _EvaluateBezier(const CPoint& p0, const CPoint& p1, const CPoint& p2, const CPoint& p3);
|
||||
void _EvaluateLine(CPoint p0, CPoint p1);
|
||||
void _OverlapRegion(Array<Span>& dst, Array<Span>& src, int dx, int dy);
|
||||
|
||||
public:
|
||||
Rasterizer();
|
||||
virtual ~Rasterizer();
|
||||
|
||||
bool ScanConvert(GlyphPath& path, const CRect& bbox);
|
||||
bool CreateWidenedRegion(int r);
|
||||
bool Rasterize(int xsub, int ysub);
|
||||
void Reuse(Rasterizer& r);
|
||||
|
||||
void Blur(float n, int plane);
|
||||
CRect Draw(const SubPicDesc& spd, const CRect& clip, int xsub, int ysub, const DWORD* switchpts, int plane);
|
||||
};
|
||||
}
|
819
vsfilter/libssf/Renderer.cpp
Normal file
819
vsfilter/libssf/Renderer.cpp
Normal file
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* TODO: do something about bidi (at least handle these ranges: 0590-07BF, FB1D-FDFF, FE70-FEFF)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Renderer.h"
|
||||
#include "Arabic.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
template <class T>
|
||||
void ReverseList(T& l)
|
||||
{
|
||||
POSITION pos = l.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION cur = pos;
|
||||
l.GetNext(pos);
|
||||
l.AddHead(l.GetAt(cur));
|
||||
l.RemoveAt(cur);
|
||||
}
|
||||
}
|
||||
|
||||
static CPoint GetAlignPoint(const Placement& placement, const Size& scale, const CRect& frame, const CSize& size)
|
||||
{
|
||||
CPoint p;
|
||||
|
||||
p.x = frame.left;
|
||||
p.x += placement.pos.auto_x
|
||||
? placement.align.h * (frame.Width() - size.cx)
|
||||
: placement.pos.x * scale.cx - placement.align.h * size.cx;
|
||||
|
||||
p.y = frame.top;
|
||||
p.y += placement.pos.auto_y
|
||||
? placement.align.v * (frame.Height() - size.cy)
|
||||
: placement.pos.y * scale.cy - placement.align.v * size.cy;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static CPoint GetAlignPoint(const Placement& placement, const Size& scale, const CRect& frame)
|
||||
{
|
||||
CSize size(0, 0);
|
||||
return GetAlignPoint(placement, scale, frame, size);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Renderer::Renderer()
|
||||
{
|
||||
m_hDC = CreateCompatibleDC(NULL);
|
||||
SetBkMode(m_hDC, TRANSPARENT);
|
||||
SetTextColor(m_hDC, 0xffffff);
|
||||
SetMapMode(m_hDC, MM_TEXT);
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
DeleteDC(m_hDC);
|
||||
}
|
||||
|
||||
void Renderer::NextSegment(const CAutoPtrList<Subtitle>& subs)
|
||||
{
|
||||
StringMapW<bool> names;
|
||||
POSITION pos = subs.GetHeadPosition();
|
||||
while(pos) names[subs.GetNext(pos)->m_name] = true;
|
||||
|
||||
pos = m_sra.GetStartPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION cur = pos;
|
||||
const CStringW& name = m_sra.GetNextKey(pos);
|
||||
if(!names.Lookup(name)) m_sra.RemoveAtPos(cur);
|
||||
}
|
||||
}
|
||||
|
||||
RenderedSubtitle* Renderer::Lookup(const Subtitle* s, const CSize& vs, const CRect& vr)
|
||||
{
|
||||
m_sra.UpdateTarget(vs, vr);
|
||||
|
||||
if(s->m_text.IsEmpty())
|
||||
return NULL;
|
||||
|
||||
CRect spdrc = s->m_frame.reference == _T("video") ? vr : CRect(CPoint(0, 0), vs);
|
||||
|
||||
if(spdrc.IsRectEmpty())
|
||||
return NULL;
|
||||
|
||||
RenderedSubtitle* rs = NULL;
|
||||
|
||||
if(m_rsc.Lookup(s->m_name, rs))
|
||||
{
|
||||
if(!s->m_animated && rs->m_spdrc == spdrc)
|
||||
return rs;
|
||||
|
||||
m_rsc.Invalidate(s->m_name);
|
||||
}
|
||||
|
||||
const Style& style = s->m_text.GetHead().style;
|
||||
|
||||
Size scale;
|
||||
|
||||
scale.cx = (float)spdrc.Width() / s->m_frame.resolution.cx;
|
||||
scale.cy = (float)spdrc.Height() / s->m_frame.resolution.cy;
|
||||
|
||||
CRect frame;
|
||||
|
||||
frame.left = (int)(64.0f * (spdrc.left + style.placement.margin.l * scale.cx) + 0.5);
|
||||
frame.top = (int)(64.0f * (spdrc.top + style.placement.margin.t * scale.cy) + 0.5);
|
||||
frame.right = (int)(64.0f * (spdrc.right - style.placement.margin.r * scale.cx) + 0.5);
|
||||
frame.bottom = (int)(64.0f * (spdrc.bottom - style.placement.margin.b * scale.cy) + 0.5);
|
||||
|
||||
CRect clip;
|
||||
|
||||
if(style.placement.clip.l == -1) clip.left = 0;
|
||||
else clip.left = (int)(spdrc.left + style.placement.clip.l * scale.cx);
|
||||
if(style.placement.clip.t == -1) clip.top = 0;
|
||||
else clip.top = (int)(spdrc.top + style.placement.clip.t * scale.cy);
|
||||
if(style.placement.clip.r == -1) clip.right = vs.cx;
|
||||
else clip.right = (int)(spdrc.left + style.placement.clip.r * scale.cx);
|
||||
if(style.placement.clip.b == -1) clip.bottom = vs.cy;
|
||||
else clip.bottom = (int)(spdrc.top + style.placement.clip.b * scale.cy);
|
||||
|
||||
clip.left = max(clip.left, 0);
|
||||
clip.top = max(clip.top, 0);
|
||||
clip.right = min(clip.right, vs.cx);
|
||||
clip.bottom = min(clip.bottom, vs.cy);
|
||||
|
||||
scale.cx *= 64;
|
||||
scale.cy *= 64;
|
||||
|
||||
bool vertical = s->m_direction.primary == _T("down") || s->m_direction.primary == _T("up");
|
||||
|
||||
// create glyph paths
|
||||
|
||||
WCHAR c_prev = 0, c_next;
|
||||
|
||||
CAutoPtrList<Glyph> glyphs;
|
||||
|
||||
POSITION pos = s->m_text.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
const Text& t = s->m_text.GetNext(pos);
|
||||
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(lf));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
_tcscpy_s(lf.lfFaceName, CString(t.style.font.face));
|
||||
lf.lfHeight = (LONG)(t.style.font.size * scale.cy + 0.5);
|
||||
lf.lfWeight = (LONG)(t.style.font.weight + 0.5);
|
||||
lf.lfItalic = !!t.style.font.italic;
|
||||
lf.lfUnderline = !!t.style.font.underline;
|
||||
lf.lfStrikeOut = !!t.style.font.strikethrough;
|
||||
lf.lfOutPrecision = OUT_TT_PRECIS;
|
||||
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
lf.lfQuality = ANTIALIASED_QUALITY;
|
||||
lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
|
||||
|
||||
FontWrapper* font;
|
||||
|
||||
if(!(font = m_fc.Create(m_hDC, lf)))
|
||||
{
|
||||
_tcscpy_s(lf.lfFaceName, _T("Arial"));
|
||||
|
||||
if(!(font = m_fc.Create(m_hDC, lf)))
|
||||
{
|
||||
ASSERT(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
HFONT hOldFont = SelectFont(m_hDC, *font);
|
||||
|
||||
const TEXTMETRIC& tm = font->GetTextMetric();
|
||||
|
||||
for(LPCWSTR c = t.str; *c; c++)
|
||||
{
|
||||
CAutoPtr<Glyph> g(new Glyph());
|
||||
|
||||
g->c = *c;
|
||||
g->style = t.style;
|
||||
g->scale = scale;
|
||||
g->vertical = vertical;
|
||||
g->font = font;
|
||||
|
||||
c_next = !c[1] && pos ? c_next = s->m_text.GetAt(pos).str[0] : c[1];
|
||||
Arabic::Replace(g->c, c_prev, c_next);
|
||||
c_prev = c[0];
|
||||
|
||||
CSize extent;
|
||||
GetTextExtentPoint32W(m_hDC, &g->c, 1, &extent);
|
||||
ASSERT(extent.cx >= 0 && extent.cy >= 0);
|
||||
|
||||
if(vertical)
|
||||
{
|
||||
g->spacing = (int)(t.style.font.spacing * scale.cy + 0.5);
|
||||
g->ascent = extent.cx / 2;
|
||||
g->descent = extent.cx - g->ascent;
|
||||
g->width = extent.cy;
|
||||
|
||||
// TESTME
|
||||
if(g->c == Text::SP)
|
||||
{
|
||||
g->width /= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g->spacing = (int)(t.style.font.spacing * scale.cx + 0.5);
|
||||
g->ascent = tm.tmAscent;
|
||||
g->descent = tm.tmDescent;
|
||||
g->width = extent.cx;
|
||||
}
|
||||
|
||||
if(g->c == Text::LSEP)
|
||||
{
|
||||
g->spacing = 0;
|
||||
g->width = 0;
|
||||
g->ascent /= 2;
|
||||
g->descent /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
GlyphPath* path = m_gpc.Create(m_hDC, font, g->c);
|
||||
if(!path) {ASSERT(0); continue;}
|
||||
g->path = *path;
|
||||
}
|
||||
|
||||
glyphs.AddTail(g);
|
||||
}
|
||||
|
||||
SelectFont(m_hDC, hOldFont);
|
||||
}
|
||||
|
||||
// break glyphs into rows
|
||||
|
||||
CAutoPtrList<Row> rows;
|
||||
CAutoPtr<Row> row;
|
||||
|
||||
pos = glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
CAutoPtr<Glyph> g = glyphs.GetNext(pos);
|
||||
if(!row) row.Attach(new Row());
|
||||
WCHAR c = g->c;
|
||||
row->AddTail(g);
|
||||
if(c == Text::LSEP || !pos) rows.AddTail(row);
|
||||
}
|
||||
|
||||
// kerning
|
||||
|
||||
if(s->m_direction.primary == _T("right")) // || s->m_direction.primary == _T("left")
|
||||
{
|
||||
for(POSITION rpos = rows.GetHeadPosition(); rpos; rows.GetNext(rpos))
|
||||
{
|
||||
Row* r = rows.GetAt(rpos);
|
||||
|
||||
POSITION gpos = r->GetHeadPosition();
|
||||
while(gpos)
|
||||
{
|
||||
Glyph* g1 = r->GetNext(gpos);
|
||||
if(!gpos) break;
|
||||
|
||||
Glyph* g2 = r->GetAt(gpos);
|
||||
if(g1->font != g2->font || !g1->style.font.kerning || !g2->style.font.kerning)
|
||||
continue;
|
||||
|
||||
if(int size = g1->font->GetKernAmount(g1->c, g2->c))
|
||||
{
|
||||
g2->path.MovePoints(CPoint(size, 0));
|
||||
g2->width += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wrap rows
|
||||
|
||||
if(s->m_wrap == _T("normal") || s->m_wrap == _T("even"))
|
||||
{
|
||||
int maxwidth = abs((int)(vertical ? frame.Height() : frame.Width()));
|
||||
int minwidth = 0;
|
||||
|
||||
for(POSITION rpos = rows.GetHeadPosition(); rpos; rows.GetNext(rpos))
|
||||
{
|
||||
Row* r = rows.GetAt(rpos);
|
||||
|
||||
POSITION brpos = NULL;
|
||||
|
||||
if(s->m_wrap == _T("even"))
|
||||
{
|
||||
int fullwidth = 0;
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
const Glyph* g = r->GetAt(gpos);
|
||||
|
||||
fullwidth += g->width + g->spacing;
|
||||
}
|
||||
|
||||
fullwidth = abs(fullwidth);
|
||||
|
||||
if(fullwidth > maxwidth)
|
||||
{
|
||||
maxwidth = fullwidth / ((fullwidth / maxwidth) + 1);
|
||||
minwidth = maxwidth;
|
||||
}
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
const Glyph* g = r->GetAt(gpos);
|
||||
|
||||
width += g->width + g->spacing;
|
||||
|
||||
if(brpos && abs(width) > maxwidth && g->c != Text::SP)
|
||||
{
|
||||
row.Attach(new Row());
|
||||
POSITION next = brpos;
|
||||
r->GetNext(next);
|
||||
do {row->AddHead(r->GetPrev(brpos));} while(brpos);
|
||||
rows.InsertBefore(rpos, row);
|
||||
while(!r->IsEmpty() && r->GetHeadPosition() != next) r->RemoveHeadNoReturn();
|
||||
g = r->GetAt(gpos = next);
|
||||
width = g->width + g->spacing;
|
||||
}
|
||||
|
||||
if(abs(width) >= minwidth)
|
||||
{
|
||||
if(g->style.linebreak == _T("char")
|
||||
|| g->style.linebreak == _T("word") && g->c == Text::SP)
|
||||
{
|
||||
brpos = gpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trim rows
|
||||
|
||||
for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos))
|
||||
{
|
||||
Row* r = rows.GetAt(pos);
|
||||
|
||||
while(!r->IsEmpty() && r->GetHead()->c == Text::SP)
|
||||
r->RemoveHead();
|
||||
|
||||
while(!r->IsEmpty() && r->GetTail()->c == Text::SP)
|
||||
r->RemoveTail();
|
||||
}
|
||||
|
||||
// calc fill width for each glyph
|
||||
|
||||
CAtlList<Glyph*> glypsh2fill;
|
||||
int fill_id = 0;
|
||||
int fill_width = 0;
|
||||
|
||||
for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos))
|
||||
{
|
||||
Row* r = rows.GetAt(pos);
|
||||
|
||||
POSITION gpos = r->GetHeadPosition();
|
||||
while(gpos)
|
||||
{
|
||||
Glyph* g = r->GetNext(gpos);
|
||||
|
||||
if(!glypsh2fill.IsEmpty() && fill_id && (g->style.fill.id != fill_id || !pos && !gpos))
|
||||
{
|
||||
int w = (int)(g->style.fill.width * fill_width + 0.5);
|
||||
|
||||
while(!glypsh2fill.IsEmpty())
|
||||
{
|
||||
Glyph* g = glypsh2fill.RemoveTail();
|
||||
fill_width -= g->width;
|
||||
g->fill = w - fill_width;
|
||||
}
|
||||
|
||||
ASSERT(glypsh2fill.IsEmpty());
|
||||
ASSERT(fill_width == 0);
|
||||
|
||||
glypsh2fill.RemoveAll();
|
||||
fill_width = 0;
|
||||
}
|
||||
|
||||
fill_id = g->style.fill.id;
|
||||
|
||||
if(g->style.fill.id)
|
||||
{
|
||||
glypsh2fill.AddTail(g);
|
||||
fill_width += g->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calc row sizes and total subtitle size
|
||||
|
||||
CSize size(0, 0);
|
||||
|
||||
if(s->m_direction.secondary == _T("left") || s->m_direction.secondary == _T("up"))
|
||||
ReverseList(rows);
|
||||
|
||||
for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos))
|
||||
{
|
||||
Row* r = rows.GetAt(pos);
|
||||
|
||||
if(s->m_direction.primary == _T("left") || s->m_direction.primary == _T("up"))
|
||||
ReverseList(*r);
|
||||
|
||||
int w = 0, h = 0;
|
||||
|
||||
r->width = 0;
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
const Glyph* g = r->GetAt(gpos);
|
||||
|
||||
w += g->width;
|
||||
if(gpos) w += g->spacing;
|
||||
h = max(h, g->ascent + g->descent);
|
||||
|
||||
r->width += g->width;
|
||||
if(gpos) r->width += g->spacing;
|
||||
r->ascent = max(r->ascent, g->ascent);
|
||||
r->descent = max(r->descent, g->descent);
|
||||
r->border = max(r->border, g->GetBackgroundSize());
|
||||
}
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
Glyph* g = r->GetAt(gpos);
|
||||
g->row_ascent = r->ascent;
|
||||
g->row_descent = r->descent;
|
||||
}
|
||||
|
||||
if(vertical)
|
||||
{
|
||||
size.cx += h;
|
||||
size.cy = max(size.cy, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
size.cx = max(size.cx, w);
|
||||
size.cy += h;
|
||||
}
|
||||
}
|
||||
|
||||
// align rows and calc glyph positions
|
||||
|
||||
rs = new RenderedSubtitle(spdrc, clip);
|
||||
|
||||
CPoint p = GetAlignPoint(style.placement, scale, frame, size);
|
||||
CPoint org = GetAlignPoint(style.placement, scale, frame);
|
||||
|
||||
// collision detection
|
||||
|
||||
if(!s->m_animated)
|
||||
{
|
||||
int tlb = !rows.IsEmpty() ? rows.GetHead()->border : 0;
|
||||
int brb = !rows.IsEmpty() ? rows.GetTail()->border : 0;
|
||||
|
||||
CRect r(p, size);
|
||||
m_sra.GetRect(r, s, style.placement.align, tlb, brb);
|
||||
org += r.TopLeft() - p;
|
||||
p = r.TopLeft();
|
||||
}
|
||||
|
||||
CRect subrect(p, size);
|
||||
|
||||
// continue positioning
|
||||
|
||||
for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos))
|
||||
{
|
||||
Row* r = rows.GetAt(pos);
|
||||
|
||||
CSize rsize;
|
||||
rsize.cx = rsize.cy = r->width;
|
||||
|
||||
if(vertical)
|
||||
{
|
||||
p.y = GetAlignPoint(style.placement, scale, frame, rsize).y;
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
CAutoPtr<Glyph> g = r->GetAt(gpos);
|
||||
g->tl.x = p.x + (int)(g->style.placement.offset.x * scale.cx + 0.5) + r->ascent - g->ascent;
|
||||
g->tl.y = p.y + (int)(g->style.placement.offset.y * scale.cy + 0.5);
|
||||
p.y += g->width + g->spacing;
|
||||
rs->m_glyphs.AddTail(g);
|
||||
}
|
||||
|
||||
p.x += r->ascent + r->descent;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.x = GetAlignPoint(style.placement, scale, frame, rsize).x;
|
||||
|
||||
for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos))
|
||||
{
|
||||
CAutoPtr<Glyph> g = r->GetAt(gpos);
|
||||
g->tl.x = p.x + (int)(g->style.placement.offset.x * scale.cx + 0.5);
|
||||
g->tl.y = p.y + (int)(g->style.placement.offset.y * scale.cy + 0.5) + r->ascent - g->ascent;
|
||||
p.x += g->width + g->spacing;
|
||||
rs->m_glyphs.AddTail(g);
|
||||
}
|
||||
|
||||
p.y += r->ascent + r->descent;
|
||||
}
|
||||
}
|
||||
|
||||
// bkg, precalc style.placement.path, transform
|
||||
|
||||
pos = rs->m_glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Glyph* g = rs->m_glyphs.GetNext(pos);
|
||||
g->CreateBkg();
|
||||
g->CreateSplineCoeffs(spdrc);
|
||||
g->Transform(org, subrect);
|
||||
}
|
||||
|
||||
// merge glyphs (TODO: merge 'fill' too)
|
||||
|
||||
Glyph* g0 = NULL;
|
||||
|
||||
pos = rs->m_glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
POSITION cur = pos;
|
||||
|
||||
Glyph* g = rs->m_glyphs.GetNext(pos);
|
||||
|
||||
CRect r = g->bbox + g->tl;
|
||||
|
||||
int size = (int)(g->GetBackgroundSize() + 0.5);
|
||||
int depth = (int)(g->GetShadowDepth() + 0.5);
|
||||
|
||||
r.InflateRect(size, size);
|
||||
r.InflateRect(depth, depth);
|
||||
|
||||
r.left >>= 6;
|
||||
r.top >>= 6;
|
||||
r.right = (r.right + 32) >> 6;
|
||||
r.bottom = (r.bottom + 32) >> 6;
|
||||
|
||||
if((r & clip).IsRectEmpty()) // clip
|
||||
{
|
||||
rs->m_glyphs.RemoveAt(cur);
|
||||
}
|
||||
else if(g0 && g0->style.IsSimilar(g->style)) // append
|
||||
{
|
||||
CPoint o = g->tl - g0->tl;
|
||||
|
||||
g->path.MovePoints(o);
|
||||
|
||||
g0->path.types.Append(g->path.types);
|
||||
g0->path.points.Append(g->path.points);
|
||||
|
||||
g->path_bkg.MovePoints(o);
|
||||
|
||||
g0->path_bkg.types.Append(g->path_bkg.types);
|
||||
g0->path_bkg.points.Append(g->path_bkg.points);
|
||||
|
||||
g0->bbox |= g->bbox + o;
|
||||
|
||||
rs->m_glyphs.RemoveAt(cur);
|
||||
}
|
||||
else // leave alone
|
||||
{
|
||||
g0 = g;
|
||||
}
|
||||
}
|
||||
|
||||
// rasterize
|
||||
|
||||
pos = rs->m_glyphs.GetHeadPosition();
|
||||
while(pos) rs->m_glyphs.GetNext(pos)->Rasterize();
|
||||
|
||||
// cache
|
||||
|
||||
m_rsc.Add(s->m_name, rs);
|
||||
|
||||
m_fc.Flush();
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
CRect RenderedSubtitle::Draw(SubPicDesc& spd) const
|
||||
{
|
||||
CRect bbox;
|
||||
bbox.SetRectEmpty();
|
||||
|
||||
// shadow
|
||||
|
||||
POSITION pos = m_glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Glyph* g = m_glyphs.GetNext(pos);
|
||||
|
||||
if(g->style.shadow.depth <= 0) continue;
|
||||
|
||||
DWORD c = g->style.shadow.color;
|
||||
DWORD sw[6] = {c, -1};
|
||||
|
||||
bool outline = g->style.background.type == L"outline" && g->style.background.size > 0;
|
||||
|
||||
bbox |= g->ras_shadow.Draw(spd, m_clip, g->tls.x, g->tls.y, sw, outline ? 1 : 0);
|
||||
}
|
||||
|
||||
// background
|
||||
|
||||
pos = m_glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Glyph* g = m_glyphs.GetNext(pos);
|
||||
|
||||
DWORD c = g->style.background.color;
|
||||
DWORD sw[6] = {c, -1};
|
||||
|
||||
if(g->style.background.type == L"outline" && g->style.background.size > 0)
|
||||
{
|
||||
bbox |= g->ras.Draw(spd, m_clip, g->tl.x, g->tl.y, sw, g->style.font.color.a < 255 ? 2 : 1);
|
||||
}
|
||||
else if(g->style.background.type == L"enlarge" && g->style.background.size > 0
|
||||
|| g->style.background.type == L"box" && g->style.background.size >= 0)
|
||||
{
|
||||
bbox |= g->ras_bkg.Draw(spd, m_clip, g->tl.x, g->tl.y, sw, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
|
||||
pos = m_glyphs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Glyph* g = m_glyphs.GetNext(pos);
|
||||
|
||||
DWORD c = g->style.font.color;
|
||||
DWORD sw[6] = {c, -1}; // TODO: fill
|
||||
|
||||
bbox |= g->ras.Draw(spd, m_clip, g->tl.x, g->tl.y, sw, 0);
|
||||
}
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SubRectAllocator::UpdateTarget(const CSize& s, const CRect& r)
|
||||
{
|
||||
if(vs != s || vr != r) RemoveAll();
|
||||
vs = s;
|
||||
vr = r;
|
||||
}
|
||||
|
||||
void SubRectAllocator::GetRect(CRect& rect, const Subtitle* s, const Align& align, int tlb, int brb)
|
||||
{
|
||||
SubRect sr(rect, s->m_layer);
|
||||
sr.rect.InflateRect(tlb, tlb, brb, brb);
|
||||
|
||||
StringMapW<SubRect>::CPair* pPair = Lookup(s->m_name);
|
||||
|
||||
if(pPair && pPair->m_value.rect != sr.rect)
|
||||
{
|
||||
RemoveKey(s->m_name);
|
||||
pPair = NULL;
|
||||
}
|
||||
|
||||
if(!pPair)
|
||||
{
|
||||
bool vertical = s->m_direction.primary == _T("down") || s->m_direction.primary == _T("up");
|
||||
|
||||
bool fOK = false;
|
||||
|
||||
while(!fOK)
|
||||
{
|
||||
fOK = true;
|
||||
|
||||
POSITION pos = GetStartPosition();
|
||||
while(pos)
|
||||
{
|
||||
const SubRect& sr2 = GetNextValue(pos);
|
||||
|
||||
if(sr.layer == sr2.layer && !(sr.rect & sr2.rect).IsRectEmpty())
|
||||
{
|
||||
if(vertical)
|
||||
{
|
||||
if(align.h < 0.5)
|
||||
{
|
||||
sr.rect.right = sr2.rect.right + sr.rect.Width();
|
||||
sr.rect.left = sr2.rect.right;
|
||||
}
|
||||
else
|
||||
{
|
||||
sr.rect.left = sr2.rect.left - sr.rect.Width();
|
||||
sr.rect.right = sr2.rect.left;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(align.v < 0.5)
|
||||
{
|
||||
sr.rect.bottom = sr2.rect.bottom + sr.rect.Height();
|
||||
sr.rect.top = sr2.rect.bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
sr.rect.top = sr2.rect.top - sr.rect.Height();
|
||||
sr.rect.bottom = sr2.rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
fOK = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetAt(s->m_name, sr);
|
||||
|
||||
rect = sr.rect;
|
||||
rect.DeflateRect(tlb, tlb, brb, brb);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
FontWrapper* FontCache::Create(HDC hDC, const LOGFONT& lf)
|
||||
{
|
||||
CStringW key;
|
||||
|
||||
key.Format(L"%s,%d,%d,%d",
|
||||
CStringW(lf.lfFaceName), lf.lfHeight, lf.lfWeight,
|
||||
((lf.lfItalic&1)<<2) | ((lf.lfUnderline&1)<<1) | ((lf.lfStrikeOut&1)<<0));
|
||||
|
||||
FontWrapper* pFW = NULL;
|
||||
|
||||
if(m_key2obj.Lookup(key, pFW))
|
||||
{
|
||||
return pFW;
|
||||
}
|
||||
|
||||
HFONT hFont;
|
||||
|
||||
if(!(hFont = CreateFontIndirect(&lf)))
|
||||
{
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pFW = new FontWrapper(hDC, hFont, key);
|
||||
|
||||
Add(key, pFW, false);
|
||||
|
||||
return pFW;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GlyphPath* GlyphPathCache::Create(HDC hDC, const FontWrapper* f, WCHAR c)
|
||||
{
|
||||
CStringW key = CStringW((LPCWSTR)*f) + c;
|
||||
|
||||
GlyphPath* path = NULL;
|
||||
|
||||
if(m_key2obj.Lookup(key, path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
BeginPath(hDC);
|
||||
TextOutW(hDC, 0, 0, &c, 1);
|
||||
CloseFigure(hDC);
|
||||
if(!EndPath(hDC)) {AbortPath(hDC); ASSERT(0); return NULL;}
|
||||
|
||||
path = new GlyphPath();
|
||||
|
||||
int count = GetPath(hDC, NULL, NULL, 0);
|
||||
|
||||
if(count > 0)
|
||||
{
|
||||
path->points.SetCount(count);
|
||||
path->types.SetCount(count);
|
||||
|
||||
if(count != GetPath(hDC, path->points.GetData(), path->types.GetData(), count))
|
||||
{
|
||||
ASSERT(0);
|
||||
delete path;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Add(key, path);
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
160
vsfilter/libssf/Renderer.h
Normal file
160
vsfilter/libssf/Renderer.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringMap.h"
|
||||
#include "Glyph.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
template<class T>
|
||||
class Cache
|
||||
{
|
||||
protected:
|
||||
StringMapW<T> m_key2obj;
|
||||
CAtlList<CStringW> m_objs;
|
||||
size_t m_limit;
|
||||
|
||||
public:
|
||||
Cache(size_t limit) {m_limit = max(1, limit);}
|
||||
virtual ~Cache() {RemoveAll();}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
POSITION pos = m_key2obj.GetStartPosition();
|
||||
while(pos) delete m_key2obj.GetNextValue(pos);
|
||||
m_key2obj.RemoveAll();
|
||||
m_objs.RemoveAll();
|
||||
}
|
||||
|
||||
void Add(const CStringW& key, T& obj, bool fFlush = true)
|
||||
{
|
||||
if(StringMapW<T>::CPair* p = m_key2obj.Lookup(key)) delete p->m_value;
|
||||
else m_objs.AddTail(key);
|
||||
|
||||
m_key2obj[key] = obj;
|
||||
|
||||
if(fFlush) Flush();
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
while(m_objs.GetCount() > m_limit)
|
||||
{
|
||||
CStringW key = m_objs.RemoveHead();
|
||||
ASSERT(m_key2obj.Lookup(key));
|
||||
delete m_key2obj[key];
|
||||
m_key2obj.RemoveKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool Lookup(const CStringW& key, T& val)
|
||||
{
|
||||
return m_key2obj.Lookup(key, val) && val;
|
||||
}
|
||||
|
||||
void Invalidate(const CStringW& key)
|
||||
{
|
||||
T val;
|
||||
if(m_key2obj.Lookup(key, val))
|
||||
{
|
||||
delete val;
|
||||
m_key2obj[key] = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class FontCache : public Cache<FontWrapper*>
|
||||
{
|
||||
public:
|
||||
FontCache() : Cache(20) {}
|
||||
FontWrapper* Create(HDC hDC, const LOGFONT& lf);
|
||||
};
|
||||
|
||||
class GlyphPathCache : public Cache<GlyphPath*>
|
||||
{
|
||||
public:
|
||||
GlyphPathCache() : Cache(100) {}
|
||||
GlyphPath* Create(HDC hDC, const FontWrapper* f, WCHAR c);
|
||||
};
|
||||
|
||||
class Row : public CAutoPtrList<Glyph>
|
||||
{
|
||||
public:
|
||||
int ascent, descent, border, width;
|
||||
Row() {ascent = descent = border = width = 0;}
|
||||
};
|
||||
|
||||
class RenderedSubtitle
|
||||
{
|
||||
public:
|
||||
CRect m_spdrc;
|
||||
CRect m_clip;
|
||||
CAutoPtrList<Glyph> m_glyphs;
|
||||
|
||||
RenderedSubtitle(const CRect& spdrc, const CRect& clip) : m_spdrc(spdrc), m_clip(clip) {}
|
||||
virtual ~RenderedSubtitle() {}
|
||||
|
||||
CRect Draw(SubPicDesc& spd) const;
|
||||
};
|
||||
|
||||
class RenderedSubtitleCache : public Cache<RenderedSubtitle*>
|
||||
{
|
||||
public:
|
||||
RenderedSubtitleCache() : Cache(10) {}
|
||||
};
|
||||
|
||||
class SubRect
|
||||
{
|
||||
public:
|
||||
CRect rect;
|
||||
float layer;
|
||||
SubRect() {}
|
||||
SubRect(const CRect& r, float l) : rect(r), layer(l) {}
|
||||
};
|
||||
|
||||
class SubRectAllocator : public StringMapW<SubRect>
|
||||
{
|
||||
CSize vs;
|
||||
CRect vr;
|
||||
public:
|
||||
void UpdateTarget(const CSize& vs, const CRect& vr);
|
||||
void GetRect(CRect& rect, const Subtitle* s, const Align& align, int tlb, int brb);
|
||||
};
|
||||
|
||||
class Renderer
|
||||
{
|
||||
HDC m_hDC;
|
||||
|
||||
FontCache m_fc;
|
||||
GlyphPathCache m_gpc;
|
||||
RenderedSubtitleCache m_rsc;
|
||||
SubRectAllocator m_sra;
|
||||
|
||||
public:
|
||||
Renderer();
|
||||
virtual ~Renderer();
|
||||
|
||||
void NextSegment(const CAutoPtrList<Subtitle>& subs);
|
||||
RenderedSubtitle* Lookup(const Subtitle* s, const CSize& vs, const CRect& vr);
|
||||
};
|
||||
}
|
74
vsfilter/libssf/Split.cpp
Normal file
74
vsfilter/libssf/Split.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Split.h"
|
||||
#include "Exception.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
Split::Split(LPCWSTR sep, CStringW str, size_t limit, SplitType type)
|
||||
{
|
||||
DoSplit(sep, str, limit, type);
|
||||
}
|
||||
|
||||
Split::Split(WCHAR sep, CStringW str, size_t limit, SplitType type)
|
||||
{
|
||||
DoSplit(CStringW(sep), str, limit, type);
|
||||
}
|
||||
|
||||
void Split::DoSplit(LPCWSTR sep, CStringW str, size_t limit, SplitType type)
|
||||
{
|
||||
RemoveAll();
|
||||
|
||||
if(size_t seplen = wcslen(sep))
|
||||
{
|
||||
for(int i = 0, j = 0, len = str.GetLength();
|
||||
i <= len && (limit == 0 || GetCount() < limit);
|
||||
i = j + (int)seplen)
|
||||
{
|
||||
j = str.Find(sep, i);
|
||||
if(j < 0) j = len;
|
||||
|
||||
CStringW s = i < j ? str.Mid(i, j - i) : L"";
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case Min: s.Trim(); // fall through
|
||||
case Def: if(s.IsEmpty()) break; // else fall through
|
||||
case Max: Add(s); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Split::GetAtInt(size_t i)
|
||||
{
|
||||
if(i >= GetCount()) throw Exception(_T("Index out of bounds"));
|
||||
return _wtoi(GetAt(i));
|
||||
}
|
||||
|
||||
float Split::GetAtFloat(size_t i)
|
||||
{
|
||||
if(i >= GetCount()) throw Exception(_T("Index out of bounds"));
|
||||
return (float)_wtof(GetAt(i));
|
||||
}
|
||||
}
|
38
vsfilter/libssf/Split.h
Normal file
38
vsfilter/libssf/Split.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Split : public CAtlArray<CStringW>
|
||||
{
|
||||
public:
|
||||
enum SplitType {Min, Def, Max};
|
||||
Split();
|
||||
Split(LPCWSTR sep, CStringW str, size_t limit = 0, SplitType type = Def);
|
||||
Split(WCHAR sep, CStringW str, size_t limit = 0, SplitType type = Def);
|
||||
operator size_t() {return GetCount();}
|
||||
void DoSplit(LPCWSTR sep, CStringW str, size_t limit, SplitType type);
|
||||
int GetAtInt(size_t i);
|
||||
float GetAtFloat(size_t i);
|
||||
};
|
||||
}
|
360
vsfilter/libssf/Stream.cpp
Normal file
360
vsfilter/libssf/Stream.cpp
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Stream.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
Stream::Stream()
|
||||
: m_encoding(none)
|
||||
, m_line(0)
|
||||
, m_col(-1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Stream::~Stream()
|
||||
{
|
||||
}
|
||||
|
||||
void Stream::ThrowError(LPCTSTR fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = _vsctprintf(fmt, args) + 1;
|
||||
CString str;
|
||||
if(len > 0) _vstprintf_s(str.GetBufferSetLength(len), len, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
throw Exception(_T("Error (Ln %d Col %d): %s"), m_line+1, m_col+1, str);
|
||||
}
|
||||
|
||||
bool Stream::IsWhiteSpace(int c, LPCWSTR morechars)
|
||||
{
|
||||
return c != 0xa0 && iswspace(c) || morechars && wcschr(morechars, (WCHAR)c);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
InputStream::InputStream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
InputStream::~InputStream()
|
||||
{
|
||||
}
|
||||
|
||||
int InputStream::NextChar()
|
||||
{
|
||||
if(m_encoding == none)
|
||||
{
|
||||
m_encoding = unknown;
|
||||
|
||||
switch(NextByte())
|
||||
{
|
||||
case 0xef:
|
||||
if(NextByte() == 0xbb && NextByte() == 0xbf) m_encoding = utf8;
|
||||
break;
|
||||
case 0xff:
|
||||
if(NextByte() == 0xfe) m_encoding = utf16le;
|
||||
break;
|
||||
case 0xfe:
|
||||
if(NextByte() == 0xff) m_encoding = utf16be;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_encoding == unknown)
|
||||
{
|
||||
throw Exception(_T("unknown character encoding, missing BOM"));
|
||||
}
|
||||
|
||||
int i, c;
|
||||
|
||||
int cur = NextByte();
|
||||
|
||||
switch(m_encoding)
|
||||
{
|
||||
case utf8:
|
||||
for(i = 7; i >= 0 && (cur & (1 << i)); i--);
|
||||
cur &= (1 << i) - 1;
|
||||
while(++i < 7) {c = NextByte(); if(c == EOS) {cur = EOS; break;} cur = (cur << 6) | (c & 0x3f);}
|
||||
break;
|
||||
case utf16le:
|
||||
c = NextByte();
|
||||
if(c == EOS) {cur = EOS; break;}
|
||||
cur = (c << 8) | cur;
|
||||
break;
|
||||
case utf16be:
|
||||
c = NextByte();
|
||||
if(c == EOS) {cur = EOS; break;}
|
||||
cur = cur | (c << 8);
|
||||
break;
|
||||
case wchar:
|
||||
break;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
int InputStream::PushChar()
|
||||
{
|
||||
int c = NextChar();
|
||||
m_queue.AddTail(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
int InputStream::PopChar()
|
||||
{
|
||||
if(m_queue.IsEmpty()) ThrowError(_T("fatal stream error"));
|
||||
|
||||
int c = m_queue.RemoveHead();
|
||||
|
||||
if(c != EOS)
|
||||
{
|
||||
if(c == '\n') {m_line++; m_col = -1;}
|
||||
m_col++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int InputStream::PeekChar()
|
||||
{
|
||||
while(m_queue.GetCount() < 2) PushChar();
|
||||
|
||||
ASSERT(m_queue.GetCount() == 2);
|
||||
|
||||
if(m_queue.GetHead() == '/' && m_queue.GetTail() == '/')
|
||||
{
|
||||
while(!m_queue.IsEmpty()) PopChar();
|
||||
int c;
|
||||
do {PushChar(); c = PopChar();} while(!(c == '\n' || c == EOS));
|
||||
return PeekChar();
|
||||
}
|
||||
else if(m_queue.GetHead() == '/' && m_queue.GetTail() == '*')
|
||||
{
|
||||
while(!m_queue.IsEmpty()) PopChar();
|
||||
int c1, c2;
|
||||
PushChar();
|
||||
do {c2 = PushChar(); c1 = PopChar();} while(!((c1 == '*' && c2 == '/') || c1 == EOS));
|
||||
PopChar();
|
||||
return PeekChar();
|
||||
}
|
||||
|
||||
return m_queue.GetHead();
|
||||
}
|
||||
|
||||
int InputStream::GetChar()
|
||||
{
|
||||
if(m_queue.GetCount() < 2) PeekChar();
|
||||
return PopChar();
|
||||
}
|
||||
|
||||
int InputStream::SkipWhiteSpace(LPCWSTR morechars)
|
||||
{
|
||||
int c = PeekChar();
|
||||
for(; IsWhiteSpace(c, morechars); c = PeekChar())
|
||||
GetChar();
|
||||
return c;
|
||||
}
|
||||
|
||||
// FileInputStream
|
||||
|
||||
FileInputStream::FileInputStream(const TCHAR* fn)
|
||||
: m_file(NULL)
|
||||
{
|
||||
if(_tfopen_s(&m_file, fn, _T("r")) != 0) ThrowError(_T("cannot open file '%s'"), fn);
|
||||
}
|
||||
|
||||
FileInputStream::~FileInputStream()
|
||||
{
|
||||
if(m_file) {fclose(m_file); m_file = NULL;}
|
||||
}
|
||||
|
||||
int FileInputStream::NextByte()
|
||||
{
|
||||
if(!m_file) ThrowError(_T("file pointer is NULL"));
|
||||
return fgetc(m_file);
|
||||
}
|
||||
|
||||
// MemoryInputStream
|
||||
|
||||
MemoryInputStream::MemoryInputStream(BYTE* pBytes, int len, bool fCopy, bool fFree)
|
||||
: m_pBytes(NULL)
|
||||
, m_pos(0)
|
||||
, m_len(len)
|
||||
{
|
||||
if(fCopy)
|
||||
{
|
||||
m_pBytes = new BYTE[len];
|
||||
if(m_pBytes) memcpy(m_pBytes, pBytes, len);
|
||||
m_fFree = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBytes = pBytes;
|
||||
m_fFree = fFree;
|
||||
}
|
||||
|
||||
if(!m_pBytes) ThrowError(_T("memory stream pointer is NULL"));
|
||||
}
|
||||
|
||||
MemoryInputStream::~MemoryInputStream()
|
||||
{
|
||||
if(m_fFree) delete [] m_pBytes;
|
||||
m_pBytes = NULL;
|
||||
}
|
||||
|
||||
int MemoryInputStream::NextByte()
|
||||
{
|
||||
if(!m_pBytes) ThrowError(_T("memory stream pointer is NULL"));
|
||||
if(m_pos >= m_len) return Stream::EOS;
|
||||
return (int)m_pBytes[m_pos++];
|
||||
}
|
||||
|
||||
// WCharInputStream
|
||||
|
||||
WCharInputStream::WCharInputStream(CStringW str)
|
||||
: m_str(str)
|
||||
, m_pos(0)
|
||||
{
|
||||
m_encoding = Stream::wchar; // HACK: it should return real bytes from NextByte (two per wchar_t), but this way it's a lot more simple...
|
||||
}
|
||||
|
||||
int WCharInputStream::NextByte()
|
||||
{
|
||||
if(m_pos >= m_str.GetLength()) return Stream::EOS;
|
||||
return m_str[m_pos++];
|
||||
}
|
||||
|
||||
// OutputStream
|
||||
|
||||
OutputStream::OutputStream(encoding_t e)
|
||||
{
|
||||
m_encoding = e;
|
||||
m_bof = true;
|
||||
}
|
||||
|
||||
OutputStream::~OutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
void OutputStream::PutChar(WCHAR c)
|
||||
{
|
||||
if(m_bof)
|
||||
{
|
||||
m_bof = false;
|
||||
|
||||
switch(m_encoding)
|
||||
{
|
||||
case utf8:
|
||||
case utf16le:
|
||||
case utf16be:
|
||||
PutChar(0xfeff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(m_encoding)
|
||||
{
|
||||
case utf8:
|
||||
if(0 <= c && c < 0x80) // 0xxxxxxx
|
||||
{
|
||||
NextByte(c);
|
||||
}
|
||||
else if(0x80 <= c && c < 0x800) // 110xxxxx 10xxxxxx
|
||||
{
|
||||
NextByte(0xc0 | ((c<<2)&0x1f));
|
||||
NextByte(0x80 | ((c<<0)&0x3f));
|
||||
}
|
||||
else if(0x800 <= c && c < 0xFFFF) // 1110xxxx 10xxxxxx 10xxxxxx
|
||||
{
|
||||
NextByte(0xe0 | ((c<<4)&0x0f));
|
||||
NextByte(0x80 | ((c<<2)&0x3f));
|
||||
NextByte(0x80 | ((c<<0)&0x3f));
|
||||
}
|
||||
else
|
||||
{
|
||||
NextByte('?');
|
||||
}
|
||||
break;
|
||||
case utf16le:
|
||||
NextByte(c & 0xff);
|
||||
NextByte((c >> 8) & 0xff);
|
||||
break;
|
||||
case utf16be:
|
||||
NextByte((c >> 8) & 0xff);
|
||||
NextByte(c & 0xff);
|
||||
break;
|
||||
case wchar:
|
||||
NextByte(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OutputStream::PutString(LPCWSTR fmt, ...)
|
||||
{
|
||||
CStringW str;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = _vscwprintf(fmt, args) + 1;
|
||||
if(len > 0) vswprintf_s(str.GetBufferSetLength(len), len, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
LPCWSTR s = str;
|
||||
while(*s) PutChar(*s++);
|
||||
}
|
||||
|
||||
// WCharOutputStream
|
||||
|
||||
WCharOutputStream::WCharOutputStream()
|
||||
: OutputStream(wchar)
|
||||
{
|
||||
}
|
||||
|
||||
void WCharOutputStream::NextByte(int b)
|
||||
{
|
||||
m_str += (WCHAR)b;
|
||||
}
|
||||
|
||||
// DebugOutputStream
|
||||
|
||||
DebugOutputStream::DebugOutputStream()
|
||||
: OutputStream(wchar)
|
||||
{
|
||||
}
|
||||
|
||||
DebugOutputStream::~DebugOutputStream()
|
||||
{
|
||||
TRACE(_T("%s\n"), m_str);
|
||||
}
|
||||
|
||||
void DebugOutputStream::NextByte(int b)
|
||||
{
|
||||
if(b == '\n') {TRACE(_T("%s\n"), m_str); m_str.Empty();}
|
||||
else if(b != '\r') m_str += (WCHAR)b;
|
||||
}
|
||||
}
|
143
vsfilter/libssf/Stream.h
Normal file
143
vsfilter/libssf/Stream.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Exception.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
enum {EOS = -1};
|
||||
enum encoding_t {none, unknown, utf8, utf16le, utf16be, wchar};
|
||||
|
||||
protected:
|
||||
int m_line, m_col;
|
||||
encoding_t m_encoding;
|
||||
|
||||
public:
|
||||
Stream();
|
||||
virtual ~Stream();
|
||||
|
||||
static bool IsWhiteSpace(int c, LPCWSTR morechars = NULL);
|
||||
|
||||
void ThrowError(LPCTSTR fmt, ...);
|
||||
};
|
||||
|
||||
class InputStream : public Stream
|
||||
{
|
||||
CAtlList<int> m_queue;
|
||||
int PushChar(), PopChar();
|
||||
|
||||
int NextChar();
|
||||
|
||||
protected:
|
||||
virtual int NextByte() = 0;
|
||||
|
||||
public:
|
||||
InputStream();
|
||||
~InputStream();
|
||||
|
||||
int PeekChar(), GetChar();
|
||||
|
||||
int SkipWhiteSpace(LPCWSTR morechars = NULL);
|
||||
};
|
||||
|
||||
class FileInputStream : public InputStream
|
||||
{
|
||||
FILE* m_file;
|
||||
|
||||
protected:
|
||||
int NextByte();
|
||||
|
||||
public:
|
||||
FileInputStream(const TCHAR* fn);
|
||||
~FileInputStream();
|
||||
};
|
||||
|
||||
class MemoryInputStream : public InputStream
|
||||
{
|
||||
BYTE* m_pBytes;
|
||||
int m_pos, m_len;
|
||||
bool m_fFree;
|
||||
|
||||
protected:
|
||||
int NextByte();
|
||||
|
||||
public:
|
||||
MemoryInputStream(BYTE* pBytes, int len, bool fCopy, bool fFree);
|
||||
~MemoryInputStream();
|
||||
};
|
||||
|
||||
class WCharInputStream : public InputStream
|
||||
{
|
||||
CStringW m_str;
|
||||
int m_pos;
|
||||
|
||||
protected:
|
||||
int NextByte();
|
||||
|
||||
public:
|
||||
WCharInputStream(CStringW str);
|
||||
};
|
||||
|
||||
class OutputStream : public Stream
|
||||
{
|
||||
bool m_bof;
|
||||
|
||||
protected:
|
||||
virtual void NextByte(int b) = 0;
|
||||
|
||||
public:
|
||||
OutputStream(encoding_t e);
|
||||
virtual ~OutputStream();
|
||||
|
||||
void PutChar(WCHAR c);
|
||||
void PutString(LPCWSTR fmt, ...);
|
||||
};
|
||||
|
||||
class WCharOutputStream : public OutputStream
|
||||
{
|
||||
CStringW m_str;
|
||||
|
||||
protected:
|
||||
void NextByte(int b);
|
||||
|
||||
public:
|
||||
WCharOutputStream();
|
||||
|
||||
const CStringW& GetString() {return m_str;}
|
||||
};
|
||||
|
||||
class DebugOutputStream : public OutputStream
|
||||
{
|
||||
CStringW m_str;
|
||||
|
||||
protected:
|
||||
void NextByte(int b);
|
||||
|
||||
public:
|
||||
DebugOutputStream();
|
||||
~DebugOutputStream();
|
||||
};
|
||||
}
|
28
vsfilter/libssf/StringMap.cpp
Normal file
28
vsfilter/libssf/StringMap.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Exception.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
|
||||
}
|
46
vsfilter/libssf/StringMap.h
Normal file
46
vsfilter/libssf/StringMap.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
template <class T = CString, class S = CString>
|
||||
class StringMap : public CAtlMap<S, T, CStringElementTraits<S> >
|
||||
{
|
||||
public:
|
||||
StringMap() {}
|
||||
StringMap(const StringMap& s2t) {*this = s2t;}
|
||||
StringMap& operator = (const StringMap& s2t)
|
||||
{
|
||||
RemoveAll();
|
||||
POSITION pos = s2t.GetStartPosition();
|
||||
while(pos) {const StringMap::CPair* p = s2t.GetNext(pos); SetAt(p->m_key, p->m_value);}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = CStringA, class S = CStringA>
|
||||
class StringMapA : public StringMap<T, S> {};
|
||||
|
||||
template <class T = CStringW, class S = CStringW>
|
||||
class StringMapW : public StringMap<T, S> {};
|
||||
}
|
701
vsfilter/libssf/Subtitle.cpp
Normal file
701
vsfilter/libssf/Subtitle.cpp
Normal file
|
@ -0,0 +1,701 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Subtitle.h"
|
||||
#include "Split.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
struct Subtitle::n2n_t Subtitle::m_n2n;
|
||||
|
||||
Subtitle::Subtitle(File* pFile)
|
||||
: m_pFile(pFile)
|
||||
, m_animated(false)
|
||||
{
|
||||
if(m_n2n.align[0].IsEmpty())
|
||||
{
|
||||
m_n2n.align[0][L"left"] = 0;
|
||||
m_n2n.align[0][L"center"] = 0.5;
|
||||
m_n2n.align[0][L"middle"] = 0.5;
|
||||
m_n2n.align[0][L"right"] = 1;
|
||||
}
|
||||
|
||||
if(m_n2n.align[1].IsEmpty())
|
||||
{
|
||||
m_n2n.align[1][L"top"] = 0;
|
||||
m_n2n.align[1][L"middle"] = 0.5;
|
||||
m_n2n.align[1][L"center"] = 0.5;
|
||||
m_n2n.align[1][L"bottom"] = 1;
|
||||
}
|
||||
|
||||
if(m_n2n.weight.IsEmpty())
|
||||
{
|
||||
m_n2n.weight[L"thin"] = FW_THIN;
|
||||
m_n2n.weight[L"normal"] = FW_NORMAL;
|
||||
m_n2n.weight[L"bold"] = FW_BOLD;
|
||||
}
|
||||
|
||||
if(m_n2n.transition.IsEmpty())
|
||||
{
|
||||
m_n2n.transition[L"start"] = 0;
|
||||
m_n2n.transition[L"stop"] = 1e10;
|
||||
m_n2n.transition[L"linear"] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Subtitle::~Subtitle()
|
||||
{
|
||||
}
|
||||
|
||||
bool Subtitle::Parse(Definition* pDef, float start, float stop, float at)
|
||||
{
|
||||
ASSERT(m_pFile && pDef);
|
||||
|
||||
m_name = pDef->m_name;
|
||||
|
||||
m_text.RemoveAll();
|
||||
|
||||
m_time.start = start;
|
||||
m_time.stop = stop;
|
||||
|
||||
at -= start;
|
||||
|
||||
Fill::gen_id = 0;
|
||||
|
||||
m_pFile->Commit();
|
||||
|
||||
try
|
||||
{
|
||||
Definition& frame = (*pDef)[L"frame"];
|
||||
|
||||
m_frame.reference = frame[L"reference"];
|
||||
m_frame.resolution.cx = frame[L"resolution"][L"cx"];
|
||||
m_frame.resolution.cy = frame[L"resolution"][L"cy"];
|
||||
|
||||
Definition& direction = (*pDef)[L"direction"];
|
||||
|
||||
m_direction.primary = direction[L"primary"];
|
||||
m_direction.secondary = direction[L"secondary"];
|
||||
|
||||
m_wrap = (*pDef)[L"wrap"];
|
||||
|
||||
m_layer = (*pDef)[L"layer"];
|
||||
|
||||
Style style;
|
||||
GetStyle(&(*pDef)[L"style"], style);
|
||||
|
||||
StringMapW<float> offset;
|
||||
Definition& block = (*pDef)[L"@"];
|
||||
Parse(WCharInputStream((LPCWSTR)block), style, at, offset, dynamic_cast<Reference*>(block.m_parent));
|
||||
|
||||
// TODO: trimming should be done by the renderer later, after breaking the words into lines
|
||||
|
||||
while(!m_text.IsEmpty() && (m_text.GetHead().str == Text::SP || m_text.GetHead().str == Text::LSEP))
|
||||
m_text.RemoveHead();
|
||||
|
||||
while(!m_text.IsEmpty() && (m_text.GetTail().str == Text::SP || m_text.GetTail().str == Text::LSEP))
|
||||
m_text.RemoveTail();
|
||||
|
||||
for(POSITION pos = m_text.GetHeadPosition(); pos; m_text.GetNext(pos))
|
||||
{
|
||||
if(m_text.GetAt(pos).str == Text::LSEP)
|
||||
{
|
||||
POSITION prev = pos;
|
||||
m_text.GetPrev(prev);
|
||||
|
||||
while(prev && m_text.GetAt(prev).str == Text::SP)
|
||||
{
|
||||
POSITION tmp = prev;
|
||||
m_text.GetPrev(prev);
|
||||
m_text.RemoveAt(tmp);
|
||||
}
|
||||
|
||||
POSITION next = pos;
|
||||
m_text.GetNext(next);
|
||||
|
||||
while(next && m_text.GetAt(next).str == Text::SP)
|
||||
{
|
||||
POSITION tmp = next;
|
||||
m_text.GetNext(next);
|
||||
m_text.RemoveAt(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception& e)
|
||||
{
|
||||
TRACE(_T("%s"), e.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pFile->Rollback();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Subtitle::GetStyle(Definition* pDef, Style& style)
|
||||
{
|
||||
style.placement.pos.x = 0;
|
||||
style.placement.pos.y = 0;
|
||||
style.placement.pos.auto_x = true;
|
||||
style.placement.pos.auto_y = true;
|
||||
|
||||
style.placement.org.x = 0;
|
||||
style.placement.org.y = 0;
|
||||
style.placement.org.auto_x = true;
|
||||
style.placement.org.auto_y = true;
|
||||
|
||||
Rect frame = {0, m_frame.resolution.cx, m_frame.resolution.cy, 0};
|
||||
|
||||
style.placement.clip.t = -1;
|
||||
style.placement.clip.r = -1;
|
||||
style.placement.clip.b = -1;
|
||||
style.placement.clip.l = -1;
|
||||
|
||||
//
|
||||
|
||||
style.linebreak = (*pDef)[L"linebreak"];
|
||||
|
||||
Definition& placement = (*pDef)[L"placement"];
|
||||
|
||||
Definition& clip = placement[L"clip"];
|
||||
|
||||
if(clip.IsValue(Definition::string))
|
||||
{
|
||||
CStringW str = clip;
|
||||
|
||||
if(str == L"frame") style.placement.clip = frame;
|
||||
// else ?
|
||||
}
|
||||
else
|
||||
{
|
||||
if(clip[L"t"].IsValue()) style.placement.clip.t = clip[L"t"];
|
||||
if(clip[L"r"].IsValue()) style.placement.clip.r = clip[L"r"];
|
||||
if(clip[L"b"].IsValue()) style.placement.clip.b = clip[L"b"];
|
||||
if(clip[L"l"].IsValue()) style.placement.clip.l = clip[L"l"];
|
||||
}
|
||||
|
||||
StringMapW<float> n2n_margin[2];
|
||||
|
||||
n2n_margin[0][L"top"] = 0;
|
||||
n2n_margin[0][L"right"] = 0;
|
||||
n2n_margin[0][L"bottom"] = frame.b - frame.t;
|
||||
n2n_margin[0][L"left"] = frame.r - frame.l;
|
||||
n2n_margin[1][L"top"] = frame.b - frame.t;
|
||||
n2n_margin[1][L"right"] = frame.r - frame.l;
|
||||
n2n_margin[1][L"bottom"] = 0;
|
||||
n2n_margin[1][L"left"] = 0;
|
||||
|
||||
placement[L"margin"][L"t"].GetAsNumber(style.placement.margin.t, &n2n_margin[0]);
|
||||
placement[L"margin"][L"r"].GetAsNumber(style.placement.margin.r, &n2n_margin[0]);
|
||||
placement[L"margin"][L"b"].GetAsNumber(style.placement.margin.b, &n2n_margin[1]);
|
||||
placement[L"margin"][L"l"].GetAsNumber(style.placement.margin.l, &n2n_margin[1]);
|
||||
|
||||
placement[L"align"][L"h"].GetAsNumber(style.placement.align.h, &m_n2n.align[0]);
|
||||
placement[L"align"][L"v"].GetAsNumber(style.placement.align.v, &m_n2n.align[1]);
|
||||
|
||||
if(placement[L"pos"][L"x"].IsValue()) {style.placement.pos.x = placement[L"pos"][L"x"]; style.placement.pos.auto_x = false;}
|
||||
if(placement[L"pos"][L"y"].IsValue()) {style.placement.pos.y = placement[L"pos"][L"y"]; style.placement.pos.auto_y = false;}
|
||||
|
||||
placement[L"offset"][L"x"].GetAsNumber(style.placement.offset.x);
|
||||
placement[L"offset"][L"y"].GetAsNumber(style.placement.offset.y);
|
||||
|
||||
style.placement.angle.x = placement[L"angle"][L"x"];
|
||||
style.placement.angle.y = placement[L"angle"][L"y"];
|
||||
style.placement.angle.z = placement[L"angle"][L"z"];
|
||||
|
||||
if(placement[L"org"][L"x"].IsValue()) {style.placement.org.x = placement[L"org"][L"x"]; style.placement.org.auto_x = false;}
|
||||
if(placement[L"org"][L"y"].IsValue()) {style.placement.org.y = placement[L"org"][L"y"]; style.placement.org.auto_y = false;}
|
||||
|
||||
style.placement.path = placement[L"path"];
|
||||
|
||||
Definition& font = (*pDef)[L"font"];
|
||||
|
||||
style.font.face = font[L"face"];
|
||||
style.font.size = font[L"size"];
|
||||
font[L"weight"].GetAsNumber(style.font.weight, &m_n2n.weight);
|
||||
style.font.color.a = font[L"color"][L"a"];
|
||||
style.font.color.r = font[L"color"][L"r"];
|
||||
style.font.color.g = font[L"color"][L"g"];
|
||||
style.font.color.b = font[L"color"][L"b"];
|
||||
style.font.underline = font[L"underline"];
|
||||
style.font.strikethrough = font[L"strikethrough"];
|
||||
style.font.italic = font[L"italic"];
|
||||
style.font.spacing = font[L"spacing"];
|
||||
style.font.scale.cx = font[L"scale"][L"cx"];
|
||||
style.font.scale.cy = font[L"scale"][L"cy"];
|
||||
style.font.kerning = font[L"kerning"];
|
||||
|
||||
Definition& background = (*pDef)[L"background"];
|
||||
|
||||
style.background.color.a = background[L"color"][L"a"];
|
||||
style.background.color.r = background[L"color"][L"r"];
|
||||
style.background.color.g = background[L"color"][L"g"];
|
||||
style.background.color.b = background[L"color"][L"b"];
|
||||
style.background.size = background[L"size"];
|
||||
style.background.type = background[L"type"];
|
||||
style.background.blur = background[L"blur"];
|
||||
|
||||
Definition& shadow = (*pDef)[L"shadow"];
|
||||
|
||||
style.shadow.color.a = shadow[L"color"][L"a"];
|
||||
style.shadow.color.r = shadow[L"color"][L"r"];
|
||||
style.shadow.color.g = shadow[L"color"][L"g"];
|
||||
style.shadow.color.b = shadow[L"color"][L"b"];
|
||||
style.shadow.depth = shadow[L"depth"];
|
||||
style.shadow.angle = shadow[L"angle"];
|
||||
style.shadow.blur = shadow[L"blur"];
|
||||
|
||||
Definition& fill = (*pDef)[L"fill"];
|
||||
|
||||
style.fill.color.a = fill[L"color"][L"a"];
|
||||
style.fill.color.r = fill[L"color"][L"r"];
|
||||
style.fill.color.g = fill[L"color"][L"g"];
|
||||
style.fill.color.b = fill[L"color"][L"b"];
|
||||
style.fill.width = fill[L"width"];
|
||||
}
|
||||
|
||||
float Subtitle::GetMixWeight(Definition* pDef, float at, StringMapW<float>& offset, int default_id)
|
||||
{
|
||||
float t = 1;
|
||||
|
||||
try
|
||||
{
|
||||
StringMapW<float> n2n;
|
||||
|
||||
n2n[L"start"] = 0;
|
||||
n2n[L"stop"] = m_time.stop - m_time.start;
|
||||
|
||||
Definition::Time time;
|
||||
if(pDef->GetAsTime(time, offset, &n2n, default_id) && time.start.value < time.stop.value)
|
||||
{
|
||||
t = (at - time.start.value) / (time.stop.value - time.start.value);
|
||||
|
||||
float u = t;
|
||||
|
||||
if(t < 0) t = 0;
|
||||
else if(t >= 1) t = 0.99999f; // doh
|
||||
|
||||
if((*pDef)[L"loop"].IsValue()) t *= (float)(*pDef)[L"loop"];
|
||||
|
||||
CStringW direction = (*pDef)[L"direction"].IsValue() ? (*pDef)[L"direction"] : L"fw";
|
||||
if(direction == L"fwbw" || direction == L"bwfw") t *= 2;
|
||||
|
||||
float n;
|
||||
t = modf(t, &n);
|
||||
|
||||
if(direction == L"bw"
|
||||
|| direction == L"fwbw" && ((int)n & 1)
|
||||
|| direction == L"bwfw" && !((int)n & 1))
|
||||
t = 1 - t;
|
||||
|
||||
float accel = 1;
|
||||
|
||||
if((*pDef)[L"transition"].IsValue())
|
||||
{
|
||||
Definition::Number<float> n;
|
||||
(*pDef)[L"transition"].GetAsNumber(n, &m_n2n.transition);
|
||||
if(n.value >= 0) accel = n.value;
|
||||
}
|
||||
|
||||
if(t == 0.99999f) t = 1;
|
||||
|
||||
if(u >= 0 && u < 1)
|
||||
{
|
||||
t = accel == 0 ? 1 :
|
||||
accel == 1 ? t :
|
||||
accel >= 1e10 ? 0 :
|
||||
pow(t, accel);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception&)
|
||||
{
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Subtitle::MixValue(Definition& def, T& value, float t)
|
||||
{
|
||||
StringMapW<T> n2n;
|
||||
return MixValue(def, value, t, &n2n);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Subtitle::MixValue(Definition& def, float& value, float t)
|
||||
{
|
||||
StringMapW<float> n2n;
|
||||
return MixValue(def, value, t, &n2n);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Subtitle::MixValue(Definition& def, T& value, float t, StringMapW<T>* n2n)
|
||||
{
|
||||
if(!def.IsValue()) return false;
|
||||
|
||||
if(t >= 0.5)
|
||||
{
|
||||
if(n2n && def.IsValue(Definition::string))
|
||||
{
|
||||
if(StringMapW<T>::CPair* p = n2n->Lookup(def))
|
||||
{
|
||||
value = p->m_value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value = (T)def;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Subtitle::MixValue(Definition& def, float& value, float t, StringMapW<float>* n2n)
|
||||
{
|
||||
if(!def.IsValue()) return false;
|
||||
|
||||
if(t > 0)
|
||||
{
|
||||
if(n2n && def.IsValue(Definition::string))
|
||||
{
|
||||
if(StringMap<float, CStringW>::CPair* p = n2n->Lookup(def))
|
||||
{
|
||||
value += (p->m_value - value) * t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value += ((float)def - value) * t;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Subtitle::MixValue(Definition& def, Path& src, float t)
|
||||
{
|
||||
if(!def.IsValue(Definition::string)) return false;
|
||||
|
||||
if(t >= 1)
|
||||
{
|
||||
src = (LPCWSTR)def;
|
||||
}
|
||||
else if(t > 0)
|
||||
{
|
||||
Path dst = (LPCWSTR)def;
|
||||
|
||||
if(src.GetCount() == dst.GetCount())
|
||||
{
|
||||
for(size_t i = 0, j = src.GetCount(); i < j; i++)
|
||||
{
|
||||
Point& s = src[i];
|
||||
const Point& d = dst[i];
|
||||
s.x += (d.x - s.x) * t;
|
||||
s.y += (d.y - s.y) * t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Subtitle::MixStyle(Definition* pDef, Style& dst, float t)
|
||||
{
|
||||
const Style src = dst;
|
||||
|
||||
if(t <= 0) return;
|
||||
else if(t > 1) t = 1;
|
||||
|
||||
MixValue((*pDef)[L"linebreak"], dst.linebreak, t);
|
||||
|
||||
Definition& placement = (*pDef)[L"placement"];
|
||||
|
||||
MixValue(placement[L"clip"][L"t"], dst.placement.clip.t, t);
|
||||
MixValue(placement[L"clip"][L"r"], dst.placement.clip.r, t);
|
||||
MixValue(placement[L"clip"][L"b"], dst.placement.clip.b, t);
|
||||
MixValue(placement[L"clip"][L"l"], dst.placement.clip.l, t);
|
||||
MixValue(placement[L"align"][L"h"], dst.placement.align.h, t, &m_n2n.align[0]);
|
||||
MixValue(placement[L"align"][L"v"], dst.placement.align.v, t, &m_n2n.align[1]);
|
||||
dst.placement.pos.auto_x = !MixValue(placement[L"pos"][L"x"], dst.placement.pos.x, dst.placement.pos.auto_x ? 1 : t);
|
||||
dst.placement.pos.auto_y = !MixValue(placement[L"pos"][L"y"], dst.placement.pos.y, dst.placement.pos.auto_y ? 1 : t);
|
||||
MixValue(placement[L"offset"][L"x"], dst.placement.offset.x, t);
|
||||
MixValue(placement[L"offset"][L"y"], dst.placement.offset.y, t);
|
||||
MixValue(placement[L"angle"][L"x"], dst.placement.angle.x, t);
|
||||
MixValue(placement[L"angle"][L"y"], dst.placement.angle.y, t);
|
||||
MixValue(placement[L"angle"][L"z"], dst.placement.angle.z, t);
|
||||
dst.placement.org.auto_x = !MixValue(placement[L"org"][L"x"], dst.placement.org.x, dst.placement.org.auto_x ? 1 : t);
|
||||
dst.placement.org.auto_y = !MixValue(placement[L"org"][L"y"], dst.placement.org.y, dst.placement.org.auto_y ? 1 : t);
|
||||
MixValue(placement[L"path"], dst.placement.path, t);
|
||||
|
||||
Definition& font = (*pDef)[L"font"];
|
||||
|
||||
MixValue(font[L"face"], dst.font.face, t);
|
||||
MixValue(font[L"size"], dst.font.size, t);
|
||||
MixValue(font[L"weight"], dst.font.weight, t, &m_n2n.weight);
|
||||
MixValue(font[L"color"][L"a"], dst.font.color.a, t);
|
||||
MixValue(font[L"color"][L"r"], dst.font.color.r, t);
|
||||
MixValue(font[L"color"][L"g"], dst.font.color.g, t);
|
||||
MixValue(font[L"color"][L"b"], dst.font.color.b, t);
|
||||
MixValue(font[L"underline"], dst.font.underline, t);
|
||||
MixValue(font[L"strikethrough"], dst.font.strikethrough, t);
|
||||
MixValue(font[L"italic"], dst.font.italic, t);
|
||||
MixValue(font[L"spacing"], dst.font.spacing, t);
|
||||
MixValue(font[L"scale"][L"cx"], dst.font.scale.cx, t);
|
||||
MixValue(font[L"scale"][L"cy"], dst.font.scale.cy, t);
|
||||
MixValue(font[L"kerning"], dst.font.kerning, t);
|
||||
|
||||
Definition& background = (*pDef)[L"background"];
|
||||
|
||||
MixValue(background[L"color"][L"a"], dst.background.color.a, t);
|
||||
MixValue(background[L"color"][L"r"], dst.background.color.r, t);
|
||||
MixValue(background[L"color"][L"g"], dst.background.color.g, t);
|
||||
MixValue(background[L"color"][L"b"], dst.background.color.b, t);
|
||||
MixValue(background[L"size"], dst.background.size, t);
|
||||
MixValue(background[L"type"], dst.background.type, t);
|
||||
MixValue(background[L"blur"], dst.background.blur, t);
|
||||
|
||||
Definition& shadow = (*pDef)[L"shadow"];
|
||||
|
||||
MixValue(shadow[L"color"][L"a"], dst.shadow.color.a, t);
|
||||
MixValue(shadow[L"color"][L"r"], dst.shadow.color.r, t);
|
||||
MixValue(shadow[L"color"][L"g"], dst.shadow.color.g, t);
|
||||
MixValue(shadow[L"color"][L"b"], dst.shadow.color.b, t);
|
||||
MixValue(shadow[L"depth"], dst.shadow.depth, t);
|
||||
MixValue(shadow[L"angle"], dst.shadow.angle, t);
|
||||
MixValue(shadow[L"blur"], dst.shadow.blur, t);
|
||||
|
||||
Definition& fill = (*pDef)[L"fill"];
|
||||
|
||||
MixValue(fill[L"color"][L"a"], dst.fill.color.a, t);
|
||||
MixValue(fill[L"color"][L"r"], dst.fill.color.r, t);
|
||||
MixValue(fill[L"color"][L"g"], dst.fill.color.g, t);
|
||||
MixValue(fill[L"color"][L"b"], dst.fill.color.b, t);
|
||||
MixValue(fill[L"width"], dst.fill.width, t);
|
||||
|
||||
if(fill.m_priority >= PNormal) // this assumes there is no way to set low priority inline overrides
|
||||
{
|
||||
if(dst.fill.id > 0) throw Exception(_T("cannot apply fill more than once on the same text"));
|
||||
dst.fill.id = ++Fill::gen_id;
|
||||
}
|
||||
}
|
||||
|
||||
void Subtitle::Parse(InputStream& s, Style style, float at, StringMapW<float> offset, Reference* pParentRef)
|
||||
{
|
||||
Text text;
|
||||
text.style = style;
|
||||
|
||||
for(int c = s.PeekChar(); c != Stream::EOS; c = s.PeekChar())
|
||||
{
|
||||
s.GetChar();
|
||||
|
||||
if(c == '[')
|
||||
{
|
||||
AddText(text);
|
||||
|
||||
style = text.style;
|
||||
|
||||
StringMapW<float> inneroffset = offset;
|
||||
|
||||
int default_id = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Definition* pDef = m_pFile->CreateDef(pParentRef);
|
||||
|
||||
m_pFile->ParseRefs(s, pDef, L",;]");
|
||||
|
||||
ASSERT(pDef->IsType(L"style") || pDef->IsTypeUnknown());
|
||||
|
||||
if((*pDef)[L"time"][L"start"].IsValue() && (*pDef)[L"time"][L"stop"].IsValue())
|
||||
{
|
||||
m_animated = true;
|
||||
}
|
||||
|
||||
float t = GetMixWeight(pDef, at, offset, ++default_id);
|
||||
MixStyle(pDef, style, t);
|
||||
|
||||
if((*pDef)[L"@"].IsValue())
|
||||
{
|
||||
Parse(WCharInputStream((LPCWSTR)(*pDef)[L"@"]), style, at, offset, pParentRef);
|
||||
}
|
||||
|
||||
s.SkipWhiteSpace();
|
||||
c = s.GetChar();
|
||||
}
|
||||
while(c == ',' || c == ';');
|
||||
|
||||
if(c != ']') s.ThrowError(_T("unterminated override"));
|
||||
|
||||
bool fWhiteSpaceNext = s.IsWhiteSpace(s.PeekChar());
|
||||
c = s.SkipWhiteSpace();
|
||||
|
||||
if(c == '{')
|
||||
{
|
||||
s.GetChar();
|
||||
Parse(s, style, at, inneroffset, pParentRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fWhiteSpaceNext) text.str += (WCHAR)Text::SP;
|
||||
text.style = style;
|
||||
}
|
||||
}
|
||||
else if(c == ']')
|
||||
{
|
||||
s.ThrowError(_T("unexpected ] found"));
|
||||
}
|
||||
else if(c == '{')
|
||||
{
|
||||
AddText(text);
|
||||
Parse(s, text.style, at, offset, pParentRef);
|
||||
}
|
||||
else if(c == '}')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c == '\\')
|
||||
{
|
||||
c = s.GetChar();
|
||||
if(c == Stream::EOS) break;
|
||||
else if(c == 'n') {AddText(text); text.str = (WCHAR)Text::LSEP; AddText(text); continue;}
|
||||
else if(c == 'h') c = Text::NBSP;
|
||||
}
|
||||
|
||||
AddChar(text, (WCHAR)c);
|
||||
}
|
||||
}
|
||||
|
||||
AddText(text);
|
||||
}
|
||||
|
||||
void Subtitle::AddChar(Text& t, WCHAR c)
|
||||
{
|
||||
bool f1 = !t.str.IsEmpty() && Stream::IsWhiteSpace(t.str[t.str.GetLength()-1]);
|
||||
bool f2 = Stream::IsWhiteSpace(c);
|
||||
if(f2) c = Text::SP;
|
||||
if(!f1 || !f2) t.str += (WCHAR)c;
|
||||
}
|
||||
|
||||
void Subtitle::AddText(Text& t)
|
||||
{
|
||||
if(t.str.IsEmpty()) return;
|
||||
|
||||
Split sa(' ', t.str, 0, Split::Max);
|
||||
|
||||
for(size_t i = 0, n = sa; i < n; i++)
|
||||
{
|
||||
CStringW str = sa[i];
|
||||
|
||||
if(!str.IsEmpty())
|
||||
{
|
||||
t.str = str;
|
||||
m_text.AddTail(t);
|
||||
}
|
||||
|
||||
if(i < n-1 && (m_text.IsEmpty() || m_text.GetTail().str != Text::SP))
|
||||
{
|
||||
t.str = (WCHAR)Text::SP;
|
||||
m_text.AddTail(t);
|
||||
}
|
||||
}
|
||||
|
||||
t.str.Empty();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
unsigned int Fill::gen_id = 0;
|
||||
|
||||
Color::operator DWORD()
|
||||
{
|
||||
DWORD c =
|
||||
(min(max((DWORD)b, 0), 255) << 0) |
|
||||
(min(max((DWORD)g, 0), 255) << 8) |
|
||||
(min(max((DWORD)r, 0), 255) << 16) |
|
||||
(min(max((DWORD)a, 0), 255) << 24);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Path& Path::operator = (LPCWSTR str)
|
||||
{
|
||||
Split s(' ', str);
|
||||
|
||||
SetCount(s/2);
|
||||
|
||||
for(size_t i = 0, j = GetCount(); i < j; i++)
|
||||
{
|
||||
Point p;
|
||||
p.x = s.GetAtFloat(i*2+0);
|
||||
p.y = s.GetAtFloat(i*2+1);
|
||||
SetAt(i, p);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStringW Path::ToString()
|
||||
{
|
||||
CStringW ret;
|
||||
|
||||
for(size_t i = 0, j = GetCount(); i < j; i++)
|
||||
{
|
||||
const Point& p = GetAt(i);
|
||||
|
||||
CStringW str;
|
||||
str.Format(L"%f %f ", p.x, p.y);
|
||||
ret += str;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Style::IsSimilar(const Style& s)
|
||||
{
|
||||
return
|
||||
font.color.r == s.font.color.r
|
||||
&& font.color.g == s.font.color.g
|
||||
&& font.color.b == s.font.color.b
|
||||
&& font.color.a == s.font.color.a
|
||||
&& background.color.r == s.background.color.r
|
||||
&& background.color.g == s.background.color.g
|
||||
&& background.color.b == s.background.color.b
|
||||
&& background.color.a == s.background.color.a
|
||||
&& background.size == s.background.size
|
||||
&& background.type == s.background.type
|
||||
&& background.blur == s.background.blur
|
||||
&& shadow.color.r == s.shadow.color.r
|
||||
&& shadow.color.g == s.shadow.color.g
|
||||
&& shadow.color.b == s.shadow.color.b
|
||||
&& shadow.color.a == s.shadow.color.a
|
||||
&& shadow.depth == s.shadow.depth
|
||||
&& shadow.angle == s.shadow.angle
|
||||
&& shadow.blur == s.shadow.blur
|
||||
&& fill.id == s.fill.id;
|
||||
}
|
||||
}
|
138
vsfilter/libssf/Subtitle.h
Normal file
138
vsfilter/libssf/Subtitle.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "File.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
struct Point {float x, y;};
|
||||
struct PointAuto : public Point {bool auto_x, auto_y;};
|
||||
struct Size {float cx, cy;};
|
||||
struct Rect {float t, r, b, l;};
|
||||
struct Align {float v, h;};
|
||||
struct Angle {float x, y, z;};
|
||||
struct Color {float a, r, g, b; operator DWORD(); void operator = (DWORD c);};
|
||||
struct Frame {CStringW reference; Size resolution;};
|
||||
struct Direction {CStringW primary, secondary;};
|
||||
struct Time {float start, stop;};
|
||||
struct Background {Color color; float size, blur; CStringW type;};
|
||||
struct Shadow {Color color; float depth, angle, blur;};
|
||||
|
||||
class Path : public CAtlArray<Point>
|
||||
{
|
||||
public:
|
||||
Path() {}
|
||||
Path(const Path& path) {*this = path;}
|
||||
Path& operator = (const Path& path) {Copy(path); return *this;}
|
||||
Path(LPCWSTR str) {*this = str;}
|
||||
Path& operator = (LPCWSTR str);
|
||||
CStringW ToString();
|
||||
};
|
||||
|
||||
struct Placement
|
||||
{
|
||||
Rect clip, margin;
|
||||
Align align;
|
||||
PointAuto pos;
|
||||
Point offset;
|
||||
Angle angle;
|
||||
PointAuto org;
|
||||
Path path;
|
||||
};
|
||||
|
||||
struct Font
|
||||
{
|
||||
CStringW face;
|
||||
float size, weight;
|
||||
Color color;
|
||||
bool underline, strikethrough, italic;
|
||||
float spacing;
|
||||
Size scale;
|
||||
bool kerning;
|
||||
};
|
||||
|
||||
struct Fill
|
||||
{
|
||||
static unsigned int gen_id;
|
||||
int id;
|
||||
Color color;
|
||||
float width;
|
||||
struct Fill() : id(0) {}
|
||||
};
|
||||
|
||||
struct Style
|
||||
{
|
||||
CStringW linebreak;
|
||||
Placement placement;
|
||||
Font font;
|
||||
Background background;
|
||||
Shadow shadow;
|
||||
Fill fill;
|
||||
|
||||
bool IsSimilar(const Style& s);
|
||||
};
|
||||
|
||||
struct Text
|
||||
{
|
||||
enum {SP = 0x20, NBSP = 0xa0, LSEP = 0x0a};
|
||||
Style style;
|
||||
CStringW str;
|
||||
};
|
||||
|
||||
class Subtitle
|
||||
{
|
||||
static struct n2n_t {StringMapW<float> align[2], weight, transition;} m_n2n;
|
||||
|
||||
File* m_pFile;
|
||||
|
||||
void GetStyle(Definition* pDef, Style& style);
|
||||
float GetMixWeight(Definition* pDef, float at, StringMapW<float>& offset, int default_id);
|
||||
template<class T> bool MixValue(Definition& def, T& value, float t);
|
||||
template<> bool MixValue(Definition& def, float& value, float t);
|
||||
template<class T> bool MixValue(Definition& def, T& value, float t, StringMapW<T>* n2n);
|
||||
template<> bool MixValue(Definition& def, float& value, float t, StringMapW<float>* n2n);
|
||||
template<> bool MixValue(Definition& def, Path& value, float t);
|
||||
void MixStyle(Definition* pDef, Style& dst, float t);
|
||||
|
||||
void Parse(InputStream& s, Style style, float at, StringMapW<float> offset, Reference* pParentRef);
|
||||
|
||||
void AddChar(Text& t, WCHAR c);
|
||||
void AddText(Text& t);
|
||||
|
||||
public:
|
||||
CStringW m_name;
|
||||
bool m_animated;
|
||||
Frame m_frame;
|
||||
Direction m_direction;
|
||||
CStringW m_wrap;
|
||||
float m_layer;
|
||||
Time m_time;
|
||||
CAtlList<Text> m_text;
|
||||
|
||||
public:
|
||||
Subtitle(File* pFile);
|
||||
virtual ~Subtitle();
|
||||
|
||||
bool Parse(Definition* pDef, float start, float stop, float at);
|
||||
};
|
||||
};
|
403
vsfilter/libssf/SubtitleFile.cpp
Normal file
403
vsfilter/libssf/SubtitleFile.cpp
Normal file
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SubtitleFile.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
SubtitleFile::SubtitleFile()
|
||||
{
|
||||
}
|
||||
|
||||
SubtitleFile::~SubtitleFile()
|
||||
{
|
||||
}
|
||||
|
||||
void SubtitleFile::Parse(InputStream& s)
|
||||
{
|
||||
m_segments.RemoveAll();
|
||||
|
||||
__super::Parse(s, s_predef);
|
||||
|
||||
// TODO: check file.format == "ssf" and file.version == 1
|
||||
|
||||
CAtlList<Definition*> defs;
|
||||
GetRootRef()->GetChildDefs(defs, L"subtitle");
|
||||
|
||||
StringMapW<float> offset;
|
||||
|
||||
POSITION pos = defs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Definition* pDef = defs.GetNext(pos);
|
||||
|
||||
try
|
||||
{
|
||||
Definition::Time time;
|
||||
|
||||
if(pDef->GetAsTime(time, offset) && (*pDef)[L"@"].IsValue())
|
||||
{
|
||||
m_segments.Insert(time.start.value, time.stop.value, pDef);
|
||||
}
|
||||
}
|
||||
catch(Exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SubtitleFile::Append(InputStream& s, float start, float stop, bool fSetTime)
|
||||
{
|
||||
Reference* pRootRef = GetRootRef();
|
||||
|
||||
ParseDefs(s, pRootRef);
|
||||
|
||||
CAtlList<Definition*> defs;
|
||||
GetNewDefs(defs);
|
||||
|
||||
POSITION pos = defs.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
Definition* pDef = defs.GetNext(pos);
|
||||
|
||||
if(pDef->m_parent == pRootRef && pDef->m_type == L"subtitle" && (*pDef)[L"@"].IsValue())
|
||||
{
|
||||
m_segments.Insert(start, stop, pDef);
|
||||
|
||||
if(fSetTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
Definition::Time time;
|
||||
StringMapW<float> offset;
|
||||
pDef->GetAsTime(time, offset);
|
||||
if(time.start.value == start && time.stop.value == stop)
|
||||
continue;
|
||||
}
|
||||
catch(Exception&)
|
||||
{
|
||||
}
|
||||
|
||||
CStringW str;
|
||||
str.Format(L"%.3f", start);
|
||||
pDef->SetChildAsNumber(L"time.start", str, L"s");
|
||||
str.Format(L"%.3f", stop);
|
||||
pDef->SetChildAsNumber(L"time.stop", str, L"s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Commit();
|
||||
}
|
||||
|
||||
bool SubtitleFile::Lookup(float at, CAutoPtrList<Subtitle>& subs)
|
||||
{
|
||||
if(!subs.IsEmpty()) {ASSERT(0); return false;}
|
||||
|
||||
CAtlList<SegmentItem> sis;
|
||||
m_segments.Lookup(at, sis);
|
||||
|
||||
POSITION pos = sis.GetHeadPosition();
|
||||
while(pos)
|
||||
{
|
||||
SegmentItem& si = sis.GetNext(pos);
|
||||
|
||||
CAutoPtr<Subtitle> s(new Subtitle(this));
|
||||
|
||||
if(s->Parse(si.pDef, si.start, si.stop, at))
|
||||
{
|
||||
for(POSITION pos = subs.GetHeadPosition(); pos; subs.GetNext(pos))
|
||||
{
|
||||
if(s->m_layer < subs.GetAt(pos)->m_layer)
|
||||
{
|
||||
subs.InsertBefore(pos, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(s)
|
||||
{
|
||||
subs.AddTail(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !subs.IsEmpty();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
SubtitleFile::Segment::Segment(float start, float stop, const SegmentItem* si)
|
||||
{
|
||||
m_start = start;
|
||||
m_stop = stop;
|
||||
if(si) AddTail(*si);
|
||||
}
|
||||
|
||||
SubtitleFile::Segment::Segment(const Segment& s)
|
||||
{
|
||||
*this = s;
|
||||
}
|
||||
|
||||
void SubtitleFile::Segment::operator = (const Segment& s)
|
||||
{
|
||||
m_start = s.m_start;
|
||||
m_stop = s.m_stop;
|
||||
RemoveAll();
|
||||
AddTailList(&s);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SubtitleFile::SegmentList::RemoveAll()
|
||||
{
|
||||
__super::RemoveAll();
|
||||
m_index.RemoveAll();
|
||||
}
|
||||
|
||||
void SubtitleFile::SegmentList::Insert(float start, float stop, Definition* pDef)
|
||||
{
|
||||
if(start >= stop) {ASSERT(0); return;}
|
||||
|
||||
m_index.RemoveAll();
|
||||
|
||||
SegmentItem si = {pDef, start, stop};
|
||||
|
||||
if(IsEmpty())
|
||||
{
|
||||
AddTail(Segment(start, stop, &si));
|
||||
return;
|
||||
}
|
||||
|
||||
Segment& head = GetHead();
|
||||
Segment& tail = GetTail();
|
||||
|
||||
if(start >= tail.m_stop && stop > tail.m_stop)
|
||||
{
|
||||
if(start > tail.m_stop) AddTail(Segment(tail.m_stop, start));
|
||||
AddTail(Segment(start, stop, &si));
|
||||
}
|
||||
else if(start < head.m_start && stop <= head.m_start)
|
||||
{
|
||||
if(stop < head.m_start) AddHead(Segment(stop, head.m_start));
|
||||
AddHead(Segment(start, stop, &si));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(start < head.m_start)
|
||||
{
|
||||
AddHead(Segment(start, head.m_start, &si));
|
||||
start = head.m_start;
|
||||
}
|
||||
|
||||
if(stop > tail.m_stop)
|
||||
{
|
||||
AddTail(Segment(tail.m_stop, stop, &si));
|
||||
stop = tail.m_stop;
|
||||
}
|
||||
|
||||
for(POSITION pos = GetHeadPosition(); pos; GetNext(pos))
|
||||
{
|
||||
Segment& s = GetAt(pos);
|
||||
|
||||
if(start >= s.m_stop) continue;
|
||||
if(stop <= s.m_start) break;
|
||||
|
||||
if(s.m_start < start && start < s.m_stop)
|
||||
{
|
||||
Segment s2 = s;
|
||||
s2.m_start = start;
|
||||
InsertAfter(pos, s2);
|
||||
s.m_stop = start;
|
||||
}
|
||||
else if(s.m_start == start)
|
||||
{
|
||||
if(stop > s.m_stop)
|
||||
{
|
||||
start = s.m_stop;
|
||||
}
|
||||
else if(stop < s.m_stop)
|
||||
{
|
||||
Segment s2 = s;
|
||||
s2.m_start = stop;
|
||||
InsertAfter(pos, s2);
|
||||
s.m_stop = stop;
|
||||
}
|
||||
|
||||
s.AddTail(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t SubtitleFile::SegmentList::Index(bool fForce)
|
||||
{
|
||||
if(m_index.IsEmpty() || fForce)
|
||||
{
|
||||
m_index.RemoveAll();
|
||||
POSITION pos = GetHeadPosition();
|
||||
while(pos) m_index.Add(&GetNext(pos));
|
||||
}
|
||||
|
||||
return m_index.GetCount();
|
||||
}
|
||||
|
||||
void SubtitleFile::SegmentList::Lookup(float at, CAtlList<SegmentItem>& sis)
|
||||
{
|
||||
sis.RemoveAll();
|
||||
|
||||
size_t k;
|
||||
if(Lookup(at, k))
|
||||
{
|
||||
sis.AddTailList(GetSegment(k));
|
||||
}
|
||||
}
|
||||
|
||||
bool SubtitleFile::SegmentList::Lookup(float at, size_t& k)
|
||||
{
|
||||
if(!Index()) return false;
|
||||
|
||||
size_t i = 0, j = m_index.GetCount()-1;
|
||||
|
||||
if(m_index[i]->m_start <= at && at < m_index[j]->m_stop)
|
||||
do
|
||||
{
|
||||
k = (i+j)/2;
|
||||
if(m_index[k]->m_start <= at && at < m_index[k]->m_stop) {return true;}
|
||||
else if(at < m_index[k]->m_start) {if(j == k) k--; j = k;}
|
||||
else if(at >= m_index[k]->m_stop) {if(i == k) k++; i = k;}
|
||||
}
|
||||
while(i <= j);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const SubtitleFile::Segment* SubtitleFile::SegmentList::GetSegment(size_t k)
|
||||
{
|
||||
return 0 <= k && k < m_index.GetCount() ? m_index[k] : NULL;
|
||||
}
|
||||
|
||||
// TODO: this should be overridable from outside
|
||||
|
||||
LPCWSTR SubtitleFile::s_predef =
|
||||
L"color#white {a: 255; r: 255; g: 255; b: 255;}; \n"
|
||||
L"color#black {a: 255; r: 0; g: 0; b: 0;}; \n"
|
||||
L"color#gray {a: 255; r: 128; g: 128; b: 128;}; \n"
|
||||
L"color#red {a: 255; r: 255; g: 0; b: 0;}; \n"
|
||||
L"color#green {a: 255; r: 0; g: 255; b: 0;}; \n"
|
||||
L"color#blue {a: 255; r: 0; g: 0; b: 255;}; \n"
|
||||
L"color#cyan {a: 255; r: 0; g: 255; b: 255;}; \n"
|
||||
L"color#yellow {a: 255; r: 255; g: 255; b: 0;}; \n"
|
||||
L"color#magenta {a: 255; r: 255; g: 0; b: 255;}; \n"
|
||||
L" \n"
|
||||
L"align#topleft {v: \"top\"; h: \"left\";}; \n"
|
||||
L"align#topcenter {v: \"top\"; h: \"center\";}; \n"
|
||||
L"align#topright {v: \"top\"; h: \"right\";}; \n"
|
||||
L"align#middleleft {v: \"middle\"; h: \"left\";}; \n"
|
||||
L"align#middlecenter {v: \"middle\"; h: \"center\";}; \n"
|
||||
L"align#middleright {v: \"middle\"; h: \"right\";}; \n"
|
||||
L"align#bottomleft {v: \"bottom\"; h: \"left\";}; \n"
|
||||
L"align#bottomcenter {v: \"bottom\"; h: \"center\";}; \n"
|
||||
L"align#bottomright {v: \"bottom\"; h: \"right\";}; \n"
|
||||
L" \n"
|
||||
L"time#time {scale: 1;}; \n"
|
||||
L"time#startstop {start: \"start\"; stop: \"stop\";}; \n"
|
||||
L" \n"
|
||||
L"#b {font.weight: \"bold\"}; \n"
|
||||
L"#i {font.italic: \"true\"}; \n"
|
||||
L"#u {font.underline: \"true\"}; \n"
|
||||
L"#s {font.strikethrough: \"true\"}; \n"
|
||||
L" \n"
|
||||
L"#nobr {linebreak: \"none\"}; \n"
|
||||
L" \n"
|
||||
L"subtitle#subtitle \n"
|
||||
L"{ \n"
|
||||
L" frame \n"
|
||||
L" { \n"
|
||||
L" reference: \"video\"; \n"
|
||||
L" resolution: {cx: 640; cy: 480;}; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" direction \n"
|
||||
L" { \n"
|
||||
L" primary: \"right\"; \n"
|
||||
L" secondary: \"down\"; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" wrap: \"normal\"; \n"
|
||||
L" \n"
|
||||
L" layer: 0; \n"
|
||||
L" \n"
|
||||
L" style \n"
|
||||
L" { \n"
|
||||
L" linebreak: \"word\"; \n"
|
||||
L" \n"
|
||||
L" placement \n"
|
||||
L" { \n"
|
||||
L" clip: \"none\"; \n"
|
||||
L" margin: {t: 0; r: 0; b: 0; l: 0;}; \n"
|
||||
L" align: bottomcenter; \n"
|
||||
L" pos: \"auto\" \n"
|
||||
L" offset: {x: 0; y: 0;}; \n"
|
||||
L" angle: {x: 0; y: 0; z: 0;}; \n"
|
||||
L" org: \"auto\" \n"
|
||||
L" path: \"\"; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" font \n"
|
||||
L" { \n"
|
||||
L" face: \"Arial\"; \n"
|
||||
L" size: 20; \n"
|
||||
L" weight: \"bold\"; \n"
|
||||
L" color: white; \n"
|
||||
L" underline: \"false\"; \n"
|
||||
L" strikethrough: \"false\"; \n"
|
||||
L" italic: \"false\"; \n"
|
||||
L" spacing: 0; \n"
|
||||
L" scale: {cx: 1; cy: 1;}; \n"
|
||||
L" kerning: \"true\"; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" background \n"
|
||||
L" { \n"
|
||||
L" color: black; \n"
|
||||
L" size: 2; \n"
|
||||
L" type: \"outline\"; \n"
|
||||
L" blur: 0; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" shadow \n"
|
||||
L" { \n"
|
||||
L" color: black {a: 128;}; \n"
|
||||
L" depth: 2; \n"
|
||||
L" angle: -45; \n"
|
||||
L" blur: 0; \n"
|
||||
L" }; \n"
|
||||
L" \n"
|
||||
L" fill \n"
|
||||
L" { \n"
|
||||
L" color: yellow; \n"
|
||||
L" width: 0; \n"
|
||||
L" }; \n"
|
||||
L" }; \n"
|
||||
L"}; \n";
|
||||
}
|
73
vsfilter/libssf/SubtitleFile.h
Normal file
73
vsfilter/libssf/SubtitleFile.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Gabest
|
||||
* http://www.gabest.org
|
||||
*
|
||||
* 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, 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "File.h"
|
||||
#include "Subtitle.h"
|
||||
|
||||
namespace ssf
|
||||
{
|
||||
class SubtitleFile : public File
|
||||
{
|
||||
static LPCWSTR s_predef;
|
||||
|
||||
public:
|
||||
struct SegmentItem
|
||||
{
|
||||
Definition* pDef;
|
||||
float start, stop;
|
||||
};
|
||||
|
||||
class Segment : public CAtlList<SegmentItem>
|
||||
{
|
||||
public:
|
||||
float m_start, m_stop;
|
||||
Segment() {}
|
||||
Segment(float start, float stop, const SegmentItem* si = NULL);
|
||||
Segment(const Segment& s);
|
||||
void operator = (const Segment& s);
|
||||
};
|
||||
|
||||
class SegmentList : public CAtlList<Segment>
|
||||
{
|
||||
CAtlArray<Segment*> m_index;
|
||||
size_t Index(bool fForce = false);
|
||||
|
||||
public:
|
||||
void RemoveAll();
|
||||
void Insert(float start, float stop, Definition* pDef);
|
||||
void Lookup(float at, CAtlList<SegmentItem>& sis);
|
||||
bool Lookup(float at, size_t& k);
|
||||
const Segment* GetSegment(size_t k);
|
||||
};
|
||||
|
||||
SegmentList m_segments;
|
||||
|
||||
public:
|
||||
SubtitleFile();
|
||||
virtual ~SubtitleFile();
|
||||
|
||||
void Parse(InputStream& s);
|
||||
void Append(InputStream& s, float start, float stop, bool fSetTime = false);
|
||||
bool Lookup(float at, CAutoPtrList<Subtitle>& subs);
|
||||
};
|
||||
}
|
87
vsfilter/libssf/demo/demo.ssa
Normal file
87
vsfilter/libssf/demo/demo.ssa
Normal file
|
@ -0,0 +1,87 @@
|
|||
[Script Info]
|
||||
; This is a Sub Station Alpha v4 script.
|
||||
; For Sub Station Alpha info and downloads,
|
||||
; go to http://www.eswat.demon.co.uk/
|
||||
; or email kotus@eswat.demon.co.uk
|
||||
;
|
||||
ScriptType: v4.00
|
||||
Collisions: Normal
|
||||
PlayResX: 320
|
||||
PlayResY: 240
|
||||
Timer: 100.0000
|
||||
|
||||
[V4 Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
|
||||
Style: MainB,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0,-1,1,2,4,1,16,16,16,0,0
|
||||
Style: Default,Arial,18,&Hffffff,&H00ffff,&H000000,&H000000, -1, 0,1,2,3,2,20,20,20,0,1
|
||||
Style: MainT,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,0
|
||||
Style: Karaoke,Arial,14,&H40ffff,&Hff4040,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,0
|
||||
Style: B4S4B,Arial,14,&He0e0e0,&H00ff00,&H804000,&H804000, 0,-1,1,4,4,5,16,16,40,0,0
|
||||
Style: B0S0K,Arial,14,&He0e0e0,&H00ff00,&H000000,&H000000, 0,-1,1,0,0,5,16,16,40,0,0
|
||||
Style: B2S2R,Arial,14,&He0e0e0,&H00ff00,&H004080,&H004080, 0,-1,1,2,2,5,16,16,40,0,0
|
||||
Style: B2S6G,Arial,14,&He0e0e0,&H00ff00,&H408000,&H408000, 0,-1,1,2,6,5,16,16,40,0,0
|
||||
Style: ShiftJIS,MS Gothic,20,&He0e0e0,&H00ff00,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,128
|
||||
Style: Timer,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0,-1,1,2,4,5,16,16,40,0,0
|
||||
|
||||
|
||||
[Events]
|
||||
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: Marked=0,0:00:00.00,0:00:05.00,MainB,,0000,0000,0000,!Effect,{\q1}Subtitler filter for VirtualDub\NDemonstration script\N\NAvery Lee <phaeron@virtualdub.org>
|
||||
Dialogue: Marked=0,0:00:05.00,0:00:10.00,MainB,,0000,0000,0000,!Effect,{\q1}Introduction\N\NThis script will demonstrate some of the simpler features of the subtitler. You will want to refer to the {\fnCourier New\b1}readme.txt{\r} file for a more complete reference.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:21.00,MainB,,0000,0000,0000,!Effect,{\q1}Dialogue lines\N\NScripts are based on dialogue lines. Each dialogue line has a start time, an end time, and text to display in between.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:11.00,Timer,,0000,0000,0000,!Effect,0:00
|
||||
Dialogue: Marked=0,0:00:11.00,0:00:12.00,Timer,,0000,0000,0000,!Effect,0:01
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:13.00,Timer,,0000,0000,0000,!Effect,0:02
|
||||
Dialogue: Marked=0,0:00:13.00,0:00:14.00,Timer,,0000,0000,0000,!Effect,0:03
|
||||
Dialogue: Marked=0,0:00:14.00,0:00:15.00,Timer,,0000,0000,0000,!Effect,0:04
|
||||
Dialogue: Marked=0,0:00:15.00,0:00:16.00,Timer,,0000,0000,0000,!Effect,0:05
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:17.00,Timer,,0000,0000,0000,!Effect,0:06
|
||||
Dialogue: Marked=0,0:00:17.00,0:00:18.00,Timer,,0000,0000,0000,!Effect,0:07
|
||||
Dialogue: Marked=0,0:00:18.00,0:00:19.00,Timer,,0000,0000,0000,!Effect,0:08
|
||||
Dialogue: Marked=0,0:00:19.00,0:00:20.00,Timer,,0000,0000,0000,!Effect,0:09
|
||||
Dialogue: Marked=0,0:00:20.00,0:00:21.00,Timer,,0000,0000,0000,!Effect,0:10
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:15.00,MainT,,0000,0000,0000,!Effect,{\c&H80FF00&}Hello.
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:19.00,MainT,,0000,0000,0000,!Effect,{\c&HE0E0E0&}Oh, hi.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:12.00,MainT,,0000,0000,0080,!Effect,{\c&H407F00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:15.00,MainT,,0000,0000,0080,!Effect,{\c&H80FF00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:15.00,0:00:21.00,MainT,,0000,0000,0080,!Effect,{\c&H407F00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:16.00,MainT,,0000,0000,0080,!Effect,{\c&H707070&}[06:00-09:00] Oh, hi.
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:19.00,MainT,,0000,0000,0080,!Effect,{\c&HE0E0E0&}[06:00-09:00] Oh, hi.
|
||||
Dialogue: Marked=0,0:00:19.00,0:00:21.00,MainT,,0000,0000,0080,!Effect,{\c&H707070&}[06:00-09:00] Oh, hi.
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0055,0055,0000,!Effect,{\q1\a10}Alignment\N\NDialogue lines may be placed in any of three horizontal placements and any of three vertical placements.
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a1\c&HE0E0E0&}Bottom\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a2\c&HE0E0E0&}Bottom\Ncenter
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a3\c&HE0E0E0&}Bottom\Nright
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a5\c&HE0E0E0&}Top\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a6\c&HE0E0E0&}Top\Ncenter
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a7\c&HE0E0E0&}Top\Nright
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a9\c&HE0E0E0&}Middle\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a11\c&HE0E0E0&}Middle\Nright
|
||||
Dialogue: Marked=0,0:00:35.00,0:00:45.00,MainB,,0000,0000,0000,!Effect,{\q1}Text styles\N\NText may be varied in font, size, color, and style.
|
||||
Dialogue: Marked=0,0:00:35.00,0:00:45.00,MainT,,0000,0000,0000,!Effect,{\q1}You can have your text in {\c&H4060FF&}red{\r}, {\c&H60FF40&}green{\r}, and {\c&HFF6040&}blue{\r}; {\fnCourier New}Courier{\r}; {\fs16}16 point{\r} or {\fs32}32 point{\r}; {\b1}bold{\r}, {\i1}italic{\r}, or even {\b1\i1}bold italic{\r}.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainB,,0000,0000,0000,!Effect,{\q1}Wrapping styles\N\NThree wrapping modes are supported: manual only, automatic wrapping, and smart wrapping. Smart wrapping is automatic wrapping, but with the lines broken as evenly as possible.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0000,!Effect,{\q2\c&HE0FF80&}This line uses manual wrapping and won't\nbe wrapped except where explicitly broken.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0045,!Effect,{\q1\c&H80E0FF&}This line uses automatic wrapping and is broken automatically.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0090,!Effect,{\q0\a6\c&HFFE080&}This line uses smart wrapping and is broken with even lines. It's good for centered text.
|
||||
Dialogue: Marked=0,0:00:59.00,0:01:24.00,MainB,,0000,0000,0000,!Effect,{\q1}Collisions\N\NIf two dialogue items attempt to display at the same time and place, the second one is pushed clear of the first. However, text stays in place after it is resolved, even if the collider disappears.
|
||||
Dialogue: Marked=0,0:01:02.00,0:01:07.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Man, I gotta get out of here!
|
||||
Dialogue: Marked=0,0:01:07.00,0:01:17.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Which way should I go? I'm not going back to school....
|
||||
Dialogue: Marked=0,0:01:10.00,0:01:21.00,MainT,,0000,0000,0000,!Effect,{\q1\a7\c&H50D0FF&}Ranma, you're in the way! Move!
|
||||
Dialogue: Marked=0,0:01:15.00,0:01:21.30,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Why would I move for an uncute tomboy like you?
|
||||
Dialogue: Marked=0,0:01:21.00,0:01:25.00,MainT,,0000,0000,0000,!Effect,{\q1\a7\c&H50D0FF&}Ranma no baka!!!
|
||||
Dialogue: Marked=0,0:01:21.50,0:01:24.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}*wham*
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,MainB,,0000,0000,0000,!Effect,{\q1}Shadows and borders\N\NYou can vary the depth of the translucent shadow as well as the thickness and color of the border.
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B0S0K,,0000,0000,0000,!Effect,Border=0, shadow=0
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B2S2R,,0000,0000,0030,!Effect,Border=2, shadow=2 (red)
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B2S6G,,0000,0000,0060,!Effect,Border=2, shadow=6 (green)
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B4S4B,,0000,0000,0090,!Effect,Border=4, shadow=4 (blue)
|
||||
Dialogue: Marked=0,0:01:38.00,0:01:48.00,MainB,,0000,0000,0000,!Effect,{\q1}Karaoke\N\NLetting people sing to music is dangerous. But if they're going to do it anyway, they might as well have some help. Both snap and smooth styles are supported.
|
||||
Dialogue: Marked=0,0:01:40.00,0:01:45.00,Karaoke,,0000,0000,0000,Karaoke,{\fs18\k100}one {\k100}two {\k50}three-{\k50}and {\k100}four
|
||||
Dialogue: Marked=0,0:01:40.00,0:01:45.00,Karaoke,,0000,0000,0030,Karaoke,{\fs18\K100}one {\K100}two {\K50}three-{\K50}and {\K100}four
|
||||
Dialogue: Marked=0,0:01:50.00,0:02:00.00,MainB,,0000,0000,0000,!Effect,{\q1}DBCS (double-byte character set) support\N\NIf you have the appropriate language support installed, you can display far-east text in your subtitles. (By the way, I don't really know Japanese, so I'm kind of winged it above with the JWPce dictionary.)
|
||||
Dialogue: Marked=0,0:01:50.00,0:02:00.00,ShiftJIS,,0000,0000,0000,!Effect,{\q1}{\fe0}[Keitarou]{\fe128}だ。。。大丈夫?
|
||||
Dialogue: Marked=0,0:01:52.00,0:02:00.00,ShiftJIS,,0000,0000,0000,!Effect,{\a7\q1\c&HFFFF00&\fe0}[Naru]{\fe128}何よ!
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainB,,0000,0000,0000,!Effect,{\q1}Motion effects\N\NYou can scroll text in like a banner, or up the screen.
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainT,,0000,0000,0000,Banner;30,Text is fun. We like scrolling text.
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainT,,0000,0000,0000,Scroll Up;40;50;120,{\q1}You can scroll lots of text up this way. Personally, I find it a little annoying to have a lot of text coming up very slowly on screen, but it's a useful technique to have for credits and other long lists in tabular form.
|
||||
Dialogue: Marked=0,0:02:19.00,0:02:50.00,MainB,,0000,0000,0000,!Effect,{\q1}Conclusion\N\NThat concludes the demo. I hope you've enjoyed the brief glimpse I've given you here, and encourage you to read the {\fnCourier New\b1}readme.txt{\r} file for more information on the effects you've seen here. Also, if you're bored, try loading this script into Kotus' Sub Station Alpha V4 program. Not all effects will render correctly, but most of the file will. Have fun, and keep on subtitling!\N\N{\fnCourier New}--{\r}Avery Lee <phaeron@virtualdub.org>\N{\fnCourier New}\h\h{\r}Author of VirtualDub and the 'subtitler' filter
|
595
vsfilter/libssf/demo/demo.ssf
Normal file
595
vsfilter/libssf/demo/demo.ssf
Normal file
|
@ -0,0 +1,595 @@
|
|||
/*
|
||||
This file is the direct translation of demo.ssa of the "subtitler" virtualdub plugin
|
||||
*/
|
||||
|
||||
file#file
|
||||
{
|
||||
format: "ssf";
|
||||
version: 1;
|
||||
};
|
||||
|
||||
/*
|
||||
PlayResX: 320
|
||||
PlayResY: 240
|
||||
*/
|
||||
|
||||
subtitle#subtitle
|
||||
{
|
||||
frame
|
||||
{
|
||||
reference: "video";
|
||||
resolution: {cx: 320; cy: 240;};
|
||||
};
|
||||
|
||||
style
|
||||
{
|
||||
placement {align: bottomleft; margin {t: 16; r: 16; b: 16; l: 16;};};
|
||||
font {size: 14; weight: "normal"; color: yellow;};
|
||||
shadow.depth: 4;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Style: MainB,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0,-1,1,2,4,1,16,16,16,0,0
|
||||
Style: Default,Arial,18,&Hffffff,&H00ffff,&H000000,&H000000, -1, 0,1,2,3,2,20,20,20,0,1
|
||||
Style: MainT,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,0
|
||||
Style: Karaoke,Arial,14,&H40ffff,&Hff4040,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,0
|
||||
Style: B4S4B,Arial,14,&He0e0e0,&H00ff00,&H804000,&H804000, 0,-1,1,4,4,5,16,16,40,0,0
|
||||
Style: B0S0K,Arial,14,&He0e0e0,&H00ff00,&H000000,&H000000, 0,-1,1,0,0,5,16,16,40,0,0
|
||||
Style: B2S2R,Arial,14,&He0e0e0,&H00ff00,&H004080,&H004080, 0,-1,1,2,2,5,16,16,40,0,0
|
||||
Style: B2S6G,Arial,14,&He0e0e0,&H00ff00,&H408000,&H408000, 0,-1,1,2,6,5,16,16,40,0,0
|
||||
Style: ShiftJIS,MS Gothic,20,&He0e0e0,&H00ff00,&H000000,&H000000, 0, 0,1,2,4,5,16,16,16,0,128
|
||||
Style: Timer,Arial,14,&H00ffff,&H00ff00,&H000000,&H000000, 0,-1,1,2,4,5,16,16,40,0,0
|
||||
*/
|
||||
|
||||
#MainT {placement.align: topleft;};
|
||||
#MainB {font.italic: "true";};
|
||||
#Karaoke : MainT {font.color.b: 0x40;};
|
||||
#Timer : MainT MainB {placement.margin.t: 40;};
|
||||
#BxSxC : Timer {font.color {r: 0xe0; g: 0xe0; b: 0xe0;};};
|
||||
#B4S4B : BxSxC {background {color: {r: 0x00; g: 0x40; b: 0x80;}; size: 4;};};
|
||||
#B0S0K : BxSxC {background.size: 0; shadow.depth: 0;};
|
||||
#B2S2R : BxSxC {background.color {r: 0x80; g: 0x40; b: 0x00;}; shadow.depth: 2;};
|
||||
#B2S6G : BxSxC {background.color {r: 0x00; g: 0x80; b: 0x40;}; shadow.depth: 6;};
|
||||
#ShiftJIS : MainT {font {face: "MS Gothic"; size: 20; color: {r: 0xe0; g: 0xe0; b: 0xe0;};};};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:00.00,0:00:05.00,MainB,,0000,0000,0000,!Effect,{\q1}Subtitler filter for VirtualDub\NDemonstration script\N\NAvery Lee <phaeron@virtualdub.org>
|
||||
Dialogue: Marked=0,0:00:05.00,0:00:10.00,MainB,,0000,0000,0000,!Effect,{\q1}Introduction\N\NThis script will demonstrate some of the simpler features of the subtitler. You will want to refer to the {\fnCourier New\b1}readme.txt{\r} file for a more complete reference.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:21.00,MainB,,0000,0000,0000,!Effect,{\q1}Dialogue lines\N\NScripts are based on dialogue lines. Each dialogue line has a start time, an end time, and text to display in between.
|
||||
*/
|
||||
|
||||
#notes
|
||||
{
|
||||
style: MainB;
|
||||
};
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:00:00.000; stop: 00:00:05.000;};
|
||||
|
||||
@ {
|
||||
Subtitler filter for VirtualDub\n
|
||||
Demonstration script\n\n
|
||||
Avery Lee <phaeron@virtualdub.org>
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:00:05.000; stop: 00:00:10.000;};
|
||||
|
||||
@ {
|
||||
Introduction\n\n
|
||||
This script will demonstrate some of the simpler features of the subtitler. You will want to
|
||||
refer to the [{font {face: "Courier New"; weight: "bold";};}] {readme.txt} file for a more
|
||||
complete reference.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:00:10.000; stop: 00:00:21.000;};
|
||||
|
||||
@ {
|
||||
Dialogue lines\n\n
|
||||
Scripts are based on dialogue lines. Each dialogue line has a start time, an end time, and text
|
||||
to display in between.
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:11.00,Timer,,0000,0000,0000,!Effect,0:00
|
||||
Dialogue: Marked=0,0:00:11.00,0:00:12.00,Timer,,0000,0000,0000,!Effect,0:01
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:13.00,Timer,,0000,0000,0000,!Effect,0:02
|
||||
Dialogue: Marked=0,0:00:13.00,0:00:14.00,Timer,,0000,0000,0000,!Effect,0:03
|
||||
Dialogue: Marked=0,0:00:14.00,0:00:15.00,Timer,,0000,0000,0000,!Effect,0:04
|
||||
Dialogue: Marked=0,0:00:15.00,0:00:16.00,Timer,,0000,0000,0000,!Effect,0:05
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:17.00,Timer,,0000,0000,0000,!Effect,0:06
|
||||
Dialogue: Marked=0,0:00:17.00,0:00:18.00,Timer,,0000,0000,0000,!Effect,0:07
|
||||
Dialogue: Marked=0,0:00:18.00,0:00:19.00,Timer,,0000,0000,0000,!Effect,0:08
|
||||
Dialogue: Marked=0,0:00:19.00,0:00:20.00,Timer,,0000,0000,0000,!Effect,0:09
|
||||
Dialogue: Marked=0,0:00:20.00,0:00:21.00,Timer,,0000,0000,0000,!Effect,0:10
|
||||
*/
|
||||
|
||||
#clocktest
|
||||
{
|
||||
time {start: +0s; stop: +1s;};
|
||||
style: Timer;
|
||||
};
|
||||
|
||||
subtitle : clocktest {@ {0:00}; time.start: 00:00:10.000;};
|
||||
subtitle : clocktest {@ {0:01};};
|
||||
subtitle : clocktest {@ {0:02};};
|
||||
subtitle : clocktest {@ {0:03};};
|
||||
subtitle : clocktest {@ {0:04};};
|
||||
subtitle : clocktest {@ {0:05};};
|
||||
subtitle : clocktest {@ {0:06};};
|
||||
subtitle : clocktest {@ {0:07};};
|
||||
subtitle : clocktest {@ {0:08};};
|
||||
subtitle : clocktest {@ {0:09};};
|
||||
subtitle : clocktest {@ {0:10};};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:15.00,MainT,,0000,0000,0000,!Effect,{\c&H80FF00&}Hello.
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:19.00,MainT,,0000,0000,0000,!Effect,{\c&HE0E0E0&}Oh, hi.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:12.00,MainT,,0000,0000,0080,!Effect,{\c&H407F00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:12.00,0:00:15.00,MainT,,0000,0000,0080,!Effect,{\c&H80FF00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:15.00,0:00:21.00,MainT,,0000,0000,0080,!Effect,{\c&H407F00&}[02:00-05:00] Hello.
|
||||
Dialogue: Marked=0,0:00:10.00,0:00:16.00,MainT,,0000,0000,0080,!Effect,{\c&H707070&}[06:00-09:00] Oh, hi.
|
||||
Dialogue: Marked=0,0:00:16.00,0:00:19.00,MainT,,0000,0000,0080,!Effect,{\c&HE0E0E0&}[06:00-09:00] Oh, hi.
|
||||
Dialogue: Marked=0,0:00:19.00,0:00:21.00,MainT,,0000,0000,0080,!Effect,{\c&H707070&}[06:00-09:00] Oh, hi.
|
||||
*/
|
||||
|
||||
subtitle
|
||||
{
|
||||
time {start: 00:00:12.000; stop: 00:00:15.000;};
|
||||
style: MainT {font.color {r: 0x00; g: 0xff; b: 0x80;};};
|
||||
@ {Hello.};
|
||||
};
|
||||
|
||||
subtitle
|
||||
{
|
||||
time {start: 00:00:16.000; stop: 00:00:19.000;};
|
||||
style: MainT {font.color {r: 0xe0; g: 0xe0; b: 0xe0;};};
|
||||
@ {Oh, hi.};
|
||||
};
|
||||
|
||||
#dialogtest
|
||||
{
|
||||
style: MainT {placement.margin.t: 80;};
|
||||
time.start: +0s;
|
||||
};
|
||||
|
||||
#dialogtest1 : dialogtest
|
||||
{
|
||||
@ {\[02:00-05:00\] Hello.};
|
||||
};
|
||||
|
||||
#dialogtest2 : dialogtest
|
||||
{
|
||||
@ {\[06:00-09:00\] Oh, hi.};
|
||||
};
|
||||
|
||||
subtitle : dialogtest1
|
||||
{
|
||||
time.start: 00:00:10.000;
|
||||
time.stop: +2s;
|
||||
style.font.color {r: 0x00; g: 0x7f; b: 0x40;};
|
||||
};
|
||||
|
||||
subtitle : dialogtest1
|
||||
{
|
||||
time.stop: +3s;
|
||||
style.font.color {r: 0x00; g: 0xff; b: 0x80;};
|
||||
};
|
||||
|
||||
subtitle : dialogtest1
|
||||
{
|
||||
time.stop: +6s;
|
||||
style.font.color {r: 0x00; g: 0x7f; b: 0x40;};
|
||||
};
|
||||
|
||||
subtitle : dialogtest2
|
||||
{
|
||||
time.start: 00:00:10.000;
|
||||
time.stop: +6s;
|
||||
style.font.color {r: 0x70; g: 0x70; b: 0x70;};
|
||||
};
|
||||
|
||||
subtitle : dialogtest2
|
||||
{
|
||||
time.stop: +3s;
|
||||
style.font.color {r: 0xe0; g: 0xe0; b: 0xe0;};
|
||||
};
|
||||
|
||||
subtitle : dialogtest2
|
||||
{
|
||||
time.stop: +2s;
|
||||
style.font.color {r: 0x70; g: 0x70; b: 0x70;};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0055,0055,0000,!Effect,{\q1\a10}Alignment\N\NDialogue lines may be placed in any of three horizontal placements and any of three vertical placements.
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a1\c&HE0E0E0&}Bottom\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a2\c&HE0E0E0&}Bottom\Ncenter
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a3\c&HE0E0E0&}Bottom\Nright
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a5\c&HE0E0E0&}Top\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a6\c&HE0E0E0&}Top\Ncenter
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a7\c&HE0E0E0&}Top\Nright
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a9\c&HE0E0E0&}Middle\Nleft
|
||||
Dialogue: Marked=0,0:00:23.00,0:00:33.00,MainB,,0008,0008,0008,!Effect,{\a11\c&HE0E0E0&}Middle\Nright
|
||||
*/
|
||||
|
||||
#aligntest : notes
|
||||
{
|
||||
time {start: 00:00:23.000; stop: 00:00:33.000;};
|
||||
style {placement.margin {t: 8; r: 8; b: 8; l: 8;};};
|
||||
};
|
||||
|
||||
#aligntestside : aligntest
|
||||
{
|
||||
style.font.color {r: 0xe0; g: 0xe0; b: 0xe0;};
|
||||
};
|
||||
|
||||
subtitle : aligntest
|
||||
{
|
||||
style.placement {align: middlecenter; margin {r: 55; l: 55;};};
|
||||
|
||||
@ {
|
||||
Alignment\n\n
|
||||
Dialogue lines may be placed in any of three horizontal placements and any of three vertical placements.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : aligntestside {style.placement.align: bottomleft; @ {Bottom\nleft};};
|
||||
subtitle : aligntestside {style.placement.align: bottomcenter; @ {Bottom\ncenter};};
|
||||
subtitle : aligntestside {style.placement.align: bottomright; @ {Bottom\nright};};
|
||||
subtitle : aligntestside {style.placement.align: topleft; @ {Top\nleft};};
|
||||
subtitle : aligntestside {style.placement.align: topcenter; @ {Top\ncenter};};
|
||||
subtitle : aligntestside {style.placement.align: topright; @ {Top\nright};};
|
||||
subtitle : aligntestside {style.placement.align: middleleft; @ {Middle\nleft};};
|
||||
subtitle : aligntestside {style.placement.align: middleright; @ {Middle\nright};};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:35.00,0:00:45.00,MainB,,0000,0000,0000,!Effect,{\q1}Text styles\N\NText may be varied in font, size, color, and style.
|
||||
Dialogue: Marked=0,0:00:35.00,0:00:45.00,MainT,,0000,0000,0000,!Effect,{\q1}You can have your text in {\c&H4060FF&}red{\r}, {\c&H60FF40&}green{\r}, and {\c&HFF6040&}blue{\r}; {\fnCourier New}Courier{\r}; {\fs16}16 point{\r} or {\fs32}32 point{\r}; {\b1}bold{\r}, {\i1}italic{\r}, or even {\b1\i1}bold italic{\r}.
|
||||
*/
|
||||
|
||||
#fonttest
|
||||
{
|
||||
time {start: 00:00:35.000; stop: 00:00:45.000;};
|
||||
};
|
||||
|
||||
subtitle : fonttest notes
|
||||
{
|
||||
@ {
|
||||
Text styles\n\n
|
||||
Text may be varied in font, size, color, and style.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : fonttest
|
||||
{
|
||||
style: MainT;
|
||||
|
||||
@ {
|
||||
You can have your text in
|
||||
[{font.color {r: 0xff; g: 0x60; b: 0x40;};}] {red},
|
||||
[{font.color {r: 0x40; g: 0xff; b: 0x60;};}] {green}, and
|
||||
[{font.color {r: 0x40; g: 0x60; b: 0xff;};}] {blue};
|
||||
[{font.face: "Courier New";}] {Courier};
|
||||
[{font.size: 16;}] {16 point} or
|
||||
[{font.size: 32;}] {32 point};
|
||||
[{font.weight: "bold";}] {bold},
|
||||
[{font.italic: "true";}] {italic},
|
||||
or even
|
||||
[{font {weight: "bold"; italic: "true";};}] {bold italic}.
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainB,,0000,0000,0000,!Effect,{\q1}Wrapping styles\N\NThree wrapping modes are supported: manual only, automatic wrapping, and smart wrapping. Smart wrapping is automatic wrapping, but with the lines broken as evenly as possible.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0000,!Effect,{\q2\c&HE0FF80&}This line uses manual wrapping and won't\nbe wrapped except where explicitly broken.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0045,!Effect,{\q1\c&H80E0FF&}This line uses automatic wrapping and is broken automatically.
|
||||
Dialogue: Marked=0,0:00:47.00,0:00:57.00,MainT,,0000,0000,0090,!Effect,{\q0\a6\c&HFFE080&}This line uses smart wrapping and is broken with even lines. It's good for centered text.
|
||||
*/
|
||||
|
||||
#wraptest
|
||||
{
|
||||
time {start: 00:00:47.000; stop: 00:00:57.000;};
|
||||
};
|
||||
|
||||
subtitle : wraptest notes
|
||||
{
|
||||
@ {
|
||||
Wrapping styles\n\n
|
||||
Three wrapping modes are supported: manual only, automatic wrapping, and smart wrapping.
|
||||
Smart wrapping is automatic wrapping, but with the lines broken as evenly as possible.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : wraptest
|
||||
{
|
||||
style: MainT {font.color {r: 0x80; g: 0xff; b: 0xe0;};};
|
||||
wrap: "manual";
|
||||
@ {This line uses manual wrapping and won't\nbe wrapped except where explicitly broken.};
|
||||
};
|
||||
|
||||
subtitle : wraptest
|
||||
{
|
||||
style: MainT {font.color {r: 0xff; g: 0xe0; b: 0x80;}; placement.margin.t: 45;};
|
||||
wrap: "normal";
|
||||
@ {This line uses automatic wrapping and is broken automatically.};
|
||||
};
|
||||
|
||||
subtitle : wraptest
|
||||
{
|
||||
style: MainT {font.color {r: 0x80; g: 0xe0; b: 0xff;}; placement.margin.t: 90; placement.align: topcenter; };
|
||||
wrap: "even";
|
||||
@ {This line uses smart wrapping and is broken with even lines. It's good for centered text.};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:00:59.00,0:01:24.00,MainB,,0000,0000,0000,!Effect,{\q1}Collisions\N\NIf two dialogue items attempt to display at the same time and place, the second one is pushed clear of the first. However, text stays in place after it is resolved, even if the collider disappears.
|
||||
Dialogue: Marked=0,0:01:02.00,0:01:07.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Man, I gotta get out of here!
|
||||
Dialogue: Marked=0,0:01:07.00,0:01:17.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Which way should I go? I'm not going back to school....
|
||||
Dialogue: Marked=0,0:01:10.00,0:01:21.00,MainT,,0000,0000,0000,!Effect,{\q1\a7\c&H50D0FF&}Ranma, you're in the way! Move!
|
||||
Dialogue: Marked=0,0:01:15.00,0:01:21.30,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}Why would I move for an uncute tomboy like you?
|
||||
Dialogue: Marked=0,0:01:21.00,0:01:25.00,MainT,,0000,0000,0000,!Effect,{\q1\a7\c&H50D0FF&}Ranma no baka!!!
|
||||
Dialogue: Marked=0,0:01:21.50,0:01:24.00,MainT,,0000,0000,0000,!Effect,{\q1\c&HE0E0E0&}*wham*
|
||||
*/
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:00:59.000; stop: 00:01:24.000;};
|
||||
|
||||
@ {
|
||||
Collisions\n\n
|
||||
If two dialogue items attempt to display at the same time and place, the second one is
|
||||
pushed clear of the first. However, text stays in place after it is resolved, even if
|
||||
the collider disappears.
|
||||
};
|
||||
};
|
||||
|
||||
#actor1
|
||||
{
|
||||
style: MainT {font.color {r: 0xe0; g: 0xe0; b: 0xe0;};};
|
||||
};
|
||||
|
||||
#actor2
|
||||
{
|
||||
style: MainT {font.color {r: 0xff; g: 0xd0; b: 0x50;}; placement.align: topright;};
|
||||
};
|
||||
|
||||
subtitle : actor1
|
||||
{
|
||||
time {start: 00:01:02.000; stop: 00:01:07.000;};
|
||||
@ {Man, I gotta get out of here!};
|
||||
};
|
||||
|
||||
subtitle : actor1
|
||||
{
|
||||
time {start: 00:01:07.000; stop: 00:01:17.000;};
|
||||
@ {Which way should I go? I'm not going back to school....};
|
||||
};
|
||||
|
||||
subtitle : actor2
|
||||
{
|
||||
time {start: 00:01:10.000; stop: 00:01:21.000;};
|
||||
@ {Ranma, you're in the way! Move!};
|
||||
};
|
||||
|
||||
subtitle : actor1
|
||||
{
|
||||
time {start: 00:01:15.000; stop: 00:01:21.300;};
|
||||
@ {Why would I move for an uncute tomboy like you?};
|
||||
};
|
||||
|
||||
subtitle : actor2
|
||||
{
|
||||
time {start: 00:01:21.000; stop: 00:01:25.000;};
|
||||
@ {Ranma no baka!!!};
|
||||
};
|
||||
|
||||
subtitle : actor1
|
||||
{
|
||||
time {start: 00:01:21.500; stop: 00:01:24.000;};
|
||||
@ {*wham*};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,MainB,,0000,0000,0000,!Effect,{\q1}Shadows and borders\N\NYou can vary the depth of the translucent shadow as well as the thickness and color of the border.
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B0S0K,,0000,0000,0000,!Effect,Border=0, shadow=0
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B2S2R,,0000,0000,0030,!Effect,Border=2, shadow=2 (red)
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B2S6G,,0000,0000,0060,!Effect,Border=2, shadow=6 (green)
|
||||
Dialogue: Marked=0,0:01:26.00,0:01:36.00,B4S4B,,0000,0000,0090,!Effect,Border=4, shadow=4 (blue)
|
||||
*/
|
||||
|
||||
#bordershadowtest
|
||||
{
|
||||
time {start: 00:01:26.000; stop: 00:01:36.000;};
|
||||
};
|
||||
|
||||
subtitle : bordershadowtest notes
|
||||
{
|
||||
@ {
|
||||
Shadows and borders\n\n
|
||||
You can vary the depth of the translucent shadow as well as the thickness and color of the border.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : bordershadowtest
|
||||
{
|
||||
style: B0S0K;
|
||||
@ {Border=0, shadow=0};
|
||||
};
|
||||
|
||||
subtitle : bordershadowtest
|
||||
{
|
||||
style: B2S2R {placement.margin.t: 30;};
|
||||
@ {Border=2, shadow=2 (red)};
|
||||
};
|
||||
|
||||
subtitle : bordershadowtest
|
||||
{
|
||||
style: B2S6G {placement.margin.t: 60;};
|
||||
@ {Border=2, shadow=6 (green)};
|
||||
};
|
||||
|
||||
subtitle : bordershadowtest
|
||||
{
|
||||
style: B4S4B {placement.margin.t: 90;};
|
||||
@ {Border=4, shadow=4 (blue)};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:01:38.00,0:01:48.00,MainB,,0000,0000,0000,!Effect,{\q1}Karaoke\N\NLetting people sing to music is dangerous. But if they're going to do it anyway, they might as well have some help. Both snap and smooth styles are supported.
|
||||
Dialogue: Marked=0,0:01:40.00,0:01:45.00,Karaoke,,0000,0000,0000,Karaoke,{\fs18\k100}one {\k100}two {\k50}three-{\k50}and {\k100}four
|
||||
Dialogue: Marked=0,0:01:40.00,0:01:45.00,Karaoke,,0000,0000,0030,Karaoke,{\fs18\K100}one {\K100}two {\K50}three-{\K50}and {\K100}four
|
||||
*/
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:01:38.000; stop: 00:01:48.000;};
|
||||
|
||||
@ {
|
||||
Karaoke\n\n
|
||||
Letting people sing to music is dangerous. But if they're going to do it anyway,
|
||||
they might as well have some help. Both snap and smooth styles are supported.
|
||||
};
|
||||
};
|
||||
|
||||
#karaoketest
|
||||
{
|
||||
time {start: 00:01:40.000; stop: 00:01:45.000;};
|
||||
style: Karaoke {font.size: 18;};
|
||||
};
|
||||
|
||||
#hlcolor {r: 0x40; g: 0x40; b: 0xff;};
|
||||
#hleffect1 {time {scale: 0.01; start: +0s;}; transition: "start"; font.color: hlcolor;};
|
||||
#hleffect2 {time {scale: 0.01; start: +0s;}; fill.width: 1;};
|
||||
|
||||
subtitle : karaoketest
|
||||
{
|
||||
@ {
|
||||
[hleffect1 {time.stop: +100;}] {one}
|
||||
[hleffect1 {time.stop: +100;}] {two}
|
||||
[hleffect1 {time.stop: +50;}] {three-}
|
||||
[hleffect1 {time.stop: +50;}] {and}
|
||||
[hleffect1 {time.stop: +100;}] {four}
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : karaoketest
|
||||
{
|
||||
style {placement.margin.t: 30; fill.color: hlcolor;};
|
||||
|
||||
@ {
|
||||
[hleffect2 {time.stop: +100;}] {one}
|
||||
[hleffect2 {time.stop: +100;}] {two}
|
||||
[hleffect2 {time.stop: +50;}] {three-}
|
||||
[hleffect2 {time.stop: +50;}] {and}
|
||||
[hleffect2 {time.stop: +100;}] {four}
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:01:50.00,0:02:00.00,MainB,,0000,0000,0000,!Effect,{\q1}DBCS (double-byte character set) support\N\NIf you have the appropriate language support installed, you can display far-east text in your subtitles. (By the way, I don't really know Japanese, so I'm kind of winged it above with the JWPce dictionary.)
|
||||
Dialogue: Marked=0,0:01:50.00,0:02:00.00,ShiftJIS,,0000,0000,0000,!Effect,{\q1}{\fe0}[Keitarou]{\fe128} ...
|
||||
Dialogue: Marked=0,0:01:52.00,0:02:00.00,ShiftJIS,,0000,0000,0000,!Effect,{\a7\q1\c&HFFFF00&\fe0}[Naru]{\fe128} ...
|
||||
*/
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:01:50.000; stop: 00:02:00.000;};
|
||||
|
||||
@ {
|
||||
DBCS (double-byte character set) support\n\n
|
||||
If you have the appropriate language support installed, you can display far-east text
|
||||
in your subtitles. (By the way, I don't really know Japanese, so I'm kind of winged it
|
||||
above with the JWPce dictionary.)
|
||||
};
|
||||
};
|
||||
|
||||
subtitle
|
||||
{
|
||||
time {start: 00:01:50.000; stop: 00:02:00.000;};
|
||||
style: ShiftJIS;
|
||||
@ {\[Keitarou\]だ。。。大丈夫?};
|
||||
};
|
||||
|
||||
subtitle
|
||||
{
|
||||
time {start: 00:01:52.000; stop: 00:02:00.000;};
|
||||
style: ShiftJIS {font.color: cyan; placement.align: topright;};
|
||||
@ {\[Naru\]何よ!};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainB,,0000,0000,0000,!Effect,{\q1}Motion effects\N\NYou can scroll text in like a banner, or up the screen.
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainT,,0000,0000,0000,Banner;30,Text is fun. We like scrolling text.
|
||||
Dialogue: Marked=0,0:02:02.00,0:02:17.00,MainT,,0000,0000,0000,Scroll Up;40;50;120,{\q1}You can scroll lots of text up this way. Personally, I find it a little annoying to have a lot of text coming up very slowly on screen, but it's a useful technique to have for credits and other long lists in tabular form.
|
||||
*/
|
||||
|
||||
#effecttest
|
||||
{
|
||||
time {start: 00:02:02.000; stop: 00:02:17.000;};
|
||||
style.placement.clip: "frame";
|
||||
};
|
||||
|
||||
subtitle : effecttest notes
|
||||
{
|
||||
@ {
|
||||
Motion effects\n\n
|
||||
You can scroll text in like a banner, or up the screen.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : effecttest
|
||||
{
|
||||
wrap: "manual";
|
||||
style: MainT {placement {margin {l: "right"; r: "left";}; align.h: "left";};};
|
||||
#hscroll {time {start: "start"; stop: "stop";}; placement.align.h: "right";};
|
||||
|
||||
@ {
|
||||
[hscroll]
|
||||
Text is fun. We like scrolling text.
|
||||
};
|
||||
};
|
||||
|
||||
subtitle : effecttest
|
||||
{
|
||||
style: MainT {placement {margin {t: 120; b: 200;}; clip {t: 40; b: 120;}; align.v: "top";};};
|
||||
#vscroll {time {start: "start"; stop: "stop";}; placement.align.v: "bottom";};
|
||||
|
||||
@ {
|
||||
[vscroll]
|
||||
You can scroll lots of text up this way. Personally, I find it a little annoying
|
||||
to have a lot of text coming up very slowly on screen, but it's a useful technique
|
||||
to have for credits and other long lists in tabular form.
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Dialogue: Marked=0,0:02:19.00,0:02:50.00,MainB,,0000,0000,0000,!Effect,{\q1}Conclusion\N\NThat concludes the demo. I hope you've enjoyed the brief glimpse I've given you here, and encourage you to read the {\fnCourier New\b1}readme.txt{\r} file for more information on the effects you've seen here. Also, if you're bored, try loading this script into Kotus' Sub Station Alpha V4 program. Not all effects will render correctly, but most of the file will. Have fun, and keep on subtitling!\N\N{\fnCourier New}--{\r}Avery Lee <phaeron@virtualdub.org>\N{\fnCourier New}\h\h{\r}Author of VirtualDub and the 'subtitler' filter
|
||||
*/
|
||||
|
||||
subtitle : notes
|
||||
{
|
||||
time {start: 00:02:19.000; stop: 00:02:50.000;};
|
||||
|
||||
#monospace {font.face: "Courier New";};
|
||||
#monospacebold : monospace {font.weight: "bold";};
|
||||
|
||||
@ {
|
||||
Conclusion\n\n
|
||||
That concludes the demo. I hope you've enjoyed the brief glimpse I've given you here,
|
||||
and encourage you to read the [monospacebold] {readme.txt} file for more information
|
||||
on the effects you've seen here. Also, if you're bored, try loading this script into
|
||||
Kotus' Sub Station Alpha V4 program. Not all effects will render correctly, but most
|
||||
of the file will. Have fun, and keep on subtitling!\n\n
|
||||
[monospace]{--}Avery Lee <phaeron@virtualdub.org>\n
|
||||
[monospace]{\h\h}Author of VirtualDub and the 'subtitler' filter
|
||||
};
|
||||
};
|
613
vsfilter/libssf/docs/ssf-specs.txt
Normal file
613
vsfilter/libssf/docs/ssf-specs.txt
Normal file
|
@ -0,0 +1,613 @@
|
|||
Structured Subtitle Format 1.0 (boring name, need a better one)
|
||||
------------------------------
|
||||
|
||||
The encoding must be utf-8/16le/16be with the BOM at the beginning.
|
||||
|
||||
Parsing is prefered to be stream oriented, which means:
|
||||
- new-line characters in text do not differ from the rest of the white-space characters
|
||||
- forward references are not allowed
|
||||
|
||||
Comments
|
||||
--------
|
||||
|
||||
// a comment, ends at the end of the line
|
||||
/* this is a comment, too */
|
||||
|
||||
Syntax
|
||||
------
|
||||
|
||||
Fortunatelly, there is only one general way to define something. The elements are broken
|
||||
into lines for better understanding, but they can be compressed into one single line as well,
|
||||
whichever suits your preference. The term "type" could be read as "attribute" or "member of
|
||||
a structure" too.
|
||||
|
||||
[!]
|
||||
[type[.type[..]]]
|
||||
[#name]
|
||||
[: | =]
|
||||
[refs | quoted string | num | bool | raw]
|
||||
;
|
||||
|
||||
As you can see nearly everything is optional, even the terminating semi-colon is not required
|
||||
when a closing bracket ends the definition anyway. However, either type or #name must be given,
|
||||
otherwise there would be no meaning of the expression.
|
||||
|
||||
"!":
|
||||
- gives the definition high priority, normal priority types of the same kind cannot override it:
|
||||
#a {!t: 123;};
|
||||
#b {t: 234;};
|
||||
#c a b; // t of c equals to 123
|
||||
- works on references too:
|
||||
!#a {t: 123;};
|
||||
#b {t: 234;};
|
||||
#ab a b;
|
||||
#c ab; // t of c still equals to 123
|
||||
|
||||
"type" and "name":
|
||||
- alphanumeric or underscore characters only, without spaces
|
||||
- cannot start with a number
|
||||
- case-sensitive
|
||||
|
||||
"type":
|
||||
- type is optional but can be inherited through referencing other names which happen to have a type already
|
||||
color#c1 {a: 0x80;};
|
||||
#c2: c1; // c2 also has the type of color now
|
||||
#c3: c2; // c3 too
|
||||
- if there is a type already additional references cannot change it
|
||||
- when mixing different types (not recommended) the first one decides
|
||||
- there is one special type which have an important but a limited use: @ (see 'subtitle' for an example usage)
|
||||
- it is not parsed for references or nested definitions
|
||||
- the content of the following block {...} is saved as-is for the application
|
||||
- cannot be global or named and therefore referenced
|
||||
- { and } have to be escaped with \ inside the block (other block specific characters may as well)
|
||||
- type.type.type.... is equal to writing: type {type {type {...};};};
|
||||
|
||||
"name":
|
||||
- every name is globally visible
|
||||
- redefining a name is forbidden, unless it was predefined by the application
|
||||
- using the type as the name (type#type) can change the type's default values
|
||||
- however, the scope is important:
|
||||
|
||||
subtitle#subtitle {style.font.size: 20;};
|
||||
style#style {font.size: 30;};
|
||||
style#s1 {font.face: "Arial";};
|
||||
style#s2 : s1 {font.color: red;};
|
||||
subtitle#a {style: s2 {font.weight: "normal";};};
|
||||
|
||||
Here font.size equals to 20, because it inherits from subtitle#subtitle.style instead of the
|
||||
global style#style, additionally it gets the properties of s2-s1 and the inline def. If it also
|
||||
inherited properties from style#style through s2-s1 indirectly, there would be two default base
|
||||
definitions and the order of overriding eachother would not be clear.
|
||||
|
||||
subtitle#a.style
|
||||
<- subtitle#subtitle.style
|
||||
<- s2 <- s1 <-NOT- style#style
|
||||
<- {font.weight: "normal";}
|
||||
|
||||
"refs":
|
||||
- combination of any names or nested definitions separated by spaces
|
||||
- forward references are not allowed
|
||||
- referencing a value type directly is not allowed: (TODO: this may change)
|
||||
OK:
|
||||
color#c1: {a: 12;};
|
||||
color#c2: c1;
|
||||
BAD:
|
||||
#twelve: 12;
|
||||
color#c2: {a: twelve;};
|
||||
- 'name' must have been defined by a parent node
|
||||
OK:
|
||||
#c1: {a: 12;};
|
||||
style#s1 {color: c1;};
|
||||
style#s2 {color: c1;};
|
||||
BAD:
|
||||
style#s1 {color#c1: {a: 12;};};
|
||||
style#s2 {color: c1;}; // c1 cannot be accessed here
|
||||
|
||||
"quoted string" or 'quoted string':
|
||||
- \ escapes characters, including " and '
|
||||
- cannot contain any new-line characters
|
||||
|
||||
"num":
|
||||
- decimal, hexadecimal (prefixed with: 0x), float [+ unit (optional, see 'time' below for an example)]
|
||||
- there are numbers with restricted range or special formatting:
|
||||
- degrees: <num> mod 360
|
||||
- percent: must be between 0 and 1
|
||||
- time: [+] [<num>:[<num>:[<num>.]]]<num> | <num>h | <num>m | <num>s | <num>ms
|
||||
|
||||
"bool":
|
||||
- "true" | "false" | "on" | "off" | "yes" | "no" | 1 | 0
|
||||
- unrecognizable values will result in unpredictable behaviour, since there can't be a default fallback value
|
||||
|
||||
Recognized types and attributes
|
||||
-------------------------------
|
||||
|
||||
file
|
||||
{
|
||||
format: <string>; // identifies the file format ("ssf")
|
||||
version: <num>; // file format version (1)
|
||||
language: <string>; // iso6392
|
||||
title: <string>;
|
||||
year: <num>;
|
||||
author: <string>;
|
||||
};
|
||||
|
||||
color
|
||||
{
|
||||
// a, r, g, b: 0 - 255 or 0x00 - 0xff
|
||||
|
||||
a: <num>;
|
||||
r: <num>;
|
||||
g: <num>;
|
||||
b: <num>;
|
||||
};
|
||||
|
||||
point
|
||||
{
|
||||
x: <num>;
|
||||
y: <num>;
|
||||
};
|
||||
|
||||
size
|
||||
{
|
||||
cx: <num>;
|
||||
cy: <num>;
|
||||
};
|
||||
|
||||
rect
|
||||
{
|
||||
t: <num>;
|
||||
r: <num>;
|
||||
b: <num>;
|
||||
l: <num>;
|
||||
};
|
||||
|
||||
align
|
||||
{
|
||||
// when given in percent, 0 means top/left, 1 bottom/right, 0.5 middle/center
|
||||
|
||||
v: ["top" | "middle" | "bottom" | <percent>];
|
||||
h: ["left" | "center" | "right" | <percent>];
|
||||
};
|
||||
|
||||
angle
|
||||
{
|
||||
x: <degrees>;
|
||||
y: <degrees>;
|
||||
z: <degrees>;
|
||||
};
|
||||
|
||||
frame
|
||||
{
|
||||
reference: ["video" | "window"];
|
||||
resolution: <size>;
|
||||
};
|
||||
|
||||
direction
|
||||
{
|
||||
primary: ["right" | "left" | "down" | "up"];
|
||||
secondary: ["right" | "left" | "down" | "up"]; // must be perpendicular to primary
|
||||
};
|
||||
|
||||
placement
|
||||
{
|
||||
clip: ["none" | "frame" | <rect>]; // anything drawn outside this rectangle is clipped, negative or larger than 'resolution' values are not allowed for rect
|
||||
margin: <rect>; // "top" "right" "bottom" "left" are also valid values for the rect members, they refer to the values of the "frame" rect (0, 0, frame.resolution.cx, frame.resolution.cy)
|
||||
align: <align>;
|
||||
pos: ["auto" | <point>]; // absolute values, pos.x or pos.y can be animated only when both the source and destination style defined it
|
||||
offset: <point>; // relative to pos, unlike pos this can be applied to fragments of the text as an override
|
||||
angle: <angle>; // origin of rotation is the alignment point, unless it is overriden
|
||||
org: ["auto" | <point>]; // override for the origin
|
||||
path: <string>; // a series of x y coord pairs (at least two points)
|
||||
};
|
||||
|
||||
font
|
||||
{
|
||||
face: <string>;
|
||||
size: <num>;
|
||||
weight: ["normal" | "bold" | "thin" | <num>];
|
||||
color: <color>;
|
||||
underline: <bool>;
|
||||
strikethrough: <bool>;
|
||||
italic: <bool>;
|
||||
spacing: <num>;
|
||||
scale: <size>;
|
||||
kerning: <bool>;
|
||||
};
|
||||
|
||||
background
|
||||
{
|
||||
color: <color>;
|
||||
size: <num>;
|
||||
type: ["outline" | "enlarge" | "box"];
|
||||
blur: <num>; // number of passes
|
||||
|
||||
// "enlarge" can be computed faster, but because it follows the path of the original outline it is
|
||||
// not rounded and size > 1 can make it look pretty bad if it intersects with itself.
|
||||
};
|
||||
|
||||
shadow
|
||||
{
|
||||
color: <color>;
|
||||
depth: <num>;
|
||||
angle: <degrees>;
|
||||
blur: <num>; // number of passes
|
||||
};
|
||||
|
||||
fill
|
||||
{
|
||||
color: <color>;
|
||||
width: <percent>;
|
||||
|
||||
// It cannot be applied to the same text multiple times as an override.
|
||||
//
|
||||
// #k1 {fill.width:1; time {start: +0; stop: +1s;}};
|
||||
// #k2 {fill.width:1; time {start: 0; stop: 2s;}};
|
||||
//
|
||||
// OK:
|
||||
// [k1] {Hello}
|
||||
//
|
||||
// BAD:
|
||||
// [k1] {Wo[k2]{r}ld!}
|
||||
//
|
||||
};
|
||||
|
||||
time
|
||||
{
|
||||
id: [<string> | <num>];
|
||||
start: <time>; // inclusive
|
||||
stop: <time>; // exclusive
|
||||
scale: <num>; // if the time was set WITHOUT a unit, then start and stop are measured in [scale * seconds]
|
||||
};
|
||||
|
||||
style
|
||||
{
|
||||
linebreak: ["word" | "char" | "none"]; // ignored if subtitle.wrap: "manual"
|
||||
placement: <placement>;
|
||||
font: <font>;
|
||||
background: <background>;
|
||||
shadow: <shadow>;
|
||||
fill: <fill>;
|
||||
};
|
||||
|
||||
animation
|
||||
{
|
||||
time: <time>; // before start: previous style, after stop: this style, animation is done between start and stop according to transition
|
||||
transition: ["linear" | "start" | "stop" | <num>]; // <num> is the same as the acceleration parameter of advanced ssa (see the "ass-specs"), "start" or "stop" sets num to 0 and inf, "linear" sets it to 1.0
|
||||
loop: <num>; // the number of times the effect should repeat, e.g. loop set to 2 makes the style turn from src to dst twice, between start => (start+stop)/2 and (start+stop)/2 => stop
|
||||
direction: ["fw" | "bw" | "fwbw" | "bwfw"]; // "bwfw" and "fwbw" makes the value of loop multiplied by two internally
|
||||
};
|
||||
|
||||
subtitle
|
||||
{
|
||||
frame: <frame>;
|
||||
direction: <direction>;
|
||||
wrap: ["normal" | "even" | "manual"];
|
||||
layer: <num>;
|
||||
time: <time>;
|
||||
style: <style>;
|
||||
@: {... dialog lines ...};
|
||||
|
||||
To have a subtitle displayed the minimal set of fields required are:
|
||||
- time.start
|
||||
- time.stop
|
||||
- @
|
||||
|
||||
About dialog lines
|
||||
------------------
|
||||
|
||||
All white-space will be compressed into one space character.
|
||||
|
||||
Special characters can be enforced:
|
||||
- new-line: \n
|
||||
- non-breaking space: \h
|
||||
|
||||
Empty space will be completly removed at these places:
|
||||
- before and after outermost text block brackets:
|
||||
@ { --> here <-- Hello World! --> here <-- }
|
||||
- between the inner closing and opening brackets of overrides:
|
||||
[s1] --> here <-- {Hello World!}
|
||||
- around forced new-lines:
|
||||
Hello --> here <-- \n --> here <-- World!
|
||||
|
||||
When neighboring spaces have different styles, the style of the trailing space is used:
|
||||
#u {font.underline: "true"};
|
||||
#s {font.strikethrough: "true"};
|
||||
[u] { Hello }
|
||||
[s] { World! }
|
||||
=>
|
||||
Hello_World!-
|
||||
______-------
|
||||
|
||||
These special characters have to be escaped with a backslash:
|
||||
{ } [ ] \
|
||||
|
||||
Style overrides
|
||||
---------------
|
||||
|
||||
[refs] {... more dialog text ...}
|
||||
|
||||
"name" as in type#name ... is unimportant and ignored.
|
||||
|
||||
If there is a text block right after an override, the new style will be used only inside
|
||||
that block.
|
||||
|
||||
Style and time offsets are restored at the end of text blocks.
|
||||
|
||||
Examples:
|
||||
|
||||
[s1] {s1 applies only to this block.}
|
||||
|
||||
[s2] s2 applies till the end of the container block.
|
||||
|
||||
[s1 s2 {color: red;} s3] {Multiple styles are valid just like in a normal ref list}
|
||||
|
||||
{
|
||||
Nesting text blocks. Some may have overrides, others may not.
|
||||
|
||||
[s1]
|
||||
{
|
||||
Every text block will be trimmed and white-space compressed,
|
||||
so we can use the space freely to make it a bit more readable.
|
||||
|
||||
{Yet another nested block}
|
||||
}
|
||||
}
|
||||
|
||||
Animation:
|
||||
|
||||
The override is style + animation mixed.
|
||||
|
||||
[{time.stop: +00:00:01.000; transition: "linear"; font.size: 20;}]
|
||||
{
|
||||
Here the size of the font gradually becomes 20 after one second.
|
||||
}
|
||||
|
||||
[{font.color: white;}]
|
||||
{
|
||||
[{time.stop: +00:00:10.000; font.color: black;}]
|
||||
{Text turns from white to black in the first 10 seconds}
|
||||
|
||||
[a1]
|
||||
{This one does whatever a1 tells to do}
|
||||
}
|
||||
|
||||
[{time.start: "start"; time.stop: "stop"; font.size: 20}]
|
||||
{
|
||||
This is a way to refer to the subtitle's own start and stop values.
|
||||
|
||||
You can predefine it for easier use:
|
||||
|
||||
#a1 {time.start: "start"; time.stop: "stop";};
|
||||
[a1 {font.size: 20}] {...}
|
||||
}
|
||||
|
||||
Karaoke effect using animation:
|
||||
|
||||
[{background.size: 0;}]
|
||||
{
|
||||
[{time.start: 0s; time.stop: +1s; background.size: 10;}]
|
||||
{Ka}
|
||||
[{time.start: 1s; time.stop: +1s; background.size: 10;}]
|
||||
{ra}
|
||||
[{time.start: 2s; time.stop: +1s; background.size: 10;}]
|
||||
{o}
|
||||
[{time.start: 3s; time.stop: +1s; background.size: 10;}]
|
||||
{ke!}
|
||||
}
|
||||
|
||||
To simplify the above, we can predefine the common parameters:
|
||||
|
||||
#s1 {background.size: 0;};
|
||||
#a1 {time.start: +0s; time.stop: +1s; background.size: 10;};
|
||||
|
||||
[s1]
|
||||
{
|
||||
[a1]{Ka}[a1]{ra}[a1]{o}[a1 {font.color: red;}]{ke!}
|
||||
|
||||
// That last piece has even turned into a red in the end :)
|
||||
|
||||
// And to make sure s1 has not been red already, we could derive it
|
||||
// from "whitefont" (defined somewhere else as: #whitefont {font.color: white;};)
|
||||
|
||||
[a1]{Ka}[a1]{ra}[a1]{o}[a1 whitefont {font.color: red;};}]{ke!}
|
||||
}
|
||||
|
||||
When specifying multiple style references watch out for the start/stop values
|
||||
of time. Since they override eachother you should only set them once.
|
||||
|
||||
#a2 {font.color.a: 0;};
|
||||
#a3 {placement.angle.x: 360;};
|
||||
|
||||
[s1] [a1 a2 a3]{Ka}[a1 a2 a3]{ra}[a1 a2 a3]{o}[a1 a2 a3]{ke!}
|
||||
|
||||
If you want to be even lazier:
|
||||
|
||||
#a4: a1 a2 a3;
|
||||
|
||||
[s1] [a4]{Ka}[a4]{ra}[a4]{o}[a4]{ke!}
|
||||
|
||||
To avoid the times overriding eachother use either nested text blocks ...
|
||||
|
||||
#a2 {time.start: +0.5s; time.stop: +1s; font.color.a: 0;};
|
||||
#a3 {time.start: +1s; time.stop: +1s; placement.angle.x: 360;};
|
||||
|
||||
[s1] [a1]{[a2]{[a3]Ka}}[a1]{[a2]{[a3]ra}}[a1]{[a2]{[a3]o}}[a1]{[a2]{[a3]ke}}
|
||||
|
||||
... or a list of references were each has a different time.id ...
|
||||
|
||||
#a1 {time {id: 1; start: +0s; stop: +1s;}; background.size: 10;};
|
||||
#a2 {time {id: 2; start: +0.5s; stop: +1s;}; font.color.a: 0;};
|
||||
#a3 {time {id: 3; start: +1s; stop: +1s;}; placement.angle.x: 360;};
|
||||
|
||||
[s1] [a1,a2,a3]{Ka}[a1,a2,a3]{ra}[a1,a2,a3]{o}[a1,a2,a3]{ke!}
|
||||
|
||||
... or just let it auto-number the ids, each timer id becomes the actual position
|
||||
in the comma separated list (a1 id => 1, a2 id => 2, a3 id => 3).
|
||||
|
||||
#a1 {time {start: +0s; stop: +1s;}; background.size: 10;};
|
||||
#a2 {time {start: +0.5s; stop: +1s;}; font.color.a: 0;};
|
||||
#a3 {time {start: +1s; stop: +1s;}; placement.angle.x: 360;};
|
||||
|
||||
[s1] [a1,a2,a3]{Ka}[a1,a2,a3]{ra}[a1,a2,a3]{o}[a1,a2,a3]{ke!}
|
||||
|
||||
It is also possible to leave some of the ref list slots empty.
|
||||
|
||||
[s1] [a1,a2,a3]{Ka}[,a2,a3]{ra}[a1,,a3]{o}[a1,a2,]{ke!}
|
||||
|
||||
Text includes
|
||||
-------------
|
||||
|
||||
Text blocks can also be defined outside subtitles and included later.
|
||||
|
||||
#hw { @ {[{font.italic: "true"}]Hello World!}; };
|
||||
subtitle { @ {[hw]}; };
|
||||
|
||||
When mixing style overrides and text includes, the new style applies to the text too.
|
||||
|
||||
#hw { @ {Hello World!}; };
|
||||
subtitle { @ {[hw {font.italic: "true"}]}; };
|
||||
|
||||
Multiple levels of recursion:
|
||||
|
||||
#dblspace { @ {[{font.scale.cx: 2;}] }; }; // note: there is still only one space character here because of white space compression
|
||||
#hw { @ {Hello[dblspace]World!}; };
|
||||
subtitle { @ {[hw]}; };
|
||||
};
|
||||
|
||||
Defaults and predefined names
|
||||
-----------------------------
|
||||
|
||||
These must be predefined by the application and always assumed to be there for ssf version 1.
|
||||
|
||||
color#white {a: 255; r: 255; g: 255; b: 255;};
|
||||
color#black {a: 255; r: 0; g: 0; b: 0;};
|
||||
color#gray {a: 255; r: 128; g: 128; b: 128;};
|
||||
color#red {a: 255; r: 255; g: 0; b: 0;};
|
||||
color#green {a: 255; r: 0; g: 255; b: 0;};
|
||||
color#blue {a: 255; r: 0; g: 0; b: 255;};
|
||||
color#cyan {a: 255; r: 0; g: 255; b: 255;};
|
||||
color#yellow {a: 255; r: 255; g: 255; b: 0;};
|
||||
color#magenta {a: 255; r: 255; g: 0; b: 255;};
|
||||
|
||||
align#topleft {v: "top"; h: "left";};
|
||||
align#topcenter {v: "top"; h: "center";};
|
||||
align#topright {v: "top"; h: "right";};
|
||||
align#middleleft {v: "middle"; h: "left";};
|
||||
align#middlecenter {v: "middle"; h: "center";};
|
||||
align#middleright {v: "middle"; h: "right";};
|
||||
align#bottomleft {v: "bottom"; h: "left";};
|
||||
align#bottomcenter {v: "bottom"; h: "center";};
|
||||
align#bottomright {v: "bottom"; h: "right";};
|
||||
|
||||
time#time {scale: 1;};
|
||||
time#startstop {start: "start"; stop: "stop";};
|
||||
|
||||
#b {font.weight: "bold"};
|
||||
#i {font.italic: "true"};
|
||||
#u {font.underline: "true"};
|
||||
#s {font.strikethrough: "true"};
|
||||
|
||||
#nobr {linebreak: "none"};
|
||||
|
||||
subtitle#subtitle
|
||||
{
|
||||
frame
|
||||
{
|
||||
reference: "video";
|
||||
resolution: {cx: 640; cy: 480;};
|
||||
};
|
||||
|
||||
direction
|
||||
{
|
||||
primary: "right";
|
||||
secondary: "down";
|
||||
};
|
||||
|
||||
wrap: "normal";
|
||||
|
||||
layer: 0;
|
||||
|
||||
style
|
||||
{
|
||||
linebreak: "word";
|
||||
|
||||
placement
|
||||
{
|
||||
clip: "none";
|
||||
margin: {t: 0; r: 0; b: 0; l: 0;};
|
||||
align: bottomcenter;
|
||||
pos: "auto";
|
||||
offset: {x: 0; y: 0;};
|
||||
angle: {x: 0; y: 0; z: 0;};
|
||||
};
|
||||
|
||||
font
|
||||
{
|
||||
face: "Arial";
|
||||
size: 20;
|
||||
weight: "bold";
|
||||
color: white;
|
||||
underline: "false";
|
||||
strikethrough: "false";
|
||||
italic: "false";
|
||||
spacing: 0;
|
||||
scale: {cx: 1; cy: 1;};
|
||||
kerning: "true";
|
||||
};
|
||||
|
||||
background
|
||||
{
|
||||
color: black;
|
||||
size: 2;
|
||||
type: "outline";
|
||||
};
|
||||
|
||||
shadow
|
||||
{
|
||||
color: black {a: 128;};
|
||||
depth: 2;
|
||||
angle: -45;
|
||||
blur: 0;
|
||||
};
|
||||
|
||||
fill
|
||||
{
|
||||
color: yellow;
|
||||
width: 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Streaming
|
||||
---------
|
||||
|
||||
Correct packetization is important when a subtitle file has to be embeded into a media
|
||||
file. Putting everything into the header would be trivial, but sending the whole track
|
||||
data ahead cannot be called streaming really, and it also makes editing impossible
|
||||
unless the application learns how to parse and resave our format.
|
||||
|
||||
The recommended way of segmenting ssf into media samples:
|
||||
- Search top level definitions which do not satisfy the requirements of a displayable
|
||||
subtitle (one of start/stop/@ is absent) and save them into the file header of the media
|
||||
file as the initializer data for playback.
|
||||
- Multiplex the rest of the top level definitions as media samples, their timestamps
|
||||
shall be used for interleaving with other streams.
|
||||
|
||||
Example:
|
||||
|
||||
#mystyle {font.face: "Times New Roman";};
|
||||
subtitle#s1 {time.start: 2s;};
|
||||
subtitle#s2 : s1 {style: mystyle; time.stop: +1s; @ {2s -> 3s};};
|
||||
subtitle#s3 {style: mystyle; time.start: 5s; @ {5s -> 7s};};
|
||||
subtitle#s4 : s3 {time.stop: +2s;};
|
||||
|
||||
File header:
|
||||
|
||||
#mystyle {font.face: "Times New Roman";};
|
||||
subtitle#s1 {time.start: 2s;};
|
||||
subtitle#s3 {style: mystyle; time.start: 5s; @ {5s -> 7s};};
|
||||
|
||||
Media samples:
|
||||
|
||||
subtitle#s2 : s1 {style: mystyle; time.stop: +1s; @ {2s -> 3s};};
|
||||
subtitle#s4 : s3 {time.stop: +2s;};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue