GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 776
Functions: 0.0% 0 / 0 / 166
Branches: 0.0% 0 / 0 / 580

core/avisynth_c.cpp
Line Branch Exec Source
1 // Avisynth C Interface
2 // Based on Copyright 2003 Kevin Atkinson
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9
10 #include <avisynth.h>
11 #include <avisynth_c.h>
12 #include "AVSMap.h"
13 #include "internal.h"
14
15 #ifdef AVS_WINDOWS
16 #include <avs/win.h>
17 #else
18 #include <avs/posix.h>
19 #endif
20
21 #include <algorithm>
22 #include <cstdarg>
23
24
25 struct AVS_Clip
26 {
27 PClip clip;
28 IScriptEnvironment* env;
29 const char* error;
30 AVS_Clip() : env(0), error(0) {}
31 };
32
33 class C_VideoFilter : public IClip {
34 public: // but don't use
35 AVS_Clip child;
36 AVS_ScriptEnvironment env;
37 AVS_FilterInfo d;
38 public:
39 C_VideoFilter() { memset(&d, 0, sizeof(d)); }
40 PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
41 void __stdcall GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env);
42 const VideoInfo& __stdcall GetVideoInfo();
43 bool __stdcall GetParity(int n);
44 int __stdcall SetCacheHints(int cachehints, int frame_range);
45 AVSC_CC ~C_VideoFilter();
46 };
47
48 /////////////////////////////////////////////////////////////////////
49 //
50 //
51 //
52
53 extern "C"
54 int AVSC_CC avs_is_rgb48(const AVS_VideoInfo * p)
55 {
56 return ((p->pixel_type & AVS_CS_BGR24) == AVS_CS_BGR24) && ((p->pixel_type & AVS_CS_SAMPLE_BITS_MASK) == AVS_CS_SAMPLE_BITS_16);
57 }
58
59 extern "C"
60 int AVSC_CC avs_is_rgb64(const AVS_VideoInfo * p)
61 {
62 return ((p->pixel_type & AVS_CS_BGR32) == AVS_CS_BGR32) && ((p->pixel_type & AVS_CS_SAMPLE_BITS_MASK) == AVS_CS_SAMPLE_BITS_16);
63 }
64
65 extern "C"
66 int AVSC_CC avs_is_yv24(const AVS_VideoInfo * p)
67 {
68 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YV24 & AVS_CS_PLANAR_FILTER);
69 }
70
71 extern "C"
72 int AVSC_CC avs_is_yv16(const AVS_VideoInfo * p)
73 {
74 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YV16 & AVS_CS_PLANAR_FILTER);
75 }
76
77 extern "C"
78 int AVSC_CC avs_is_yv12(const AVS_VideoInfo * p)
79 {
80 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YV12 & AVS_CS_PLANAR_FILTER);
81 }
82
83 extern "C"
84 int AVSC_CC avs_is_yv411(const AVS_VideoInfo * p)
85 {
86 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YV411 & AVS_CS_PLANAR_FILTER);
87 }
88
89 extern "C"
90 int AVSC_CC avs_is_y8(const AVS_VideoInfo * p)
91 {
92 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_Y8 & AVS_CS_PLANAR_FILTER);
93 }
94
95 extern "C"
96 int AVSC_CC avs_is_yuv444p16(const AVS_VideoInfo * p)
97 {
98 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV444P16 & AVS_CS_PLANAR_FILTER);
99 }
100
101 extern "C"
102 int AVSC_CC avs_is_yuv422p16(const AVS_VideoInfo * p)
103 {
104 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV422P16 & AVS_CS_PLANAR_FILTER);
105 }
106
107 extern "C"
108 int AVSC_CC avs_is_yuv420p16(const AVS_VideoInfo * p)
109 {
110 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV420P16 & AVS_CS_PLANAR_FILTER);
111 }
112
113 extern "C"
114 int AVSC_CC avs_is_y16(const AVS_VideoInfo * p)
115 {
116 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_Y16 & AVS_CS_PLANAR_FILTER);
117 }
118
119 extern "C"
120 int AVSC_CC avs_is_yuv444ps(const AVS_VideoInfo * p)
121 {
122 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV444PS & AVS_CS_PLANAR_FILTER);
123 }
124
125 extern "C"
126 int AVSC_CC avs_is_yuv422ps(const AVS_VideoInfo * p)
127 {
128 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV422PS & AVS_CS_PLANAR_FILTER);
129 }
130
131 extern "C"
132 int AVSC_CC avs_is_yuv420ps(const AVS_VideoInfo * p)
133 {
134 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_YUV420PS & AVS_CS_PLANAR_FILTER);
135 }
136
137 extern "C"
138 int AVSC_CC avs_is_y32(const AVS_VideoInfo * p)
139 {
140 return (p->pixel_type & AVS_CS_PLANAR_MASK) == (AVS_CS_Y32 & AVS_CS_PLANAR_FILTER);
141 }
142
143 extern "C"
144 int AVSC_CC avs_is_444(const AVS_VideoInfo * p)
145 {
146 return ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUV444 & AVS_CS_PLANAR_FILTER)) ||
147 ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUVA444 & AVS_CS_PLANAR_FILTER));
148 }
149
150 extern "C"
151 int AVSC_CC avs_is_422(const AVS_VideoInfo * p)
152 {
153 return ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUV422 & AVS_CS_PLANAR_FILTER)) ||
154 ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUVA422 & AVS_CS_PLANAR_FILTER));
155 }
156
157 extern "C"
158 int AVSC_CC avs_is_420(const AVS_VideoInfo * p)
159 {
160 return ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUV420 & AVS_CS_PLANAR_FILTER)) ||
161 ((p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_YUVA420 & AVS_CS_PLANAR_FILTER));
162 }
163
164 extern "C"
165 int AVSC_CC avs_is_y(const AVS_VideoInfo * p)
166 {
167 return (p->pixel_type & AVS_CS_PLANAR_MASK & ~AVS_CS_SAMPLE_BITS_MASK) == (AVS_CS_GENERIC_Y & AVS_CS_PLANAR_FILTER);
168 }
169
170 extern "C"
171 int AVSC_CC avs_is_color_space(const AVS_VideoInfo * p, int c_space)
172 {
173 return avs_is_planar(p) ?
174 ((p->pixel_type & AVS_CS_PLANAR_MASK) == (c_space & AVS_CS_PLANAR_FILTER))
175 :
176 (((p->pixel_type & ~AVS_CS_SAMPLE_BITS_MASK & c_space) == (c_space & ~AVS_CS_SAMPLE_BITS_MASK)) && // RGB got sample bits
177 ((p->pixel_type & AVS_CS_SAMPLE_BITS_MASK) == (c_space & AVS_CS_SAMPLE_BITS_MASK)));
178 }
179
180 extern "C"
181 int AVSC_CC avs_is_yuva(const AVS_VideoInfo * p)
182 {
183 return !!(p->pixel_type & AVS_CS_YUVA);
184 }
185
186 extern "C"
187 int AVSC_CC avs_is_planar_rgb(const AVS_VideoInfo * p)
188 {
189 return !!(p->pixel_type & AVS_CS_PLANAR) && !!(p->pixel_type & AVS_CS_BGR) && !!(p->pixel_type & AVS_CS_RGB_TYPE);
190 }
191
192 extern "C"
193 int AVSC_CC avs_is_planar_rgba(const AVS_VideoInfo * p)
194 {
195 return !!(p->pixel_type & AVS_CS_PLANAR) && !!(p->pixel_type & AVS_CS_BGR) && !!(p->pixel_type & AVS_CS_RGBA_TYPE);
196 }
197
198 extern "C"
199 int AVSC_CC avs_get_plane_width_subsampling(const AVS_VideoInfo * p, int plane)
200 {
201 try {
202 return ((VideoInfo*)p)->GetPlaneWidthSubsampling(plane);
203 }
204 catch (const AvisynthError& err) {
205 (void)err; // silence warning about unused variable; variable is kept for debugging
206 return -1;
207 }
208 }
209
210 extern "C"
211 int AVSC_CC avs_get_plane_height_subsampling(const AVS_VideoInfo * p, int plane)
212 {
213 try {
214 return ((VideoInfo*)p)->GetPlaneHeightSubsampling(plane);
215 }
216 catch (const AvisynthError& err) {
217 (void)err; // silence warning about unused variable; variable is kept for debugging
218 return -1;
219 }
220 }
221
222 extern "C"
223 int AVSC_CC avs_bits_per_pixel(const AVS_VideoInfo * p)
224 {
225 return ((VideoInfo*)p)->BitsPerPixel();
226 }
227
228 extern "C"
229 int AVSC_CC avs_bytes_from_pixels(const AVS_VideoInfo * p, int pixels)
230 {
231 return ((VideoInfo*)p)->BytesFromPixels(pixels);
232 }
233
234 // This method should be called avs_row_size_p,
235 // but we won't change it anymore to avoid breaking
236 // the interface.
237 extern "C"
238 int AVSC_CC avs_row_size(const AVS_VideoInfo * p, int plane)
239 {
240 return ((VideoInfo*)p)->RowSize(plane);
241 }
242
243 extern "C"
244 int AVSC_CC avs_bmp_size(const AVS_VideoInfo * vi)
245 {
246 return ((VideoInfo*)vi)->BMPSize();
247 }
248
249
250 /////////////////////////////////////////////////////////////////////
251 //
252 //
253 //
254
255 extern "C"
256 int AVSC_CC avs_get_pitch_p(const AVS_VideoFrame * p, int plane)
257 {
258 // Memo: the lines in class PVideoFrame:
259 // VideoFrame* p;
260 // VideoFrame* operator->() const { return p; }
261 // help when you use the arrow operator on a PVideoFrame object, it will return
262 // the "VideoFrame* p" pointer, allowing you to access members of the
263 // VideoFrame class directly.
264 return (*(const PVideoFrame*)&p)->GetPitch(plane);
265 }
266
267 extern "C"
268 int AVSC_CC avs_get_row_size_p(const AVS_VideoFrame * p, int plane)
269 {
270 return (*(const PVideoFrame*)&p)->GetRowSize(plane);
271 }
272
273 extern "C"
274 int AVSC_CC avs_get_height_p(const AVS_VideoFrame * p, int plane)
275 {
276 return (*(const PVideoFrame*)&p)->GetHeight(plane);
277 }
278
279 extern "C"
280 const BYTE * AVSC_CC avs_get_read_ptr_p(const AVS_VideoFrame * p, int plane)
281 {
282 return (*(const PVideoFrame*)&p)->GetReadPtr(plane);
283 }
284
285 extern "C"
286 int AVSC_CC avs_is_writable(const AVS_VideoFrame * p)
287 {
288 return (*(const PVideoFrame*)&p)->IsWritable() ? 1 : 0;
289 }
290
291 // V9
292 extern "C"
293 int AVSC_CC avs_is_property_writable(const AVS_VideoFrame * p)
294 {
295 return (*(const PVideoFrame*)&p)->IsPropertyWritable() ? 1 : 0;
296 }
297
298 // V10
299 extern "C"
300 int AVSC_CC avs_video_frame_get_pixel_type(const AVS_VideoFrame * p)
301 {
302 return (*(const PVideoFrame*)&p)->GetPixelType();
303 }
304
305 // V10
306 void AVSC_CC avs_video_frame_amend_pixel_type(AVS_VideoFrame* p, int new_pixel_type)
307 {
308 (*(PVideoFrame*)&p)->AmendPixelType(new_pixel_type);
309 }
310
311 extern "C"
312 BYTE * AVSC_CC avs_get_write_ptr_p(const AVS_VideoFrame * p, int plane)
313 {
314 return (*(const PVideoFrame*)&p)->GetWritePtr(plane);
315 }
316
317 extern "C"
318 void AVSC_CC avs_release_video_frame(AVS_VideoFrame * f)
319 {
320 ((PVideoFrame*)&f)->~PVideoFrame();
321 }
322
323 extern "C"
324 AVS_VideoFrame * AVSC_CC avs_copy_video_frame(AVS_VideoFrame * f)
325 {
326 AVS_VideoFrame* fnew;
327 new ((PVideoFrame*)&fnew) PVideoFrame(*(PVideoFrame*)&f);
328 return fnew;
329 }
330
331
332 extern "C"
333 int AVSC_CC avs_num_components(const AVS_VideoInfo * p)
334 {
335 return ((VideoInfo*)p)->NumComponents();
336 }
337
338 extern "C"
339 int AVSC_CC avs_component_size(const AVS_VideoInfo * p)
340 {
341 return ((VideoInfo*)p)->ComponentSize();
342 }
343
344 extern "C"
345 int AVSC_CC avs_bits_per_component(const AVS_VideoInfo * p)
346 {
347 return ((VideoInfo*)p)->BitsPerComponent();
348 }
349
350 // V10.1
351 extern "C"
352 bool AVSC_CC avs_is_channel_mask_known(const AVS_VideoInfo * p)
353 {
354 return ((VideoInfo*)p)->IsChannelMaskKnown();
355 }
356
357 extern "C"
358 void AVSC_CC avs_set_channel_mask(const AVS_VideoInfo * p, bool isChannelMaskKnown, unsigned int dwChannelMask)
359 {
360 ((VideoInfo*)p)->SetChannelMask(isChannelMaskKnown, dwChannelMask);
361 }
362
363 extern "C"
364 unsigned int AVSC_CC avs_get_channel_mask(const AVS_VideoInfo * p)
365 {
366 return ((VideoInfo*)p)->GetChannelMask();
367 }
368
369 //////////////////////////////////////////////////////////
370 //
371 // frame properties
372 //
373 extern "C"
374 void AVSC_CC avs_copy_frame_props(AVS_ScriptEnvironment * p, const AVS_VideoFrame * src, AVS_VideoFrame * dst)
375 {
376 p->error = 0;
377 try {
378 p->env->copyFrameProps(*(const PVideoFrame*)&src, *(PVideoFrame*)&dst);
379 }
380 catch (const AvisynthError& err) {
381 p->error = err.msg;
382 }
383 }
384
385 extern "C"
386 const AVS_Map * AVSC_CC avs_get_frame_props_ro(AVS_ScriptEnvironment * p, const AVS_VideoFrame * frame)
387 {
388 p->error = 0;
389 try {
390 return (const AVS_Map*)(p->env->getFramePropsRO(*(const PVideoFrame*)&frame));
391 }
392 catch (const AvisynthError& err) {
393 p->error = err.msg;
394 return 0;
395 }
396 }
397
398 extern "C"
399 AVS_Map * AVSC_CC avs_get_frame_props_rw(AVS_ScriptEnvironment * p, AVS_VideoFrame * frame)
400 {
401 p->error = 0;
402 try {
403 return (AVS_Map*)(p->env->getFramePropsRW(*(PVideoFrame*)&frame));
404 }
405 catch (const AvisynthError& err) {
406 p->error = err.msg;
407 return 0;
408 }
409 }
410
411 extern "C"
412 int AVSC_CC avs_prop_num_keys(AVS_ScriptEnvironment * p, const AVS_Map * map)
413 {
414 p->error = 0;
415 try {
416 return (p->env->propNumKeys((const AVSMap*)map));
417 }
418 catch (const AvisynthError& err) {
419 p->error = err.msg;
420 return 0;
421 }
422 }
423
424 extern "C"
425 const char* AVSC_CC avs_prop_get_key(AVS_ScriptEnvironment * p, const AVS_Map * map, int index)
426 {
427 p->error = 0;
428 try {
429 const char* key = (p->env->propGetKey((const AVSMap*)map, index));
430 return p->env->SaveString(key);
431 }
432 catch (const AvisynthError& err) {
433 p->error = err.msg;
434 return 0;
435 }
436 }
437
438 extern "C"
439 int AVSC_CC avs_prop_num_elements(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key)
440 {
441 p->error = 0;
442 try {
443 return (p->env->propNumElements((const AVSMap*)map, key));
444 }
445 catch (const AvisynthError& err) {
446 p->error = err.msg;
447 return 0;
448 }
449 }
450
451 extern "C"
452 char AVSC_CC avs_prop_get_type(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key)
453 {
454 p->error = 0;
455 try {
456 return (p->env->propGetType((const AVSMap*)map, key));
457 }
458 catch (const AvisynthError& err) {
459 p->error = err.msg;
460 return 0;
461 }
462 }
463
464 extern "C"
465 int AVSC_CC avs_prop_delete_key(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key)
466 {
467 p->error = 0;
468 try {
469 return (p->env->propDeleteKey((AVSMap*)map, key));
470 }
471 catch (const AvisynthError& err) {
472 p->error = err.msg;
473 return 0;
474 }
475 }
476
477 extern "C"
478 int64_t AVSC_CC avs_prop_get_int(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int index, int* error)
479 {
480 p->error = 0;
481 try {
482 return (p->env->propGetInt((const AVSMap*)map, key, index, error));
483 }
484 catch (const AvisynthError& err) {
485 p->error = err.msg;
486 return 0;
487 }
488 }
489
490 extern "C"
491 int AVSC_CC avs_prop_get_int_saturated(AVS_ScriptEnvironment* p, const AVS_Map* map, const char* key, int index, int* error)
492 {
493 p->error = 0;
494 try {
495 return (p->env->propGetIntSaturated((const AVSMap*)map, key, index, error));
496 }
497 catch (const AvisynthError& err) {
498 p->error = err.msg;
499 return 0;
500 }
501 }
502
503 extern "C"
504 double AVSC_CC avs_prop_get_float(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int index, int* error)
505 {
506 p->error = 0;
507 try {
508 return (p->env->propGetFloat((const AVSMap*)map, key, index, error));
509 }
510 catch (const AvisynthError& err) {
511 p->error = err.msg;
512 return 0;
513 }
514 }
515
516 // v11
517 extern "C"
518 float AVSC_CC avs_prop_get_float_saturated(AVS_ScriptEnvironment* p, const AVS_Map* map, const char* key, int index, int* error)
519 {
520 p->error = 0;
521 try {
522 return (p->env->propGetFloatSaturated((const AVSMap*)map, key, index, error));
523 }
524 catch (const AvisynthError& err) {
525 p->error = err.msg;
526 return 0;
527 }
528 }
529
530 extern "C"
531 const char* AVSC_CC avs_prop_get_data(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int index, int* error)
532 {
533 p->error = 0;
534 try {
535 const char* data = p->env->propGetData((const AVSMap*)map, key, index, error);
536 if (!data)
537 return nullptr;
538 else
539 return data;
540 }
541 catch (const AvisynthError& err) {
542 p->error = err.msg;
543 return 0;
544 }
545 }
546
547 extern "C"
548 int AVSC_CC avs_prop_get_data_size(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int index, int* error)
549 {
550 p->error = 0;
551 try {
552 return (p->env->propGetDataSize((const AVSMap*)map, key, index, error));
553 }
554 catch (const AvisynthError& err) {
555 p->error = err.msg;
556 return 0;
557 }
558 }
559
560 extern "C"
561 int AVSC_CC avs_prop_get_data_type_hint(AVS_ScriptEnvironment* p, const AVS_Map* map, const char* key, int index, int* error)
562 {
563 p->error = 0;
564 try {
565 return (p->env->propGetDataTypeHint((const AVSMap*)map, key, index, error));
566 }
567 catch (const AvisynthError& err) {
568 p->error = err.msg;
569 return 0;
570 }
571 }
572
573 extern "C"
574 AVS_Clip* AVSC_CC avs_prop_get_clip(AVS_ScriptEnvironment* p, const AVS_Map* map, const char* key, int index, int* error)
575 {
576 p->error = 0;
577 try {
578 PClip c0 = p->env->propGetClip((const AVSMap*)map, key, index, error);
579 AVS_Clip* c;
580 new((PClip*)&c) PClip(c0);
581 return c;
582 }
583 catch (const AvisynthError& err) {
584 p->error = err.msg;
585 return 0;
586 }
587 }
588
589 extern "C"
590 const AVS_VideoFrame * AVSC_CC avs_prop_get_frame(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int index, int* error)
591 {
592 p->error = 0;
593 try {
594 const PVideoFrame f0 = p->env->propGetFrame((const AVSMap*)map, key, index, error);
595 AVS_VideoFrame* f;
596 new((PVideoFrame*)&f) PVideoFrame(f0);
597 return f;
598 }
599 catch (const AvisynthError& err) {
600 p->error = err.msg;
601 return 0;
602 }
603 }
604
605 extern "C"
606 int AVSC_CC avs_prop_set_int(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, int64_t i, int append)
607 {
608 p->error = 0;
609 try {
610 return (p->env->propSetInt((AVSMap*)map, key, i, append));
611 }
612 catch (const AvisynthError& err) {
613 p->error = err.msg;
614 return 0;
615 }
616 }
617
618 extern "C"
619 int AVSC_CC avs_prop_set_float(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, double d, int append)
620 {
621 p->error = 0;
622 try {
623 return (p->env->propSetFloat((AVSMap*)map, key, d, append));
624 }
625 catch (const AvisynthError& err) {
626 p->error = err.msg;
627 return 0;
628 }
629 }
630
631 extern "C"
632 int AVSC_CC avs_prop_set_data(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, const char* d, int length, int append)
633 {
634 // length = -1 -> auto strlen
635 p->error = 0;
636 try {
637 return (p->env->propSetData((AVSMap*)map, key, d, length, append));
638 }
639 catch (const AvisynthError& err) {
640 p->error = err.msg;
641 return 0;
642 }
643 }
644
645 extern "C"
646 int AVSC_CC avs_prop_set_data_h(AVS_ScriptEnvironment* p, AVS_Map* map, const char* key, const char* d, int length, int type, int append)
647 {
648 // length = -1 -> auto strlen
649 p->error = 0;
650 try {
651 return (p->env->propSetDataH((AVSMap*)map, key, d, length, type, append));
652 }
653 catch (const AvisynthError& err) {
654 p->error = err.msg;
655 return 0;
656 }
657 }
658
659 extern "C"
660 int AVSC_CC avs_prop_set_clip(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, AVS_Clip * clip, int append)
661 {
662 p->error = 0;
663 try {
664 return (p->env->propSetClip((AVSMap*)map, key, *(PClip*)clip, append));
665 }
666 catch (const AvisynthError& err) {
667 p->error = err.msg;
668 return 0;
669 }
670 }
671
672 extern "C"
673 int AVSC_CC avs_prop_set_frame(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, const AVS_VideoFrame * frame, int append)
674 {
675 p->error = 0;
676 try {
677 return (p->env->propSetFrame((AVSMap*)map, key, *(PVideoFrame*)&frame, append));
678 }
679 catch (const AvisynthError& err) {
680 p->error = err.msg;
681 return 0;
682 }
683 }
684
685
686 extern "C"
687 const int64_t * AVSC_CC avs_prop_get_int_array(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int* error)
688 {
689 p->error = 0;
690 try {
691 return p->env->propGetIntArray((const AVSMap*)map, key, error);
692 }
693 catch (const AvisynthError& err) {
694 p->error = err.msg;
695 return 0;
696 }
697 }
698
699 extern "C"
700 const double* AVSC_CC avs_prop_get_float_array(AVS_ScriptEnvironment * p, const AVS_Map * map, const char* key, int* error)
701 {
702 p->error = 0;
703 try {
704 return p->env->propGetFloatArray((const AVSMap*)map, key, error);
705 }
706 catch (const AvisynthError& err) {
707 p->error = err.msg;
708 return 0;
709 }
710 }
711
712 extern "C"
713 int AVSC_CC avs_prop_set_int_array(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, const int64_t * i, int size)
714 {
715 p->error = 0;
716 try {
717 return (p->env->propSetIntArray((AVSMap*)map, key, i, size));
718 }
719 catch (const AvisynthError& err) {
720 p->error = err.msg;
721 return 0;
722 }
723 }
724
725 extern "C"
726 int AVSC_CC avs_prop_set_float_array(AVS_ScriptEnvironment * p, AVS_Map * map, const char* key, const double* d, int size)
727 {
728 p->error = 0;
729 try {
730 return (p->env->propSetFloatArray((AVSMap*)map, key, d, size));
731 }
732 catch (const AvisynthError& err) {
733 p->error = err.msg;
734 return 0;
735 }
736 }
737
738 extern "C"
739 void AVSC_CC avs_clear_map(AVS_ScriptEnvironment * p, AVS_Map * map)
740 {
741 p->error = 0;
742 try {
743 p->env->clearMap((AVSMap*)map);
744 }
745 catch (const AvisynthError& err) {
746 p->error = err.msg;
747 }
748 }
749
750
751
752 /////////////////////////////////////////////////////////////////////
753 //
754 // C_VideoFilter
755 //
756
757 PVideoFrame C_VideoFilter::GetFrame(int n, IScriptEnvironment* env)
758 {
759 if (d.get_frame) {
760 d.error = 0;
761 AVS_VideoFrame* f = d.get_frame(&d, n);
762 if (d.error)
763 throw AvisynthError(d.error);
764 if (d.child != NULL && d.child->error)
765 throw AvisynthError(d.child->error);
766 PVideoFrame fr((VideoFrame*)f);
767 ((PVideoFrame*)&f)->~PVideoFrame();
768 return fr;
769 }
770 else {
771 return d.child->clip->GetFrame(n, env);
772 }
773 }
774
775 void __stdcall C_VideoFilter::GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env)
776 {
777 if (d.get_audio) {
778 d.error = 0;
779 d.get_audio(&d, buf, start, count);
780 if (d.error)
781 throw AvisynthError(d.error);
782 }
783 else {
784 d.child->clip->GetAudio(buf, start, count, env);
785 }
786 }
787
788 const VideoInfo& __stdcall C_VideoFilter::GetVideoInfo()
789 {
790 return *(VideoInfo*)&d.vi;
791 }
792
793 bool __stdcall C_VideoFilter::GetParity(int n)
794 {
795 if (d.get_parity) {
796 d.error = 0;
797 int res = d.get_parity(&d, n);
798 if (d.error)
799 throw AvisynthError(d.error);
800 return !!res;
801 }
802 else {
803 return d.child->clip->GetParity(n);
804 }
805 }
806
807 int __stdcall C_VideoFilter::SetCacheHints(int cachehints, int frame_range)
808 {
809 if (d.set_cache_hints) {
810 d.error = 0;
811 int res = d.set_cache_hints(&d, cachehints, frame_range);
812 if (d.error)
813 throw AvisynthError(d.error);
814 return res;
815 }
816 // We do not pass cache requests upwards, only to the hosted filter.
817 return 0;
818 }
819
820 C_VideoFilter::~C_VideoFilter()
821 {
822 if (d.free_filter)
823 d.free_filter(&d);
824 }
825
826 /////////////////////////////////////////////////////////////////////
827 //
828 // AVS_Clip
829 //
830
831 extern "C"
832 void AVSC_CC avs_release_clip(AVS_Clip * p)
833 {
834 delete p;
835 }
836
837 AVS_Clip* AVSC_CC avs_copy_clip(AVS_Clip* p)
838 {
839 return new AVS_Clip(*p);
840 }
841
842 extern "C"
843 const char* AVSC_CC avs_clip_get_error(AVS_Clip * p) // return 0 if no error
844 {
845 return p->error;
846 }
847
848 extern "C"
849 int AVSC_CC avs_get_version(AVS_Clip * p)
850 {
851 return p->clip->GetVersion();
852 }
853
854 extern "C"
855 const AVS_VideoInfo * AVSC_CC avs_get_video_info(AVS_Clip * p)
856 {
857 return (const AVS_VideoInfo*)&p->clip->GetVideoInfo();
858 }
859
860
861 extern "C"
862 AVS_VideoFrame * AVSC_CC avs_get_frame(AVS_Clip * p, int n)
863 {
864 p->error = 0;
865 try {
866 PVideoFrame f0 = p->clip->GetFrame(n, p->env);
867 AVS_VideoFrame* f;
868 new((PVideoFrame*)&f) PVideoFrame(f0);
869 return f;
870 }
871 catch (const AvisynthError& err) {
872 p->error = err.msg;
873 return 0;
874 }
875 }
876
877 extern "C"
878 int AVSC_CC avs_get_parity(AVS_Clip * p, int n) // return field parity if field_based, else parity of first field in frame
879 {
880 try {
881 p->error = 0;
882 return p->clip->GetParity(n);
883 }
884 catch (const AvisynthError& err) {
885 p->error = err.msg;
886 return -1;
887 }
888 }
889
890 extern "C"
891 int AVSC_CC avs_get_audio(AVS_Clip * p, void* buf, int64_t start, int64_t count) // start and count are in samples
892 {
893 try {
894 p->error = 0;
895 p->clip->GetAudio(buf, start, count, p->env);
896 return 0;
897 }
898 catch (const AvisynthError& err) {
899 p->error = err.msg;
900 return -1;
901 }
902 }
903
904 extern "C"
905 int AVSC_CC avs_set_cache_hints(AVS_Clip * p, int cachehints, int frame_range) // We do not pass cache requests upwards, only to the next filter.
906 {
907 try {
908 p->error = 0;
909 return p->clip->SetCacheHints(cachehints, frame_range);
910 }
911 catch (const AvisynthError& err) {
912 p->error = err.msg;
913 return -1;
914 }
915 }
916
917 //////////////////////////////////////////////////////////////////
918 //
919 //
920 //
921 extern "C"
922 AVS_Clip * AVSC_CC avs_take_clip(AVS_Value v, AVS_ScriptEnvironment * env)
923 {
924 AVS_Clip* c = new AVS_Clip;
925 c->env = env->env;
926 c->clip = (IClip*)v.d.clip;
927 return c;
928 }
929
930 // v11 API AVS_Value type checkers.
931 extern "C"
932 int AVSC_CC avs_val_defined(AVS_Value v) { return ((const AVSValue*)(&v))->Defined() ? 1 : 0; }
933 extern "C"
934 int AVSC_CC avs_val_is_clip(AVS_Value v) { return ((const AVSValue*)(&v))->IsClip() ? 1 : 0; }
935 extern "C"
936 int AVSC_CC avs_val_is_bool(AVS_Value v) { return ((const AVSValue*)(&v))->IsBool() ? 1 : 0; }
937 extern "C"
938 int AVSC_CC avs_val_is_int(AVS_Value v) { return ((const AVSValue*)(&v))->IsInt() ? 1 : 0; }
939 extern "C"
940 int AVSC_CC avs_val_is_long_strict(AVS_Value v) { return ((const AVSValue*)(&v))->IsLongStrict() ? 1 : 0; }
941 extern "C"
942 int AVSC_CC avs_val_is_float(AVS_Value v) { return ((const AVSValue*)(&v))->IsFloat() ? 1 : 0; }
943 extern "C"
944 int AVSC_CC avs_val_is_floatf_strict(AVS_Value v) { return ((const AVSValue*)(&v))->IsFloatfStrict() ? 1 : 0; }
945 extern "C"
946 int AVSC_CC avs_val_is_string(AVS_Value v) { return ((const AVSValue*)(&v))->IsString() ? 1 : 0; }
947 extern "C"
948 int AVSC_CC avs_val_is_array(AVS_Value v) { return ((const AVSValue*)(&v))->IsArray() ? 1 : 0; }
949 extern "C"
950 int AVSC_CC avs_val_is_error(AVS_Value v) { return v.type == 'e' ? 1 : 0; }
951
952
953 // v11 API AVS_Value setters
954 extern "C"
955 void AVSC_CC avs_set_to_error(AVS_Value* v, const char* v0) { new(v) AVSValue(v0); /*string->error*/ v->type = 'e'; }
956 extern "C"
957 void AVSC_CC avs_set_to_bool(AVS_Value* v, int v0) { new(v) AVSValue(v0 != 0); }
958 extern "C"
959 void AVSC_CC avs_set_to_int(AVS_Value* v, int v0) { new(v) AVSValue(v0); }
960 extern "C"
961 void AVSC_CC avs_set_to_float(AVS_Value* v, float v0) { new(v) AVSValue(v0); }
962 extern "C"
963 void AVSC_CC avs_set_to_string(AVS_Value* v, const char* v0) { new(v) AVSValue(v0); }
964 extern "C"
965 void AVSC_CC avs_set_to_double(AVS_Value* v, double d) { new(v) AVSValue(d); }
966 extern "C"
967 void AVSC_CC avs_set_to_long(AVS_Value* v, int64_t l) { new(v) AVSValue(l); }
968 extern "C"
969 void AVSC_CC avs_set_to_array(AVS_Value* v, AVS_Value* src, int size) { new(v) AVSValue((AVSValue *)src, size); }
970 extern "C"
971 void AVSC_CC avs_set_to_void(AVS_Value* v) { new(v) AVSValue(); }
972 // existed pre V11
973 extern "C"
974 void AVSC_CC avs_set_to_clip(AVS_Value* v, AVS_Clip* c) { new(v) AVSValue(c->clip); }
975
976 extern "C"
977 void AVSC_CC avs_copy_value(AVS_Value * dest, AVS_Value src)
978 {
979 #if 0
980 // no need to guard multidim arrays. avs_release_value will release properly.
981 // true: don't copy array elements recursively
982 new(dest) AVSValue(*(const AVSValue*)&src, true);
983 #endif
984 // CONSTRUCTOR9-->Assign(&v, init=true) ensures that the original content
985 // is simply overwritten and will not be freed.
986 new(dest) AVSValue(*(const AVSValue*)&src);
987 }
988
989 // Releases/free resources contained in an AVS_Value
990 // Such types are:
991 // - clip
992 // - function (not supported on C interface)
993 // - double and long on 32 bit architects
994 // - Avisynth+ arrays
995 // Since AVS_Value is just a struct passed by value, nothing else happens.
996 // If AVS_Value has no extra resource to free up, nothing is done.
997 // release is mandatory for results of:
998 // - avs_invoke
999 // - avs_copy_value
1000 // - avs_set_to_double (x86)
1001 // - avs_set_to_long (x86)
1002 // - avs_set_to_array, avs_set_to_clip
1003 // - in general: all avs_set_xxx values
1004
1005 // Note:
1006 // Unlike dynamic arrays, which have a full create-copy-modify-release cycle,
1007 // C plugins/clients can use in-source arrays, typically for assembling function
1008 // parameters ("args"). Do not call avs_release_value on such arrays, as it causes
1009 // a crash since the array itself and the elements are not maintained by the
1010 // Avisynth core.However, it is good practice to release the array content
1011 // with avs_release_value one-by-one for the resource-allocated types mentioned above.
1012
1013 extern "C"
1014 void AVSC_CC avs_release_value(AVS_Value v)
1015 {
1016 #if 0
1017 // This would prevent crashes when a C client calls it for an array.
1018 // However, since Avisynth+ arrays can be returned by avs_invoke, avs_copy_value,
1019 // and avs_set_to_array, this exemption is no longer valid.
1020 // This rule was not explicitly written earlier and must be enforced in clients/plugins,
1021 // see the Python wrapper issue in AvsPmod, which was fixed.
1022 if (((AVSValue*)&v)->IsArray()) {
1023 // signing for destructor: don't free array elements
1024 ((AVSValue*)&v)->MarkArrayAsNonDeepCopy();
1025 }
1026 #endif
1027 ((AVSValue*)&v)->~AVSValue();
1028 }
1029
1030 // API AVS_Value getters, like INLINE versions
1031 extern "C"
1032 int AVSC_CC avs_get_as_bool(AVS_Value v) { return ((AVSValue*)&v)->AsBool() ? 1 : 0; }
1033
1034 extern "C"
1035 AVS_Clip* AVSC_CC avs_get_as_clip(AVS_Value v, AVS_ScriptEnvironment* env) {
1036 // like the existing avs_take_clip, to fit in the avs_get_as_xxxx line
1037 AVS_Clip* c = new AVS_Clip;
1038 c->env = env->env;
1039 c->clip = (IClip*)(v.d.clip);
1040 return c;
1041 }
1042
1043 extern "C"
1044 int AVSC_CC avs_get_as_int(AVS_Value v) { return ((AVSValue*)&v)->AsInt(); }
1045 extern "C"
1046 int64_t AVSC_CC avs_get_as_long(AVS_Value v) { return ((AVSValue*)&v)->AsLong(); }
1047 extern "C"
1048 const char* AVSC_CC avs_get_as_string(AVS_Value v) { return ((AVSValue*)&v)->AsString(); }
1049 extern "C"
1050 double AVSC_CC avs_get_as_float(AVS_Value v) { return ((AVSValue*)&v)->AsFloat(); }
1051 extern "C"
1052 const char* AVSC_CC avs_get_as_error(AVS_Value v) {
1053 if (v.type == 'e') {
1054 v.type = 's'; // 'e'rror is unknown in c++ api
1055 return ((AVSValue*)&v)->AsString();
1056 }
1057 return nullptr;
1058 }
1059 extern "C"
1060 const AVS_Value * AVSC_CC avs_get_as_array(AVS_Value v) { return v.d.array; }
1061 extern "C"
1062 AVS_Value AVSC_CC avs_get_array_elt(AVS_Value v, int index)
1063 { // just a dumb data copy, no ref counting, no resource handling
1064 return avs_is_array(v) ? v.d.array[index] : v;
1065 }
1066 extern "C"
1067 int AVSC_CC avs_get_array_size(AVS_Value v) { return ((AVSValue*)&v)->ArraySize(); }
1068
1069
1070 //////////////////////////////////////////////////////////////////
1071 //
1072 //
1073 //
1074
1075 extern "C"
1076 AVS_Clip * AVSC_CC avs_new_c_filter(AVS_ScriptEnvironment * e,
1077 AVS_FilterInfo * *fi,
1078 AVS_Value child, int store_child)
1079 {
1080 C_VideoFilter* f = new C_VideoFilter();
1081 AVS_Clip* ff = new AVS_Clip();
1082 ff->clip = f; // IClip descendant
1083 ff->env = e->env;
1084 f->env.env = e->env;
1085 f->d.env = &f->env;
1086 if (store_child) {
1087 _ASSERTE(child.type == 'c');
1088 f->child.clip = (IClip*)child.d.clip;
1089 f->child.env = e->env;
1090 f->d.child = &f->child;
1091 }
1092 *fi = &f->d;
1093 // (*fi)->free_filter will be set later by the plugin.
1094 // It is used in ~C_VideoFilter, which is called when the clip's
1095 // reference count reaches zero and it is released. This serves
1096 // as the filter destructor in C.
1097 if (child.type == 'c')
1098 f->d.vi = *(const AVS_VideoInfo*)(&((IClip*)child.d.clip)->GetVideoInfo());
1099 return ff;
1100 }
1101
1102 /////////////////////////////////////////////////////////////////////
1103 //
1104 // AVS_ScriptEnvironment::add_function
1105 //
1106
1107 struct C_VideoFilter_UserData {
1108 void* user_data;
1109 AVS_ApplyFunc func;
1110 AVS_ApplyFuncR func_r;
1111 };
1112
1113 AVSValue __cdecl create_c_video_filter(AVSValue args, void* user_data,
1114 IScriptEnvironment* e0)
1115 {
1116 C_VideoFilter_UserData* d = (C_VideoFilter_UserData*)user_data;
1117 AVS_ScriptEnvironment env;
1118 env.env = e0;
1119 env.error = NULL;
1120
1121 AVS_Value res;
1122 if(d->func)
1123 res = (d->func)(&env, *(AVS_Value*)&args, d->user_data);
1124 else
1125 (d->func_r)(&env, (AVS_Value*)&res, *(AVS_Value*)&args, d->user_data); // new in v11: byref
1126 if (res.type == 'e') {
1127 throw AvisynthError(res.d.string);
1128 }
1129 else {
1130 AVSValue val;
1131 val = (*(const AVSValue*)&res);
1132 ((AVSValue*)&res)->~AVSValue();
1133 return val;
1134 }
1135 }
1136
1137 extern "C"
1138 int AVSC_CC
1139 avs_add_function(AVS_ScriptEnvironment * p, const char* name, const char* params,
1140 AVS_ApplyFunc applyf, void* user_data)
1141 {
1142 C_VideoFilter_UserData* dd, * d = new C_VideoFilter_UserData;
1143 p->error = 0;
1144 d->func = applyf; // return value struct
1145 d->func_r = nullptr;
1146 d->user_data = user_data;
1147 dd = (C_VideoFilter_UserData*)p->env->SaveString((const char*)d, sizeof(C_VideoFilter_UserData));
1148 delete d;
1149 try {
1150 p->env->AddFunction(name, params, create_c_video_filter, dd);
1151 }
1152 catch (AvisynthError& err) {
1153 p->error = err.msg;
1154 return -1;
1155 }
1156 return 0;
1157 }
1158
1159 // v11
1160 extern "C"
1161 int AVSC_CC
1162 avs_add_function_r(AVS_ScriptEnvironment* p, const char* name, const char* params,
1163 AVS_ApplyFuncR applyf, void* user_data)
1164 {
1165 C_VideoFilter_UserData* dd, * d = new C_VideoFilter_UserData;
1166 p->error = 0;
1167 d->func = nullptr;
1168 d->func_r = applyf; // return value among parameters byref struct (Python cref callbacks like it better)
1169 d->user_data = user_data;
1170 dd = (C_VideoFilter_UserData*)p->env->SaveString((const char*)d, sizeof(C_VideoFilter_UserData));
1171 delete d;
1172 try {
1173 p->env->AddFunction(name, params, create_c_video_filter, dd);
1174 }
1175 catch (AvisynthError& err) {
1176 p->error = err.msg;
1177 return -1;
1178 }
1179 return 0;
1180 }
1181
1182 /////////////////////////////////////////////////////////////////////
1183 //
1184 // AVS_ScriptEnvironment
1185 //
1186
1187 extern "C"
1188 const char* AVSC_CC avs_get_error(AVS_ScriptEnvironment * p) // return 0 if no error
1189 {
1190 return p->error;
1191 }
1192
1193 extern "C"
1194 int AVSC_CC avs_get_cpu_flags(AVS_ScriptEnvironment * p)
1195 {
1196 p->error = 0;
1197 return p->env->GetCPUFlags();
1198 }
1199
1200 extern "C"
1201 int64_t AVSC_CC avs_get_cpu_flags_ex(AVS_ScriptEnvironment* p)
1202 {
1203 p->error = 0;
1204 return p->env->GetCPUFlagsEx();
1205 }
1206
1207 extern "C"
1208 char* AVSC_CC avs_save_string(AVS_ScriptEnvironment * p, const char* s, int length)
1209 {
1210 p->error = 0;
1211 return p->env->SaveString(s, length);
1212 }
1213
1214 extern "C"
1215 char* AVSC_CC avs_sprintf(AVS_ScriptEnvironment * p, const char* fmt, ...)
1216 {
1217 p->error = 0;
1218 va_list vl;
1219 va_start(vl, fmt);
1220 char* v = p->env->VSprintf(fmt, vl);
1221 va_end(vl);
1222 return v;
1223 }
1224
1225 // note: val is really a va_list; I hope everyone typedefs va_list to a pointer
1226 extern "C"
1227 char* AVSC_CC avs_vsprintf(AVS_ScriptEnvironment * p, const char* fmt, va_list val)
1228 {
1229 p->error = 0;
1230 return p->env->VSprintf(fmt, val);
1231 }
1232
1233 extern "C"
1234 int AVSC_CC avs_function_exists(AVS_ScriptEnvironment * p, const char* name)
1235 {
1236 p->error = 0;
1237 return p->env->FunctionExists(name);
1238 }
1239
1240 extern "C"
1241 AVS_Value AVSC_CC avs_invoke(AVS_ScriptEnvironment* p, const char* name, AVS_Value args, const char** arg_names)
1242 {
1243 AVS_Value v = { 0,0 };
1244 p->error = 0;
1245 try {
1246 // AVSValue(*(AVSValue*)&args) is deep-copying input array
1247
1248 // Invoke has a special InvokePreV11C variant if pre V11 C interface
1249 // detected, which converts a possible 64 bit result to 32 bit one for
1250 // compatibility. double->float, long->int. Nothing should be done here.
1251 AVSValue v0 = p->env->Invoke(name, *(AVSValue*)&args, arg_names);
1252 new ((AVSValue*)&v) AVSValue(v0);
1253 }
1254 catch (const IScriptEnvironment::NotFound&) {
1255 p->error = "Function Not Found";
1256 }
1257 catch (const AvisynthError& err) {
1258 p->error = err.msg;
1259 }
1260 if (p->error)
1261 v = avs_new_value_error(p->error);
1262 return v;
1263 }
1264
1265 extern "C"
1266 AVS_Value AVSC_CC avs_get_var(AVS_ScriptEnvironment * p, const char* name)
1267 {
1268 AVS_Value v = { 0,0 };
1269 p->error = 0;
1270 try {
1271 AVSValue v0 = p->env->GetVar(name);
1272 new ((AVSValue*)&v) AVSValue(v0);
1273 }
1274 catch (const IScriptEnvironment::NotFound&) {}
1275 catch (const AvisynthError& err) {
1276 p->error = err.msg;
1277 v = avs_new_value_error(p->error);
1278 }
1279 return v;
1280 }
1281
1282 extern "C"
1283 int AVSC_CC avs_set_var(AVS_ScriptEnvironment * p, const char* name, AVS_Value val)
1284 {
1285 p->error = 0;
1286 try {
1287 return p->env->SetVar(p->env->SaveString(name), *(const AVSValue*)(&val));
1288 }
1289 catch (const AvisynthError& err) {
1290 p->error = err.msg;
1291 return -1;
1292 }
1293 }
1294
1295 extern "C"
1296 int AVSC_CC avs_set_global_var(AVS_ScriptEnvironment * p, const char* name, AVS_Value val)
1297 {
1298 p->error = 0;
1299 try {
1300 return p->env->SetGlobalVar(p->env->SaveString(name), *(const AVSValue*)(&val));
1301 }
1302 catch (const AvisynthError& err) {
1303 p->error = err.msg;
1304 return -1;
1305 }
1306 }
1307
1308 extern "C"
1309 AVS_VideoFrame * AVSC_CC avs_new_video_frame_a(AVS_ScriptEnvironment * p, const AVS_VideoInfo * vi, int align)
1310 {
1311 p->error = 0;
1312 try {
1313 PVideoFrame f0 = p->env->NewVideoFrame(*(const VideoInfo*)vi, align);
1314 AVS_VideoFrame* f;
1315 new((PVideoFrame*)&f) PVideoFrame(f0);
1316 return f;
1317 }
1318 catch (const AvisynthError& err) {
1319 p->error = err.msg;
1320 }
1321 return 0;
1322 }
1323
1324 // with frame properties, and alignment
1325 // note: in general there is no need for alignment specificationm use avs_new_video_frame_p
1326 extern "C"
1327 AVS_VideoFrame * AVSC_CC avs_new_video_frame_p_a(AVS_ScriptEnvironment * p, const AVS_VideoInfo * vi, const AVS_VideoFrame * prop_src, int align)
1328 {
1329 p->error = 0;
1330 try {
1331 PVideoFrame f0 = p->env->NewVideoFrameP(*(const VideoInfo*)vi, (const PVideoFrame*)&prop_src, align);
1332 AVS_VideoFrame* f;
1333 new((PVideoFrame*)&f) PVideoFrame(f0);
1334 return f;
1335 }
1336 catch (const AvisynthError& err) {
1337 p->error = err.msg;
1338 }
1339 return 0;
1340 }
1341
1342 // with frame properties, no extra alignment requirement
1343 extern "C"
1344 AVS_VideoFrame * AVSC_CC avs_new_video_frame_p(AVS_ScriptEnvironment * p, const AVS_VideoInfo * vi, const AVS_VideoFrame * prop_src)
1345 {
1346 p->error = 0;
1347 try {
1348 PVideoFrame f0 = p->env->NewVideoFrameP(*(const VideoInfo*)vi, (const PVideoFrame*)&prop_src, AVS_FRAME_ALIGN);
1349 AVS_VideoFrame* f;
1350 new((PVideoFrame*)&f) PVideoFrame(f0);
1351 return f;
1352 }
1353 catch (const AvisynthError& err) {
1354 p->error = err.msg;
1355 }
1356 return 0;
1357 }
1358
1359
1360 extern "C"
1361 int AVSC_CC avs_make_writable(AVS_ScriptEnvironment * p, AVS_VideoFrame * *pvf)
1362 {
1363 p->error = 0;
1364 try {
1365 return p->env->MakeWritable((PVideoFrame*)(pvf));
1366 }
1367 catch (const AvisynthError& err) {
1368 p->error = err.msg;
1369 }
1370 return -1;
1371 }
1372
1373 // Since V9
1374 extern "C"
1375 int AVSC_CC avs_make_property_writable(AVS_ScriptEnvironment * p, AVS_VideoFrame * *pvf)
1376 {
1377 p->error = 0;
1378 try {
1379 return p->env->MakePropertyWritable((PVideoFrame*)(pvf));
1380 }
1381 catch (const AvisynthError& err) {
1382 p->error = err.msg;
1383 }
1384 return -1;
1385 }
1386
1387 extern "C"
1388 void AVSC_CC avs_bit_blt(AVS_ScriptEnvironment * p, BYTE * dstp, int dst_pitch, const BYTE * srcp, int src_pitch, int row_size, int height)
1389 {
1390 p->error = 0;
1391 try {
1392 p->env->BitBlt(dstp, dst_pitch, srcp, src_pitch, row_size, height);
1393 }
1394 catch (const AvisynthError& err) {
1395 p->error = err.msg;
1396 }
1397 }
1398
1399 struct ShutdownFuncData
1400 {
1401 AVS_ShutdownFunc func;
1402 void* user_data;
1403 };
1404
1405 void __cdecl shutdown_func_bridge(void* user_data, IScriptEnvironment* env)
1406 {
1407 ShutdownFuncData* d = (ShutdownFuncData*)user_data;
1408 AVS_ScriptEnvironment e;
1409 e.env = env;
1410 e.error = NULL;
1411 d->func(d->user_data, &e);
1412 }
1413
1414 extern "C"
1415 void AVSC_CC avs_at_exit(AVS_ScriptEnvironment * p,
1416 AVS_ShutdownFunc function, void* user_data)
1417 {
1418 p->error = 0;
1419 ShutdownFuncData* dd, * d = new ShutdownFuncData;
1420 d->func = function;
1421 d->user_data = user_data;
1422 dd = (ShutdownFuncData*)p->env->SaveString((const char*)d, sizeof(ShutdownFuncData));
1423 delete d;
1424 p->env->AtExit(shutdown_func_bridge, dd);
1425 }
1426
1427 extern "C"
1428 int AVSC_CC avs_check_version(AVS_ScriptEnvironment * p, int version)
1429 {
1430 p->error = 0;
1431 try {
1432 p->env->CheckVersion(version);
1433 return 0;
1434 }
1435 catch (const AvisynthError& err) {
1436 p->error = err.msg;
1437 return -1;
1438 }
1439 }
1440
1441 extern "C"
1442 AVS_VideoFrame * AVSC_CC avs_subframe(AVS_ScriptEnvironment * p, AVS_VideoFrame * src0,
1443 int rel_offset, int new_pitch, int new_row_size, int new_height)
1444 {
1445 p->error = 0;
1446 try {
1447 PVideoFrame f0 = p->env->Subframe((VideoFrame*)src0, rel_offset, new_pitch, new_row_size, new_height);
1448 AVS_VideoFrame* f;
1449 new((PVideoFrame*)&f) PVideoFrame(f0);
1450 return f;
1451 }
1452 catch (const AvisynthError& err) {
1453 p->error = err.msg;
1454 return 0;
1455 }
1456 }
1457
1458 extern "C"
1459 AVS_VideoFrame * AVSC_CC avs_subframe_planar(AVS_ScriptEnvironment * p, AVS_VideoFrame * src0,
1460 int rel_offset, int new_pitch, int new_row_size, int new_height,
1461 int rel_offsetU, int rel_offsetV, int new_pitchUV)
1462 {
1463 p->error = 0;
1464 try {
1465 PVideoFrame f0 = p->env->SubframePlanar((VideoFrame*)src0, rel_offset, new_pitch, new_row_size,
1466 new_height, rel_offsetU, rel_offsetV, new_pitchUV);
1467 AVS_VideoFrame* f;
1468 new((PVideoFrame*)&f) PVideoFrame(f0);
1469 return f;
1470 }
1471 catch (const AvisynthError& err) {
1472 p->error = err.msg;
1473 return 0;
1474 }
1475 }
1476
1477 // Interface V8
1478 extern "C"
1479 AVS_VideoFrame * AVSC_CC avs_subframe_planar_a(AVS_ScriptEnvironment * p, AVS_VideoFrame * src0,
1480 int rel_offset, int new_pitch, int new_row_size, int new_height,
1481 int rel_offsetU, int rel_offsetV, int new_pitchUV, int rel_offsetA)
1482 {
1483 p->error = 0;
1484 try {
1485 PVideoFrame f0 = p->env->SubframePlanarA((VideoFrame*)src0, rel_offset, new_pitch, new_row_size,
1486 new_height, rel_offsetU, rel_offsetV, new_pitchUV, rel_offsetA);
1487 AVS_VideoFrame* f;
1488 new((PVideoFrame*)&f) PVideoFrame(f0);
1489 return f;
1490 }
1491 catch (const AvisynthError& err) {
1492 p->error = err.msg;
1493 return 0;
1494 }
1495 }
1496
1497 extern "C"
1498 int AVSC_CC avs_set_memory_max(AVS_ScriptEnvironment * p, int mem)
1499 {
1500 p->error = 0;
1501 try {
1502 return p->env->SetMemoryMax(mem);
1503 }
1504 catch (const AvisynthError& err) {
1505 p->error = err.msg;
1506 return -1;
1507 }
1508 }
1509
1510 extern "C"
1511 int AVSC_CC avs_set_working_dir(AVS_ScriptEnvironment * p, const char* newdir)
1512 {
1513 p->error = 0;
1514 try {
1515 return p->env->SetWorkingDir(newdir);
1516 }
1517 catch (const AvisynthError& err) {
1518 p->error = err.msg;
1519 return -1;
1520 }
1521 }
1522
1523 // V12
1524 extern "C"
1525 int AVSC_CC avs_acquire_global_lock(AVS_ScriptEnvironment* p, const char* name)
1526 {
1527 p->error = 0;
1528 try {
1529 return p->env->AcquireGlobalLock(name) ? 1 : 0;
1530 }
1531 catch (const AvisynthError& err) {
1532 p->error = err.msg;
1533 return 0;
1534 }
1535 }
1536
1537 // V12
1538 extern "C"
1539 void AVSC_CC avs_release_global_lock(AVS_ScriptEnvironment* p, const char* name)
1540 {
1541 p->error = 0;
1542 try {
1543 p->env->ReleaseGlobalLock(name);
1544 }
1545 catch (const AvisynthError& err) {
1546 p->error = err.msg;
1547 }
1548 }
1549
1550 // Interface V8. See AVS_AEP_xxx enums
1551 extern "C"
1552 size_t AVSC_CC avs_get_env_property(AVS_ScriptEnvironment * p, int avs_aep_prop)
1553 {
1554 p->error = 0;
1555 try {
1556 return p->env->GetEnvProperty((AvsEnvProperty)avs_aep_prop);
1557 }
1558 catch (const AvisynthError& err) {
1559 p->error = err.msg;
1560 return 0;
1561 }
1562 }
1563
1564 // Interface V8, buffer pool, Support functions
1565 // see AVS_ALLOCTYPE_xxx enum
1566 extern "C"
1567 void * AVSC_CC avs_pool_allocate(AVS_ScriptEnvironment * p, size_t nBytes, size_t alignment, int avs_alloc_type)
1568 {
1569 p->error = 0;
1570 try {
1571 return p->env->Allocate(nBytes, alignment, (AvsAllocType)avs_alloc_type);
1572 }
1573 catch (const AvisynthError& err) {
1574 p->error = err.msg;
1575 return 0;
1576 }
1577 }
1578
1579 extern "C"
1580 void AVSC_CC avs_pool_free(AVS_ScriptEnvironment * p, void* ptr)
1581 {
1582 p->error = 0;
1583 try {
1584 return p->env->Free(ptr);
1585 }
1586 catch (const AvisynthError& err) {
1587 p->error = err.msg;
1588 }
1589 }
1590
1591 // Returns TRUE (1) and the requested variable. If the method fails, returns 0 (FALSE) and does not touch 'val'.
1592 // The returned AVS_Value *val value must be be released with avs_release_value only on success
1593 // AVS_Value *val is not caller allocated
1594 extern "C"
1595 int AVSC_CC avs_get_var_try(AVS_ScriptEnvironment * p, const char* name, AVS_Value *val)
1596 {
1597 p->error = 0;
1598 AVSValue v0;
1599 const bool success = p->env->GetVarTry(name, &v0);
1600 if (success) {
1601 new ((AVSValue*)val) AVSValue(v0);
1602 return 1;
1603 }
1604 return 0;
1605 }
1606
1607 // Return the value of the requested variable.
1608 // If the variable was not found or had the wrong type,
1609 // return the supplied default value.
1610 extern "C"
1611 int AVSC_CC avs_get_var_bool(AVS_ScriptEnvironment * p, const char* name, int def)
1612 {
1613 p->error = 0;
1614 return (int)(p->env->GetVarBool(name, (bool)def));
1615 }
1616
1617 extern "C"
1618 int AVSC_CC avs_get_var_int(AVS_ScriptEnvironment * p, const char* name, int def)
1619 {
1620 p->error = 0;
1621 return p->env->GetVarInt(name, def);
1622 }
1623
1624 extern "C"
1625 double AVSC_CC avs_get_var_double(AVS_ScriptEnvironment * p, const char* name, double def)
1626 {
1627 p->error = 0;
1628 return p->env->GetVarDouble(name, def);
1629 }
1630
1631 extern "C"
1632 const char * AVSC_CC avs_get_var_string(AVS_ScriptEnvironment * p, const char* name, const char* def)
1633 {
1634 p->error = 0;
1635 return p->env->GetVarString(name, def);
1636 }
1637
1638 extern "C"
1639 int64_t AVSC_CC avs_get_var_long(AVS_ScriptEnvironment * p, const char* name, int64_t def)
1640 {
1641 p->error = 0;
1642 return p->env->GetVarLong(name, def);
1643 }
1644
1645 /////////////////////////////////////////////////////////////////////
1646 //
1647 //
1648 //
1649
1650 // prototype from avisynth.cpp
1651 IScriptEnvironment2* CreateScriptEnvironment2_internal(int version, bool fromAvs25, bool fromC);
1652
1653 extern "C"
1654 AVS_ScriptEnvironment * AVSC_CC avs_create_script_environment(int version)
1655 {
1656 AVS_ScriptEnvironment* e = new AVS_ScriptEnvironment;
1657 try {
1658 if (version < AVISYNTH_CLASSIC_INTERFACE_VERSION)
1659 version = AVISYNTH_CLASSIC_INTERFACE_VERSION; // always request a more modern ScriptEnvironment.
1660 e->env = CreateScriptEnvironment2_internal(version, false, true); // flag: from C
1661 e->error = NULL;
1662 }
1663 catch (const AvisynthError& err) {
1664 e->error = err.msg;
1665 e->env = 0;
1666 }
1667 return e;
1668 }
1669
1670
1671 /////////////////////////////////////////////////////////////////////
1672 //
1673 //
1674 //
1675
1676 extern "C"
1677 void AVSC_CC avs_delete_script_environment(AVS_ScriptEnvironment * e)
1678 {
1679 if (e) {
1680 if (e->env) {
1681 try {
1682 e->env->DeleteScriptEnvironment();
1683 }
1684 catch (const AvisynthError& err) {
1685 (void)err; // silence warning about unused variable; variable is kept for debugging
1686 }
1687 e->env = 0;
1688 }
1689 delete e;
1690 }
1691 }
1692