aja-props.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "aja-props.hpp"
  2. #include "aja-common.hpp"
  3. #include <ajantv2/includes/ntv2devicefeatures.h>
  4. #include <ajantv2/includes/ntv2utils.h>
  5. // AJASource Properties
  6. SourceProps::SourceProps()
  7. : deviceID{DEVICE_ID_NOTFOUND},
  8. ioSelect{IOSelection::Invalid},
  9. // inputSource{NTV2_INPUTSOURCE_INVALID},
  10. videoFormat{NTV2_FORMAT_UNKNOWN},
  11. pixelFormat{NTV2_FBF_INVALID},
  12. sdiTransport{SDITransport::SingleLink},
  13. sdi4kTransport{SDITransport4K::TwoSampleInterleave},
  14. audioNumChannels{8},
  15. audioSampleSize{4},
  16. audioSampleRate{48000},
  17. vpids{},
  18. autoDetect{false},
  19. deactivateWhileNotShowing{false}
  20. {
  21. }
  22. SourceProps::SourceProps(NTV2DeviceID devID)
  23. : deviceID{devID},
  24. ioSelect{IOSelection::Invalid},
  25. // inputSource{NTV2_INPUTSOURCE_INVALID},
  26. videoFormat{NTV2_FORMAT_UNKNOWN},
  27. pixelFormat{NTV2_FBF_INVALID},
  28. sdiTransport{SDITransport::SingleLink},
  29. sdi4kTransport{SDITransport4K::TwoSampleInterleave},
  30. audioNumChannels{8},
  31. audioSampleSize{4},
  32. audioSampleRate{48000},
  33. vpids{},
  34. autoDetect{false},
  35. deactivateWhileNotShowing{false}
  36. {
  37. }
  38. SourceProps::SourceProps(const SourceProps &props)
  39. {
  40. deviceID = props.deviceID;
  41. ioSelect = props.ioSelect;
  42. // inputSource = props.inputSource;
  43. videoFormat = props.videoFormat;
  44. pixelFormat = props.pixelFormat;
  45. sdiTransport = props.sdiTransport;
  46. sdi4kTransport = props.sdi4kTransport;
  47. audioNumChannels = props.audioNumChannels;
  48. audioSampleSize = props.audioSampleSize;
  49. audioSampleRate = props.audioSampleRate;
  50. vpids = props.vpids;
  51. autoDetect = props.autoDetect;
  52. deactivateWhileNotShowing = props.deactivateWhileNotShowing;
  53. }
  54. SourceProps::SourceProps(SourceProps &&props)
  55. {
  56. deviceID = props.deviceID;
  57. ioSelect = props.ioSelect;
  58. // inputSource = props.inputSource;
  59. videoFormat = props.videoFormat;
  60. pixelFormat = props.pixelFormat;
  61. sdiTransport = props.sdiTransport;
  62. sdi4kTransport = props.sdi4kTransport;
  63. audioNumChannels = props.audioNumChannels;
  64. audioSampleSize = props.audioSampleSize;
  65. audioSampleRate = props.audioSampleRate;
  66. vpids = props.vpids;
  67. autoDetect = props.autoDetect;
  68. deactivateWhileNotShowing = props.deactivateWhileNotShowing;
  69. }
  70. void SourceProps::operator=(const SourceProps &props)
  71. {
  72. deviceID = props.deviceID;
  73. ioSelect = props.ioSelect;
  74. // inputSource = props.inputSource;
  75. videoFormat = props.videoFormat;
  76. pixelFormat = props.pixelFormat;
  77. sdiTransport = props.sdiTransport;
  78. sdi4kTransport = props.sdi4kTransport;
  79. audioNumChannels = props.audioNumChannels;
  80. audioSampleSize = props.audioSampleSize;
  81. audioSampleRate = props.audioSampleRate;
  82. vpids = props.vpids;
  83. autoDetect = props.autoDetect;
  84. deactivateWhileNotShowing = props.deactivateWhileNotShowing;
  85. }
  86. void SourceProps::operator=(SourceProps &&props)
  87. {
  88. deviceID = props.deviceID;
  89. ioSelect = props.ioSelect;
  90. // inputSource = props.inputSource;
  91. videoFormat = props.videoFormat;
  92. pixelFormat = props.pixelFormat;
  93. sdiTransport = props.sdiTransport;
  94. sdi4kTransport = props.sdi4kTransport;
  95. audioNumChannels = props.audioNumChannels;
  96. audioSampleSize = props.audioSampleSize;
  97. audioSampleRate = props.audioSampleRate;
  98. vpids = props.vpids;
  99. autoDetect = props.autoDetect;
  100. deactivateWhileNotShowing = props.deactivateWhileNotShowing;
  101. }
  102. bool SourceProps::operator==(const SourceProps &props)
  103. {
  104. return (deviceID == props.deviceID && ioSelect == props.ioSelect &&
  105. // inputSource == props.inputSource &&
  106. videoFormat == props.videoFormat &&
  107. pixelFormat == props.pixelFormat &&
  108. // vpid == props.vpid &&
  109. autoDetect == props.autoDetect &&
  110. sdiTransport == props.sdiTransport &&
  111. sdi4kTransport == props.sdi4kTransport &&
  112. audioNumChannels == props.audioNumChannels &&
  113. audioSampleSize == props.audioSampleSize &&
  114. audioSampleRate == props.audioSampleRate &&
  115. deactivateWhileNotShowing == props.deactivateWhileNotShowing);
  116. }
  117. bool SourceProps::operator!=(const SourceProps &props)
  118. {
  119. return !operator==(props);
  120. }
  121. NTV2InputSource SourceProps::InitialInputSource() const
  122. {
  123. auto inputSources = InputSources();
  124. if (!inputSources.empty()) {
  125. return *inputSources.begin();
  126. }
  127. return NTV2_INPUTSOURCE_INVALID;
  128. }
  129. NTV2InputSourceSet SourceProps::InputSources() const
  130. {
  131. NTV2InputSourceSet inputSources;
  132. aja::IOSelectionToInputSources(ioSelect, inputSources);
  133. return inputSources;
  134. }
  135. NTV2Channel SourceProps::Channel() const
  136. {
  137. return NTV2InputSourceToChannel(InitialInputSource());
  138. }
  139. NTV2Channel SourceProps::Framestore() const
  140. {
  141. if (deviceID == DEVICE_ID_KONAHDMI && ioSelect == IOSelection::HDMI2 &&
  142. NTV2_IS_4K_VIDEO_FORMAT(videoFormat)) {
  143. return NTV2_CHANNEL3;
  144. }
  145. return NTV2InputSourceToChannel(InitialInputSource());
  146. }
  147. NTV2AudioSystem SourceProps::AudioSystem() const
  148. {
  149. return NTV2ChannelToAudioSystem(Channel());
  150. }
  151. NTV2AudioRate SourceProps::AudioRate() const
  152. {
  153. NTV2AudioRate rate = NTV2_AUDIO_48K;
  154. switch (audioSampleRate) {
  155. default:
  156. case 48000:
  157. rate = NTV2_AUDIO_48K;
  158. break;
  159. case 96000:
  160. rate = NTV2_AUDIO_96K;
  161. break;
  162. case 192000:
  163. rate = NTV2_AUDIO_192K;
  164. break;
  165. }
  166. return rate;
  167. }
  168. // Size in bytes of N channels of audio
  169. size_t SourceProps::AudioSize() const
  170. {
  171. return audioNumChannels * audioSampleSize;
  172. }
  173. audio_format SourceProps::AudioFormat() const
  174. {
  175. // NTV2 is always 32-bit PCM
  176. return AUDIO_FORMAT_32BIT;
  177. }
  178. speaker_layout SourceProps::SpeakerLayout() const
  179. {
  180. if (audioNumChannels == 2)
  181. return SPEAKERS_STEREO;
  182. // NTV2 is always at least 8ch on modern boards
  183. return SPEAKERS_7POINT1;
  184. }
  185. //
  186. // AJAOutput Properties
  187. //
  188. OutputProps::OutputProps(NTV2DeviceID devID)
  189. : deviceID{devID},
  190. ioSelect{IOSelection::Invalid},
  191. outputDest{NTV2_OUTPUTDESTINATION_ANALOG},
  192. videoFormat{NTV2_FORMAT_UNKNOWN},
  193. pixelFormat{NTV2_FBF_INVALID},
  194. sdi4kTransport{SDITransport4K::TwoSampleInterleave},
  195. audioNumChannels{8},
  196. audioSampleSize{4},
  197. audioSampleRate{48000}
  198. {
  199. }
  200. OutputProps::OutputProps(OutputProps &&props)
  201. {
  202. deviceID = props.deviceID;
  203. ioSelect = props.ioSelect;
  204. outputDest = props.outputDest;
  205. videoFormat = props.videoFormat;
  206. pixelFormat = props.pixelFormat;
  207. sdiTransport = props.sdiTransport;
  208. sdi4kTransport = props.sdi4kTransport;
  209. audioNumChannels = props.audioNumChannels;
  210. audioSampleSize = props.audioSampleSize;
  211. audioSampleRate = props.audioSampleRate;
  212. }
  213. OutputProps::OutputProps(const OutputProps &props)
  214. {
  215. deviceID = props.deviceID;
  216. ioSelect = props.ioSelect;
  217. outputDest = props.outputDest;
  218. videoFormat = props.videoFormat;
  219. pixelFormat = props.pixelFormat;
  220. sdiTransport = props.sdiTransport;
  221. sdi4kTransport = props.sdi4kTransport;
  222. audioNumChannels = props.audioNumChannels;
  223. audioSampleSize = props.audioSampleSize;
  224. audioSampleRate = props.audioSampleRate;
  225. }
  226. void OutputProps::operator=(const OutputProps &props)
  227. {
  228. deviceID = props.deviceID;
  229. ioSelect = props.ioSelect;
  230. outputDest = props.outputDest;
  231. videoFormat = props.videoFormat;
  232. pixelFormat = props.pixelFormat;
  233. sdiTransport = props.sdiTransport;
  234. sdi4kTransport = props.sdi4kTransport;
  235. audioNumChannels = props.audioNumChannels;
  236. audioSampleSize = props.audioSampleSize;
  237. audioSampleRate = props.audioSampleRate;
  238. }
  239. void OutputProps::operator=(OutputProps &&props)
  240. {
  241. deviceID = props.deviceID;
  242. ioSelect = props.ioSelect;
  243. outputDest = props.outputDest;
  244. videoFormat = props.videoFormat;
  245. pixelFormat = props.pixelFormat;
  246. sdiTransport = props.sdiTransport;
  247. sdi4kTransport = props.sdi4kTransport;
  248. audioNumChannels = props.audioNumChannels;
  249. audioSampleSize = props.audioSampleSize;
  250. audioSampleRate = props.audioSampleRate;
  251. }
  252. bool OutputProps::operator==(const OutputProps &props)
  253. {
  254. return (deviceID == props.deviceID && ioSelect == props.ioSelect &&
  255. // outputDest == props.outputDest &&
  256. videoFormat == props.videoFormat &&
  257. pixelFormat == props.pixelFormat &&
  258. sdiTransport == props.sdiTransport &&
  259. sdi4kTransport == props.sdi4kTransport &&
  260. audioNumChannels == props.audioNumChannels &&
  261. audioSampleSize == props.audioSampleSize &&
  262. audioSampleRate == props.audioSampleRate);
  263. }
  264. bool OutputProps::operator!=(const OutputProps &props)
  265. {
  266. return !operator==(props);
  267. }
  268. NTV2FormatDesc OutputProps::FormatDesc()
  269. {
  270. return NTV2FormatDesc(videoFormat, pixelFormat, NTV2_VANCMODE_OFF);
  271. }
  272. NTV2Channel OutputProps::Channel() const
  273. {
  274. // Output Channel Special Cases
  275. // KONA1 -- Has 2 framestores but only 1 bi-directional SDI widget
  276. if (deviceID == DEVICE_ID_KONA1) {
  277. return NTV2_CHANNEL2;
  278. } else if ((deviceID == DEVICE_ID_IO4K ||
  279. deviceID == DEVICE_ID_IO4KPLUS) &&
  280. outputDest == NTV2_OUTPUTDESTINATION_SDI5) {
  281. // IO4K/IO4K+ SDI Monitor - Use framestore 4 but SDI5
  282. return NTV2_CHANNEL4;
  283. }
  284. if (NTV2_OUTPUT_DEST_IS_HDMI(outputDest)) {
  285. if (aja::CardCanDoHDMIMonitorOutput(deviceID) &&
  286. NTV2_IS_4K_VIDEO_FORMAT(videoFormat))
  287. return NTV2_CHANNEL3;
  288. return static_cast<NTV2Channel>(
  289. NTV2DeviceGetNumFrameStores(deviceID) - 1);
  290. }
  291. return NTV2OutputDestinationToChannel(outputDest);
  292. }
  293. NTV2Channel OutputProps::Framestore() const
  294. {
  295. if (deviceID == DEVICE_ID_TTAP_PRO) {
  296. return NTV2_CHANNEL1;
  297. } else if (deviceID == DEVICE_ID_KONA1) {
  298. return NTV2_CHANNEL2;
  299. } else if (deviceID == DEVICE_ID_IO4K ||
  300. deviceID == DEVICE_ID_IO4KPLUS) {
  301. // SDI Monitor output uses framestore 4
  302. if (ioSelect == IOSelection::SDI5)
  303. return NTV2_CHANNEL4;
  304. }
  305. // HDMI Monitor output uses framestore 4
  306. if (ioSelect == IOSelection::HDMIMonitorOut) {
  307. if (deviceID == DEVICE_ID_KONA5_8K)
  308. return NTV2_CHANNEL4;
  309. if (NTV2_IS_4K_VIDEO_FORMAT(videoFormat))
  310. return NTV2_CHANNEL3;
  311. else
  312. return NTV2_CHANNEL4;
  313. }
  314. return NTV2OutputDestinationToChannel(outputDest);
  315. }
  316. NTV2AudioSystem OutputProps::AudioSystem() const
  317. {
  318. return NTV2ChannelToAudioSystem(Channel());
  319. }
  320. NTV2AudioRate OutputProps::AudioRate() const
  321. {
  322. NTV2AudioRate rate = NTV2_AUDIO_48K;
  323. switch (audioSampleRate) {
  324. default:
  325. case 48000:
  326. rate = NTV2_AUDIO_48K;
  327. break;
  328. case 96000:
  329. rate = NTV2_AUDIO_96K;
  330. break;
  331. case 192000:
  332. rate = NTV2_AUDIO_192K;
  333. break;
  334. }
  335. return rate;
  336. }
  337. // Size in bytes of N channels of audio
  338. size_t OutputProps::AudioSize() const
  339. {
  340. return audioNumChannels * audioSampleSize;
  341. }
  342. audio_format OutputProps::AudioFormat() const
  343. {
  344. // NTV2 is always 32-bit PCM
  345. return AUDIO_FORMAT_32BIT;
  346. }
  347. speaker_layout OutputProps::SpeakerLayout() const
  348. {
  349. if (audioNumChannels == 2)
  350. return SPEAKERS_STEREO;
  351. // NTV2 is always at least 8ch on modern boards
  352. return SPEAKERS_7POINT1;
  353. }