X64 transport [Part 5] (Update plugins.cpp)
[xy_vsfilter.git] / src / filters / transform / vsfilter / plugins.cpp
blob1160a861e22c44fe6f0ac319aa3ce848f022ae72
1 /*
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)
8 * any later version.
9 *
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
22 #include "stdafx.h"
23 #include <afxdlgs.h>
24 #include <atlpath.h>
25 #include "resource.h"
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"
34 #include "vfr.h"
36 #ifndef _WIN64
37 #include "vd2/extras/FilterSDK/VirtualDub.h"
38 #else
39 #include "vd2/plugin/vdplugin.h"
40 #include "vd2/plugin/vdvideofilt.h"
41 #endif
43 using namespace DirectVobSubXyOptions;
46 // Generic interface
49 namespace Plugin
52 class CFilter : public CUnknown, public CDirectVobSub, public CAMThread, public CCritSec
54 private:
55 CString m_fn;
57 protected:
58 float m_fps;
59 CCritSec m_csSubLock;
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;
67 bool m_fLazyInit;
68 public:
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;
89 CAMThread::Create();
91 virtual ~CFilter() {CAMThread::CallWorker(0);}
93 DECLARE_IUNKNOWN;
94 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
96 CheckPointer(ppv, E_POINTER);
98 return QI(IDirectVobSub)
99 QI(IDirectVobSub2)
100 QI(IDirectVobSubXy)
101 QI(IFilterVersion)
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;
119 break;
120 case CSimpleTextSubtitle::YCbCrMatrix_BT709:
121 yuv_matrix = ColorConvTable::BT709;
122 break;
123 case CSimpleTextSubtitle::YCbCrMatrix_AUTO:
124 default:
125 yuv_matrix = ColorConvTable::BT601;
126 break;
129 else
131 switch(m_xy_int_opt[INT_COLOR_SPACE])
133 case CDirectVobSub::BT_601:
134 yuv_matrix = ColorConvTable::BT601;
135 break;
136 case CDirectVobSub::BT_709:
137 yuv_matrix = ColorConvTable::BT709;
138 break;
139 case CDirectVobSub::GUESS:
140 yuv_matrix = (dst.w > m_bt601Width || dst.h > m_bt601Height) ? ColorConvTable::BT709 : ColorConvTable::BT601;
141 break;
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;
151 break;
152 case CSimpleTextSubtitle::YCbCrRange_TV:
153 yuv_range = ColorConvTable::RANGE_TV;
154 break;
155 case CSimpleTextSubtitle::YCbCrRange_AUTO:
156 default:
157 yuv_range = ColorConvTable::RANGE_TV;
158 break;
161 else
163 switch(m_xy_int_opt[INT_YUV_RANGE])
165 case CDirectVobSub::YuvRange_TV:
166 yuv_range = ColorConvTable::RANGE_TV;
167 break;
168 case CDirectVobSub::YuvRange_PC:
169 yuv_range = ColorConvTable::RANGE_PC;
170 break;
171 case CDirectVobSub::YuvRange_Auto:
172 yuv_range = ColorConvTable::RANGE_TV;
173 break;
177 ColorConvTable::SetDefaultConvType(yuv_matrix, yuv_range);
180 bool Render(SubPicDesc& dst, REFERENCE_TIME rt, float fps)
182 if(!m_pSubPicProvider)
183 return(false);
185 if(!m_fLazyInit)
187 m_fLazyInit = true;
189 SetYuvMatrix(dst);
191 CSize size(dst.w, dst.h);
193 if(!m_simple_provider)
195 HRESULT hr;
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;
199 return(false);
201 XySetSize(SIZE_ORIGINAL_VIDEO, size);
204 if(m_SubPicProviderId != (DWORD_PTR)(ISubPicProvider*)m_pSubPicProvider)
206 CSize playres(0,0);
207 CLSID clsid;
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))
223 return(false);
225 if(dst.type == MSP_RGB32 || dst.type == MSP_RGB24 || dst.type == MSP_RGB16 || dst.type == MSP_RGB15)
226 dst.h = -dst.h;
227 pSubPic->AlphaBlt(&dst);
229 return(true);
232 DWORD ThreadProc()
234 SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST);
236 CAtlArray<HANDLE> handles;
237 handles.Add(GetRequestHandle());
239 CString fn = GetFileName();
240 CFileStatus fs;
241 fs.m_mtime = 0;
242 CFileGetStatus(fn, fs);
244 while(1)
246 DWORD i = WaitForMultipleObjects(handles.GetCount(), handles.GetData(), FALSE, 1000);
248 if(WAIT_OBJECT_0 == i)
250 Reply(S_OK);
251 break;
253 else if(WAIT_OBJECT_0 + 1 >= i && i <= WAIT_OBJECT_0 + handles.GetCount())
255 if(FindNextChangeNotification(handles[i - WAIT_OBJECT_0]))
257 CFileStatus fs2;
258 fs2.m_mtime = 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();
277 if(fn != fn2)
279 CPath p(fn2);
280 p.RemoveFileSpec();
281 HANDLE h = FindFirstChangeNotification(p, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
282 if(h != INVALID_HANDLE_VALUE)
284 fn = fn2;
285 handles.SetCount(1);
286 handles.Add(h);
290 else // if(WAIT_ABANDONED_0 == i || WAIT_FAILED == i)
292 break;
296 m_hThread = 0;
298 for(int i = 1; i < handles.GetCount(); i++)
299 FindCloseChangeNotification(handles[i]);
301 return 0;
305 class CVobSubFilter : virtual public CFilter
307 public:
308 CVobSubFilter(CString fn = _T(""))
310 if(!fn.IsEmpty()) Open(fn);
313 bool Open(CString fn)
315 SetFileName(_T(""));
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
331 int m_CharSet;
333 public:
334 CTextSubFilter(CString fn = _T(""), int CharSet = DEFAULT_CHARSET, float fps = -1)
335 : m_CharSet(CharSet)
337 m_fps = fps;
338 if(!fn.IsEmpty()) Open(fn, CharSet);
341 int GetCharSet() {return(m_CharSet);}
343 bool Open(CString fn, int CharSet = DEFAULT_CHARSET)
345 SetFileName(_T(""));
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;
375 #ifndef _WIN64
377 // old VirtualDub interface
380 namespace VirtualDub
382 class CVirtualDubFilter : virtual public CFilter
384 public:
385 CVirtualDubFilter() {}
386 virtual ~CVirtualDubFilter() {}
388 virtual int RunProc(const FilterActivation* fa, const FilterFunctions* ff) {
389 SubPicDesc dst;
390 dst.type = MSP_RGB32;
391 dst.w = fa->src.w;
392 dst.h = fa->src.h;
393 dst.bpp = 32;
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);
399 return 0;
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;
407 return 0;
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
417 public:
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) {
428 return 1;
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);
442 return true;
446 class CTextSubVirtualDubFilter : public CTextSubFilter, public CVirtualDubFilter
448 public:
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) {
466 return 1;
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());
475 } else {
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());
484 return true;
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;
503 SAFE_DELETE(f);
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;
527 if (f) {
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;
542 if (f) {
543 delete f;
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;
553 if (f) {
554 delete f;
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" },
562 { NULL },
565 CScriptObject vobsub_obj = {
566 NULL, vobsub_func_defs
569 struct FilterDefinition filterDef_vobsub = {
570 NULL, NULL, NULL, // next, prev, module
571 "VobSub", // name
572 "Adds subtitles from a vob sequence.", // desc
573 "Gabest", // maker
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
582 NULL, // startProc
583 NULL, // endProc
584 &vobsub_obj, // script_obj
585 baseFssProc, // fssProc
588 ScriptFunctionDef textsub_func_defs[] = {
589 { (ScriptFunctionPtr)textsubScriptConfig, "Config", "0si" },
590 { NULL },
593 CScriptObject textsub_obj = {
594 NULL, textsub_func_defs
597 struct FilterDefinition filterDef_textsub = {
598 NULL, NULL, NULL, // next, prev, module
599 "TextSub", // name
600 "Adds subtitles from srt, sub, psb, smi, ssa, ass file formats.", // desc
601 "Gabest", // maker
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
610 NULL, // startProc
611 NULL, // endProc
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));
622 if (!fd_vobsub) {
623 return 1;
625 fd_textsub = ff->addFilter(fm, &filterDef_textsub, sizeof(FilterDefinition));
626 if (!fd_textsub) {
627 return 1;
630 vdfd_ver = VIRTUALDUB_FILTERDEF_VERSION;
631 vdfd_compat = VIRTUALDUB_FILTERDEF_COMPATIBLE;
633 return 0;
636 extern "C" __declspec(dllexport) void __cdecl VirtualdubFilterModuleDeinit(FilterModule* fm, const FilterFunctions* ff)
638 ff->removeFilter(fd_textsub);
639 ff->removeFilter(fd_vobsub);
641 }/**/
643 #else
645 // VirtualDub new plugin interface sdk 1.1
647 namespace VirtualDubNew
649 class CVirtualDubFilter : virtual public CFilter
651 public:
652 CVirtualDubFilter() {}
653 virtual ~CVirtualDubFilter() {}
655 virtual int RunProc(const VDXFilterActivation* fa, const VDXFilterFunctions* ff) {
656 SubPicDesc dst;
657 dst.type = MSP_RGB32;
658 dst.w = fa->src.w;
659 dst.h = fa->src.h;
660 dst.bpp = 32;
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);
666 return 0;
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;
674 return 0;
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
684 public:
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) {
695 return 1;
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);
709 return true;
713 class CTextSubVirtualDubFilter : public CTextSubFilter, public CVirtualDubFilter
715 public:
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 */
723 #ifndef _DEBUG
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;
733 #else
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));
737 #endif
738 if (fd.DoModal() != IDOK) {
739 return 1;
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());
748 } else {
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());
757 return true;
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;
774 SAFE_DELETE(f);
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;
798 if (f) {
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;
813 if (f) {
814 delete f;
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;
824 if (f) {
825 delete f;
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" },
833 { NULL },
836 VDXScriptObject vobsub_obj = {
837 NULL, vobsub_func_defs
840 struct VDXFilterDefinition filterDef_vobsub = {
841 NULL, NULL, NULL, // next, prev, module
842 "VobSub", // name
843 "Adds subtitles from a vob sequence.", // desc
844 "Gabest", // maker
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
853 NULL, // startProc
854 NULL, // endProc
855 &vobsub_obj, // script_obj
856 baseFssProc, // fssProc
859 VDXScriptFunctionDef textsub_func_defs[] = {
860 { (VDXScriptFunctionPtr)textsubScriptConfig, "Config", "0si" },
861 { NULL },
864 VDXScriptObject textsub_obj = {
865 NULL, textsub_func_defs
868 struct VDXFilterDefinition filterDef_textsub = {
869 NULL, NULL, NULL, // next, prev, module
870 "TextSub", // name
871 "Adds subtitles from srt, sub, psb, smi, ssa, ass file formats.", // desc
872 "Gabest", // maker
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
881 NULL, // startProc
882 NULL, // endProc
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)) {
894 return 1;
897 vdfd_ver = VIRTUALDUB_FILTERDEF_VERSION;
898 vdfd_compat = VIRTUALDUB_FILTERDEF_COMPATIBLE;
900 return 0;
903 extern "C" __declspec(dllexport) void __cdecl VirtualdubFilterModuleDeinit(VDXFilterModule* fm, const VDXFilterFunctions* ff)
905 ff->removeFilter(fd_textsub);
906 ff->removeFilter(fd_vobsub);
909 #endif
911 // Avisynth interface
914 namespace AviSynth1
916 #include "avisynth/avisynth1.h"
918 class CAvisynthFilter : public GenericVideoFilter, virtual public CFilter
920 public:
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);
928 SubPicDesc dst;
929 dst.w = vi.width;
930 dst.h = vi.height;
931 dst.pitch = frame->GetPitch();
932 dst.bits = (void**)frame->GetWritePtr();
933 dst.bpp = vi.BitsPerPixel();
934 dst.type =
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);
944 return frame;
948 class CVobSubAvisynthFilter : public CVobSubFilter, public CAvisynthFilter
950 public:
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
967 public:
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");
995 AVSValue tab[5] = {
996 args[1],
997 args[2],
998 args[3],
999 args[4],
1000 rgb32
1002 AVSValue value(tab, 5);
1003 const char* nom[5] = {
1004 "width",
1005 "height",
1006 "fps",
1007 "length",
1008 "pixel_type"
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);
1023 return NULL;
1027 namespace AviSynth25
1029 #include "avisynth/avisynth25.h"
1031 static bool s_fSwapUV = false;
1033 class CAvisynthFilter : public GenericVideoFilter, virtual public CFilter
1035 public:
1036 VFRTranslator* vfr;
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);
1045 SubPicDesc dst;
1046 dst.w = vi.width;
1047 dst.h = vi.height;
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();
1054 dst.type =
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;
1066 if (!vfr) {
1067 timestamp = (REFERENCE_TIME)(10000000i64 * n / fps);
1068 } else {
1069 timestamp = (REFERENCE_TIME)(10000000 * vfr->TimeStampFromFrameNumber(n));
1072 Render(dst, timestamp, fps);
1074 return frame;
1078 class CVobSubAvisynthFilter : public CVobSubFilter, public CAvisynthFilter
1080 public:
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
1097 public:
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(
1118 args[0].AsClip(),
1119 env,
1120 args[1].AsString(),
1121 args[2].AsInt(DEFAULT_CHARSET),
1122 (float)args[3].AsFloat(-1),
1123 vfr));
1126 AVSValue __cdecl TextSubSwapUV(AVSValue args, void* user_data, IScriptEnvironment* env)
1128 s_fSwapUV = args[0].AsBool(false);
1129 return AVSValue();
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));
1147 AVSValue tab[6] = {
1148 args[1],
1149 args[2],
1150 args[3],
1151 args[4],
1152 rgb32
1154 AVSValue value(tab, 5);
1155 const char* nom[5] = {
1156 "width",
1157 "height",
1158 "fps",
1159 "length",
1160 "pixel_type"
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(
1166 clip.AsClip(),
1167 env,
1168 args[0].AsString(),
1169 args[5].AsInt(DEFAULT_CHARSET),
1170 (float)args[3].AsFloat(-1),
1171 vfr));
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);
1181 return NULL;
1187 UINT_PTR CALLBACK OpenHookProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1189 switch (uiMsg) {
1190 case WM_NOTIFY: {
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)];
1197 break;
1200 case WM_INITDIALOG: {
1201 SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
1203 for (ptrdiff_t i = 0; i < CharSetLen; i++) {
1204 CString s;
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);
1212 break;
1215 default:
1216 break;
1219 return FALSE;