| 2180 | |
| 2181 | |
| 2182 | virtual void renderFrame(int time, |
| 2183 | const std::vector<ViewIdx>& viewsToRender, |
| 2184 | bool enableRenderStats) |
| 2185 | { |
| 2186 | boost::shared_ptr<OutputEffectInstance> output = _imp->output.lock(); |
| 2187 | |
| 2188 | if (!output) { |
| 2189 | _imp->scheduler->notifyRenderFailure(""); |
| 2190 | |
| 2191 | return; |
| 2192 | } |
| 2193 | |
| 2194 | AbortableThread* isAbortableThread = dynamic_cast<AbortableThread*>( QThread::currentThread() ); |
| 2195 | |
| 2196 | ///Even if enableRenderStats is false, we at least profile the time spent rendering the frame when rendering with a Write node. |
| 2197 | ///Though we don't enable render stats for sequential renders (e.g: WriteFFMPEG) since this is 1 file. |
| 2198 | RenderStatsPtr stats( new RenderStats(enableRenderStats) ); |
| 2199 | NodePtr outputNode = output->getNode(); |
| 2200 | std::string cb = outputNode->getBeforeFrameRenderCallback(); |
| 2201 | if ( !cb.empty() ) { |
| 2202 | std::vector<std::string> args; |
| 2203 | std::string error; |
| 2204 | try { |
| 2205 | NATRON_PYTHON_NAMESPACE::getFunctionArguments(cb, &error, &args); |
| 2206 | } catch (const std::exception& e) { |
| 2207 | output->getApp()->appendToScriptEditor( std::string("Failed to run beforeFrameRendered callback: ") |
| 2208 | + e.what() ); |
| 2209 | |
| 2210 | return; |
| 2211 | } |
| 2212 | |
| 2213 | if ( !error.empty() ) { |
| 2214 | output->getApp()->appendToScriptEditor("Failed to run before frame render callback: " + error); |
| 2215 | |
| 2216 | return; |
| 2217 | } |
| 2218 | |
| 2219 | std::string signatureError; |
| 2220 | signatureError.append("The before frame render callback supports the following signature(s):\n"); |
| 2221 | signatureError.append("- callback(frame, thisNode, app)"); |
| 2222 | if (args.size() != 3) { |
| 2223 | output->getApp()->appendToScriptEditor("Failed to run before frame render callback: " + signatureError); |
| 2224 | |
| 2225 | return; |
| 2226 | } |
| 2227 | |
| 2228 | if ( (args[0] != "frame") || (args[1] != "thisNode") || (args[2] != "app") ) { |
| 2229 | output->getApp()->appendToScriptEditor("Failed to run before frame render callback: " + signatureError); |
| 2230 | |
| 2231 | return; |
| 2232 | } |
| 2233 | |
| 2234 | std::stringstream ss; |
| 2235 | std::string appStr = outputNode->getApp()->getAppIDString(); |
| 2236 | std::string outputNodeName = appStr + "." + outputNode->getFullyQualifiedName(); |
| 2237 | ss << cb << "(" << time << ", " << outputNodeName << ", " << appStr << ")"; |
| 2238 | std::string script = ss.str(); |
| 2239 | try { |
nothing calls this directly
no test coverage detected