2 * Copyright (c) 2012 Fredrik Mellbin
4 * This file is part of VapourSynth.
6 * VapourSynth is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * VapourSynth is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with VapourSynth; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "cpufeatures.h"
24 void VS_CC
configPlugin(const char *identifier
, const char *defaultNamespace
, const char *name
, int apiVersion
, int readOnly
, VSPlugin
*plugin
) {
25 plugin
->configPlugin(identifier
, defaultNamespace
, name
, apiVersion
, readOnly
);
28 void VS_CC
registerFunction(const char *name
, const char *args
, VSPublicFunction argsFunc
, void *functionData
, VSPlugin
*plugin
) {
29 plugin
->registerFunction(name
, args
, argsFunc
, functionData
);
32 static const VSFormat
*VS_CC
getFormatPreset(int id
, VSCore
*core
) {
33 return core
->getFormatPreset((VSPresetFormat
)id
);
36 static const VSFormat
*VS_CC
registerFormat(int colorFamily
, int sampleType
, int bitsPerSample
, int subSamplingW
, int subSamplingH
, VSCore
*core
) {
37 return core
->registerFormat((VSColorFamily
)colorFamily
, (VSSampleType
)sampleType
, bitsPerSample
, subSamplingW
, subSamplingH
);
40 static const VSFrameRef
*VS_CC
cloneFrameRef(const VSFrameRef
*frame
) {
42 return new VSFrameRef(frame
->frame
);
45 static VSNodeRef
*VS_CC
cloneNodeRef(VSNodeRef
*node
) {
47 return new VSNodeRef(node
->clip
, node
->index
);
50 static int VS_CC
getStride(const VSFrameRef
*frame
, int plane
) {
51 return frame
->frame
->getStride(plane
);
54 static const uint8_t *VS_CC
getReadPtr(const VSFrameRef
*frame
, int plane
) {
55 return frame
->frame
->getReadPtr(plane
);
58 static uint8_t *VS_CC
getWritePtr(VSFrameRef
*frame
, int plane
) {
59 return frame
->frame
->getWritePtr(plane
);
62 static void VS_CC
getFrameAsync(int n
, VSNodeRef
*clip
, VSFrameDoneCallback fdc
, void *userData
) {
63 PFrameContext
c(new FrameContext(n
, clip
->index
, clip
, fdc
, userData
));
64 clip
->clip
->getFrame(c
);
67 struct GetFrameWaiter
{
73 GetFrameWaiter(char *errorMsg
, int bufSize
) : errorMsg(errorMsg
), bufSize(bufSize
) {}
76 static void VS_CC
frameWaiterCallback(void *userData
, const VSFrameRef
*frame
, int n
, VSNodeRef
*node
, const char *errorMsg
) {
77 GetFrameWaiter
*g
= (GetFrameWaiter
*)userData
;
78 QMutexLocker
l(&g
->b
);
80 memset(g
->errorMsg
, 0, g
->bufSize
);
82 strncpy(g
->errorMsg
, errorMsg
, g
->bufSize
);
83 g
->errorMsg
[g
->bufSize
- 1] = 0;
88 static const VSFrameRef
*VS_CC
getFrame(int n
, VSNodeRef
*clip
, char *errorMsg
, int bufSize
) {
89 GetFrameWaiter
g(errorMsg
, bufSize
);
91 PFrameContext
c(new FrameContext(n
, clip
->index
, clip
, &frameWaiterCallback
, &g
));
92 VSNode
*node
= clip
->clip
.data();
93 bool isWorker
= node
->isWorkerThread();
95 node
->releaseThread();
99 node
->reserveThread();
103 static void VS_CC
requestFrameFilter(int n
, VSNodeRef
*clip
, VSFrameContext
*ctxHandle
) {
104 PFrameContext
f(*(PFrameContext
*)ctxHandle
);
105 PFrameContext
g(new FrameContext(n
, clip
->index
, clip
->clip
.data(), f
));
106 clip
->clip
->getFrame(g
);
109 static const VSFrameRef
*VS_CC
getFrameFilter(int n
, VSNodeRef
*clip
, VSFrameContext
*ctxHandle
) {
110 PFrameContext
f(*(PFrameContext
*)ctxHandle
);
111 PVideoFrame g
= f
->availableFrames
.value(NodeOutputKey(clip
->clip
.data(), n
, clip
->index
));
114 return new VSFrameRef(g
);
119 static void VS_CC
freeFrame(const VSFrameRef
*frame
) {
123 static void VS_CC
freeNode(VSNodeRef
*clip
) {
127 static VSFrameRef
*VS_CC
newVideoFrame(const VSFormat
*format
, int width
, int height
, const VSFrameRef
*propSrc
, VSCore
*core
) {
129 return new VSFrameRef(core
->newVideoFrame(format
, width
, height
, propSrc
? propSrc
->frame
.data() : NULL
));
132 static VSFrameRef
*VS_CC
newVideoFrame2(const VSFormat
*format
, int width
, int height
, const VSFrameRef
**planeSrc
, const int *planes
, const VSFrameRef
*propSrc
, VSCore
*core
) {
135 for (int i
= 0; i
< format
->numPlanes
; i
++)
136 fp
[i
] = planeSrc
[i
] ? planeSrc
[i
]->frame
.data() : NULL
;
137 return new VSFrameRef(core
->newVideoFrame(format
, width
, height
, fp
, planes
, propSrc
? propSrc
->frame
.data() : NULL
));
140 static VSFrameRef
*VS_CC
copyFrame(const VSFrameRef
*frame
, VSCore
*core
) {
141 return new VSFrameRef(core
->copyFrame(frame
->frame
));
144 static void VS_CC
copyFrameProps(const VSFrameRef
*src
, VSFrameRef
*dst
, VSCore
*core
) {
145 core
->copyFrameProps(src
->frame
, dst
->frame
);
148 static void VS_CC
createFilter(const VSMap
*in
, VSMap
*out
, const char *name
, VSFilterInit init
, VSFilterGetFrame getFrame
, VSFilterFree free
, int filterMode
, int flags
, void *instanceData
, VSCore
*core
) {
149 core
->createFilter(in
, out
, name
, init
, getFrame
, free
, static_cast<VSFilterMode
>(filterMode
), flags
, instanceData
, VAPOURSYNTH_API_VERSION
);
152 static void VS_CC
setError(VSMap
*map
, const char *errorMessage
) {
154 VSVariant
l(VSVariant::vData
);
155 l
.s
.append(errorMessage
? errorMessage
: "Error: no error specified");
156 map
->insert("_Error", l
);
159 static const char *VS_CC
getError(const VSMap
*map
) {
160 if (map
->contains("_Error"))
161 return (*map
)["_Error"].s
[0].constData();
166 static void VS_CC
setFilterError(const char *errorMessage
, VSFrameContext
*context
) {
167 PFrameContext
f(*(PFrameContext
*)context
);
168 f
->setError(errorMessage
);
171 //property access functions
172 static const VSVideoInfo
*VS_CC
getVideoInfo(VSNodeRef
*c
) {
173 return &c
->clip
->getVideoInfo(c
->index
);
176 static void VS_CC
setVideoInfo(const VSVideoInfo
*vi
, int numOutputs
, VSNode
*c
) {
177 c
->setVideoInfo(vi
, numOutputs
);
180 static const VSFormat
*VS_CC
getFrameFormat(const VSFrameRef
*f
) {
181 return f
->frame
->getFormat();
184 static int VS_CC
getFrameWidth(const VSFrameRef
*f
, int plane
) {
185 return f
->frame
->getWidth(plane
);
188 static int VS_CC
getFrameHeight(const VSFrameRef
*f
, int plane
) {
189 return f
->frame
->getHeight(plane
);
192 static const VSMap
*VS_CC
getFramePropsRO(const VSFrameRef
*frame
) {
193 return &frame
->frame
->getConstProperties();
196 static VSMap
*VS_CC
getFramePropsRW(VSFrameRef
*frame
) {
197 return &frame
->frame
->getProperties();
200 static int VS_CC
propNumKeys(const VSMap
*props
) {
201 return props
->keys().count();
204 static const char *VS_CC
propGetKey(const VSMap
*props
, int index
) {
205 if (index
< 0 || index
>= props
->count())
206 qFatal("Out of bound index");
208 return props
->keys()[index
].constData();
211 static int VS_CC
propNumElements(const VSMap
*props
, const char *name
) {
212 if (!props
->contains(name
))
215 const VSVariant
&val
= (*props
)[name
];
219 static char VS_CC
propGetType(const VSMap
*props
, const char *name
) {
220 if (!props
->contains(name
))
223 const char a
[] = { 'u', 'i', 'f', 's', 'c', 'v', 'm'};
224 const VSVariant
&val
= (*props
)[name
];
228 static int getPropErrorCheck(const VSMap
*props
, const char *name
, int index
, int *error
, int type
) {
232 qFatal("Attempted to read from a map with error set: %s", getError(props
));
234 if (!props
->contains(name
))
237 if (!err
&& props
->value(name
).vtype
!= type
)
240 int c
= propNumElements(props
, name
);
242 if ((!err
&& c
<= index
) || index
< 0)
246 qFatal("Property read unsuccessful but no error output: %s", name
);
254 static int64_t VS_CC
propGetInt(const VSMap
*props
, const char *name
, int index
, int *error
) {
255 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vInt
);
260 const VSVariant
&l
= (*props
)[name
];
264 static double VS_CC
propGetFloat(const VSMap
*props
, const char *name
, int index
, int *error
) {
265 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vFloat
);
270 const VSVariant
&l
= (*props
)[name
];
274 static const char *VS_CC
propGetData(const VSMap
*props
, const char *name
, int index
, int *error
) {
275 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vData
);
280 const VSVariant
&l
= (*props
)[name
];
281 return l
.s
[index
].constData();
284 static int VS_CC
propGetDataSize(const VSMap
*props
, const char *name
, int index
, int *error
) {
285 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vData
);
290 const VSVariant
&l
= (*props
)[name
];
291 return l
.s
[index
].size();
294 static VSNodeRef
*VS_CC
propGetNode(const VSMap
*props
, const char *name
, int index
, int *error
) {
295 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vNode
);
300 const VSVariant
&l
= (*props
)[name
];
301 return new VSNodeRef(l
.c
[index
]);
304 static const VSFrameRef
*VS_CC
propGetFrame(const VSMap
*props
, const char *name
, int index
, int *error
) {
305 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vFrame
);
310 const VSVariant
&l
= (*props
)[name
];
311 return new VSFrameRef(l
.v
[index
]);
314 static int VS_CC
propDeleteKey(VSMap
*props
, const char *name
) {
315 return props
->remove(name
);
318 static void sharedPropSet(VSMap
*props
, const char *name
, int &append
) {
319 if (append
!= paReplace
&& append
!= paAppend
&& append
!= paTouch
)
320 qFatal("Invalid prop append mode given");
322 if (append
== paReplace
) {
328 static int VS_CC
propSetInt(VSMap
*props
, const char *name
, int64_t i
, int append
) {
329 sharedPropSet(props
, name
, append
);
330 if (props
->contains(name
)) {
331 VSVariant
&l
= (*props
)[name
];
333 if (l
.vtype
!= VSVariant::vInt
)
335 else if (append
== paAppend
)
338 VSVariant
l(VSVariant::vInt
);
339 if (append
== paAppend
)
341 props
->insert(name
, l
);
347 static int VS_CC
propSetFloat(VSMap
*props
, const char *name
, double d
, int append
) {
348 sharedPropSet(props
, name
, append
);
349 if (props
->contains(name
)) {
350 VSVariant
&l
= (*props
)[name
];
352 if (l
.vtype
!= VSVariant::vFloat
)
354 else if (append
== paAppend
)
357 VSVariant
l(VSVariant::vFloat
);
358 if (append
== paAppend
)
360 props
->insert(name
, l
);
366 static int VS_CC
propSetData(VSMap
*props
, const char *name
, const char *d
, int length
, int append
) {
367 sharedPropSet(props
, name
, append
);
368 if (props
->contains(name
)) {
369 VSVariant
&l
= (*props
)[name
];
371 if (l
.vtype
!= VSVariant::vData
)
373 else if (append
== paAppend
)
376 VSVariant
l(VSVariant::vData
);
377 if (append
== paAppend
)
378 l
.s
.append(length
>= 0 ? QByteArray(d
, length
) : QByteArray(d
));
379 props
->insert(name
, l
);
385 static int VS_CC
propSetNode(VSMap
*props
, const char *name
, VSNodeRef
*clip
, int append
) {
386 sharedPropSet(props
, name
, append
);
387 if (props
->contains(name
)) {
388 VSVariant
&l
= (*props
)[name
];
390 if (l
.vtype
!= VSVariant::vNode
)
392 else if (append
== paAppend
)
395 VSVariant
l(VSVariant::vNode
);
396 if (append
== paAppend
)
398 props
->insert(name
, l
);
404 static int VS_CC
propSetFrame(VSMap
*props
, const char *name
, const VSFrameRef
*frame
, int append
) {
405 sharedPropSet(props
, name
, append
);
406 if (props
->contains(name
)) {
407 VSVariant
&l
= (*props
)[name
];
409 if (l
.vtype
!= VSVariant::vFrame
)
411 else if (append
== paAppend
)
412 l
.v
.append(frame
->frame
);
414 VSVariant
l(VSVariant::vFrame
);
415 if (append
== paAppend
)
416 l
.v
.append(frame
->frame
);
417 props
->insert(name
, l
);
423 static VSMap
*VS_CC
invoke(VSPlugin
*plugin
, const char *name
, const VSMap
*args
) {
425 return new VSMap(plugin
->invoke(name
, *args
));
428 static VSMap
*VS_CC
newMap() {
432 static void VS_CC
freeMap(VSMap
*map
) {
436 static void VS_CC
clearMap(VSMap
*map
) {
440 static VSCore
*VS_CC
createCore(int threads
) {
441 return new VSCore(threads
);
444 static void VS_CC
freeCore(VSCore
*core
) {
448 static VSPlugin
*VS_CC
getPluginId(const char *identifier
, VSCore
*core
) {
449 return core
->getPluginId(identifier
);
452 static VSPlugin
*VS_CC
getPluginNs(const char *ns
, VSCore
*core
) {
453 return core
->getPluginNs(ns
);
456 static VSMap
*VS_CC
getPlugins(VSCore
*core
) {
457 return new VSMap(core
->getPlugins());
460 static VSMap
*VS_CC
getFunctions(VSPlugin
*plugin
) {
461 return new VSMap(plugin
->getFunctions());
464 static const VSCoreInfo
*VS_CC
getCoreInfo(VSCore
*core
) {
465 return &core
->getCoreInfo();
468 static VSFuncRef
*VS_CC
propGetFunc(const VSMap
*props
, const char *name
, int index
, int *error
) {
469 int err
= getPropErrorCheck(props
, name
, index
, error
, VSVariant::vMethod
);
474 const VSVariant
&l
= (*props
)[name
];
475 return new VSFuncRef(l
.m
[index
]);
478 static int VS_CC
propSetFunc(VSMap
*props
, const char *name
, VSFuncRef
*func
, int append
) {
482 if (props
->contains(name
)) {
483 VSVariant
&l
= (*props
)[name
];
485 if (l
.vtype
!= VSVariant::vMethod
)
488 l
.m
.append(func
->func
);
490 VSVariant
l(VSVariant::vMethod
);
491 l
.m
.append(func
->func
);
492 props
->insert(name
, l
);
498 static void VS_CC
callFunc(VSFuncRef
*func
, const VSMap
*in
, VSMap
*out
, VSCore
*core
, const VSAPI
*vsapi
) {
499 func
->func
->call(in
, out
, core
, vsapi
);
502 static VSFuncRef
*VS_CC
createFunc(VSPublicFunction func
, void *userData
, VSFreeFuncData free
) {
503 return new VSFuncRef(PExtFunction(new ExtFunction(func
, userData
, free
)));
506 static void VS_CC
freeFunc(VSFuncRef
*f
) {
510 static void VS_CC
queryCompletedFrame(VSNodeRef
**node
, int *n
, VSFrameContext
*frameCtx
) {
511 PFrameContext
f(*(PFrameContext
*)frameCtx
);
512 *node
= f
->lastCompletedNode
;
513 *n
= f
->lastCompletedN
;
516 static void VS_CC
releaseFrameEarly(VSNodeRef
*node
, int n
, VSFrameContext
*frameCtx
) {
517 PFrameContext
f(*(PFrameContext
*)frameCtx
);
518 f
->availableFrames
.remove(NodeOutputKey(node
->clip
.data(), n
, node
->index
));
521 static VSFuncRef
*VS_CC
cloneFuncRef(VSFuncRef
*f
) {
522 return new VSFuncRef(f
->func
);
525 static int64_t VS_CC
setMaxCacheSize(int64_t bytes
, VSCore
*core
) {
526 return core
->setMaxCacheSize(bytes
);
529 static int VS_CC
getOutputIndex(VSFrameContext
*frameCtx
) {
530 PFrameContext
f(*(PFrameContext
*)frameCtx
);
534 static VSMessageHandler handler
= NULL
;
536 void vsMessageHandler(QtMsgType type
, const char *msg
) {
538 if (type
== QtFatalMsg
)
542 static void VS_CC
setMessageHandler(VSMessageHandler handler
) {
545 qInstallMsgHandler(vsMessageHandler
);
547 qInstallMsgHandler(NULL
);
552 const VSAPI vsapi
= {
584 &queryCompletedFrame
,
632 //////////////////////////
635 typedef void (VS_CC
*VSSetVideoInfo_R2
)(const VSVideoInfo
*vi
, VSNode
*node
);
636 typedef VSNodeRef
*(VS_CC
*VSCreateFilter_R2
)(const VSMap
*in
, VSMap
*out
, const char *name
, VSFilterInit init
, VSFilterGetFrame getFrame
, VSFilterFree free
, int filterMode
, int flags
, void *instanceData
, VSCore
*core
);
638 static void VS_CC
setVideoInfoR2(const VSVideoInfo
*vi
, VSNode
*c
) {
639 setVideoInfo(vi
, 1, c
);
642 static VSNodeRef
*VS_CC
createFilterR2(const VSMap
*in
, VSMap
*out
, const char *name
, VSFilterInit init
, VSFilterGetFrame getFrame
, VSFilterFree free
, int filterMode
, int flags
, void *instanceData
, VSCore
*core
) {
643 core
->createFilter(in
, out
, name
, init
, getFrame
, free
, static_cast<VSFilterMode
>(filterMode
), flags
, instanceData
, 2);
644 return propGetNode(out
, "clip", 0, NULL
);
648 VSCreateCore createCore
;
650 VSGetCoreInfo getCoreInfo
;
652 VSCloneFrameRef cloneFrameRef
;
653 VSCloneNodeRef cloneNodeRef
;
654 VSCloneFuncRef cloneFuncRef
;
656 VSFreeFrame freeFrame
;
660 VSNewVideoFrame newVideoFrame
;
661 VSCopyFrame copyFrame
;
662 VSCopyFrameProps copyFrameProps
;
664 VSRegisterFunction registerFunction
;
665 VSGetPluginId getPluginId
;
666 VSGetPluginNs getPluginNs
;
667 VSGetPlugins getPlugins
;
668 VSGetFunctions getFunctions
;
669 VSCreateFilter_R2 createFilter
;
672 VSSetFilterError setFilterError
;
675 VSGetFormatPreset getFormatPreset
;
676 VSRegisterFormat registerFormat
;
679 VSGetFrameAsync getFrameAsync
;
680 VSGetFrameFilter getFrameFilter
;
681 VSRequestFrameFilter requestFrameFilter
;
682 VSQueryCompletedFrame queryCompletedFrame
;
683 VSReleaseFrameEarly releaseFrameEarly
;
685 VSGetStride getStride
;
686 VSGetReadPtr getReadPtr
;
687 VSGetWritePtr getWritePtr
;
689 VSCreateFunc createFunc
;
692 //property access functions
693 VSCreateMap createMap
;
697 VSGetVideoInfo getVideoInfo
;
698 VSSetVideoInfo_R2 setVideoInfo
;
699 VSGetFrameFormat getFrameFormat
;
700 VSGetFrameWidth getFrameWidth
;
701 VSGetFrameHeight getFrameHeight
;
702 VSGetFramePropsRO getFramePropsRO
;
703 VSGetFramePropsRW getFramePropsRW
;
705 VSPropNumKeys propNumKeys
;
706 VSPropGetKey propGetKey
;
707 VSPropNumElements propNumElements
;
708 VSPropGetType propGetType
;
709 VSPropGetInt propGetInt
;
710 VSPropGetFloat propGetFloat
;
711 VSPropGetData propGetData
;
712 VSPropGetDataSize propGetDataSize
;
713 VSPropGetNode propGetNode
;
714 VSPropGetFrame propGetFrame
;
715 VSPropGetFunc propGetFunc
;
717 VSPropDeleteKey propDeleteKey
;
718 VSPropSetInt propSetInt
;
719 VSPropSetFloat propSetFloat
;
720 VSPropSetData propSetData
;
721 VSPropSetNode propSetNode
;
722 VSPropSetFrame propSetFrame
;
723 VSPropSetFunc propSetFunc
;
725 VSSetMaxCacheSize setMaxCacheSize
;
726 VSGetOutputIndex getOutputIndex
;
729 ///////////////////////////////
731 const VSAPI
*getVSAPIInternal(int version
) {
732 if (version
== VAPOURSYNTH_API_VERSION
) {
735 qFatal("Internally requested API version %d", version
);
740 const VSAPI
*VS_CC
getVapourSynthAPI(int version
) {
744 qWarning("System does not meet minimum requirements to run VapourSynth");
746 } else if (version
== VAPOURSYNTH_API_VERSION
) {