Changing to new interface. [PART 1]
[xy_vsfilter.git] / src / filters / transform / vsfilter / plugins.cpp
blob84efa4499afdf2a60b3c60cd5998d6142056e6f3
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/SubPicQueueImpl.h"
31 #include "../../../subpic/color_conv_table.h"
32 #include "../../../subpic/SimpleSubPicWrapper.h"
33 #include "DirectVobSub.h"
34 #include "vfr.h"
37 // Generic interface
40 namespace Plugin
43 class CFilter : public CUnknown, public CDirectVobSub, public CAMThread, public CCritSec
45 private:
46 CString m_fn;
48 protected:
49 float m_fps;
50 CCritSec m_csSubLock;
51 CComPtr<ISubPicQueue> m_pSubPicQueue;
52 CComPtr<ISubPicProvider> m_pSubPicProvider;
53 DWORD_PTR m_SubPicProviderId;
55 CSimpleTextSubtitle::YCbCrMatrix m_script_selected_yuv;
56 CSimpleTextSubtitle::YCbCrRange m_script_selected_range;
58 bool m_fLazyInit;
59 public:
60 CFilter() : CUnknown(NAME("CFilter"), NULL), m_fps(-1), m_SubPicProviderId(0), m_fLazyInit(false)
62 //fix me: should not do init here
63 CacheManager::GetPathDataMruCache()->SetMaxItemNum(m_path_data_cache_max_item_num);
64 CacheManager::GetScanLineData2MruCache()->SetMaxItemNum(m_scan_line_data_cache_max_item_num);
65 CacheManager::GetOverlayNoBlurMruCache()->SetMaxItemNum(m_overlay_no_blur_cache_max_item_num);
66 CacheManager::GetOverlayMruCache()->SetMaxItemNum(m_overlay_cache_max_item_num);
67 SubpixelPositionControler::GetGlobalControler().SetSubpixelLevel( static_cast<SubpixelPositionControler::SUBPIXEL_LEVEL>(m_subpixel_pos_level) );
69 m_script_selected_yuv = CSimpleTextSubtitle::YCbCrMatrix_AUTO;
70 m_script_selected_range = CSimpleTextSubtitle::YCbCrRange_AUTO;
72 CAMThread::Create();
74 virtual ~CFilter() {CAMThread::CallWorker(0);}
76 DECLARE_IUNKNOWN;
77 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
79 CheckPointer(ppv, E_POINTER);
81 return QI(IDirectVobSub)
82 QI(IDirectVobSub2)
83 QI(IDirectVobSubXy)
84 QI(IFilterVersion)
85 __super::NonDelegatingQueryInterface(riid, ppv);
88 CString GetFileName() {CAutoLock cAutoLock(this); return m_fn;}
89 void SetFileName(CString fn) {CAutoLock cAutoLock(this); m_fn = fn;}
91 void SetYuvMatrix(SubPicDesc& dst)
93 ColorConvTable::YuvMatrixType yuv_matrix = ColorConvTable::BT601;
94 ColorConvTable::YuvRangeType yuv_range = ColorConvTable::RANGE_TV;
96 if ( m_colorSpace==CDirectVobSub::YuvMatrix_AUTO )
98 switch(m_script_selected_yuv)
100 case CSimpleTextSubtitle::YCbCrMatrix_BT601:
101 yuv_matrix = ColorConvTable::BT601;
102 break;
103 case CSimpleTextSubtitle::YCbCrMatrix_BT709:
104 yuv_matrix = ColorConvTable::BT709;
105 break;
106 case CSimpleTextSubtitle::YCbCrMatrix_AUTO:
107 default:
108 yuv_matrix = ColorConvTable::BT601;
109 break;
112 else
114 switch(m_colorSpace)
116 case CDirectVobSub::BT_601:
117 yuv_matrix = ColorConvTable::BT601;
118 break;
119 case CDirectVobSub::BT_709:
120 yuv_matrix = ColorConvTable::BT709;
121 break;
122 case CDirectVobSub::GUESS:
123 yuv_matrix = (dst.w > m_bt601Width || dst.h > m_bt601Height) ? ColorConvTable::BT709 : ColorConvTable::BT601;
124 break;
128 if( m_yuvRange==CDirectVobSub::YuvRange_Auto )
130 switch(m_script_selected_range)
132 case CSimpleTextSubtitle::YCbCrRange_PC:
133 yuv_range = ColorConvTable::RANGE_PC;
134 break;
135 case CSimpleTextSubtitle::YCbCrRange_TV:
136 yuv_range = ColorConvTable::RANGE_TV;
137 break;
138 case CSimpleTextSubtitle::YCbCrRange_AUTO:
139 default:
140 yuv_range = ColorConvTable::RANGE_TV;
141 break;
144 else
146 switch(m_yuvRange)
148 case CDirectVobSub::YuvRange_TV:
149 yuv_range = ColorConvTable::RANGE_TV;
150 break;
151 case CDirectVobSub::YuvRange_PC:
152 yuv_range = ColorConvTable::RANGE_PC;
153 break;
154 case CDirectVobSub::YuvRange_Auto:
155 yuv_range = ColorConvTable::RANGE_TV;
156 break;
160 ColorConvTable::SetDefaultConvType(yuv_matrix, yuv_range);
163 bool Render(SubPicDesc& dst, REFERENCE_TIME rt, float fps)
165 if(!m_pSubPicProvider)
166 return(false);
168 if(!m_fLazyInit)
170 m_fLazyInit = true;
172 SetYuvMatrix(dst);
174 CSize size(dst.w, dst.h);
176 if(!m_pSubPicQueue)
178 CComPtr<ISubPicExAllocator> pAllocator = new CPooledSubPicAllocator(dst.type, size, 2);
180 HRESULT hr;
181 if(!(m_pSubPicQueue = new CSubPicQueueNoThread(pAllocator, &hr)) || FAILED(hr))
183 m_pSubPicQueue = NULL;
184 return(false);
188 if(m_SubPicProviderId != (DWORD_PTR)(ISubPicProvider*)m_pSubPicProvider)
190 m_pSubPicQueue->SetSubPicProvider(m_pSubPicProvider);
191 m_SubPicProviderId = (DWORD_PTR)(ISubPicProvider*)m_pSubPicProvider;
194 CComPtr<ISubPic> pSubPic;
195 if(!m_pSubPicQueue->LookupSubPic(rt, &pSubPic))
196 return(false);
198 if(dst.type == MSP_RGB32 || dst.type == MSP_RGB24 || dst.type == MSP_RGB16 || dst.type == MSP_RGB15)
199 dst.h = -dst.h;
200 SimpleSubPicWrapper simple_subpic(pSubPic);
201 simple_subpic.AlphaBlt(&dst);
203 return(true);
206 DWORD ThreadProc()
208 SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST);
210 CAtlArray<HANDLE> handles;
211 handles.Add(GetRequestHandle());
213 CString fn = GetFileName();
214 CFileStatus fs;
215 fs.m_mtime = 0;
216 CFileGetStatus(fn, fs);
218 while(1)
220 DWORD i = WaitForMultipleObjects(handles.GetCount(), handles.GetData(), FALSE, 1000);
222 if(WAIT_OBJECT_0 == i)
224 Reply(S_OK);
225 break;
227 else if(WAIT_OBJECT_0 + 1 >= i && i <= WAIT_OBJECT_0 + handles.GetCount())
229 if(FindNextChangeNotification(handles[i - WAIT_OBJECT_0]))
231 CFileStatus fs2;
232 fs2.m_mtime = 0;
233 CFileGetStatus(fn, fs2);
235 if(fs.m_mtime < fs2.m_mtime)
237 fs.m_mtime = fs2.m_mtime;
239 if(CComQIPtr<ISubStream> pSubStream = m_pSubPicProvider)
241 CAutoLock cAutoLock(&m_csSubLock);
242 pSubStream->Reload();
247 else if(WAIT_TIMEOUT == i)
249 CString fn2 = GetFileName();
251 if(fn != fn2)
253 CPath p(fn2);
254 p.RemoveFileSpec();
255 HANDLE h = FindFirstChangeNotification(p, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
256 if(h != INVALID_HANDLE_VALUE)
258 fn = fn2;
259 handles.SetCount(1);
260 handles.Add(h);
264 else // if(WAIT_ABANDONED_0 == i || WAIT_FAILED == i)
266 break;
270 m_hThread = 0;
272 for(int i = 1; i < handles.GetCount(); i++)
273 FindCloseChangeNotification(handles[i]);
275 return 0;
279 class CVobSubFilter : virtual public CFilter
281 public:
282 CVobSubFilter(CString fn = _T(""))
284 if(!fn.IsEmpty()) Open(fn);
287 bool Open(CString fn)
289 SetFileName(_T(""));
290 m_pSubPicProvider = NULL;
292 if(CVobSubFile* vsf = new CVobSubFile(&m_csSubLock))
294 m_pSubPicProvider = (ISubPicProvider*)vsf;
295 if(vsf->Open(CString(fn))) SetFileName(fn);
296 else m_pSubPicProvider = NULL;
299 return !!m_pSubPicProvider;
303 class CTextSubFilter : virtual public CFilter
305 int m_CharSet;
307 public:
308 CTextSubFilter(CString fn = _T(""), int CharSet = DEFAULT_CHARSET, float fps = -1)
309 : m_CharSet(CharSet)
311 m_fps = fps;
312 if(!fn.IsEmpty()) Open(fn, CharSet);
315 int GetCharSet() {return(m_CharSet);}
317 bool Open(CString fn, int CharSet = DEFAULT_CHARSET)
319 SetFileName(_T(""));
320 m_pSubPicProvider = NULL;
322 if(!m_pSubPicProvider)
324 if(ssf::CRenderer* ssf = new ssf::CRenderer(&m_csSubLock))
326 m_pSubPicProvider = (ISubPicProvider*)ssf;
327 if(ssf->Open(CString(fn))) SetFileName(fn);
328 else m_pSubPicProvider = NULL;
332 if(!m_pSubPicProvider)
334 if(CRenderedTextSubtitle* rts = new CRenderedTextSubtitle(&m_csSubLock))
336 m_pSubPicProvider = (ISubPicProvider*)rts;
337 if(rts->Open(CString(fn), CharSet)) SetFileName(fn);
338 else m_pSubPicProvider = NULL;
340 m_script_selected_yuv = rts->m_eYCbCrMatrix;
341 m_script_selected_range = rts->m_eYCbCrRange;
345 return !!m_pSubPicProvider;
350 // VirtualDub interface
353 namespace VirtualDub
355 #include "..\..\..\..\include\VirtualDub\VirtualDub.h"
357 class CVirtualDubFilter : virtual public CFilter
359 public:
360 CVirtualDubFilter() {}
361 virtual ~CVirtualDubFilter() {}
363 virtual int RunProc(const FilterActivation* fa, const FilterFunctions* ff)
365 SubPicDesc dst;
366 dst.type = MSP_RGB32;
367 dst.w = fa->src.w;
368 dst.h = fa->src.h;
369 dst.bpp = 32;
370 dst.pitch = fa->src.pitch;
371 dst.bits = (LPVOID)fa->src.data;
373 Render(dst, 10000i64*fa->pfsi->lSourceFrameMS, (float)1000 / fa->pfsi->lMicrosecsPerFrame);
375 return 0;
378 virtual long ParamProc(FilterActivation* fa, const FilterFunctions* ff)
380 fa->dst.offset = fa->src.offset;
381 fa->dst.modulo = fa->src.modulo;
382 fa->dst.pitch = fa->src.pitch;
384 return 0;
387 virtual int ConfigProc(FilterActivation* fa, const FilterFunctions* ff, HWND hwnd) = 0;
388 virtual void StringProc(const FilterActivation* fa, const FilterFunctions* ff, char* str) = 0;
389 virtual bool FssProc(FilterActivation* fa, const FilterFunctions* ff, char* buf, int buflen) = 0;
392 class CVobSubVirtualDubFilter : public CVobSubFilter, public CVirtualDubFilter
394 public:
395 CVobSubVirtualDubFilter(CString fn = _T(""))
396 : CVobSubFilter(fn) {}
398 int ConfigProc(FilterActivation* fa, const FilterFunctions* ff, HWND hwnd)
400 AFX_MANAGE_STATE(AfxGetStaticModuleState());
402 CFileDialog fd(TRUE, NULL, GetFileName(), OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY,
403 _T("VobSub files (*.idx;*.sub)|*.idx;*.sub||"), CWnd::FromHandle(hwnd), 0);
405 if(fd.DoModal() != IDOK) return 1;
407 return Open(fd.GetPathName()) ? 0 : 1;
410 void StringProc(const FilterActivation* fa, const FilterFunctions* ff, char* str)
412 sprintf(str, " (%s)", !GetFileName().IsEmpty() ? CStringA(GetFileName()) : " (empty)");
415 bool FssProc(FilterActivation* fa, const FilterFunctions* ff, char* buf, int buflen)
417 CStringA fn(GetFileName());
418 fn.Replace("\\", "\\\\");
419 _snprintf(buf, buflen, "Config(\"%s\")", fn);
420 return(true);
424 class CTextSubVirtualDubFilter : public CTextSubFilter, public CVirtualDubFilter
426 public:
427 CTextSubVirtualDubFilter(CString fn = _T(""), int CharSet = DEFAULT_CHARSET)
428 : CTextSubFilter(fn, CharSet) {}
430 int ConfigProc(FilterActivation* fa, const FilterFunctions* ff, HWND hwnd)
432 AFX_MANAGE_STATE(AfxGetStaticModuleState());
434 const TCHAR formats[] = _T("TextSub files (*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt)|*.sub;*.srt;*.smi;*.ssa;*.ass;*.xss;*.psb;*.txt||");
435 CFileDialog fd(TRUE, NULL, GetFileName(), OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ENABLETEMPLATE|OFN_ENABLEHOOK,
436 formats, CWnd::FromHandle(hwnd), OPENFILENAME_SIZE_VERSION_400 /*0*/);
438 UINT CALLBACK OpenHookProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
440 fd.m_pOFN->hInstance = AfxGetResourceHandle();
441 fd.m_pOFN->lpTemplateName = MAKEINTRESOURCE(IDD_TEXTSUBOPENTEMPLATE);
442 fd.m_pOFN->lpfnHook = OpenHookProc;
443 fd.m_pOFN->lCustData = (LPARAM)DEFAULT_CHARSET;
445 if(fd.DoModal() != IDOK) return 1;
447 return Open(fd.GetPathName(), fd.m_pOFN->lCustData) ? 0 : 1;
450 void StringProc(const FilterActivation* fa, const FilterFunctions* ff, char* str)
452 if(!GetFileName().IsEmpty()) sprintf(str, " (%s, %d)", CStringA(GetFileName()), GetCharSet());
453 else sprintf(str, " (empty)");
456 bool FssProc(FilterActivation* fa, const FilterFunctions* ff, char* buf, int buflen)
458 CStringA fn(GetFileName());
459 fn.Replace("\\", "\\\\");
460 _snprintf(buf, buflen, "Config(\"%s\", %d)", fn, GetCharSet());
461 return(true);
465 int vobsubInitProc(FilterActivation* fa, const FilterFunctions* ff)
467 return !(*(CVirtualDubFilter**)fa->filter_data = new CVobSubVirtualDubFilter());
470 int textsubInitProc(FilterActivation* fa, const FilterFunctions* ff)
472 return !(*(CVirtualDubFilter**)fa->filter_data = new CTextSubVirtualDubFilter());
475 void baseDeinitProc(FilterActivation* fa, const FilterFunctions* ff)
477 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
478 if(f) delete f, f = NULL;
481 int baseRunProc(const FilterActivation* fa, const FilterFunctions* ff)
483 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
484 return f ? f->RunProc(fa, ff) : 1;
487 long baseParamProc(FilterActivation* fa, const FilterFunctions* ff)
489 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
490 return f ? f->ParamProc(fa, ff) : 1;
493 int baseConfigProc(FilterActivation* fa, const FilterFunctions* ff, HWND hwnd)
495 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
496 return f ? f->ConfigProc(fa, ff, hwnd) : 1;
499 void baseStringProc(const FilterActivation* fa, const FilterFunctions* ff, char* str)
501 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
502 if(f) f->StringProc(fa, ff, str);
505 bool baseFssProc(FilterActivation* fa, const FilterFunctions* ff, char* buf, int buflen)
507 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
508 return f ? f->FssProc(fa, ff, buf, buflen) : false;
511 void vobsubScriptConfig(IScriptInterpreter* isi, void* lpVoid, CScriptValue* argv, int argc)
513 FilterActivation* fa = (FilterActivation*)lpVoid;
514 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
515 if(f) delete f;
516 f = new CVobSubVirtualDubFilter(CString(*argv[0].asString()));
517 *(CVirtualDubFilter**)fa->filter_data = f;
520 void textsubScriptConfig(IScriptInterpreter* isi, void* lpVoid, CScriptValue* argv, int argc)
522 FilterActivation* fa = (FilterActivation*)lpVoid;
523 CVirtualDubFilter* f = *(CVirtualDubFilter**)fa->filter_data;
524 if(f) delete f;
525 f = new CTextSubVirtualDubFilter(CString(*argv[0].asString()), argv[1].asInt());
526 *(CVirtualDubFilter**)fa->filter_data = f;
529 ScriptFunctionDef vobsub_func_defs[]={
530 { (ScriptFunctionPtr)vobsubScriptConfig, "Config", "0s" },
531 { NULL },
534 CScriptObject vobsub_obj={
535 NULL, vobsub_func_defs
538 struct FilterDefinition filterDef_vobsub =
540 NULL, NULL, NULL, // next, prev, module
541 "VobSub", // name
542 "Adds subtitles from a vob sequence.", // desc
543 "Gabest", // maker
544 NULL, // private_data
545 sizeof(CVirtualDubFilter**), // inst_data_size
546 vobsubInitProc, // initProc
547 baseDeinitProc, // deinitProc
548 baseRunProc, // runProc
549 baseParamProc, // paramProc
550 baseConfigProc, // configProc
551 baseStringProc, // stringProc
552 NULL, // startProc
553 NULL, // endProc
554 &vobsub_obj, // script_obj
555 baseFssProc, // fssProc
558 ScriptFunctionDef textsub_func_defs[]={
559 { (ScriptFunctionPtr)textsubScriptConfig, "Config", "0si" },
560 { NULL },
563 CScriptObject textsub_obj={
564 NULL, textsub_func_defs
567 struct FilterDefinition filterDef_textsub =
569 NULL, NULL, NULL, // next, prev, module
570 "TextSub", // name
571 "Adds subtitles from srt, sub, psb, smi, ssa, ass file formats.", // desc
572 "Gabest", // maker
573 NULL, // private_data
574 sizeof(CVirtualDubFilter**), // inst_data_size
575 textsubInitProc, // initProc
576 baseDeinitProc, // deinitProc
577 baseRunProc, // runProc
578 baseParamProc, // paramProc
579 baseConfigProc, // configProc
580 baseStringProc, // stringProc
581 NULL, // startProc
582 NULL, // endProc
583 &textsub_obj, // script_obj
584 baseFssProc, // fssProc
587 static FilterDefinition* fd_vobsub;
588 static FilterDefinition* fd_textsub;
590 extern "C" __declspec(dllexport) int __cdecl VirtualdubFilterModuleInit2(FilterModule *fm, const FilterFunctions *ff, int& vdfd_ver, int& vdfd_compat)
592 if(!(fd_vobsub = ff->addFilter(fm, &filterDef_vobsub, sizeof(FilterDefinition)))
593 || !(fd_textsub = ff->addFilter(fm, &filterDef_textsub, sizeof(FilterDefinition))))
594 return 1;
596 vdfd_ver = VIRTUALDUB_FILTERDEF_VERSION;
597 vdfd_compat = VIRTUALDUB_FILTERDEF_COMPATIBLE;
599 return 0;
602 extern "C" __declspec(dllexport) void __cdecl VirtualdubFilterModuleDeinit(FilterModule *fm, const FilterFunctions *ff)
604 ff->removeFilter(fd_textsub);
605 ff->removeFilter(fd_vobsub);
610 // Avisynth interface
613 namespace AviSynth1
615 #include "..\..\..\..\include\avisynth\avisynth1.h"
617 class CAvisynthFilter : public GenericVideoFilter, virtual public CFilter
619 public:
620 CAvisynthFilter(PClip c, IScriptEnvironment* env) : GenericVideoFilter(c) {}
622 PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env)
624 PVideoFrame frame = child->GetFrame(n, env);
626 env->MakeWritable(&frame);
628 SubPicDesc dst;
629 dst.w = vi.width;
630 dst.h = vi.height;
631 dst.pitch = frame->GetPitch();
632 dst.bits = (void**)frame->GetWritePtr();
633 dst.bpp = vi.BitsPerPixel();
634 dst.type =
635 vi.IsRGB32() ? ( env->GetVar("RGBA").AsBool() ? MSP_RGBA :MSP_RGB32) :
636 vi.IsRGB24() ? MSP_RGB24 :
637 vi.IsYUY2() ? MSP_YUY2 :
640 float fps = m_fps > 0 ? m_fps : (float)vi.fps_numerator / vi.fps_denominator;
642 Render(dst, (REFERENCE_TIME)(10000000i64 * n / fps), fps);
644 return(frame);
648 class CVobSubAvisynthFilter : public CVobSubFilter, public CAvisynthFilter
650 public:
651 CVobSubAvisynthFilter(PClip c, const char* fn, IScriptEnvironment* env)
652 : CVobSubFilter(CString(fn))
653 , CAvisynthFilter(c, env)
655 if(!m_pSubPicProvider)
656 env->ThrowError("VobSub: Can't open \"%s\"", fn);
660 AVSValue __cdecl VobSubCreateS(AVSValue args, void* user_data, IScriptEnvironment* env)
662 return(new CVobSubAvisynthFilter(args[0].AsClip(), args[1].AsString(), env));
665 class CTextSubAvisynthFilter : public CTextSubFilter, public CAvisynthFilter
667 public:
668 CTextSubAvisynthFilter(PClip c, IScriptEnvironment* env, const char* fn, int CharSet = DEFAULT_CHARSET, float fps = -1)
669 : CTextSubFilter(CString(fn), CharSet, fps)
670 , CAvisynthFilter(c, env)
672 if(!m_pSubPicProvider)
673 env->ThrowError("TextSub: Can't open \"%s\"", fn);
677 AVSValue __cdecl TextSubCreateS(AVSValue args, void* user_data, IScriptEnvironment* env)
679 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString()));
682 AVSValue __cdecl TextSubCreateSI(AVSValue args, void* user_data, IScriptEnvironment* env)
684 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString(), args[2].AsInt()));
687 AVSValue __cdecl TextSubCreateSIF(AVSValue args, void* user_data, IScriptEnvironment* env)
689 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString(), args[2].AsInt(), args[3].AsFloat()));
692 AVSValue __cdecl MaskSubCreateSIIFI(AVSValue args, void* user_data, IScriptEnvironment* env)
694 AVSValue rgb32("RGB32");
695 AVSValue tab[5] = {
696 args[1],
697 args[2],
698 args[3],
699 args[4],
700 rgb32
702 AVSValue value(tab,5);
703 const char * nom[5]={
704 "width",
705 "height",
706 "fps",
707 "length",
708 "pixel_type"
710 AVSValue clip(env->Invoke("Blackness",value,nom));
711 env->SetVar(env->SaveString("RGBA"),true);
712 return(new CTextSubAvisynthFilter(clip.AsClip(), env, args[0].AsString()));
715 extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit(IScriptEnvironment* env)
717 env->AddFunction("VobSub", "cs", VobSubCreateS, 0);
718 env->AddFunction("TextSub", "cs", TextSubCreateS, 0);
719 env->AddFunction("TextSub", "csi", TextSubCreateSI, 0);
720 env->AddFunction("TextSub", "csif", TextSubCreateSIF, 0);
721 env->AddFunction("MaskSub", "siifi", MaskSubCreateSIIFI, 0);
722 env->SetVar(env->SaveString("RGBA"),false);
723 return(NULL);
727 namespace AviSynth25
729 #include "..\..\..\..\include\avisynth\avisynth25.h"
731 static bool s_fSwapUV = false;
733 class CAvisynthFilter : public GenericVideoFilter, virtual public CFilter
735 VFRTranslator *vfr;
737 public:
738 CAvisynthFilter(PClip c, IScriptEnvironment* env, VFRTranslator *_vfr=0) : GenericVideoFilter(c), vfr(_vfr) {}
740 PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env)
742 PVideoFrame frame = child->GetFrame(n, env);
744 env->MakeWritable(&frame);
746 SubPicDesc dst;
747 dst.w = vi.width;
748 dst.h = vi.height;
749 dst.pitch = frame->GetPitch();
750 dst.pitchUV = frame->GetPitch(PLANAR_U);
751 dst.bits = (void**)frame->GetWritePtr();
752 dst.bitsU = frame->GetWritePtr(PLANAR_U);
753 dst.bitsV = frame->GetWritePtr(PLANAR_V);
754 dst.bpp = dst.pitch/dst.w*8; //vi.BitsPerPixel();
755 dst.type =
756 vi.IsRGB32() ?( env->GetVar("RGBA").AsBool() ? MSP_RGBA : MSP_RGB32) :
757 vi.IsRGB24() ? MSP_RGB24 :
758 vi.IsYUY2() ? MSP_YUY2 :
759 /*vi.IsYV12()*/ vi.pixel_type == VideoInfo::CS_YV12 ? (s_fSwapUV?MSP_IYUV:MSP_YV12) :
760 /*vi.IsIYUV()*/ vi.pixel_type == VideoInfo::CS_IYUV ? (s_fSwapUV?MSP_YV12:MSP_IYUV) :
763 REFERENCE_TIME timestamp;
764 float fps = m_fps > 0 ? m_fps : (float)vi.fps_numerator / vi.fps_denominator;
765 if (!vfr)
766 timestamp = (REFERENCE_TIME)(10000000i64 * n / fps);
767 else
768 timestamp = (REFERENCE_TIME)(10000000 * vfr->TimeStampFromFrameNumber(n));
770 Render(dst, timestamp, fps);
772 return(frame);
776 class CVobSubAvisynthFilter : public CVobSubFilter, public CAvisynthFilter
778 public:
779 CVobSubAvisynthFilter(PClip c, const char* fn, IScriptEnvironment* env)
780 : CVobSubFilter(CString(fn))
781 , CAvisynthFilter(c, env)
783 if(!m_pSubPicProvider)
784 env->ThrowError("VobSub: Can't open \"%s\"", fn);
788 AVSValue __cdecl VobSubCreateS(AVSValue args, void* user_data, IScriptEnvironment* env)
790 return(new CVobSubAvisynthFilter(args[0].AsClip(), args[1].AsString(), env));
793 class CTextSubAvisynthFilter : public CTextSubFilter, public CAvisynthFilter
795 public:
796 CTextSubAvisynthFilter(PClip c, IScriptEnvironment* env, const char* fn, int CharSet = DEFAULT_CHARSET, float fps = -1, VFRTranslator *vfr = 0)
797 : CTextSubFilter(CString(fn), CharSet, fps)
798 , CAvisynthFilter(c, env, vfr)
800 if(!m_pSubPicProvider)
801 env->ThrowError("TextSub: Can't open \"%s\"", fn);
805 /*AVSValue __cdecl TextSubCreateS(AVSValue args, void* user_data, IScriptEnvironment* env)
807 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString()));
810 AVSValue __cdecl TextSubCreateSI(AVSValue args, void* user_data, IScriptEnvironment* env)
812 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString(), args[2].AsInt()));
815 AVSValue __cdecl TextSubCreateSIF(AVSValue args, void* user_data, IScriptEnvironment* env)
817 return(new CTextSubAvisynthFilter(args[0].AsClip(), env, args[1].AsString(), args[2].AsInt(), args[3].AsFloat()));
820 AVSValue __cdecl TextSubCreateGeneral(AVSValue args, void* user_data, IScriptEnvironment* env)
822 if (!args[1].Defined())
823 env->ThrowError("TextSub: You must specify a subtitle file to use");
825 VFRTranslator *vfr = 0;
826 if (args[4].Defined())
827 vfr = GetVFRTranslator(args[4].AsString());
829 return(new CTextSubAvisynthFilter(
830 args[0].AsClip(),
831 env,
832 args[1].AsString(),
833 args[2].AsInt(DEFAULT_CHARSET),
834 args[3].AsFloat(-1),
835 vfr));
838 AVSValue __cdecl TextSubSwapUV(AVSValue args, void* user_data, IScriptEnvironment* env)
840 s_fSwapUV = args[0].AsBool(false);
841 return(AVSValue());
844 AVSValue __cdecl MaskSubCreate(AVSValue args, void* user_data, IScriptEnvironment* env)
846 if (!args[0].Defined())
847 env->ThrowError("MaskSub: You must specify a subtitle file to use");
849 if (!args[3].Defined() && !args[6].Defined())
850 env->ThrowError("MaskSub: You must specify either FPS or a VFR timecodes file");
852 VFRTranslator *vfr = 0;
853 if (args[6].Defined())
854 vfr = GetVFRTranslator(args[6].AsString());
856 AVSValue rgb32("RGB32");
857 AVSValue fps(args[3].AsFloat(25));
858 AVSValue tab[6] = {
859 args[1],
860 args[2],
861 fps,
862 args[4],
863 rgb32
865 AVSValue value(tab,5);
866 const char * nom[5]={
867 "width",
868 "height",
869 "fps",
870 "length",
871 "pixel_type"
874 AVSValue clip(env->Invoke("Blackness",value,nom));
875 env->SetVar(env->SaveString("RGBA"),true);
877 return(new CTextSubAvisynthFilter(
878 clip.AsClip(),
879 env,
880 args[0].AsString(),
881 args[5].AsInt(DEFAULT_CHARSET),
882 args[3].AsFloat(-1),
883 vfr));
886 extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env)
888 env->AddFunction("VobSub", "cs", VobSubCreateS, 0);
889 //env->AddFunction("TextSub", "cs", TextSubCreateS, 0);
890 //env->AddFunction("TextSub", "csi", TextSubCreateSI, 0);
891 //env->AddFunction("TextSub", "csif", TextSubCreateSIF, 0);
892 env->AddFunction("TextSub", "c[file]s[charset]i[fps]f[vfr]s", TextSubCreateGeneral, 0);
893 env->AddFunction("TextSubSwapUV", "b", TextSubSwapUV, 0);
894 env->AddFunction("MaskSub", "[file]s[width]i[height]i[fps]f[length]i[charset]i[vfr]s", MaskSubCreate, 0);
895 env->SetVar(env->SaveString("RGBA"),false);
896 return(NULL);
902 UINT CALLBACK OpenHookProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
904 switch(uiMsg)
906 case WM_NOTIFY:
908 OPENFILENAME* ofn = ((OFNOTIFY *)lParam)->lpOFN;
910 if(((NMHDR *)lParam)->code == CDN_FILEOK)
912 ofn->lCustData = (LPARAM)CharSetList[SendMessage(GetDlgItem(hDlg, IDC_COMBO1), CB_GETCURSEL, 0, 0)];
915 break;
918 case WM_INITDIALOG:
920 SetWindowLong(hDlg, GWL_USERDATA, lParam);
922 for(int i = 0; i < CharSetLen; i++)
924 CString s;
925 s.Format(_T("%s (%d)"), CharSetNames[i], CharSetList[i]);
926 SendMessage(GetDlgItem(hDlg, IDC_COMBO1), CB_ADDSTRING, 0, (LONG)(LPCTSTR)s);
927 if(CharSetList[i] == (int)((OPENFILENAME*)lParam)->lCustData)
928 SendMessage(GetDlgItem(hDlg, IDC_COMBO1), CB_SETCURSEL, i, 0);
931 break;
934 default:
935 break;
938 return FALSE;