mediaMachineAPI.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_API_MEDIA_MACHINE
  24. #define DFPSR_API_MEDIA_MACHINE
  25. #include "../math/FixedPoint.h"
  26. #include "../api/types.h"
  27. namespace dsr {
  28. MediaMachine machine_create(const ReadableString& code);
  29. // Low-level call API
  30. int machine_findMethod(MediaMachine& machine, const ReadableString& methodName);
  31. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, int32_t input);
  32. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const FixedPoint& input);
  33. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const AlignedImageU8& input);
  34. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const OrderedImageRgbaU8& input);
  35. void machine_executeMethod(MediaMachine& machine, int methodIndex);
  36. FixedPoint machine_getFixedPointOutputByIndex(MediaMachine& machine, int methodIndex, int outputIndex);
  37. AlignedImageU8 machine_getImageU8OutputByIndex(MediaMachine& machine, int methodIndex, int outputIndex);
  38. OrderedImageRgbaU8 machine_getImageRgbaU8OutputByIndex(MediaMachine& machine, int methodIndex, int outputIndex);
  39. String machine_getMethodName(MediaMachine& machine, int methodIndex);
  40. int machine_getInputCount(MediaMachine& machine, int methodIndex);
  41. int machine_getOutputCount(MediaMachine& machine, int methodIndex);
  42. inline constexpr int argCount() {
  43. return 0;
  44. }
  45. template<typename HEAD, typename... TAIL>
  46. inline constexpr int argCount(HEAD& first, TAIL&... args) {
  47. return argCount(args...) + 1;
  48. }
  49. // TODO: Prevent saving the result to avoid reading after another call
  50. class MediaResult {
  51. private:
  52. MediaMachine machine;
  53. int methodIndex;
  54. void writeResult(int outputIndex, int8_t& target) {
  55. target = fixedPoint_round(machine_getFixedPointOutputByIndex(this->machine, this->methodIndex, outputIndex));
  56. }
  57. void writeResult(int outputIndex, int16_t& target) {
  58. target = fixedPoint_round(machine_getFixedPointOutputByIndex(this->machine, this->methodIndex, outputIndex));
  59. }
  60. void writeResult(int outputIndex, int32_t& target) {
  61. target = fixedPoint_round(machine_getFixedPointOutputByIndex(this->machine, this->methodIndex, outputIndex));
  62. }
  63. void writeResult(int outputIndex, int64_t& target) {
  64. target = fixedPoint_round(machine_getFixedPointOutputByIndex(this->machine, this->methodIndex, outputIndex));
  65. }
  66. void writeResult(int outputIndex, FixedPoint& target) {
  67. target = machine_getFixedPointOutputByIndex(this->machine, this->methodIndex, outputIndex);
  68. }
  69. void writeResult(int outputIndex, AlignedImageU8& target) {
  70. target = machine_getImageU8OutputByIndex(this->machine, this->methodIndex, outputIndex);
  71. }
  72. void writeResult(int outputIndex, OrderedImageRgbaU8& target) {
  73. target = machine_getImageRgbaU8OutputByIndex(this->machine, this->methodIndex, outputIndex);
  74. }
  75. inline void writeResults(int firstInputIndex) {}
  76. template<typename HEAD, typename... TAIL>
  77. inline void writeResults(int firstInputIndex, HEAD& first, TAIL&... args) {
  78. this->writeResult(firstInputIndex, first);
  79. this->writeResults(firstInputIndex + 1, args...);
  80. }
  81. public:
  82. MediaResult(const MediaMachine& machine, int methodIndex)
  83. : machine(machine), methodIndex(methodIndex) {}
  84. // Write target references within () after a call to assign multiple outputs
  85. template <typename... ARGS>
  86. void operator () (ARGS&... args) {
  87. int givenCount = argCount(args...);
  88. int expectedCount = machine_getOutputCount(this->machine, this->methodIndex);
  89. if (givenCount != expectedCount) {
  90. throwError("The call to ", machine_getMethodName(this->machine, this->methodIndex), " expected ", expectedCount, " outputs, but ", givenCount, " references were assigned.\n");
  91. }
  92. this->writeResults(0, args...);
  93. }
  94. };
  95. class MediaMethod {
  96. public:
  97. MediaMachine machine;
  98. int methodIndex;
  99. private:
  100. inline void setInputs(int firstInputIndex) {}
  101. template<typename HEAD, typename... TAIL>
  102. inline void setInputs(int firstInputIndex, HEAD first, TAIL... args) {
  103. machine_setInputByIndex(this->machine, this->methodIndex, firstInputIndex, first);
  104. this->setInputs(firstInputIndex + 1, args...);
  105. }
  106. public:
  107. MediaMethod()
  108. : methodIndex(-1) {}
  109. MediaMethod(const MediaMachine& machine, int methodIndex)
  110. : machine(machine), methodIndex(methodIndex) {}
  111. // MediaMethod can be called like a function using arguments
  112. template <typename... ARGS>
  113. MediaResult operator () (ARGS... args) {
  114. int givenCount = argCount(args...);
  115. int expectedCount = machine_getInputCount(this->machine, this->methodIndex);
  116. if (givenCount != expectedCount) {
  117. throwError("The call to ", machine_getMethodName(this->machine, this->methodIndex), " expected ", expectedCount, " inputs, but ", givenCount, " values were given.\n");
  118. }
  119. this->setInputs(0, args...);
  120. machine_executeMethod(this->machine, this->methodIndex);
  121. return MediaResult(this->machine, this->methodIndex);
  122. }
  123. };
  124. MediaMethod machine_getMethod(MediaMachine& machine, const ReadableString& methodName);
  125. }
  126. #endif