예제 #1
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
double Scene::nextEdge(double pts)
{
	double margin = profile.getVideoFrameDuration() / 4.0;
	double npts = 0, max = 0;
	
	for ( int i = 0; i < tracks.count(); ++i ) {
		if ( !tracks[ i ]->clipCount() )
			continue;
		Clip *c = tracks[ i ]->clipAt( tracks[ i ]->clipCount() - 1 );
		double d = c->position() + c->length();
		if ( d > max )
			max = d;
	}
	
	npts = max;
	
	for ( int i = 0; i < tracks.count(); ++i ) {
		Track *t = tracks[ i ];
		for ( int j = 0; j < t->clipCount(); ++j ) {
			Clip *c = t->clipAt( j );
			double pos = c->position() - margin;
			if ( pos > pts && pos < npts ) {
				npts = pos + margin;
			}
			else {
				pos += c->length();
				if ( pos > pts && pos < npts ) {
					npts = pos + margin;
				}
			}
		}
	}
	
	return (qAbs(npts - max) < 1) ? max - profile.getVideoFrameDuration() : npts;
}
예제 #2
0
void ClipBoard::readTrack( QDomElement &element, QList<Clip*> *track, QList<Source*> *sourcesList, Scene *scene )
{
    bool readError = false;
    QDomNodeList nodes = element.childNodes();

    for ( int i = 0; i < nodes.count(); ++i ) {
        QDomElement e = nodes.at( i ).toElement();
        if ( e.isNull() )
            continue;

        if ( e.tagName() == "Clip" ) {
            Clip *clip = XMLizer::readClip( e, sourcesList, scene, readError );
            if (clip) {
                int k = 0, tc = track->count();
                // sort clips by position
                while ( k < tc ) {
                    Clip *c = track->at( k );
                    if ( clip->position() < c->position() ) {
                        track->insert( k, clip );
                        break;
                    }
                    ++k;
                }
                if ( k == tc ) {
                    track->append( clip );
                }
            }
        }
    }
}
예제 #3
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
bool Scene::setProfile( Profile &p )
{
	bool ok = true;
	double duration = profile.getVideoFrameDuration();
	profile = p;
	double margin = profile.getVideoFrameDuration() / 4.0;
	
	if ( duration != profile.getVideoFrameDuration() ) {
		duration = profile.getVideoFrameDuration();
		for ( int i = 0; i < tracks.count(); ++i ) {
			Track *t = tracks[i];
			for ( int j = 0; j < t->clipCount(); ++j ) {
				Clip *c = t->clipAt( j );
				c->setFrameDuration( duration );
				double newPos = nearestPTS( c->position(), duration );
				if ( !c->getTransition() && j > 0 ) {
					Clip *prev = t->clipAt( j - 1 );
					if ( newPos < prev->position() + prev->length() - margin )
						newPos = prev->position() + prev->length();
					c->setPosition( newPos );
				}
				else if ( canMove( c, c->length(), newPos, i ) )
					move( c, i, newPos, i );
				else
					ok = false;
			}
		}
	}
	
	return ok;
}
예제 #4
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::removeTransitions( Clip *clip, int oldTrack, int newTrack, int newIndex, double clipPos, double clipLength, double margin, bool multi )
{
	Track *ot = tracks[oldTrack];

	int index = ot->indexOf( clip );
	if ( newTrack != oldTrack || index != newIndex ) {
		clip->removeTransition();
		if ( index < ot->clipCount() - 1 ) {
			Clip *c = ot->clipAt( index + 1 );
			c->removeTransition();
		}
	}
	else {
		if ( !multi && index < ot->clipCount() - 1 ) {
			Clip *c = ot->clipAt( index + 1 );
			if ( clipPos + clipLength - margin < c->position() )
				c->removeTransition();
		}
		if ( index > 0 ) {
			Clip *c = ot->clipAt( index - 1 );
			if ( c->position() + c->length() - margin < clipPos )
				clip->removeTransition();
		}
	}
}
예제 #5
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::updateTransitions( Clip *clip, int track, double margin )
{
	Track *t = tracks[track];
	int index = t->indexOf( clip );
	
	if ( index > 0 ) {
		Clip *c = t->clipAt( index - 1 );
		if ( clip->position() < c->position() + c->length() - margin )
			clip->setTransition( c->position() + c->length() - clip->position() );
	}
	if ( index < t->clipCount() - 1 ) {
		Clip *c = t->clipAt( index + 1 );
		if ( c->position() < clip->position() + clip->length() - margin )
			c->setTransition( clip->position() + clip->length() - c->position() );
	}
}
예제 #6
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::moveMulti( Clip *clip, int clipTrack, double newPos )
{
	QMutexLocker ml( &mutex );
	
	if ( clip->position() == newPos )
		return;
	
	double delta = newPos - clip->position();
	double margin = profile.getVideoFrameDuration() / 4.0;
	Track *t = tracks[clipTrack];
	int count = t->clipCount();
	int clipIndex = 0;
	int k = 0;
	while ( k < count ) {
		Clip *c = t->clipAt( k );
		// find clip
		if ( c == clip ) {
			clipIndex = k;
			break;
		}
		++k;
	}

	removeTransitions( clip, clipTrack, clipTrack, clipIndex, newPos, clip->length(), margin, true );
	clip->setPosition( clip->position() + delta );
	while ( ++k < count ) {
		Clip *c = t->clipAt( k );
		c->setPosition( c->position() + delta );
	}
	updateTransitions( clip, clipTrack, margin );
	clip->setInput( NULL );
	
	update = true;
}
예제 #7
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::move( Clip *clip, int clipTrack, double newPos, int newTrack )
{
	QMutexLocker ml( &mutex );
	
	if ( clip->position() == newPos && clipTrack == newTrack )
		return;
	
	double margin = profile.getVideoFrameDuration() / 4.0;
	int insert, self = 0;
	Track *t = tracks[newTrack];
	insert = t->clipCount();
	for ( int i = 0; i < t->clipCount(); ++i ) {
		Clip *c = t->clipAt( i );
		if ( c == clip ) {
			++self;
			continue;
		}
		if ( newPos < c->position() ) {
			insert = i;
			break;
		}
	}
			
	insert -= self;
	removeTransitions( clip, clipTrack, newTrack, insert, newPos, clip->length(), margin );
	tracks[clipTrack]->removeClip( clip );
	t->insertClipAt( clip, insert );
	clip->setPosition( newPos );
	updateTransitions( clip, newTrack, margin );
	clip->setInput( NULL );
	update = true;
}
예제 #8
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
bool Scene::canMoveMulti( Clip *clip, double clipLength, double &newPos, int track )
{
	newPos = nearestPTS( newPos, profile.getVideoFrameDuration() );
	double margin = profile.getVideoFrameDuration() / 4.0;
	Track *t = tracks[track];
	int count = t->clipCount();
	
	if ( newPos >= clip->position() )
		return true;

	if ( t->clipAt( 0 ) == clip )
		return true;
	
	Clip *c;
	int k = 0;
	while ( k < count ) {
		c = t->clipAt( k );
		// find clip
		if ( c == clip ) {
			break;
		}
		++k;
	}
	if ( k == count )
		return false;
	
	int clipIndex = k;
	c = t->clipAt( --k );
	if ( newPos - margin < c->position() )
			return false;
	// we are clipB, we can't end before clipA
	if ( newPos + clipLength < c->position() + c->length() - margin )
		return false;
	// we can't overlap with clip before clipA
	if ( --k >= 0 ) {
		Clip *prevA = t->clipAt( k );
		if ( newPos < prevA->position() + prevA->length() - margin )
			return false; 
	}
	// and clipC can't overlap with clipA
	if ( clipIndex < count - 1 ) {
		Clip *clipC = t->clipAt( clipIndex + 1 );
		// clipC has moved with us, calculate its new position
		double cpos = clipC->position() + ( newPos - clip->position() );
		if ( cpos < c->position() + c->length() - margin ) {
			newPos = c->position() + c->length() + clip->position() - clipC->position();
			return true;
		}
	}
	
	return true;
}
예제 #9
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::addClip( Clip *clip, int track )
{
	QMutexLocker ml( &mutex );
	double margin = profile.getVideoFrameDuration() / 4.0;
	Track *t = tracks[track];
	int i = 0, cc = t->clipCount();
	while ( i < cc ) {
		Clip *c = t->clipAt( i );
		if ( clip->position() < c->position() ) {
			t->insertClipAt( clip, i );
			updateTransitions( clip, track, margin );
			update = true;
			return;
		}
		++i;
	}
	t->insertClipAt( clip, i );
	updateTransitions( clip, track, margin );
}
예제 #10
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
double Scene::previousEdge(double pts)
{
	double margin = profile.getVideoFrameDuration() / 4.0;
	double npts = 0;
	
	for ( int i = 0; i < tracks.count(); ++i ) {
		Track *t = tracks[ i ];
		for ( int j = t->clipCount() -1; j > -1; --j ) {
			Clip *c = t->clipAt( j );
			double pos = c->position() + c->length() + margin;
			if ( pos < pts && pos > npts ) {
				npts = pos;
			}
			else {
				pos -= c->length();
				if ( pos < pts && pos > npts ) {
					npts = pos;
				}
			}
		}
	}
	
	return npts;
}
예제 #11
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
void Scene::resizeStart( Clip *clip, double newPos, double newLength, int track )
{
	QMutexLocker ml( &mutex );
	
	if ( clip->position() == newPos && clip->length() == newLength )
		return;
	
	double margin = profile.getVideoFrameDuration() / 4.0;
	int insert, self = 0;
	Track *t = tracks[track];
	insert = t->clipCount();
	for ( int i = 0; i < t->clipCount(); ++i ) {
		Clip *c = t->clipAt( i );
		if ( c == clip ) {
			++self;
			continue;
		}
		if ( newPos < c->position() ) {
			insert = i;
			break;
		}
	}
				
	insert -= self;
	double old = clip->position();
	removeTransitions( clip, track, track, insert, newPos, newLength, margin );
	t->removeClip( clip );
	t->insertClipAt( clip, insert );
	if ( clip->getSource()->getType() == InputBase::FFMPEG && clip->getSpeed() >= 0 )
		clip->setStart( clip->start() + ((clip->length() - newLength) * qAbs(clip->getSpeed())) );
	clip->setLength( newLength );
	clip->setPosition( newPos );
	updateTransitions( clip, track, margin );
	clip->setInput( NULL );
	update = updateCurrentPosition( qMin( old, clip->position() ), qMax( old, clip->position() )  );
}
예제 #12
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
bool Scene::checkPlacement( Clip *clip, int track, double clipPos, double clipLength )
{
	double margin = profile.getVideoFrameDuration() / 4.0;
	Track *t = tracks[track];
	int count = t->clipCount();
	
	// no clip in track yet
	if ( !count )
		return true;
	if ( count == 1 && t->clipAt( 0 ) == clip )
		return true;
	
	Clip *c;
	int k = 0;
	while ( k < count ) {
		c = t->clipAt( k );
		// obviously, don't check clip against itself
		if ( clip && c == clip ) {
			++k;
			continue;
		}
		// Track is ordered by Clip::position()
		// so 2 clips can't start at same pts on the same track.
		if ( qAbs( c->position() - clipPos ) < margin )
			return false;
		if ( !clipLessThan( margin, c->position(), c->length(), clipPos ) )
			break;
		++k;
	}
	// we are the last clip in track and don't overlap with anything
	if ( k == count )
		return true;
	// we are clipA
	if ( clipPos < c->position() ) {
		// we can't end after clipB
		if ( c->position() + c->length() < clipPos + clipLength - margin )
			return false;
		// and we can't overlap with clipC
		int j = k + 1;
		while ( j < count ) {
			Clip *next = t->clipAt( j++ );
			if ( clip && next == clip )
				continue;
			if ( next->position() < clipPos + clipLength - margin )
				return false;
			break;
		}
	}
	else {
		// we are clipB, we can't end before clipA
		if ( clipPos + clipLength < c->position() + c->length() - margin )
			return false;
		int j = k + 1;
		while ( j < count ) {
			Clip *next = t->clipAt( j++ );
			if ( clip && next == clip )
				continue;
			// clipC can't overlap with clipA
			if ( next->position() < c->position() + c->length() - margin )
				return false;
			// we can't end after clipC
			if ( next->position() + next->length() < clipPos + clipLength - margin )
				return false;
			// and we can't overlap with clipD
			if ( j < count ) {
				Clip *d = t->clipAt( j );
				if ( d->position() < clipPos + clipLength - margin )
					return false;
			}
			break;
		}
	}

	return true;
}
예제 #13
0
파일: scene.cpp 프로젝트: hftom/MachinTruc
Clip* Scene::sceneSplitClip( Clip *clip, int track, double pts )
{
	pts = nearestPTS( pts, profile.getVideoFrameDuration() );
	
	double start = clip->position();
	if (clip->getTransition()) {
		start += clip->getTransition()->length();
	}
	double end = clip->position() + clip->length();
	Track *t = tracks[track];
	int cc = t->clipCount();
	int index = t->indexOf(clip);
	Transition *tail = NULL;
	Clip *next = NULL;
	if (index > -1 && index < cc - 1) {
		next = t->clipAt(index + 1);
		if (next->getTransition()) {
			end -= next->getTransition()->length() + profile.getVideoFrameDuration();
			tail = new Transition(next->getTransition());
		}
	}

	double oldLength = clip->length();
	double newLength = pts - clip->position();
	
	resize( clip, newLength, track );
	Clip *nc = createClip( clip->getSource(), pts, clip->start() + newLength, oldLength - newLength );
	double newPos = nc->position();
	nc->setPosition( newPos );
	FilterCollection *fc = FilterCollection::getGlobalInstance();
	for ( int i = 0; i < clip->videoFilters.count(); ++i ) {
		QSharedPointer<GLFilter> f = clip->videoFilters.at( i );
		for ( int j = 0; j < fc->videoFilters.count(); ++j ) {
			if ( fc->videoFilters[ j ].identifier == f->getIdentifier() ) {
				QSharedPointer<Filter> nf = fc->videoFilters[ j ].create();
				GLFilter *gf = (GLFilter*)nf.data();
				if ( nf->getIdentifier() == "GLCustom" ) {
					GLCustom *gc = (GLCustom*)gf;
					gc->setCustomParams( f->getParameters().last()->value.toString() );
				}
				else if ( nf->getIdentifier() == "GLStabilize"  ) {
					GLStabilize *gs = (GLStabilize*)gf;
					gs->setSource( nc->getSource() );
				}
				f->splitParameters( gf, newLength );
				nf->setPosition( nc->position() );
				nf->setLength( nc->length() );
				nc->videoFilters.append( nf.staticCast<GLFilter>() );
				break;
			}
		}
	}
	for ( int i = 0; i < clip->audioFilters.count(); ++i ) {
		QSharedPointer<AudioFilter> f = clip->audioFilters.at( i );
		for ( int j = 0; j < fc->audioFilters.count(); ++j ) {
			if ( fc->audioFilters[ j ].identifier == f->getIdentifier() ) {
				QSharedPointer<Filter> nf = fc->audioFilters[ j ].create();
				AudioFilter *af = (AudioFilter*)nf.data();
				f->splitParameters( af, newLength );
				nf->setPosition( nc->position() );
				nf->setLength( nc->length() );
				nc->audioFilters.append( nf.staticCast<AudioFilter>() );
				break;
			}
		}
	}
	addClip( nc, track );
	if (tail) {
		next->setTransition(tail);
	}

	return nc;
}