ओएफएक्स, उर्फ ओएफएक्स इमेज प्रोसेसिंग एपीआई , 2डी विज़ुअल इफेक्ट्स और वीडियो कंपोज़िटिंग बनाने के लिए एक खुला मानक है। यह एक प्लगइन-जैसे एप्लिकेशन डेवलपमेंट मॉडल में काम करता है। अनिवार्य रूप से, यह एक होस्ट - तरीकों का एक सेट प्रदान करने वाला एक एप्लिकेशन और एक प्लग-इन - इस सेट को लागू करने वाला एक एप्लिकेशन या मॉड्यूल दोनों के रूप में कार्य करता है।
यह कॉन्फ़िगरेशन होस्ट एप्लिकेशन की कार्यक्षमता के असीमित विस्तार की क्षमता प्रदान करता है।
फ़ाइनल कट एक्स और डेविंसी रिज़ॉल्व स्टूडियो जैसे एप्लिकेशन, संस्करण 16 से शुरू होकर, ऐप्पल मेटल पाइपलाइनों का पूरी तरह से समर्थन करते हैं। ओपनसीएल और क्यूडा के समान, ओएफएक्स के मामले में, आप प्लेटफ़ॉर्म-विशिष्ट कमांड कतार का एक डिस्क्रिप्टर या हैंडलर प्राप्त कर सकते हैं। होस्ट सिस्टम ऐसी कतारों का एक पूल आवंटित करने और उन पर गणनाओं को संतुलित करने की जिम्मेदारी भी लेता है।
इसके अलावा, यह स्रोत और लक्ष्य छवि क्लिप डेटा को GPU मेमोरी में रखता है, जिससे एक्स्टेंसिबल कार्यक्षमता का विकास काफी सरल हो जाता है।
रिज़ॉल्व के साथ, चीजें थोड़ी अधिक जटिल हैं। DaVinci ने कुछ सीमाओं के साथ, OFX v1.4 के लिए समर्थन की घोषणा की। विशेष रूप से, इंटरफ़ेस फ़ंक्शंस के साथ काम करने की कुछ विधियाँ उपयोग के लिए उपलब्ध नहीं हैं। यह निर्धारित करने के लिए कि कौन सी विधि उपलब्ध है, ओएफएक्स आपको कुंजी/मूल्य प्रश्नों के माध्यम से समर्थित सुइट की जांच करने की अनुमति देता है।
प्लगइन कोड में प्रकाशन विधियाँ C कॉल पर आधारित हैं। लेकिन हम C++17 के लिए अनुकूलित OpenFXS C++ शेल का उपयोग करेंगे। सुविधा के लिए, मैंने सब कुछ एक रिपॉजिटरी में संकलित किया है: डेहांसर-एक्सटर्नल ओपन-सोर्स डेहांसर प्रोजेक्ट से लिया गया है।
इस प्रोजेक्ट में, मैं ओपनएफएक्सएस का उपयोग करूंगा, जो ओपनएफएक्स का सी++ एक्सटेंशन है जो मूल रूप से ब्रूनो निकोलेटी द्वारा लिखा गया था और समय के साथ वाणिज्यिक और ओपन-सोर्स वीडियो प्रोसेसिंग परियोजनाओं में लोकप्रिय हो गया है।
मूल OpenFXS आधुनिक C++ बोलियों के लिए अनुकूलित नहीं था, इसलिए मैंने इसे C++17 के साथ संगत बनाने के लिए अद्यतन किया।
ओएफएक्स, और परिणामस्वरूप ओएफएक्सएस, एक स्टैंडअलोन सॉफ्टवेयर मॉड्यूल है जो होस्ट प्रोग्राम द्वारा गतिशील रूप से लोड किया जाता है। अनिवार्य रूप से, यह एक गतिशील लाइब्रेरी है जो मुख्य एप्लिकेशन शुरू होने पर लोड होती है। OFX की तरह OpenFXS को भी विधि हस्ताक्षर प्रकाशित करने होंगे। इसलिए, हम कोड से एक सी विधि का उपयोग करते हैं।
ओपनएफएक्सएस में विकास शुरू करने के लिए, आपको कक्षाओं के कुछ सामान्य सेटों से सहमत होने की आवश्यकता है जिनका उपयोग आपके एप्लिकेशन में नई कार्यक्षमता बनाने के लिए किया जाता है। आमतौर पर, एक नए प्रोजेक्ट में, आपको इन कक्षाओं से विरासत प्राप्त करने और कुछ वर्चुअल तरीकों को लागू करने या ओवरराइड करने की आवश्यकता होती है।
होस्ट सिस्टम पर अपना स्वयं का प्लगइन बनाने के लिए, आइए निम्नलिखित सार्वजनिक कक्षाओं और उसी विधि से खुद को परिचित करके शुरुआत करें:
एक विशेषता जो वीडियो शूट करने की प्रक्रिया को केवल एक तस्वीर में एक छवि कैप्चर करने से अलग करती है, वह है दृश्यों का गतिशील परिवर्तन और समग्र रूप से दोनों दृश्यों और छवि के क्षेत्रों की रोशनी। यह निर्धारित करता है कि शूटिंग प्रक्रिया के दौरान एक्सपोज़र को किस प्रकार नियंत्रित किया जाता है।
डिजिटल वीडियो में, ऑपरेटरों के लिए एक नियंत्रण मॉनिटर मोड होता है जिसमें क्षेत्रों के एक्सपोज़र स्तर को ज़ोन के सीमित सेट में मैप किया जाता है, प्रत्येक को अपने रंग से रंगा जाता है।
इस मोड को कभी-कभी "प्रीडेटर" या ग़लत रंग मोड भी कहा जाता है। तराजू आमतौर पर आईआरई पैमाने के संदर्भ में होते हैं।
ऐसा मॉनिटर आपको एक्सपोज़र ज़ोन देखने और कैमरा शूटिंग पैरामीटर सेट करते समय महत्वपूर्ण गलतियों से बचने की अनुमति देता है। अर्थ में कुछ समान का उपयोग फ़ोटोग्राफ़ी में उजागर करते समय किया जाता है - उदाहरण के लिए एडम्स के अनुसार ज़ोनिंग।
आप एक एक्सपोज़र मीटर के साथ एक विशिष्ट लक्ष्य को माप सकते हैं और देख सकते हैं कि यह किस क्षेत्र में स्थित है, और वास्तविक समय में हम ज़ोन को देखते हैं, धारणा में आसानी के लिए बड़े करीने से रंगा हुआ।
ज़ोन की संख्या नियंत्रण मॉनिटर के उद्देश्यों और क्षमताओं द्वारा निर्धारित की जाती है। उदाहरण के लिए, एरी एलेक्सा कैमरों के साथ उपयोग किया जाने वाला मॉनिटर 6 ज़ोन तक को शामिल कर सकता है।
उदाहरण के साथ आगे बढ़ने से पहले, हमें मेटल टेक्सचर जैसे स्रोत डेटा को संसाधित करने के लिए एक मंच के रूप में ओपनएफएक्सएस को लागू करने के लिए कुछ सरल प्रॉक्सी कक्षाएं जोड़ने की आवश्यकता है। इन वर्गों में शामिल हैं:
imetalling::Image2Texture : क्लिप बफ़र से डेटा को मेटल टेक्सचर में स्थानांतरित करने के लिए एक फ़ंक्टर। DaVinci से, आप प्लगइन में छवि चैनल मानों की किसी भी संरचना और पैकेजिंग का एक बफर निकाल सकते हैं, और इसे एक समान रूप में वापस किया जाना चाहिए।
ओएफएक्स में स्ट्रीम प्रारूप के साथ काम करना आसान बनाने के लिए, आप होस्ट से एक विशिष्ट प्रकार का डेटा पहले से तैयार करने का अनुरोध कर सकते हैं। मैं आरजीबीए में पैक किए गए फ्लोट्स का उपयोग करूंगा - लाल/हरा/नीला/अल्फा।
हमें ओएफएक्सएस बेस क्लास विरासत में मिली है और मेटल कोर कैसे काम करता है इसके विवरण में जाए बिना हम अपनी कार्यक्षमता लिखते हैं:
इसके अतिरिक्त, हमें एमएसएल पर होस्ट कोड और कर्नेल कोड को तार्किक रूप से अलग करने के लिए मेटल के शीर्ष पर निर्मित कई उपयोगिता वर्गों की आवश्यकता होगी। इसमे शामिल है:
imetalling::FalseColorKernel : हमारा मुख्य कार्यात्मक वर्ग, एक "प्रीडेटर" एमुलेटर जो रंगों की एक निर्दिष्ट संख्या में पोस्टराइज़ (डाउनसैंपल) करता है।
"प्रीडेटर" मोड के लिए कर्नेल कोड इस तरह दिख सकता है:
static constant float3 kIMP_Y_YUV_factor = {0.2125, 0.7154, 0.0721}; constexpr sampler baseSampler(address::clamp_to_edge, filter::linear, coord::normalized); inline float when_eq(float x, float y) { return 1.0 - abs(sign(x - y)); } static inline float4 sampledColor( texture2d<float, access::sample> inTexture, texture2d<float, access::write> outTexture, uint2 gid ){ float w = outTexture.get_width(); return mix(inTexture.sample(baseSampler, float2(gid) * float2(1.0/(w-1.0), 1.0/float(outTexture.get_height()-1))), inTexture.read(gid), when_eq(inTexture.get_width(), w) // whe equal read exact texture color ); } kernel void kernel_falseColor( texture2d<float, access::sample> inTexture [[texture(0)]], texture2d<float, access::write> outTexture [[texture(1)]], device float3* color_map [[ buffer(0) ]], constant uint& level [[ buffer(1) ]], uint2 gid [[thread_position_in_grid]]) { float4 inColor = sampledColor(inTexture,outTexture,gid); float luminance = dot(inColor.rgb, kIMP_Y_YUV_factor); uint index = clamp(uint(luminance*(level-1)),uint(0),uint(level-1)); float4 color = float4(1); if (index<level) color.rgb = color_map[index]; outTexture.write(color,gid); }
ओएफएक्स प्लगइन का आरंभीकरण
हम क्लास imetalling::falsecolor::Factory.
इस कक्षा में, हम एक एकल पैरामीटर सेट करेंगे - मॉनिटर की स्थिति (या तो चालू या बंद)। यह हमारे उदाहरण के लिए आवश्यक है.
हम OFX::PluginFactoryHelper
से इनहेरिट करेंगे और पांच तरीकों को ओवरलोड करेंगे:
ImageEffectDescriptor
कोड देखें।
वर्णनInContext(ImageEffectDescriptor&,ContextEnum) : describe
विधि के समान, प्लगइन लोड होने पर इस विधि को भी कहा जाता है और इसे हमारी कक्षा में परिभाषित किया जाना चाहिए। इसे वर्तमान संदर्भ से जुड़े गुणों को परिभाषित करना चाहिए।
संदर्भ यह निर्धारित करता है कि एप्लिकेशन किस प्रकार के संचालन के साथ काम करता है, जैसे किसी क्लिप में फ़िल्टर, पेंट, ट्रांज़िशन प्रभाव या फ़्रेम रिटाइमर।
ImageEffect
प्रकार के ऑब्जेक्ट पर एक पॉइंटर लौटाते हैं। दूसरे शब्दों में, हमारा imetalling::falsecolor::Plugin
जिसमें हमने सभी कार्यात्मकताओं को परिभाषित किया है, होस्ट प्रोग्राम में उपयोगकर्ता घटनाओं के संबंध में और स्रोत फ्रेम को लक्ष्य में प्रस्तुत करना (रूपांतरित करना): OFX::ImageEffect *Factory::createInstance(OfxImageEffectHandle handle,OFX::ContextEnum) { return new Plugin(handle); }
इस स्तर पर, यदि आप OFX मॉड्यूल के साथ एक बंडल संकलित करते हैं, तो प्लगइन पहले से ही होस्ट एप्लिकेशन में उपलब्ध होगा, और DaVinci में, इसे सुधार नोड पर लोड किया जा सकता है।
हालाँकि, प्लगइन इंस्टेंस के साथ पूरी तरह से काम करने के लिए, आपको कम से कम इंटरैक्टिव भाग और आने वाली वीडियो स्ट्रीम को संसाधित करने से जुड़े भाग को परिभाषित करने की आवश्यकता है।
ऐसा करने के लिए, हम OFX::ImageEffect क्लास से इनहेरिट करते हैं और वर्चुअल तरीकों को ओवरलोड करते हैं:
ChangeParam(const OFX::InstanceChangedArgs&, const std::string&) - यह विधि हमें घटना को संभालने के लिए तर्क को परिभाषित करने की अनुमति देती है। ईवेंट प्रकार OFX::InstanceChangedArgs::reason के मान से निर्धारित होता है और यह हो सकता है: eChangeUserEdit, eChangePluginEdit, eChangeTime - ईवेंट उपयोगकर्ता द्वारा संपादित की जा रही संपत्ति के परिणामस्वरूप हुआ, प्लगइन या होस्ट एप्लिकेशन में बदला गया, या समयरेखा में परिवर्तन के परिणामस्वरूप.
दूसरा पैरामीटर उस स्ट्रिंग नाम को निर्दिष्ट करता है जिसे हमने प्लगइन आरंभीकरण चरण में परिभाषित किया था, हमारे मामले में, यह एक पैरामीटर है: false_color_enabled_check_box ।
आप Interaction.cpp कोड में OFX के साथ इंटरैक्टिव इंटरैक्शन के कार्यान्वयन को पढ़ सकते हैं। जैसा कि आप देख सकते हैं, हमें क्लिप के लिए संकेतक प्राप्त होते हैं: स्रोत एक और मेमोरी क्षेत्र जिसमें हम लक्ष्य परिवर्तन डालेंगे।
हम एक और तार्किक परत जोड़ेंगे जिस पर हम परिवर्तन शुरू करने के लिए सभी तर्कों को परिभाषित करेंगे। हमारे मामले में, अब तक ओवरराइडिंग का यही एकमात्र तरीका है:
लॉन्च चरण में, उपयोगी गुणों वाली एक वस्तु हमारे लिए उपलब्ध हो गई: हमारे पास वीडियो स्ट्रीम के लिए कम से कम एक संकेतक (अधिक सटीक रूप से, फ्रेम छवि डेटा के साथ एक मेमोरी क्षेत्र) है, और, सबसे महत्वपूर्ण बात, मेटल कमांड की एक कतार है।
अब, हम एक सामान्य वर्ग का निर्माण कर सकते हैं जो हमें कर्नेल कोड के पुन: उपयोग के एक सरल रूप के करीब लाएगा। OpenFXS एक्सटेंशन में पहले से ही ऐसा वर्ग है: OFX::ImageProcessor; हमें बस इसे ओवरलोड करने की जरूरत है।
कंस्ट्रक्टर में, इसमें OFX::ImageEffect पैरामीटर है, अर्थात, इसमें हमें न केवल प्लगइन पैरामीटर की वर्तमान स्थिति प्राप्त होगी, बल्कि GPU के साथ काम करने के लिए आवश्यक सभी चीजें प्राप्त होंगी।
इस स्तर पर, हमें केवल प्रोसेसइमेजमेटल() विधि को ओवरलोड करने और मेटल पर पहले से ही लागू कर्नेल की प्रोसेसिंग शुरू करने की आवश्यकता है।
Processor::Processor( OFX::ImageEffect *instance, OFX::Clip *source, OFX::Clip *destination, const OFX::RenderArguments &args, bool enabled ) : OFX::ImageProcessor(*instance), enabled_(enabled), interaction_(instance), wait_command_queue_(false), /// grab the current frame of a clip from OFX host memory source_(source->fetchImage(args.time)), /// create a target frame of a clip with the memory area already specified in OFX destination_(destination->fetchImage(args.time)), source_container_(nullptr), destination_container_(nullptr) { /// Set OFX rendering arguments to GPU setGPURenderArgs(args); /// Set render window setRenderWindow(args.renderWindow); /// Place source frame data in Metal texture source_container_ = std::make_unique<imetalling::Image2Texture>(_pMetalCmdQ, source_); /// Create empty target frame texture in Metal destination_container_ = std::make_unique<imetalling::Image2Texture>(_pMetalCmdQ, destination_); /// Get parameters for packing data in the memory area of the target frame OFX::BitDepthEnum dstBitDepth = destination->getPixelDepth(); OFX::PixelComponentEnum dstComponents = destination->getPixelComponents(); /// and original OFX::BitDepthEnum srcBitDepth = source->getPixelDepth(); OFX::PixelComponentEnum srcComponents = source->getPixelComponents(); /// show a message to the host system that something went wrong /// and cancel rendering of the current frame if ((srcBitDepth != dstBitDepth) || (srcComponents != dstComponents)) { OFX::throwSuiteStatusException(kOfxStatErrValue); } /// set in the current processor context a pointer to the memory area of the target frame setDstImg(destination_.get_ofx_image()); } void Processor::processImagesMetal() { try { if (enabled_) FalseColorKernel(_pMetalCmdQ, source_container_->get_texture(), destination_container_->get_texture()).process(); else PassKernel(_pMetalCmdQ, source_container_->get_texture(), destination_container_->get_texture()).process(); ImageFromTexture(_pMetalCmdQ, destination_, destination_container_->get_texture(), wait_command_queue_); } catch (std::exception &e) { interaction_->sendMessage(OFX::Message::eMessageError, "#message0", e.what()); } }
प्रोजेक्ट बनाने के लिए, आपको CMake की आवश्यकता होगी, और यह कम से कम संस्करण 3.15 होना चाहिए। इसके अतिरिक्त, आपको Qt5.13 की आवश्यकता होगी, जो सिस्टम निर्देशिका में प्लगइन इंस्टॉलर के साथ बंडल की आसान और सुविधाजनक असेंबली में सहायता करता है। सेमेक आरंभ करने के लिए, आपको पहले एक बिल्ड निर्देशिका बनानी होगी।
बिल्ड डायरेक्टरी बनाने के बाद, आप निम्न कमांड निष्पादित कर सकते हैं:
cmake -DPRINT_DEBUG=ON -DQT_INSTALLER_PREFIX=/Users/<user>/Develop/QtInstaller -DCMAKE_PREFIX_PATH=/Users/<user>/Develop/Qt/5.13.0/clang_64/lib/cmake -DPLUGIN_INSTALLER_DIR=/Users/<user>/Desktop -DCMAKE_INSTALL_PREFIX=/Library/OFX/Plugins .. && make install
इसके बाद, इंस्टॉलर, जिसे IMFalseColorOfxInstaller.app कहा जाता है, उस निर्देशिका में दिखाई देगा जिसे आपने PLUGIN_INSTALLER_DIR पैरामीटर में निर्दिष्ट किया है। आइए आगे बढ़ें और इसे लॉन्च करें! एक बार इंस्टॉलेशन सफल हो जाने पर, आप DaVinci Resolve शुरू कर सकते हैं और हमारे नए प्लगइन का उपयोग शुरू कर सकते हैं।
आप इसे रंग सुधार पृष्ठ पर ओपनएफएक्स पैनल में ढूंढ और चुन सकते हैं, और इसे एक नोड के रूप में जोड़ सकते हैं।
बाहरी संबंध