TuttleOFX
1
|
00001 #ifndef _TUTTLE_HOST_PROCESSVISITORS_HPP_ 00002 #define _TUTTLE_HOST_PROCESSVISITORS_HPP_ 00003 00004 #include "ProcessVertexData.hpp" 00005 00006 #include <tuttle/host/memory/MemoryCache.hpp> 00007 00008 #include <boost/graph/properties.hpp> 00009 #include <boost/graph/visitors.hpp> 00010 #include <boost/graph/depth_first_search.hpp> 00011 #include <boost/graph/breadth_first_search.hpp> 00012 #include <boost/foreach.hpp> 00013 #include <boost/date_time/posix_time/posix_time.hpp> 00014 #include <boost/unordered_map.hpp> 00015 00016 #include <iostream> 00017 #include <fstream> 00018 #include <vector> 00019 00020 namespace tuttle { 00021 namespace host { 00022 namespace graph { 00023 00024 template<class TGraph> 00025 inline void connectClips( TGraph& graph ) 00026 { 00027 BOOST_FOREACH( typename TGraph::edge_descriptor ed, graph.getEdges() ) 00028 { 00029 typename TGraph::Edge& edge = graph.instance( ed ); 00030 typename TGraph::Vertex& vertexOutput = graph.targetInstance( ed ); 00031 typename TGraph::Vertex& vertexInput = graph.sourceInstance( ed ); 00032 00033 TUTTLE_TLOG( TUTTLE_TRACE, "[Connect Clips] " << edge ); 00034 TUTTLE_TLOG( TUTTLE_TRACE, "[Connect Clips] " << vertexOutput << " -> " << vertexInput ); 00035 //TUTTLE_TLOG_VAR( TUTTLE_TRACE, edge.getInAttrName() ); 00036 00037 if( ! vertexOutput.isFake() && ! vertexInput.isFake() ) 00038 { 00039 INode& outputNode = vertexOutput.getProcessNode(); 00040 INode& inputNode = vertexInput.getProcessNode(); 00041 inputNode.connect( outputNode, inputNode.getAttribute( edge.getInAttrName() ) ); 00042 } 00043 } 00044 } 00045 00046 00047 namespace visitor { 00048 00049 00050 00051 template<class TGraph> 00052 class Setup1 : public boost::default_dfs_visitor 00053 { 00054 public: 00055 typedef typename TGraph::GraphContainer GraphContainer; 00056 typedef typename TGraph::Vertex Vertex; 00057 00058 Setup1( TGraph& graph ) 00059 : _graph( graph ) 00060 {} 00061 00062 template<class VertexDescriptor, class Graph> 00063 void finish_vertex( VertexDescriptor v, Graph& g ) 00064 { 00065 Vertex& vertex = _graph.instance( v ); 00066 00067 TUTTLE_TLOG( TUTTLE_TRACE, "[Setup 1] finish vertex " << vertex ); 00068 if( vertex.isFake() ) 00069 return; 00070 00071 vertex.getProcessNode().setup1(); 00072 } 00073 00074 private: 00075 TGraph& _graph; 00076 }; 00077 00078 template<class TGraph> 00079 class Setup2 : public boost::default_dfs_visitor 00080 { 00081 public: 00082 typedef typename TGraph::GraphContainer GraphContainer; 00083 typedef typename TGraph::Vertex Vertex; 00084 00085 Setup2( TGraph& graph ) 00086 : _graph( graph ) 00087 {} 00088 00089 template<class VertexDescriptor, class Graph> 00090 void discover_vertex( VertexDescriptor v, Graph& g ) 00091 { 00092 Vertex& vertex = _graph.instance( v ); 00093 00094 TUTTLE_TLOG( TUTTLE_TRACE, "[Setup 2] discover vertex " << vertex ); 00095 if( vertex.isFake() ) 00096 return; 00097 00098 vertex.getProcessNode().setup2_reverse(); 00099 } 00100 00101 private: 00102 TGraph& _graph; 00103 }; 00104 00105 00106 template<class TGraph> 00107 class Setup3 : public boost::default_dfs_visitor 00108 { 00109 public: 00110 typedef typename TGraph::GraphContainer GraphContainer; 00111 typedef typename TGraph::Vertex Vertex; 00112 00113 Setup3( TGraph& graph ) 00114 : _graph( graph ) 00115 {} 00116 template<class VertexDescriptor, class Graph> 00117 void finish_vertex( VertexDescriptor v, Graph& g ) 00118 { 00119 Vertex& vertex = _graph.instance( v ); 00120 00121 TUTTLE_TLOG( TUTTLE_TRACE, "[Setup 3] finish vertex " << vertex ); 00122 if( vertex.isFake() ) 00123 return; 00124 00125 vertex.getProcessNode().setup3(); 00126 } 00127 00128 private: 00129 TGraph& _graph; 00130 }; 00131 00132 template<class TGraph> 00133 class TimeDomain : public boost::default_dfs_visitor 00134 { 00135 public: 00136 typedef typename TGraph::GraphContainer GraphContainer; 00137 typedef typename TGraph::Vertex Vertex; 00138 00139 TimeDomain( TGraph& graph ) 00140 : _graph( graph ) 00141 {} 00142 00143 template<class VertexDescriptor, class Graph> 00144 void finish_vertex( VertexDescriptor vd, Graph& g ) 00145 { 00146 Vertex& vertex = _graph.instance( vd ); 00147 00148 TUTTLE_TLOG( TUTTLE_TRACE, "[Time Domain] finish vertex " << vertex ); 00149 if( vertex.isFake() ) 00150 return; 00151 00152 vertex.getProcessData()._timeDomain = vertex.getProcessNode().computeTimeDomain(); 00153 TUTTLE_TLOG( TUTTLE_TRACE, "[Time Domain] min: " << vertex.getProcessData()._timeDomain.min << ", max: " << vertex.getProcessData()._timeDomain.max ); 00154 } 00155 00156 private: 00157 TGraph& _graph; 00158 }; 00159 00160 template<class TGraph> 00161 class ComputeHashAtTime : public boost::default_dfs_visitor 00162 { 00163 public: 00164 typedef typename TGraph::GraphContainer GraphContainer; 00165 typedef typename TGraph::Vertex Vertex; 00166 typedef typename TGraph::Edge Edge; 00167 typedef typename TGraph::vertex_descriptor vertex_descriptor; 00168 typedef typename TGraph::edge_descriptor edge_descriptor; 00169 typedef typename TGraph::Vertex::Key VertexKey; 00170 00171 ComputeHashAtTime( TGraph& graph, NodeHashContainer& outNodesHash, const OfxTime time ) 00172 : _graph( graph ) 00173 , _outNodesHash( outNodesHash ) 00174 , _time( time ) 00175 { 00176 //TUTTLE_TLOG( TUTTLE_TRACE, "[ComputeHashAtTime] constructor" ); 00177 } 00178 00179 template<class VertexDescriptor, class Graph> 00180 void finish_vertex( VertexDescriptor vd, Graph& g ) 00181 { 00182 Vertex& vertex = _graph.instance( vd ); 00183 TUTTLE_TLOG( TUTTLE_TRACE, "[Compute Hash At Time] finish vertex " << vertex ); 00184 00185 if( vertex.isFake() ) 00186 return; 00187 00188 const std::size_t localHash = vertex.getProcessNode().getLocalHashAtTime(_time); 00189 00190 typedef std::map<VertexKey, std::size_t> InputsHash; 00191 InputsHash inputsGlobalHash; 00192 BOOST_FOREACH( const edge_descriptor& ed, _graph.getOutEdges( vd ) ) 00193 { 00194 const Edge& edge = _graph.instance( ed ); 00195 vertex_descriptor inputVertexDesc = _graph.target( ed ); 00196 Vertex& inputVertex = _graph.instance( inputVertexDesc ); 00197 00198 const std::size_t inputGlobalHash = _outNodesHash.getHash(inputVertex.getKey()); 00199 // Key is: (clipName, time) 00200 VertexKey k( edge.getInAttrName(), edge.getOutTime() ); 00201 inputsGlobalHash[k] = inputGlobalHash; 00202 } 00203 // inputGlobalHashes is put into a map to be ordered by clip name 00204 // the clipName is unique for each time used 00205 std::size_t seed = localHash; 00206 BOOST_FOREACH( const typename InputsHash::value_type& inputGlobalHash, inputsGlobalHash ) 00207 { 00208 //TUTTLE_TLOG_VAR2( TUTTLE_TRACE, inputGlobalHash.first, inputGlobalHash.second ); 00209 boost::hash_combine( seed, inputGlobalHash.first.getName() ); // name of the input clip connected 00210 boost::hash_combine( seed, inputGlobalHash.second ); 00211 } 00212 _outNodesHash.addHash( vertex.getKey(), seed ); 00213 //TUTTLE_TLOG_VAR( TUTTLE_TRACE, localHash ); 00214 //TUTTLE_TLOG_VAR2( TUTTLE_TRACE, vertex.getKey(), seed ); 00215 } 00216 00217 private: 00218 TGraph& _graph; 00219 NodeHashContainer& _outNodesHash; 00220 OfxTime _time; 00221 }; 00222 00223 00224 /** 00225 * @brief Create a new version of a graph with nodes deployed over time. 00226 * 00227 * Compute kOfxImageEffectActionGetFramesNeeded for each node if kOfxImageEffectPropTemporalClipAccess is true. 00228 */ 00229 template<class TGraph> 00230 class DeployTime : public boost::default_dfs_visitor 00231 { 00232 public: 00233 typedef typename TGraph::GraphContainer GraphContainer; 00234 typedef typename TGraph::Vertex Vertex; 00235 typedef typename TGraph::Edge Edge; 00236 typedef typename TGraph::vertex_descriptor vertex_descriptor; 00237 typedef typename TGraph::edge_descriptor edge_descriptor; 00238 00239 DeployTime( TGraph& graph, const OfxTime time ) 00240 : _graph( graph ) 00241 , _time( time ) 00242 { 00243 // clear all time informations before to fill with new values 00244 BOOST_FOREACH( const vertex_descriptor vd, graph.getVertices() ) 00245 { 00246 Vertex& v = graph.instance( vd ); 00247 v.clearTimeInfo(); 00248 } 00249 BOOST_FOREACH( const edge_descriptor ed, graph.getEdges() ) 00250 { 00251 Edge& e = graph.instance( ed ); 00252 e.clearTimeInfo(); 00253 } 00254 } 00255 00256 template<class VertexDescriptor, class Graph> 00257 void discover_vertex( VertexDescriptor v, Graph& g ) 00258 { 00259 Vertex& vertex = _graph.instance( v ); 00260 00261 TUTTLE_TLOG( TUTTLE_TRACE, "[Deploy Time] " << vertex ); 00262 if( vertex.isFake() ) 00263 { 00264 BOOST_FOREACH( const edge_descriptor& ed, _graph.getOutEdges( v ) ) 00265 { 00266 Edge& e = _graph.instance( ed ); 00267 e._timesNeeded[_time].insert( _time ); 00268 //TUTTLE_TLOG( TUTTLE_TRACE, "--- insert edge: " << _time ); 00269 } 00270 vertex._data._times.insert( _time ); 00271 return; 00272 } 00273 00274 // merge times nedded for all out edges 00275 BOOST_FOREACH( const edge_descriptor& ed, _graph.getInEdges( v ) ) 00276 { 00277 const Edge& edge = _graph.instance( ed ); 00278 //TUTTLE_TLOG( TUTTLE_TRACE, "-- outEdge: " << edge ); 00279 BOOST_FOREACH( const typename Edge::TimeMap::value_type& timesNeeded, edge._timesNeeded ) 00280 { 00281 vertex._data._times.insert( timesNeeded.second.begin(), timesNeeded.second.end() ); 00282 // std::cout << "--- insert vertex: "; 00283 // std::copy( (*timesNeeded).second.begin(), 00284 // (*timesNeeded).second.end(), 00285 // std::ostream_iterator<OfxTime>(std::cout, ",") ); 00286 // std::cout << std::endl; 00287 } 00288 } 00289 00290 // Set all times needed on each input edges 00291 BOOST_FOREACH( const OfxTime t, vertex._data._times ) 00292 { 00293 TUTTLE_TLOG( TUTTLE_TRACE, "[Deploy Time] time: " << boost::lexical_cast< std::string >(t) ); 00294 INode::ClipTimesSetMap mapInputsTimes = vertex.getProcessNode().getTimesNeeded( t ); 00295 // BOOST_FOREACH( const INode::InputsTimeMap::value_type& v, mapInputsTimes ) 00296 // { 00297 // TUTTLE_TLOG_VAR( TUTTLE_TRACE, v.first ); 00298 // } 00299 BOOST_FOREACH( const edge_descriptor& ed, _graph.getOutEdges( v ) ) 00300 { 00301 Edge& edge = _graph.instance( ed ); 00302 // TUTTLE_TLOG( TUTTLE_INFO, "-- inEdge "<<t<<": " << edge ); 00303 // const Vertex& input = _graph.targetInstance( ed ); 00304 // TUTTLE_TLOG_VAR( TUTTLE_TRACE, input.getName() ); 00305 // std::cout << "--- insert edges: "; 00306 // std::copy( mapInputsTimes[input.getName()+"." kOfxOutputAttributeName].begin(), 00307 // mapInputsTimes[input.getName()+"." kOfxOutputAttributeName].end(), 00308 // std::ostream_iterator<OfxTime>(std::cout, ",") ); 00309 edge._timesNeeded[t] = mapInputsTimes[edge.getInAttrName()]; 00310 } 00311 } 00312 } 00313 00314 private: 00315 TGraph& _graph; 00316 OfxTime _time; 00317 }; 00318 00319 template<class TGraph> 00320 struct IdentityNodeConnection 00321 { 00322 typedef typename TGraph::GraphContainer GraphContainer; 00323 typedef typename TGraph::Vertex Vertex; 00324 typedef typename Vertex::Key VertexKey; 00325 typedef typename TGraph::vertex_descriptor vertex_descriptor; 00326 typedef typename TGraph::Edge Edge; 00327 typedef typename TGraph::edge_descriptor edge_descriptor; 00328 00329 VertexKey _identityVertex; ///< the identity node to remove 00330 struct InputClipConnection 00331 { 00332 VertexKey _srcNode; 00333 std::string _inputClip; 00334 }; 00335 struct OutputClipConnection 00336 { 00337 VertexKey _dstNode; 00338 std::string _dstNodeClip; 00339 }; 00340 InputClipConnection _input; 00341 std::vector< OutputClipConnection > _outputs; 00342 }; 00343 00344 /** 00345 * @warning in progress... 00346 */ 00347 template<class TGraph> 00348 class RemoveIdentityNodes : public boost::default_dfs_visitor 00349 { 00350 public: 00351 typedef typename TGraph::GraphContainer GraphContainer; 00352 typedef typename TGraph::Vertex Vertex; 00353 typedef typename Vertex::Key VertexKey; 00354 typedef typename TGraph::vertex_descriptor vertex_descriptor; 00355 typedef typename TGraph::Edge Edge; 00356 typedef typename TGraph::edge_descriptor edge_descriptor; 00357 00358 public: 00359 RemoveIdentityNodes( TGraph& graph, std::vector<IdentityNodeConnection<TGraph> >& toRemove ) 00360 : _graph( graph ) 00361 , _toRemove( toRemove ) 00362 {} 00363 00364 template<class VertexDescriptor, class Graph> 00365 void finish_vertex( VertexDescriptor vd, Graph& g ) 00366 { 00367 Vertex& vertex = _graph.instance( vd ); 00368 00369 TUTTLE_TLOG( TUTTLE_TRACE, "[Remove identity nodes] finish vertex " << vertex ); 00370 if( vertex.isFake() ) 00371 return; 00372 00373 std::string inputClip; 00374 OfxTime atTime; 00375 if( vertex.getProcessNode().isIdentity( vertex.getProcessDataAtTime(), inputClip, atTime ) ) 00376 { 00377 try 00378 { 00379 if( inputClip.size() == 0 ) 00380 { 00381 BOOST_THROW_EXCEPTION( exception::Logic() 00382 << exception::dev() + "There is an error in the plugin: The plugin declares to be identity but don't give the name of the input clip to use." ); 00383 } 00384 IdentityNodeConnection<TGraph> reconnect; 00385 reconnect._identityVertex = _graph.instance(vd).getKey(); 00386 reconnect._input._inputClip = inputClip; 00387 BOOST_FOREACH( const edge_descriptor& ed, _graph.getOutEdges( vd ) ) 00388 { 00389 const Edge& e = _graph.instance( ed ); 00390 if( ( e.getInAttrName() == inputClip ) && 00391 ( e.getOutTime() == atTime ) 00392 ) 00393 { 00394 vertex_descriptor in = _graph.target( ed ); 00395 reconnect._input._srcNode = _graph.instance(in).getKey(); 00396 } 00397 } 00398 BOOST_FOREACH( const edge_descriptor& ed, _graph.getInEdges( vd ) ) 00399 { 00400 const Edge& e = _graph.instance( ed ); 00401 vertex_descriptor out = _graph.source( ed ); 00402 typename IdentityNodeConnection<TGraph>::OutputClipConnection c; 00403 c._dstNode = _graph.instance(out).getKey(); 00404 c._dstNodeClip = e.getInAttrName(); 00405 reconnect._outputs.push_back(c); 00406 } 00407 TUTTLE_TLOG( TUTTLE_TRACE, "isIdentity => " << vertex.getName() << " - " << inputClip << " at time " << atTime ); 00408 _toRemove.push_back( reconnect ); 00409 TUTTLE_TLOG_VAR( TUTTLE_TRACE, _toRemove.size() ); 00410 } 00411 catch( boost::exception& e ) 00412 { 00413 e << exception::user() + "A node is declared identity without given a valid input clip ("+quotes(inputClip)+", "+atTime+ ")." 00414 << exception::nodeName( vertex.getName() ) 00415 << exception::time( vertex.getProcessDataAtTime()._time ); 00416 throw; 00417 } 00418 } 00419 } 00420 00421 private: 00422 TGraph& _graph; 00423 std::vector<IdentityNodeConnection<TGraph> >& _toRemove; 00424 00425 }; 00426 00427 /** 00428 * @brief Unconnect identity nodes and re-connect neightbors nodes 00429 * 00430 * //////////////////////////////////////////////////////////////////////////////// 00431 * // Output at time 5 00432 * // | 00433 * // Retime time -2 <-- identity node declare to use Merge at time 3 00434 * // | 00435 * // Merge at time 3 <-- identity node declare to use ReadA at time 3 00436 * // / \ 00437 * // / \ 00438 * // / \ 00439 * // ReadA time 3 ReadB time 3 00440 * // 00441 * //////////////////////////////////////////////////////////////////////////////// 00442 * // After removing identity nodes: 00443 * // 00444 * // Output at time 5 00445 * // | 00446 * // ReadA time 3 00447 * // 00448 * // Retime time -2 <-- leave unconnected 00449 * // Merge at time 3 <-- leave unconnected 00450 * // ReadB time 3 <-- leave unconnected 00451 * //////////////////////////////////////////////////////////////////////////////// 00452 */ 00453 template<class TGraph> 00454 void removeIdentityNodes( TGraph& graph, const std::vector<IdentityNodeConnection<TGraph> >& nodesToRemove ) 00455 { 00456 // TUTTLE_IF_DEBUG( 00457 // TUTTLE_LOG_VAR( TUTTLE_TRACE, toRemove.size() ); 00458 // BOOST_FOREACH( const IdentityNodeConnection<TGraph>& connection, toRemove ) 00459 // { 00460 // TUTTLE_LOG( TUTTLE_TRACE, connection._identityVertex ); 00461 // TUTTLE_LOG( TUTTLE_TRACE, "IN: " 00462 // << connection._identityVertex << "::" << connection._input._inputClip 00463 // << " <<-- " 00464 // << connection._input._srcNode << "::" kOfxOutputAttributeName ); 00465 // 00466 // BOOST_FOREACH( const typename IdentityNodeConnection<TGraph>::OutputClipConnection& outputClipConnection, connection._outputs ) 00467 // { 00468 // TUTTLE_LOG( TUTTLE_TRACE, "OUT: " 00469 // << connection._identityVertex << "::" kOfxOutputAttributeName 00470 // << " -->> " 00471 // << outputClipConnection._dstNode << "::" << outputClipConnection._dstNodeClip ); 00472 // } 00473 // } 00474 // ); 00475 // TUTTLE_LOG( TUTTLE_TRACE, "-- removeIdentityNodes --" ); 00476 typedef typename TGraph::Vertex Vertex; 00477 typedef typename Vertex::Key VertexKey; 00478 00479 typedef boost::unordered_map<VertexKey, const IdentityNodeConnection<TGraph>*> IdentityMap; 00480 IdentityMap identityNodes; 00481 00482 BOOST_FOREACH( const IdentityNodeConnection<TGraph>& connection, nodesToRemove ) 00483 { 00484 identityNodes[connection._identityVertex] = &connection; 00485 } 00486 00487 BOOST_FOREACH( const IdentityNodeConnection<TGraph>& connection, nodesToRemove ) 00488 { 00489 TUTTLE_TLOG( TUTTLE_TRACE, boost::lexical_cast<std::string>(connection._identityVertex) ); 00490 TUTTLE_TLOG( TUTTLE_TRACE, "IN: " 00491 << boost::lexical_cast<std::string>(connection._identityVertex) << "::" << boost::lexical_cast<std::string>(connection._input._inputClip) 00492 << " <<-- " 00493 << boost::lexical_cast<std::string>(connection._input._srcNode) << "::" kOfxOutputAttributeName ); 00494 const typename TGraph::VertexKey* searchIn = &( connection._input._srcNode ); 00495 { 00496 // search a non-identity node to replace the connection 00497 typename IdentityMap::const_iterator it = identityNodes.find( *searchIn ); 00498 typename IdentityMap::const_iterator itEnd = identityNodes.end(); 00499 while( it != itEnd ) 00500 { 00501 searchIn = &( it->second->_input._srcNode ); 00502 it = identityNodes.find( *searchIn ); 00503 } 00504 } 00505 const typename TGraph::VertexKey& in = *searchIn; 00506 const typename TGraph::vertex_descriptor descIn = graph.getVertexDescriptor( in ); 00507 00508 // replace all input/output connections of the identity node by one edge 00509 BOOST_FOREACH( const typename IdentityNodeConnection<TGraph>::OutputClipConnection& outputClipConnection, connection._outputs ) 00510 { 00511 //TUTTLE_LOG( TUTTLE_TRACE, "OUT: " 00512 // << connection._identityVertex << "::" kOfxOutputAttributeName 00513 // << " -->> " 00514 // << outputClipConnection._dstNode << "::" << outputClipConnection._dstNodeClip ); 00515 const typename TGraph::VertexKey& out = outputClipConnection._dstNode; 00516 const std::string inAttr = outputClipConnection._dstNodeClip; 00517 00518 const typename TGraph::vertex_descriptor descOut = graph.getVertexDescriptor( out ); 00519 00520 const typename TGraph::Edge e( in, out, inAttr ); 00521 graph.addEdge( descOut, descIn, e ); 00522 } 00523 // Warning: We don't remove the vertex itself to not invalidate vertex_descriptors but only remove edges. 00524 // graph.removeVertex( graph.getVertexDescriptor(connection._identityVertex) ); 00525 // remove all node connections 00526 graph.clearVertex( graph.getVertexDescriptor(connection._identityVertex) ); 00527 } 00528 } 00529 00530 template<class TGraph> 00531 class PreProcess1 : public boost::default_dfs_visitor 00532 { 00533 public: 00534 typedef typename TGraph::GraphContainer GraphContainer; 00535 typedef typename TGraph::Vertex Vertex; 00536 00537 PreProcess1( TGraph& graph ) 00538 : _graph( graph ) 00539 {} 00540 00541 template<class VertexDescriptor, class Graph> 00542 void finish_vertex( VertexDescriptor v, Graph& g ) 00543 { 00544 Vertex& vertex = _graph.instance( v ); 00545 00546 TUTTLE_TLOG( TUTTLE_TRACE, "[Preprocess 1] finish vertex " << vertex ); 00547 if( vertex.isFake() ) 00548 return; 00549 00550 //TUTTLE_TLOG( TUTTLE_TRACE, vertex.getProcessDataAtTime()._time ); 00551 vertex.getProcessNode().preProcess1( vertex.getProcessDataAtTime() ); 00552 } 00553 00554 private: 00555 TGraph& _graph; 00556 }; 00557 00558 template<class TGraph> 00559 class PreProcess2 : public boost::default_dfs_visitor 00560 { 00561 public: 00562 typedef typename TGraph::GraphContainer GraphContainer; 00563 typedef typename TGraph::Vertex Vertex; 00564 00565 PreProcess2( TGraph& graph ) 00566 : _graph( graph ) 00567 {} 00568 00569 template<class VertexDescriptor, class Graph> 00570 void discover_vertex( VertexDescriptor v, Graph& g ) 00571 { 00572 Vertex& vertex = _graph.instance( v ); 00573 00574 TUTTLE_TLOG( TUTTLE_TRACE, "[Preprocess 2] discover vertex " << vertex ); 00575 if( vertex.isFake() ) 00576 return; 00577 00578 vertex.getProcessNode().preProcess2_reverse( vertex.getProcessDataAtTime() ); 00579 } 00580 00581 private: 00582 TGraph& _graph; 00583 }; 00584 00585 template<class TGraph> 00586 class OptimizeGraph : public boost::default_dfs_visitor 00587 { 00588 public: 00589 typedef typename TGraph::GraphContainer GraphContainer; 00590 typedef typename TGraph::Vertex Vertex; 00591 typedef typename TGraph::Edge Edge; 00592 typedef typename TGraph::vertex_descriptor vertex_descriptor; 00593 typedef typename TGraph::edge_descriptor edge_descriptor; 00594 typedef typename TGraph::in_edge_iterator in_edge_iterator; 00595 typedef typename TGraph::out_edge_iterator out_edge_iterator; 00596 00597 OptimizeGraph( TGraph& graph ) 00598 : _graph( graph ) 00599 { 00600 } 00601 00602 template <class VertexDescriptor, class Graph> 00603 void finish_vertex( VertexDescriptor v, const Graph& g ) 00604 { 00605 using namespace boost; 00606 using namespace boost::graph; 00607 Vertex& vertex = _graph.instance( v ); 00608 00609 ProcessVertexAtTimeData& procOptions = vertex.getProcessDataAtTime(); 00610 if( !vertex.isFake() ) 00611 { 00612 // compute local infos, need to be a real node ! 00613 vertex.getProcessNode().preProcess_infos( vertex.getProcessDataAtTime(), procOptions._time, procOptions._localInfos ); 00614 } 00615 00616 // compute global infos for inputs 00617 00618 // direct dependencies (originally the node inputs) 00619 BOOST_FOREACH( const edge_descriptor& oe, out_edges( v, _graph.getGraph() ) ) 00620 { 00621 // Edge& outEdge = _graph.instance(*oe); 00622 Vertex& outVertex = _graph.targetInstance( oe ); 00623 procOptions._inputsInfos += outVertex.getProcessDataAtTime()._localInfos; 00624 procOptions._globalInfos += outVertex.getProcessDataAtTime()._globalInfos; 00625 } 00626 procOptions._globalInfos += procOptions._localInfos; 00627 00628 // BOOST_FOREACH( const edge_descriptor& ie, in_edges( v, _graph.getGraph() ) ) 00629 // { 00630 // Edge& e = _graph.instance( ie ); 00631 // } 00632 00633 00634 // TUTTLE_TLOG( TUTTLE_TRACE, vertex.getName() ); 00635 // TUTTLE_TLOG( TUTTLE_TRACE, procOptions ); 00636 } 00637 00638 private: 00639 TGraph& _graph; 00640 }; 00641 00642 template<class TGraph> 00643 class Process : public boost::default_dfs_visitor 00644 { 00645 public: 00646 typedef typename TGraph::GraphContainer GraphContainer; 00647 typedef typename TGraph::Vertex Vertex; 00648 00649 Process( TGraph& graph, memory::IMemoryCache& cache ) 00650 : _graph( graph ) 00651 , _cache( cache ) 00652 , _result( NULL ) 00653 { 00654 } 00655 00656 Process( TGraph& graph, memory::IMemoryCache& cache, memory::IMemoryCache& result ) 00657 : _graph( graph ) 00658 , _cache( cache ) 00659 , _result( &result ) 00660 { 00661 } 00662 00663 /** 00664 * Set a MemoryCache object to accumulate output nodes buffers. 00665 */ 00666 void setOutputMemoryCache( memory::IMemoryCache& result ) 00667 { 00668 _result = &result; 00669 } 00670 00671 template<class VertexDescriptor, class Graph> 00672 void finish_vertex( VertexDescriptor v, Graph& g ) 00673 { 00674 Vertex& vertex = _graph.instance( v ); 00675 TUTTLE_TLOG( TUTTLE_TRACE, "[Process] finish_vertex " << vertex ); 00676 00677 // do nothing on the empty output node 00678 // it's just a link to final nodes 00679 if( vertex.isFake() ) 00680 return; 00681 00682 // check if abort ? 00683 00684 // launch the process 00685 boost::posix_time::ptime t1(boost::posix_time::microsec_clock::local_time()); 00686 vertex.getProcessNode().process( vertex.getProcessDataAtTime() ); 00687 boost::posix_time::ptime t2(boost::posix_time::microsec_clock::local_time()); 00688 _cumulativeTime += t2 - t1; 00689 00690 TUTTLE_TLOG( TUTTLE_TRACE, "[Process] " << quotes(vertex._name) << " " << vertex._data._time << " took: " << t2 - t1 << " (cumul: " << _cumulativeTime << ")" << vertex ); 00691 00692 if( _result && vertex.getProcessDataAtTime()._isFinalNode ) 00693 { 00694 memory::CACHE_ELEMENT img = _cache.get( vertex._clipName + "." kOfxOutputAttributeName, vertex._data._time ); 00695 if( ! img.get() ) 00696 { 00697 BOOST_THROW_EXCEPTION( exception::Logic() 00698 << exception::user() + "Output buffer not found in memoryCache at the end of the node process." 00699 << exception::nodeName( vertex._name ) 00700 << exception::time( vertex._data._time ) ); 00701 } 00702 _result->put( vertex._clipName, vertex._data._time, img ); 00703 } 00704 } 00705 00706 private: 00707 TGraph& _graph; 00708 memory::IMemoryCache& _cache; 00709 memory::IMemoryCache* _result; 00710 boost::posix_time::time_duration _cumulativeTime; 00711 }; 00712 00713 template<class TGraph> 00714 class PostProcess : public boost::default_dfs_visitor 00715 { 00716 public: 00717 typedef typename TGraph::GraphContainer GraphContainer; 00718 typedef typename TGraph::Vertex Vertex; 00719 00720 PostProcess( TGraph& graph ) 00721 : _graph( graph ) 00722 {} 00723 00724 template<class VertexDescriptor, class Graph> 00725 void initialize_vertex( VertexDescriptor v, Graph& g ) 00726 { 00727 Vertex& vertex = _graph.instance( v ); 00728 00729 TUTTLE_TLOG( TUTTLE_TRACE,"[Post-process] initialize_vertex " << vertex ); 00730 if( vertex.isFake() ) 00731 return; 00732 } 00733 00734 template<class VertexDescriptor, class Graph> 00735 void finish_vertex( VertexDescriptor v, Graph& g ) 00736 { 00737 Vertex& vertex = _graph.instance( v ); 00738 00739 TUTTLE_TLOG( TUTTLE_TRACE, "[Post-process] finish_vertex " << vertex ); 00740 if( vertex.isFake() ) 00741 return; 00742 00743 vertex.getProcessNode().postProcess( vertex.getProcessDataAtTime() ); 00744 } 00745 00746 private: 00747 TGraph& _graph; 00748 }; 00749 00750 } 00751 } 00752 } 00753 } 00754 00755 #endif 00756