FrameListPtr FrameListParameter::getFrameListValue( const StringData *value ) const
{
	FrameListPtr frameList = FrameList::parse( value->readable() );
	if ( !m_allowEmptyList && frameList->isInstanceOf( EmptyFrameListTypeId ) )
	{
		throw Exception( "Empty frame list not allowed!" );
	}

	return frameList;
}
	static list asList( FrameListPtr l )
	{
		std::vector<FrameList::Frame> frames;
		l->asList( frames );

		list result;

		for ( std::vector<FrameList::Frame>::const_iterator it = frames.begin(); it != frames.end(); ++it )
		{
			result.append( *it );
		}

		return result;
	}
bool FrameListParameter::valueValid( const Object *value, std::string *reason ) const
{
	if( !StringParameter::valueValid( value, reason ) )
	{
		return false;
	}

	const StringData *stringValue = assertedStaticCast<const StringData>( value );

	try
	{
		FrameListPtr frameList = FrameList::parse( stringValue->readable() );
		assert( frameList ); // If we didn't throw an exception, we must have successfully created a FrameList instance

		if ( !m_allowEmptyList && frameList->isInstanceOf( EmptyFrameListTypeId ) )
		{
			if ( reason )
			{
				*reason = "Value must not be empty.";
			}

			return false;
		}

	}
	catch ( std::exception &e )
	{
		if ( reason )
		{
			*reason = e.what();
		}

		return false;
	}

	return true;
}
	static list asClumpedList( FrameListPtr l, unsigned int clumpSize )
	{
		std::vector< std::vector<FrameList::Frame> > clumpList;
		l->asClumpedList( clumpList, clumpSize );

		list result;

		for ( std::vector< std::vector<FrameList::Frame> >::const_iterator clumpIt = clumpList.begin(); clumpIt != clumpList.end(); ++clumpIt )
		{
			list clump;

			for ( std::vector<FrameList::Frame>::const_iterator frameIt = clumpIt->begin(); frameIt != clumpIt->end(); ++ frameIt )
			{
				clump.append( *frameIt );
			}

			result.append( clump );
		}

		return result;
	}
void IECore::findSequences( const std::vector< std::string > &names, std::vector< FileSequencePtr > &sequences, size_t minSequenceSize )
{
	sequences.clear();

	/// this matches names of the form $prefix$frameNumber$suffix
	/// placing each of those in a group of the resulting match.
	/// both $prefix and $suffix may be the empty string and $frameNumber
	/// may be preceded by a minus sign.
	/// It also matches file extensions with 3 or 4 characters that contain numbers (for example: CR2, MP3 )
	boost::regex matchExpression( std::string( "^([^#]*?)(-?[0-9]+)([^0-9#]*|[^0-9#]*\\.[a-zA-Z]{2,3}[0-9])$" ) );

	/// build a mapping from ($prefix, $suffix) to a list of $frameNumbers
	typedef std::vector< std::string > Frames;
	typedef std::map< std::pair< std::string, std::string >, Frames > SequenceMap;

	SequenceMap sequenceMap;

	for ( std::vector< std::string >::const_iterator it = names.begin(); it != names.end(); ++it )
	{
		boost::smatch matches;
		if ( boost::regex_match( *it, matches, matchExpression ) )
		{
			sequenceMap[
				SequenceMap::key_type(
					std::string( matches[1].first, matches[1].second ),
					std::string( matches[3].first, matches[3].second )
				)
			].push_back( std::string( matches[2].first, matches[2].second ) );
		}
	}

	for ( SequenceMap::const_iterator it = sequenceMap.begin(); it != sequenceMap.end(); ++it )
	{
		const SequenceMap::key_type &fixes = it->first;
		const Frames &frames = it->second;
		// todo: could be more efficient by writing a custom comparison function that uses indexes 
		//	 into the const Frames vector rather than duplicating the strings and sorting them directly
		Frames sortedFrames = frames;
		std::sort( sortedFrames.begin(), sortedFrames.end() );
		
		/// in diabolical cases the elements of frames may not all have the same padding
		/// so we'll sort them out into padded and unpadded frame sequences here, by creating
		/// a map of padding->list of frames. unpadded things will be considered to have a padding
		/// of 1.
		typedef std::vector< FrameList::Frame > NumericFrames;
		typedef std::map< unsigned int, NumericFrames > PaddingToFramesMap;
		PaddingToFramesMap paddingToFrames;
		for ( Frames::const_iterator fIt = sortedFrames.begin(); fIt != sortedFrames.end(); ++fIt )
		{
			std::string frame = *fIt;
			int sign = 1;

			assert( frame.size() );
			if ( *frame.begin() == '-' )
			{
				frame = frame.substr( 1, frame.size() - 1 );
				sign = -1;
			}
			if ( *frame.begin() == '0' || paddingToFrames.find( frame.size() ) != paddingToFrames.end() )
			{
				paddingToFrames[ frame.size() ].push_back( sign * boost::lexical_cast<FrameList::Frame>( frame ) );
			}
			else
			{
				paddingToFrames[ 1 ].push_back( sign * boost::lexical_cast<FrameList::Frame>( frame ) );
			}
		}

		for ( PaddingToFramesMap::iterator pIt = paddingToFrames.begin(); pIt != paddingToFrames.end(); ++pIt )
		{
			const PaddingToFramesMap::key_type &padding = pIt->first;
			NumericFrames &numericFrames = pIt->second;
			std::sort( numericFrames.begin(), numericFrames.end() );

			FrameListPtr frameList = frameListFromList( numericFrames );

			std::vector< FrameList::Frame > expandedFrameList;
			frameList->asList( expandedFrameList );

			/// remove any sequences with less than the given minimum.
			if ( expandedFrameList.size() >= minSequenceSize )
			{
				std::string frameTemplate;
				for ( PaddingToFramesMap::key_type i = 0; i < padding; i++ )
				{
					frameTemplate += "#";
				}

				sequences.push_back(
					new FileSequence(
						fixes.first + frameTemplate + fixes.second,
						frameList
					)
				);
			}
		}
	}
}
Example #6
0
void Dispatcher::dispatch( const std::vector<NodePtr> &nodes ) const
{
	// clear job directory, so that if our node validation fails,
	// jobDirectory() won't return the result from the previous dispatch.
	m_jobDirectory = "";

	// validate the nodes we've been given

	if ( nodes.empty() )
	{
		throw IECore::Exception( getName().string() + ": Must specify at least one node to dispatch." );
	}

	std::vector<ExecutableNodePtr> executables;
	const ScriptNode *script = (*nodes.begin())->scriptNode();
	for ( std::vector<NodePtr>::const_iterator nIt = nodes.begin(); nIt != nodes.end(); ++nIt )
	{
		const ScriptNode *currentScript = (*nIt)->scriptNode();
		if ( !currentScript || currentScript != script )
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must all belong to the same ScriptNode." );
		}

		if ( ExecutableNode *executable = runTimeCast<ExecutableNode>( nIt->get() ) )
		{
			executables.push_back( executable );
		}
		else if ( const Box *box = runTimeCast<const Box>( nIt->get() ) )
		{
			for ( RecursiveOutputPlugIterator plugIt( box ); plugIt != plugIt.end(); ++plugIt )
			{
				Node *sourceNode = plugIt->get()->source<Plug>()->node();
				if ( ExecutableNode *executable = runTimeCast<ExecutableNode>( sourceNode ) )
				{
					executables.push_back( executable );
				}
			}
		}
		else
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must be ExecutableNodes or Boxes containing ExecutableNodes." );
		}
	}

	// create the job directory now, so it's available in preDispatchSignal().
	const Context *context = Context::current();
	m_jobDirectory = createJobDirectory( context );

	// this object calls this->preDispatchSignal() in its constructor and this->postDispatchSignal()
	// in its destructor, thereby guaranteeing that we always call this->postDispatchSignal().

	DispatcherSignalGuard signalGuard( this, executables );
	if ( signalGuard.cancelledByPreDispatch() )
	{
		return;
	}

	std::vector<FrameList::Frame> frames;
	FrameListPtr frameList = frameRange( script, context );
	frameList->asList( frames );

	size_t i = 0;
	ExecutableNode::Tasks tasks;
	tasks.reserve( executables.size() * frames.size() );
	for ( std::vector<FrameList::Frame>::const_iterator fIt = frames.begin(); fIt != frames.end(); ++fIt )
	{
		for ( std::vector<ExecutableNodePtr>::const_iterator nIt = executables.begin(); nIt != executables.end(); ++nIt, ++i )
		{
			ContextPtr frameContext = new Context( *context, Context::Borrowed );
			frameContext->setFrame( *fIt );
			tasks.push_back( ExecutableNode::Task( *nIt, frameContext ) );
		}
	}

	TaskBatchPtr rootBatch = batchTasks( tasks );

	if ( !rootBatch->requirements().empty() )
	{
		doDispatch( rootBatch.get() );
	}

	// inform the guard that the process has been completed, so it can pass this info to
	// postDispatchSignal():

	signalGuard.success();
}
Example #7
0
void RenderThread::RenderFrames(FrameListPtr sourceFrames, YUV_PLANE plane)
{
	FrameImpl tempFrame;

	for (int i = 0; i < sourceFrames->size(); i++) 
	{
		FramePtr sourceFrameOrig = sourceFrames->at(i);
		if (!sourceFrameOrig)
		{
			continue;
		}
		unsigned int viewID = sourceFrameOrig->Info(VIEW_ID).toUInt();

		Frame* sourceFrame = sourceFrameOrig.data();
		float scaleX = 1;
		float scaleY = 1;
		if (plane != PLANE_COLOR)
		{
			COLOR_FORMAT c = sourceFrameOrig->Format()->Color();
			if (c == I420 || c == I422 || c == I444)
			{
				sourceFrame = &tempFrame;

				FormatPtr format = sourceFrameOrig->Format();
				sourceFrame->Format()->SetColor(Y800);
				sourceFrame->Format()->SetWidth(format->PlaneWidth(plane));
				sourceFrame->Format()->SetHeight(format->PlaneHeight(plane));
				sourceFrame->Format()->SetStride(0, format->Stride(plane));
				sourceFrame->Format()->PlaneSize(0);


				sourceFrame->SetData(0, sourceFrameOrig->Data(plane));

				scaleX = ((float)format->PlaneWidth(plane))/format->Width();
				scaleY = ((float)format->PlaneHeight(plane))/format->Height();
			}
		}
		
		int pos = -1;
		for (int k = 0; k < m_RenderFrames.size(); k++) 
		{
			FramePtr _frame = m_RenderFrames.at(k);
			if (_frame && _frame->Info(VIEW_ID).toUInt() == viewID)
			{
				pos = k;
				break;
			}
		}

		if (pos == -1)
		{
			pos = m_RenderFrames.size();
			m_RenderFrames.append(FramePtr());
		}

		FramePtr& renderFrame = m_RenderFrames[pos];
		// Deallocate if resolution changed
		if (renderFrame && (sourceFrame->Format()->Width() != 
			renderFrame->Format()->Width() || 
			sourceFrame->Format()->Height() != 
			renderFrame->Format()->Height()))
		{
			m_Renderer->Deallocate(renderFrame);
			renderFrame.clear();
		}

		// Allocate if needed
		if (!renderFrame)
		{
			m_Renderer->Allocate(renderFrame, sourceFrame->Format());
		}
		
		renderFrame->SetInfo(VIEW_ID, viewID);
		renderFrame->SetInfo(RENDER_SRC_SCALE_X, scaleX);
		renderFrame->SetInfo(RENDER_SRC_SCALE_Y, scaleY);

		// Render frame
		if (m_Renderer->GetFrame(renderFrame) == OK)
		{
			if (sourceFrame->Format() == renderFrame->Format())
			{
				for (int i=0; i<4; i++)
				{
					size_t len = renderFrame->Format()->PlaneSize(i);
					if (len > 0)
					{
						memcpy(renderFrame->Data(i), sourceFrame->Data(i), len);
					}
				}

			}else
			{
				ColorConversion(*sourceFrame, *renderFrame);
			}

			m_Renderer->ReleaseFrame(renderFrame);
		}
	}
}
Example #8
0
void Dispatcher::dispatch( const std::vector<NodePtr> &nodes ) const
{
	// clear job directory, so that if our node validation fails,
	// jobDirectory() won't return the result from the previous dispatch.
	m_jobDirectory = "";

	// validate the nodes we've been given

	if ( nodes.empty() )
	{
		throw IECore::Exception( getName().string() + ": Must specify at least one node to dispatch." );
	}

	std::vector<TaskNodePtr> taskNodes;
	const ScriptNode *script = (*nodes.begin())->scriptNode();
	for ( std::vector<NodePtr>::const_iterator nIt = nodes.begin(); nIt != nodes.end(); ++nIt )
	{
		const ScriptNode *currentScript = (*nIt)->scriptNode();
		if ( !currentScript || currentScript != script )
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must all belong to the same ScriptNode." );
		}

		if ( TaskNode *taskNode = runTimeCast<TaskNode>( nIt->get() ) )
		{
			taskNodes.push_back( taskNode );
		}
		else if ( const SubGraph *subGraph = runTimeCast<const SubGraph>( nIt->get() ) )
		{
			for ( RecursiveOutputPlugIterator plugIt( subGraph ); !plugIt.done(); ++plugIt )
			{
				Node *sourceNode = plugIt->get()->source()->node();
				if ( TaskNode *taskNode = runTimeCast<TaskNode>( sourceNode ) )
				{
					taskNodes.push_back( taskNode );
				}
			}
		}
		else
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must be TaskNodes or SubGraphs containing TaskNodes." );
		}
	}

	Context::EditableScope jobScope( Context::current() );
	// create the job directory now, so it's available in preDispatchSignal().
	/// \todo: move directory creation between preDispatchSignal() and dispatchSignal()
	m_jobDirectory = createJobDirectory( Context::current() );
	jobScope.set( g_jobDirectoryContextEntry, m_jobDirectory );

	// this object calls this->preDispatchSignal() in its constructor and this->postDispatchSignal()
	// in its destructor, thereby guaranteeing that we always call this->postDispatchSignal().

	DispatcherSignalGuard signalGuard( this, taskNodes );
	if ( signalGuard.cancelledByPreDispatch() )
	{
		return;
	}

	dispatchSignal()( this, taskNodes );

	std::vector<FrameList::Frame> frames;
	FrameListPtr frameList = frameRange( script, Context::current() );
	frameList->asList( frames );

	Batcher batcher;
	for( std::vector<FrameList::Frame>::const_iterator fIt = frames.begin(); fIt != frames.end(); ++fIt )
	{
		for( std::vector<TaskNodePtr>::const_iterator nIt = taskNodes.begin(); nIt != taskNodes.end(); ++nIt )
		{
			jobScope.setFrame( *fIt );
			batcher.addTask( TaskNode::Task( *nIt, Context::current() ) );
		}
	}

	executeAndPruneImmediateBatches( batcher.rootBatch() );

	if( !batcher.rootBatch()->preTasks().empty() )
	{
		doDispatch( batcher.rootBatch() );
	}

	// inform the guard that the process has been completed, so it can pass this info to
	// postDispatchSignal():

	signalGuard.success();
}
Example #9
0
void Dispatcher::dispatch( const std::vector<NodePtr> &nodes ) const
{
	if ( nodes.empty() )
	{
		throw IECore::Exception( getName().string() + ": Must specify at least one node to dispatch." );
	}

	std::vector<ExecutableNodePtr> executables;
	const ScriptNode *script = (*nodes.begin())->scriptNode();
	for ( std::vector<NodePtr>::const_iterator nIt = nodes.begin(); nIt != nodes.end(); ++nIt )
	{
		const ScriptNode *currentScript = (*nIt)->scriptNode();
		if ( !currentScript || currentScript != script )
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must all belong to the same ScriptNode." );
		}

		if ( ExecutableNode *executable = runTimeCast<ExecutableNode>( nIt->get() ) )
		{
			executables.push_back( executable );
		}
		else if ( const Box *box = runTimeCast<const Box>( nIt->get() ) )
		{
			for ( RecursiveOutputPlugIterator plugIt( box ); plugIt != plugIt.end(); ++plugIt )
			{
				Node *sourceNode = plugIt->get()->source<Plug>()->node();
				if ( ExecutableNode *executable = runTimeCast<ExecutableNode>( sourceNode ) )
				{
					executables.push_back( executable );
				}
			}
		}
		else
		{
			throw IECore::Exception( getName().string() + ": Dispatched nodes must be ExecutableNodes or Boxes containing ExecutableNodes." );
		}
	}

	if ( preDispatchSignal()( this, executables ) )
	{
		/// \todo: communicate the cancellation to the user
		return;
	}

	const Context *context = Context::current();

	std::vector<FrameList::Frame> frames;
	FrameListPtr frameList = frameRange( script, context );
	frameList->asList( frames );

	size_t i = 0;
	ExecutableNode::Tasks tasks;
	tasks.reserve( executables.size() * frames.size() );
	for ( std::vector<FrameList::Frame>::const_iterator fIt = frames.begin(); fIt != frames.end(); ++fIt )
	{
		for ( std::vector<ExecutableNodePtr>::const_iterator nIt = executables.begin(); nIt != executables.end(); ++nIt, ++i )
		{
			ContextPtr frameContext = new Context( *context, Context::Borrowed );
			frameContext->setFrame( *fIt );
			tasks.push_back( ExecutableNode::Task( *nIt, frameContext ) );
		}
	}

	TaskBatchPtr rootBatch = batchTasks( tasks );

	if ( !rootBatch->requirements().empty() )
	{
		doDispatch( rootBatch.get() );
	}

	postDispatchSignal()( this, executables );
}