2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
26 #include "../../../Subtitles/VobSubFile.h"
27 #include "../../../Subtitles/RTS.h"
28 #include "../../../Subtitles/SSF.h"
29 #include "../../../SubPic/PooledSubPic.h"
30 #include "../../../SubPic/SimpleSubPicProviderImpl.h"
31 #include "../../../subpic/color_conv_table.h"
32 #include "../../../subpic/SimpleSubPicWrapper.h"
33 #include "DirectVobSub.h"
37 #include "vd2/extras/FilterSDK/VirtualDub.h"
39 #include "vd2/plugin/vdplugin.h"
40 #include "vd2/plugin/vdvideofilt.h"
43 using namespace DirectVobSubXyOptions
;
52 class CFilter
: public CUnknown
, public CDirectVobSub
, public CAMThread
, public CCritSec
60 CComPtr
<ISimpleSubPicProvider
> m_simple_provider
;
61 CComPtr
<ISubPicProvider
> m_pSubPicProvider
;
62 DWORD_PTR m_SubPicProviderId
;
64 CSimpleTextSubtitle::YCbCrMatrix m_script_selected_yuv
;
65 CSimpleTextSubtitle::YCbCrRange m_script_selected_range
;
69 CFilter() : CUnknown(NAME("CFilter"), NULL
), m_fps(-1), m_SubPicProviderId(0), m_fLazyInit(false)
71 //fix me: should not do init here
72 CacheManager::GetPathDataMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_PATH_DATA_CACHE_MAX_ITEM_NUM
]);
73 CacheManager::GetScanLineData2MruCache()->SetMaxItemNum(m_xy_int_opt
[INT_SCAN_LINE_DATA_CACHE_MAX_ITEM_NUM
]);
74 CacheManager::GetOverlayNoBlurMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_OVERLAY_NO_BLUR_CACHE_MAX_ITEM_NUM
]);
75 CacheManager::GetOverlayMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_OVERLAY_CACHE_MAX_ITEM_NUM
]);
77 XyFwGroupedDrawItemsHashKey::GetCacher()->SetMaxItemNum(m_xy_int_opt
[INT_BITMAP_MRU_CACHE_ITEM_NUM
]);
78 CacheManager::GetBitmapMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_BITMAP_MRU_CACHE_ITEM_NUM
]);
80 CacheManager::GetClipperAlphaMaskMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_CLIPPER_MRU_CACHE_ITEM_NUM
]);
81 CacheManager::GetTextInfoCache()->SetMaxItemNum(m_xy_int_opt
[INT_TEXT_INFO_CACHE_ITEM_NUM
]);
82 CacheManager::GetAssTagListMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_ASS_TAG_LIST_CACHE_ITEM_NUM
]);
84 SubpixelPositionControler::GetGlobalControler().SetSubpixelLevel( static_cast<SubpixelPositionControler::SUBPIXEL_LEVEL
>(m_xy_int_opt
[INT_SUBPIXEL_POS_LEVEL
]) );
86 m_script_selected_yuv
= CSimpleTextSubtitle::YCbCrMatrix_AUTO
;
87 m_script_selected_range
= CSimpleTextSubtitle::YCbCrRange_AUTO
;
91 virtual ~CFilter() {CAMThread::CallWorker(0);}
94 STDMETHODIMP
NonDelegatingQueryInterface(REFIID riid
, void** ppv
)
96 CheckPointer(ppv
, E_POINTER
);
98 return QI(IDirectVobSub
)
102 __super::NonDelegatingQueryInterface(riid
, ppv
);
105 CString
GetFileName() {CAutoLock
cAutoLock(this); return m_fn
;}
106 void SetFileName(CString fn
) {CAutoLock
cAutoLock(this); m_fn
= fn
;}
108 void SetYuvMatrix(SubPicDesc
& dst
)
110 ColorConvTable::YuvMatrixType yuv_matrix
= ColorConvTable::BT601
;
111 ColorConvTable::YuvRangeType yuv_range
= ColorConvTable::RANGE_TV
;
113 if ( m_xy_int_opt
[INT_COLOR_SPACE
]==CDirectVobSub::YuvMatrix_AUTO
)
115 switch(m_script_selected_yuv
)
117 case CSimpleTextSubtitle::YCbCrMatrix_BT601
:
118 yuv_matrix
= ColorConvTable::BT601
;
120 case CSimpleTextSubtitle::YCbCrMatrix_BT709
:
121 yuv_matrix
= ColorConvTable::BT709
;
123 case CSimpleTextSubtitle::YCbCrMatrix_AUTO
:
125 yuv_matrix
= ColorConvTable::BT601
;
131 switch(m_xy_int_opt
[INT_COLOR_SPACE
])
133 case CDirectVobSub::BT_601
:
134 yuv_matrix
= ColorConvTable::BT601
;
136 case CDirectVobSub::BT_709
:
137 yuv_matrix
= ColorConvTable::BT709
;
139 case CDirectVobSub::GUESS
:
140 yuv_matrix
= (dst
.w
> m_bt601Width
|| dst
.h
> m_bt601Height
) ? ColorConvTable::BT709
: ColorConvTable::BT601
;
145 if( m_xy_int_opt
[INT_YUV_RANGE
]==CDirectVobSub::YuvRange_Auto
)
147 switch(m_script_selected_range
)
149 case CSimpleTextSubtitle::YCbCrRange_PC
:
150 yuv_range
= ColorConvTable::RANGE_PC
;
152 case CSimpleTextSubtitle::YCbCrRange_TV
:
153 yuv_range
= ColorConvTable::RANGE_TV
;
155 case CSimpleTextSubtitle::YCbCrRange_AUTO
:
157 yuv_range
= ColorConvTable::RANGE_TV
;
163 switch(m_xy_int_opt
[INT_YUV_RANGE
])
165 case CDirectVobSub::YuvRange_TV
:
166 yuv_range
= ColorConvTable::RANGE_TV
;
168 case CDirectVobSub::YuvRange_PC
:
169 yuv_range
= ColorConvTable::RANGE_PC
;
171 case CDirectVobSub::YuvRange_Auto
:
172 yuv_range
= ColorConvTable::RANGE_TV
;
177 ColorConvTable::SetDefaultConvType(yuv_matrix
, yuv_range
);
180 bool Render(SubPicDesc
& dst
, REFERENCE_TIME rt
, float fps
)
182 if(!m_pSubPicProvider
)
191 CSize
size(dst
.w
, dst
.h
);
193 if(!m_simple_provider
)
196 if(!(m_simple_provider
= new SimpleSubPicProvider2(dst
.type
, size
, size
, CRect(CPoint(0,0), size
), this, &hr
)) || FAILED(hr
))
198 m_simple_provider
= NULL
;
201 XySetSize(SIZE_ORIGINAL_VIDEO
, size
);
204 if(m_SubPicProviderId
!= (DWORD_PTR
)(ISubPicProvider
*)m_pSubPicProvider
)
208 CComQIPtr
<IPersist
> tmp
= m_pSubPicProvider
;
209 tmp
->GetClassID(&clsid
);
210 if(clsid
== __uuidof(CRenderedTextSubtitle
))
212 CRenderedTextSubtitle
* pRTS
= dynamic_cast<CRenderedTextSubtitle
*>((ISubPicProvider
*)m_pSubPicProvider
);
213 playres
= pRTS
->m_dstScreenSize
;
215 XySetSize(SIZE_ASS_PLAY_RESOLUTION
, playres
);
217 m_simple_provider
->SetSubPicProvider(m_pSubPicProvider
);
218 m_SubPicProviderId
= (DWORD_PTR
)(ISubPicProvider
*)m_pSubPicProvider
;
221 CComPtr
<ISimpleSubPic
> pSubPic
;
222 if(!m_simple_provider
->LookupSubPic(rt
, &pSubPic
))
225 if(dst
.type
== MSP_RGB32
|| dst
.type
== MSP_RGB24
|| dst
.type
== MSP_RGB16
|| dst
.type
== MSP_RGB15
)
227 pSubPic
->AlphaBlt(&dst
);
234 SetThreadPriority(m_hThread
, THREAD_PRIORITY_LOWEST
);
236 CAtlArray
<HANDLE
> handles
;
237 handles
.Add(GetRequestHandle());
239 CString fn
= GetFileName();
242 CFileGetStatus(fn
, fs
);
246 DWORD i
= WaitForMultipleObjects(handles
.GetCount(), handles
.GetData(), FALSE
, 1000);
248 if(WAIT_OBJECT_0
== i
)
253 else if(WAIT_OBJECT_0
+ 1 >= i
&& i
<= WAIT_OBJECT_0
+ handles
.GetCount())
255 if(FindNextChangeNotification(handles
[i
- WAIT_OBJECT_0
]))
259 CFileGetStatus(fn
, fs2
);
261 if(fs
.m_mtime
< fs2
.m_mtime
)
263 fs
.m_mtime
= fs2
.m_mtime
;
265 if(CComQIPtr
<ISubStream
> pSubStream
= m_pSubPicProvider
)
267 CAutoLock
cAutoLock(&m_csSubLock
);
268 pSubStream
->Reload();
273 else if(WAIT_TIMEOUT
== i
)
275 CString fn2
= GetFileName();
281 HANDLE h
= FindFirstChangeNotification(p
, FALSE
, FILE_NOTIFY_CHANGE_LAST_WRITE
);
282 if(h
!= INVALID_HANDLE_VALUE
)
290 else // if(WAIT_ABANDONED_0 == i || WAIT_FAILED == i)
298 for(int i
= 1; i
< handles
.GetCount(); i
++)
299 FindCloseChangeNotification(handles
[i
]);
305 class CVobSubFilter
: virtual public CFilter
308 CVobSubFilter(CString fn
= _T(""))
310 if(!fn
.IsEmpty()) Open(fn
);
313 bool Open(CString fn
)
316 m_pSubPicProvider
= NULL
;
318 if(CVobSubFile
* vsf
= new CVobSubFile(&m_csSubLock
))
320 m_pSubPicProvider
= (ISubPicProvider
*)vsf
;
321 if(vsf
->Open(CString(fn
))) SetFileName(fn
);
322 else m_pSubPicProvider
= NULL
;
325 return !!m_pSubPicProvider
;
329 class CTextSubFilter
: virtual public CFilter
334 CTextSubFilter(CString fn
= _T(""), int CharSet
= DEFAULT_CHARSET
, float fps
= -1)
338 if(!fn
.IsEmpty()) Open(fn
, CharSet
);
341 int GetCharSet() {return(m_CharSet
);}
343 bool Open(CString fn
, int CharSet
= DEFAULT_CHARSET
)
346 m_pSubPicProvider
= NULL
;
348 if(!m_pSubPicProvider
)
350 if(ssf::CRenderer
* ssf
= new ssf::CRenderer(&m_csSubLock
))
352 m_pSubPicProvider
= (ISubPicProvider
*)ssf
;
353 if(ssf
->Open(CString(fn
))) SetFileName(fn
);
354 else m_pSubPicProvider
= NULL
;
358 if(!m_pSubPicProvider
)
360 if(CRenderedTextSubtitle
* rts
= new CRenderedTextSubtitle(&m_csSubLock
))
362 m_pSubPicProvider
= (ISubPicProvider
*)rts
;
363 if(rts
->Open(CString(fn
), CharSet
)) SetFileName(fn
);
364 else m_pSubPicProvider
= NULL
;
366 m_script_selected_yuv
= rts
->m_eYCbCrMatrix
;
367 m_script_selected_range
= rts
->m_eYCbCrRange
;
371 return !!m_pSubPicProvider
;
377 // old VirtualDub interface
382 class CVirtualDubFilter
: virtual public CFilter
385 CVirtualDubFilter() {}
386 virtual ~CVirtualDubFilter() {}
388 virtual int RunProc(const FilterActivation
* fa
, const FilterFunctions
* ff
) {
390 dst
.type
= MSP_RGB32
;
394 dst
.pitch
= fa
->src
.pitch
;
395 dst
.bits
= (LPVOID
)fa
->src
.data
;
397 Render(dst
, 10000i64
* fa
->pfsi
->lSourceFrameMS
, (float)1000 / fa
->pfsi
->lMicrosecsPerFrame
);
402 virtual long ParamProc(FilterActivation
* fa
, const FilterFunctions
* ff
) {
403 fa
->dst
.offset
= fa
->src
.offset
;
404 fa
->dst
.modulo
= fa
->src
.modulo
;
405 fa
->dst
.pitch
= fa
->src
.pitch
;
410 virtual int ConfigProc(FilterActivation
* fa
, const FilterFunctions
* ff
, HWND hwnd
) = 0;
411 virtual void StringProc(const FilterActivation
* fa
, const FilterFunctions
* ff
, char* str
) = 0;
412 virtual bool FssProc(FilterActivation
* fa
, const FilterFunctions
* ff
, char* buf
, int buflen
) = 0;
415 class CVobSubVirtualDubFilter
: public CVobSubFilter
, public CVirtualDubFilter
418 CVobSubVirtualDubFilter(CString fn
= _T(""))
419 : CVobSubFilter(fn
) {}
421 int ConfigProc(FilterActivation
* fa
, const FilterFunctions
* ff
, HWND hwnd
) {
422 AFX_MANAGE_STATE(AfxGetStaticModuleState());
424 CFileDialog
fd(TRUE
, NULL
, GetFileName(), OFN_EXPLORER
| OFN_ENABLESIZING
| OFN_HIDEREADONLY
,
425 _T("VobSub files (*.idx;*.sub)|*.idx;*.sub||"), CWnd::FromHandle(hwnd
), 0);
427 if (fd
.DoModal() != IDOK
) {
431 return Open(fd
.GetPathName()) ? 0 : 1;
434 void StringProc(const FilterActivation
* fa
, const FilterFunctions
* ff
, char* str
) {
435 sprintf(str
, " (%s)", !GetFileName().IsEmpty() ? CStringA(GetFileName()) : " (empty)");
438 bool FssProc(FilterActivation
* fa
, const FilterFunctions
* ff
, char* buf
, int buflen
) {
439 CStringA
fn(GetFileName());
440 fn
.Replace("\\", "\\\\");
441 _snprintf_s(buf
, buflen
, buflen
, "Config(\"%s\")", fn
);
446 class CTextSubVirtualDubFilter
: public CTextSubFilter
, public CVirtualDubFilter
449 CTextSubVirtualDubFilter(CString fn
= _T(""), int CharSet
= DEFAULT_CHARSET
)
450 : CTextSubFilter(fn
, CharSet
) {}
452 int ConfigProc(FilterActivation
* fa
, const FilterFunctions
* ff
, HWND hwnd
) {
453 AFX_MANAGE_STATE(AfxGetStaticModuleState());
455 const TCHAR formats
[] = _T("TextSub files (*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt)|*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt||");
456 CFileDialog
fd(TRUE
, NULL
, GetFileName(), OFN_EXPLORER
| OFN_ENABLESIZING
| OFN_HIDEREADONLY
| OFN_ENABLETEMPLATE
| OFN_ENABLEHOOK
,
457 formats
, CWnd::FromHandle(hwnd
), sizeof(OPENFILENAME
));
458 UINT_PTR CALLBACK
OpenHookProc(HWND hDlg
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
);
460 fd
.m_pOFN
->hInstance
= AfxGetResourceHandle();
461 fd
.m_pOFN
->lpTemplateName
= MAKEINTRESOURCE(IDD_TEXTSUBOPENTEMPLATE
);
462 fd
.m_pOFN
->lpfnHook
= (LPOFNHOOKPROC
)OpenHookProc
;
463 fd
.m_pOFN
->lCustData
= (LPARAM
)DEFAULT_CHARSET
;
465 if (fd
.DoModal() != IDOK
) {
469 return Open(fd
.GetPathName(), fd
.m_pOFN
->lCustData
) ? 0 : 1;
472 void StringProc(const FilterActivation
* fa
, const FilterFunctions
* ff
, char* str
) {
473 if (!GetFileName().IsEmpty()) {
474 sprintf(str
, " (%s, %d)", CStringA(GetFileName()), GetCharSet());
476 sprintf(str
, " (empty)");
480 bool FssProc(FilterActivation
* fa
, const FilterFunctions
* ff
, char* buf
, int buflen
) {
481 CStringA
fn(GetFileName());
482 fn
.Replace("\\", "\\\\");
483 _snprintf_s(buf
, buflen
, buflen
, "Config(\"%s\", %d)", fn
, GetCharSet());
488 int vobsubInitProc(FilterActivation
* fa
, const FilterFunctions
* ff
)
490 *(CVirtualDubFilter
**)fa
->filter_data
= DNew
CVobSubVirtualDubFilter();
491 return !(*(CVirtualDubFilter
**)fa
->filter_data
);
494 int textsubInitProc(FilterActivation
* fa
, const FilterFunctions
* ff
)
496 *(CVirtualDubFilter
**)fa
->filter_data
= DNew
CTextSubVirtualDubFilter();
497 return !(*(CVirtualDubFilter
**)fa
->filter_data
);
500 void baseDeinitProc(FilterActivation
* fa
, const FilterFunctions
* ff
)
502 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
506 int baseRunProc(const FilterActivation
* fa
, const FilterFunctions
* ff
)
508 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
509 return f
? f
->RunProc(fa
, ff
) : 1;
512 long baseParamProc(FilterActivation
* fa
, const FilterFunctions
* ff
)
514 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
515 return f
? f
->ParamProc(fa
, ff
) : 1;
518 int baseConfigProc(FilterActivation
* fa
, const FilterFunctions
* ff
, HWND hwnd
)
520 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
521 return f
? f
->ConfigProc(fa
, ff
, hwnd
) : 1;
524 void baseStringProc(const FilterActivation
* fa
, const FilterFunctions
* ff
, char* str
)
526 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
528 f
->StringProc(fa
, ff
, str
);
532 bool baseFssProc(FilterActivation
* fa
, const FilterFunctions
* ff
, char* buf
, int buflen
)
534 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
535 return f
? f
->FssProc(fa
, ff
, buf
, buflen
) : false;
538 void vobsubScriptConfig(IScriptInterpreter
* isi
, void* lpVoid
, CScriptValue
* argv
, int argc
)
540 FilterActivation
* fa
= (FilterActivation
*)lpVoid
;
541 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
545 f
= DNew
CVobSubVirtualDubFilter(CString(*argv
[0].asString()));
546 *(CVirtualDubFilter
**)fa
->filter_data
= f
;
549 void textsubScriptConfig(IScriptInterpreter
* isi
, void* lpVoid
, CScriptValue
* argv
, int argc
)
551 FilterActivation
* fa
= (FilterActivation
*)lpVoid
;
552 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
556 f
= DNew
CTextSubVirtualDubFilter(CString(*argv
[0].asString()), argv
[1].asInt());
557 *(CVirtualDubFilter
**)fa
->filter_data
= f
;
560 ScriptFunctionDef vobsub_func_defs
[] = {
561 { (ScriptFunctionPtr
)vobsubScriptConfig
, "Config", "0s" },
565 CScriptObject vobsub_obj
= {
566 NULL
, vobsub_func_defs
569 struct FilterDefinition filterDef_vobsub
= {
570 NULL
, NULL
, NULL
, // next, prev, module
572 "Adds subtitles from a vob sequence.", // desc
574 NULL
, // private_data
575 sizeof(CVirtualDubFilter
**), // inst_data_size
576 vobsubInitProc
, // initProc
577 baseDeinitProc
, // deinitProc
578 baseRunProc
, // runProc
579 baseParamProc
, // paramProc
580 baseConfigProc
, // configProc
581 baseStringProc
, // stringProc
584 &vobsub_obj
, // script_obj
585 baseFssProc
, // fssProc
588 ScriptFunctionDef textsub_func_defs
[] = {
589 { (ScriptFunctionPtr
)textsubScriptConfig
, "Config", "0si" },
593 CScriptObject textsub_obj
= {
594 NULL
, textsub_func_defs
597 struct FilterDefinition filterDef_textsub
= {
598 NULL
, NULL
, NULL
, // next, prev, module
600 "Adds subtitles from srt, sub, psb, smi, ssa, ass file formats.", // desc
602 NULL
, // private_data
603 sizeof(CVirtualDubFilter
**), // inst_data_size
604 textsubInitProc
, // initProc
605 baseDeinitProc
, // deinitProc
606 baseRunProc
, // runProc
607 baseParamProc
, // paramProc
608 baseConfigProc
, // configProc
609 baseStringProc
, // stringProc
612 &textsub_obj
, // script_obj
613 baseFssProc
, // fssProc
616 static FilterDefinition
* fd_vobsub
;
617 static FilterDefinition
* fd_textsub
;
619 extern "C" __declspec(dllexport
) int __cdecl
VirtualdubFilterModuleInit2(FilterModule
* fm
, const FilterFunctions
* ff
, int& vdfd_ver
, int& vdfd_compat
)
621 fd_vobsub
= ff
->addFilter(fm
, &filterDef_vobsub
, sizeof(FilterDefinition
));
625 fd_textsub
= ff
->addFilter(fm
, &filterDef_textsub
, sizeof(FilterDefinition
));
630 vdfd_ver
= VIRTUALDUB_FILTERDEF_VERSION
;
631 vdfd_compat
= VIRTUALDUB_FILTERDEF_COMPATIBLE
;
636 extern "C" __declspec(dllexport
) void __cdecl
VirtualdubFilterModuleDeinit(FilterModule
* fm
, const FilterFunctions
* ff
)
638 ff
->removeFilter(fd_textsub
);
639 ff
->removeFilter(fd_vobsub
);
645 // VirtualDub new plugin interface sdk 1.1
647 namespace VirtualDubNew
649 class CVirtualDubFilter
: virtual public CFilter
652 CVirtualDubFilter() {}
653 virtual ~CVirtualDubFilter() {}
655 virtual int RunProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
) {
657 dst
.type
= MSP_RGB32
;
661 dst
.pitch
= fa
->src
.pitch
;
662 dst
.bits
= (LPVOID
)fa
->src
.data
;
664 Render(dst
, 10000i64
* fa
->pfsi
->lSourceFrameMS
, (float)1000 / fa
->pfsi
->lMicrosecsPerFrame
);
669 virtual long ParamProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
) {
670 fa
->dst
.offset
= fa
->src
.offset
;
671 fa
->dst
.modulo
= fa
->src
.modulo
;
672 fa
->dst
.pitch
= fa
->src
.pitch
;
677 virtual int ConfigProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, VDXHWND hwnd
) = 0;
678 virtual void StringProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* str
) = 0;
679 virtual bool FssProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* buf
, int buflen
) = 0;
682 class CVobSubVirtualDubFilter
: public CVobSubFilter
, public CVirtualDubFilter
685 CVobSubVirtualDubFilter(CString fn
= _T(""))
686 : CVobSubFilter(fn
) {}
688 int ConfigProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, VDXHWND hwnd
) {
689 AFX_MANAGE_STATE(AfxGetStaticModuleState());
691 CFileDialog
fd(TRUE
, NULL
, GetFileName(), OFN_EXPLORER
| OFN_ENABLESIZING
| OFN_HIDEREADONLY
,
692 _T("VobSub files (*.idx;*.sub)|*.idx;*.sub||"), CWnd::FromHandle((HWND
)hwnd
), 0);
694 if (fd
.DoModal() != IDOK
) {
698 return Open(fd
.GetPathName()) ? 0 : 1;
701 void StringProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* str
) {
702 sprintf(str
, " (%s)", !GetFileName().IsEmpty() ? CStringA(GetFileName()) : " (empty)");
705 bool FssProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* buf
, int buflen
) {
706 CStringA
fn(GetFileName());
707 fn
.Replace("\\", "\\\\");
708 _snprintf_s(buf
, buflen
, buflen
, "Config(\"%s\")", fn
);
713 class CTextSubVirtualDubFilter
: public CTextSubFilter
, public CVirtualDubFilter
716 CTextSubVirtualDubFilter(CString fn
= _T(""), int CharSet
= DEFAULT_CHARSET
)
717 : CTextSubFilter(fn
, CharSet
) {}
719 int ConfigProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, VDXHWND hwnd
) {
720 AFX_MANAGE_STATE(AfxGetStaticModuleState());
722 /* off encoding changing */
724 const TCHAR formats
[] = _T("TextSub files (*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt)|*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt||");
725 CFileDialog
fd(TRUE
, NULL
, GetFileName(), OFN_EXPLORER
| OFN_ENABLESIZING
| OFN_HIDEREADONLY
| OFN_ENABLETEMPLATE
| OFN_ENABLEHOOK
,
726 formats
, CWnd::FromHandle((HWND
)hwnd
), sizeof(OPENFILENAME
));
727 UINT_PTR CALLBACK
OpenHookProc(HWND hDlg
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
);
729 fd
.m_pOFN
->hInstance
= AfxGetResourceHandle();
730 fd
.m_pOFN
->lpTemplateName
= MAKEINTRESOURCE(IDD_TEXTSUBOPENTEMPLATE
);
731 fd
.m_pOFN
->lpfnHook
= (LPOFNHOOKPROC
)OpenHookProc
;
732 fd
.m_pOFN
->lCustData
= (LPARAM
)DEFAULT_CHARSET
;
734 const TCHAR formats
[] = _T("TextSub files (*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt)|*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt||");
735 CFileDialog
fd(TRUE
, NULL
, GetFileName(), OFN_ENABLESIZING
| OFN_HIDEREADONLY
,
736 formats
, CWnd::FromHandle((HWND
)hwnd
), sizeof(OPENFILENAME
));
738 if (fd
.DoModal() != IDOK
) {
742 return Open(fd
.GetPathName(), fd
.m_pOFN
->lCustData
) ? 0 : 1;
745 void StringProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* str
) {
746 if (!GetFileName().IsEmpty()) {
747 sprintf(str
, " (%s, %d)", CStringA(GetFileName()), GetCharSet());
749 sprintf(str
, " (empty)");
753 bool FssProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* buf
, int buflen
) {
754 CStringA
fn(GetFileName());
755 fn
.Replace("\\", "\\\\");
756 _snprintf_s(buf
, buflen
, buflen
, "Config(\"%s\", %d)", fn
, GetCharSet());
761 int vobsubInitProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
)
763 return ((*(CVirtualDubFilter
**)fa
->filter_data
= DNew
CVobSubVirtualDubFilter()) == NULL
);
766 int textsubInitProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
)
768 return ((*(CVirtualDubFilter
**)fa
->filter_data
= DNew
CTextSubVirtualDubFilter()) == NULL
);
771 void baseDeinitProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
)
773 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
777 int baseRunProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
)
779 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
780 return f
? f
->RunProc(fa
, ff
) : 1;
783 long baseParamProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
)
785 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
786 return f
? f
->ParamProc(fa
, ff
) : 1;
789 int baseConfigProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, VDXHWND hwnd
)
791 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
792 return f
? f
->ConfigProc(fa
, ff
, hwnd
) : 1;
795 void baseStringProc(const VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* str
)
797 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
799 f
->StringProc(fa
, ff
, str
);
803 bool baseFssProc(VDXFilterActivation
* fa
, const VDXFilterFunctions
* ff
, char* buf
, int buflen
)
805 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
806 return f
? f
->FssProc(fa
, ff
, buf
, buflen
) : false;
809 void vobsubScriptConfig(IVDXScriptInterpreter
* isi
, void* lpVoid
, VDXScriptValue
* argv
, int argc
)
811 VDXFilterActivation
* fa
= (VDXFilterActivation
*)lpVoid
;
812 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
816 f
= DNew
CVobSubVirtualDubFilter(CString(*argv
[0].asString()));
817 *(CVirtualDubFilter
**)fa
->filter_data
= f
;
820 void textsubScriptConfig(IVDXScriptInterpreter
* isi
, void* lpVoid
, VDXScriptValue
* argv
, int argc
)
822 VDXFilterActivation
* fa
= (VDXFilterActivation
*)lpVoid
;
823 CVirtualDubFilter
* f
= *(CVirtualDubFilter
**)fa
->filter_data
;
827 f
= DNew
CTextSubVirtualDubFilter(CString(*argv
[0].asString()), argv
[1].asInt());
828 *(CVirtualDubFilter
**)fa
->filter_data
= f
;
831 VDXScriptFunctionDef vobsub_func_defs
[] = {
832 { (VDXScriptFunctionPtr
)vobsubScriptConfig
, "Config", "0s" },
836 VDXScriptObject vobsub_obj
= {
837 NULL
, vobsub_func_defs
840 struct VDXFilterDefinition filterDef_vobsub
= {
841 NULL
, NULL
, NULL
, // next, prev, module
843 "Adds subtitles from a vob sequence.", // desc
845 NULL
, // private_data
846 sizeof(CVirtualDubFilter
**), // inst_data_size
847 vobsubInitProc
, // initProc
848 baseDeinitProc
, // deinitProc
849 baseRunProc
, // runProc
850 baseParamProc
, // paramProc
851 baseConfigProc
, // configProc
852 baseStringProc
, // stringProc
855 &vobsub_obj
, // script_obj
856 baseFssProc
, // fssProc
859 VDXScriptFunctionDef textsub_func_defs
[] = {
860 { (VDXScriptFunctionPtr
)textsubScriptConfig
, "Config", "0si" },
864 VDXScriptObject textsub_obj
= {
865 NULL
, textsub_func_defs
868 struct VDXFilterDefinition filterDef_textsub
= {
869 NULL
, NULL
, NULL
, // next, prev, module
871 "Adds subtitles from srt, sub, psb, smi, ssa, ass file formats.", // desc
873 NULL
, // private_data
874 sizeof(CVirtualDubFilter
**), // inst_data_size
875 textsubInitProc
, // initProc
876 baseDeinitProc
, // deinitProc
877 baseRunProc
, // runProc
878 baseParamProc
, // paramProc
879 baseConfigProc
, // configProc
880 baseStringProc
, // stringProc
883 &textsub_obj
, // script_obj
884 baseFssProc
, // fssProc
887 static VDXFilterDefinition
* fd_vobsub
;
888 static VDXFilterDefinition
* fd_textsub
;
890 extern "C" __declspec(dllexport
) int __cdecl
VirtualdubFilterModuleInit2(VDXFilterModule
* fm
, const VDXFilterFunctions
* ff
, int& vdfd_ver
, int& vdfd_compat
)
892 if (((fd_vobsub
= ff
->addFilter(fm
, &filterDef_vobsub
, sizeof(VDXFilterDefinition
))) == NULL
)
893 || ((fd_textsub
= ff
->addFilter(fm
, &filterDef_textsub
, sizeof(VDXFilterDefinition
))) == NULL
)) {
897 vdfd_ver
= VIRTUALDUB_FILTERDEF_VERSION
;
898 vdfd_compat
= VIRTUALDUB_FILTERDEF_COMPATIBLE
;
903 extern "C" __declspec(dllexport
) void __cdecl
VirtualdubFilterModuleDeinit(VDXFilterModule
* fm
, const VDXFilterFunctions
* ff
)
905 ff
->removeFilter(fd_textsub
);
906 ff
->removeFilter(fd_vobsub
);
911 // Avisynth interface
916 #include "avisynth/avisynth1.h"
918 class CAvisynthFilter
: public GenericVideoFilter
, virtual public CFilter
921 CAvisynthFilter(PClip c
, IScriptEnvironment
* env
) : GenericVideoFilter(c
) {}
923 PVideoFrame __stdcall
GetFrame(int n
, IScriptEnvironment
* env
) {
924 PVideoFrame frame
= child
->GetFrame(n
, env
);
926 env
->MakeWritable(&frame
);
931 dst
.pitch
= frame
->GetPitch();
932 dst
.bits
= (void**)frame
->GetWritePtr();
933 dst
.bpp
= vi
.BitsPerPixel();
935 vi
.IsRGB32() ? (env
->GetVar("RGBA").AsBool() ? MSP_RGBA
: MSP_RGB32
) :
936 vi
.IsRGB24() ? MSP_RGB24
:
937 vi
.IsYUY2() ? MSP_YUY2
:
940 float fps
= m_fps
> 0 ? m_fps
: (float)vi
.fps_numerator
/ vi
.fps_denominator
;
942 Render(dst
, (REFERENCE_TIME
)(10000000i64
* n
/ fps
), fps
);
948 class CVobSubAvisynthFilter
: public CVobSubFilter
, public CAvisynthFilter
951 CVobSubAvisynthFilter(PClip c
, const char* fn
, IScriptEnvironment
* env
)
952 : CVobSubFilter(CString(fn
))
953 , CAvisynthFilter(c
, env
) {
954 if (!m_pSubPicProvider
) {
955 env
->ThrowError("VobSub: Can't open \"%s\"", fn
);
960 AVSValue __cdecl
VobSubCreateS(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
962 return (DNew
CVobSubAvisynthFilter(args
[0].AsClip(), args
[1].AsString(), env
));
965 class CTextSubAvisynthFilter
: public CTextSubFilter
, public CAvisynthFilter
968 CTextSubAvisynthFilter(PClip c
, IScriptEnvironment
* env
, const char* fn
, int CharSet
= DEFAULT_CHARSET
, float fps
= -1)
969 : CTextSubFilter(CString(fn
), CharSet
, fps
)
970 , CAvisynthFilter(c
, env
) {
971 if (!m_pSubPicProvider
) {
972 env
->ThrowError("TextSub: Can't open \"%s\"", fn
);
977 AVSValue __cdecl
TextSubCreateS(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
979 return (DNew
CTextSubAvisynthFilter(args
[0].AsClip(), env
, args
[1].AsString()));
982 AVSValue __cdecl
TextSubCreateSI(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
984 return (DNew
CTextSubAvisynthFilter(args
[0].AsClip(), env
, args
[1].AsString(), args
[2].AsInt()));
987 AVSValue __cdecl
TextSubCreateSIF(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
989 return (DNew
CTextSubAvisynthFilter(args
[0].AsClip(), env
, args
[1].AsString(), args
[2].AsInt(), (float)args
[3].AsFloat()));
992 AVSValue __cdecl
MaskSubCreateSIIFI(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
994 AVSValue
rgb32("RGB32");
1002 AVSValue
value(tab
, 5);
1003 const char* nom
[5] = {
1010 AVSValue
clip(env
->Invoke("Blackness", value
, nom
));
1011 env
->SetVar(env
->SaveString("RGBA"), true);
1012 return (DNew
CTextSubAvisynthFilter(clip
.AsClip(), env
, args
[0].AsString()));
1015 extern "C" __declspec(dllexport
) const char* __stdcall
AvisynthPluginInit(IScriptEnvironment
* env
)
1017 env
->AddFunction("VobSub", "cs", VobSubCreateS
, 0);
1018 env
->AddFunction("TextSub", "cs", TextSubCreateS
, 0);
1019 env
->AddFunction("TextSub", "csi", TextSubCreateSI
, 0);
1020 env
->AddFunction("TextSub", "csif", TextSubCreateSIF
, 0);
1021 env
->AddFunction("MaskSub", "siifi", MaskSubCreateSIIFI
, 0);
1022 env
->SetVar(env
->SaveString("RGBA"), false);
1027 namespace AviSynth25
1029 #include "avisynth/avisynth25.h"
1031 static bool s_fSwapUV
= false;
1033 class CAvisynthFilter
: public GenericVideoFilter
, virtual public CFilter
1038 CAvisynthFilter(PClip c
, IScriptEnvironment
* env
, VFRTranslator
* _vfr
= 0) : GenericVideoFilter(c
), vfr(_vfr
) {}
1040 PVideoFrame __stdcall
GetFrame(int n
, IScriptEnvironment
* env
) {
1041 PVideoFrame frame
= child
->GetFrame(n
, env
);
1043 env
->MakeWritable(&frame
);
1048 dst
.pitch
= frame
->GetPitch();
1049 dst
.pitchUV
= frame
->GetPitch(PLANAR_U
);
1050 dst
.bits
= (void**)frame
->GetWritePtr();
1051 dst
.bitsU
= frame
->GetWritePtr(PLANAR_U
);
1052 dst
.bitsV
= frame
->GetWritePtr(PLANAR_V
);
1053 dst
.bpp
= dst
.pitch
/ dst
.w
* 8; //vi.BitsPerPixel();
1055 vi
.IsRGB32() ? (env
->GetVar("RGBA").AsBool() ? MSP_RGBA
: MSP_RGB32
) :
1056 vi
.IsRGB24() ? MSP_RGB24
:
1057 vi
.IsYUY2() ? MSP_YUY2
:
1058 /*vi.IsYV12()*/ vi
.pixel_type
== VideoInfo::CS_YV12
? (s_fSwapUV
? MSP_IYUV
: MSP_YV12
) :
1059 /*vi.IsIYUV()*/ vi
.pixel_type
== VideoInfo::CS_IYUV
? (s_fSwapUV
? MSP_YV12
: MSP_IYUV
) :
1062 float fps
= m_fps
> 0 ? m_fps
: (float)vi
.fps_numerator
/ vi
.fps_denominator
;
1064 REFERENCE_TIME timestamp
;
1067 timestamp
= (REFERENCE_TIME
)(10000000i64
* n
/ fps
);
1069 timestamp
= (REFERENCE_TIME
)(10000000 * vfr
->TimeStampFromFrameNumber(n
));
1072 Render(dst
, timestamp
, fps
);
1078 class CVobSubAvisynthFilter
: public CVobSubFilter
, public CAvisynthFilter
1081 CVobSubAvisynthFilter(PClip c
, const char* fn
, IScriptEnvironment
* env
)
1082 : CVobSubFilter(CString(fn
))
1083 , CAvisynthFilter(c
, env
) {
1084 if (!m_pSubPicProvider
) {
1085 env
->ThrowError("VobSub: Can't open \"%s\"", fn
);
1090 AVSValue __cdecl
VobSubCreateS(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
1092 return (DNew
CVobSubAvisynthFilter(args
[0].AsClip(), args
[1].AsString(), env
));
1095 class CTextSubAvisynthFilter
: public CTextSubFilter
, public CAvisynthFilter
1098 CTextSubAvisynthFilter(PClip c
, IScriptEnvironment
* env
, const char* fn
, int CharSet
= DEFAULT_CHARSET
, float fps
= -1, VFRTranslator
* vfr
= 0) //vfr patch
1099 : CTextSubFilter(CString(fn
), CharSet
, fps
)
1100 , CAvisynthFilter(c
, env
, vfr
) {
1101 if (!m_pSubPicProvider
) {
1102 env
->ThrowError("TextSub: Can't open \"%s\"", fn
);
1107 AVSValue __cdecl
TextSubCreateGeneral(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
1109 if (!args
[1].Defined()) {
1110 env
->ThrowError("TextSub: You must specify a subtitle file to use");
1112 VFRTranslator
* vfr
= 0;
1113 if (args
[4].Defined()) {
1114 vfr
= GetVFRTranslator(args
[4].AsString());
1117 return (DNew
CTextSubAvisynthFilter(
1121 args
[2].AsInt(DEFAULT_CHARSET
),
1122 (float)args
[3].AsFloat(-1),
1126 AVSValue __cdecl
TextSubSwapUV(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)
1128 s_fSwapUV
= args
[0].AsBool(false);
1132 AVSValue __cdecl
MaskSubCreate(AVSValue args
, void* user_data
, IScriptEnvironment
* env
)/*SIIFI*/
1134 if (!args
[0].Defined()) {
1135 env
->ThrowError("MaskSub: You must specify a subtitle file to use");
1137 if (!args
[3].Defined() && !args
[6].Defined()) {
1138 env
->ThrowError("MaskSub: You must specify either FPS or a VFR timecodes file");
1140 VFRTranslator
* vfr
= 0;
1141 if (args
[6].Defined()) {
1142 vfr
= GetVFRTranslator(args
[6].AsString());
1145 AVSValue
rgb32("RGB32");
1146 AVSValue
fps(args
[3].AsFloat(25));
1154 AVSValue
value(tab
, 5);
1155 const char* nom
[5] = {
1162 AVSValue
clip(env
->Invoke("Blackness", value
, nom
));
1163 env
->SetVar(env
->SaveString("RGBA"), true);
1164 //return (DNew CTextSubAvisynthFilter(clip.AsClip(), env, args[0].AsString()));
1165 return (DNew
CTextSubAvisynthFilter(
1169 args
[5].AsInt(DEFAULT_CHARSET
),
1170 (float)args
[3].AsFloat(-1),
1174 extern "C" __declspec(dllexport
) const char* __stdcall
AvisynthPluginInit2(IScriptEnvironment
* env
)
1176 env
->AddFunction("VobSub", "cs", VobSubCreateS
, 0);
1177 env
->AddFunction("TextSub", "c[file]s[charset]i[fps]f[vfr]s", TextSubCreateGeneral
, 0);
1178 env
->AddFunction("TextSubSwapUV", "b", TextSubSwapUV
, 0);
1179 env
->AddFunction("MaskSub", "[file]s[width]i[height]i[fps]f[length]i[charset]i[vfr]s", MaskSubCreate
, 0);
1180 env
->SetVar(env
->SaveString("RGBA"), false);
1187 UINT_PTR CALLBACK
OpenHookProc(HWND hDlg
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
)
1191 OPENFILENAME
* ofn
= ((OFNOTIFY
*)lParam
)->lpOFN
;
1193 if (((NMHDR
*)lParam
)->code
== CDN_FILEOK
) {
1194 ofn
->lCustData
= (LPARAM
)CharSetList
[SendMessage(GetDlgItem(hDlg
, IDC_COMBO1
), CB_GETCURSEL
, 0, 0)];
1200 case WM_INITDIALOG
: {
1201 SetWindowLongPtr(hDlg
, GWLP_USERDATA
, lParam
);
1203 for (ptrdiff_t i
= 0; i
< CharSetLen
; i
++) {
1205 s
.Format(_T("%s (%d)"), CharSetNames
[i
], CharSetList
[i
]);
1206 SendMessage(GetDlgItem(hDlg
, IDC_COMBO1
), CB_ADDSTRING
, 0, (LPARAM
)(LPCTSTR
)s
);
1207 if (CharSetList
[i
] == (int)((OPENFILENAME
*)lParam
)->lCustData
) {
1208 SendMessage(GetDlgItem(hDlg
, IDC_COMBO1
), CB_SETCURSEL
, i
, 0);