Commit c56fd547 authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

You can now use the slider to change position in the render preview.

parent cd4b84ea
......@@ -123,16 +123,16 @@ void ClipWorkflow::initialize( LibVLCpp::MediaPlayer* mediaPlayer )
m_mediaPlayer = mediaPlayer;
m_mediaPlayer->setMedia( m_clip->getParent()->getVLCMedia() );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPosition() ), Qt::DirectConnection );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ), Qt::DirectConnection );
connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( endReached() ), Qt::DirectConnection );
// qDebug() << "Launching playback";
m_mediaPlayer->play();
}
void ClipWorkflow::setPosition()
void ClipWorkflow::setPositionAfterPlayback()
{
// qDebug() << "Setting position";
disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPosition() ) );
disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ) );
connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( pauseAfterPlaybackStarted() ), Qt::DirectConnection );
m_mediaPlayer->setPosition( m_clip->getBegin() );
}
......@@ -169,8 +169,19 @@ bool ClipWorkflow::isEndReached() const
void ClipWorkflow::startRender()
{
Q_ASSERT( m_isReady == true);
bool isReady;
{
QReadLocker lock( m_initMutex );
isReady = m_isReady;
}
while ( isReady == false )
{
usleep( 150 );
{
QReadLocker lock( m_initMutex );
isReady = m_isReady;
}
}
m_mediaPlayer->play();
}
......@@ -180,7 +191,32 @@ void ClipWorkflow::endReached()
m_endReached = true;
}
const Clip* ClipWorkflow::getClip() const
const Clip* ClipWorkflow::getClip() const
{
return m_clip;
}
void ClipWorkflow::stop()
{
{
QWriteLocker lock2( m_mutex );
m_renderComplete = false;
}
{
QWriteLocker lock2( m_endReachedLock );
m_endReached = false;
}
{
QWriteLocker lock( m_initMutex);
m_isReady = false;
}
m_mediaPlayer->stop();
m_mediaPlayer = NULL;
qDebug() << "Stoped ClipWorkflow";
}
void ClipWorkflow::setPosition( float pos )
{
qDebug() << "Setting position :" << pos;
m_mediaPlayer->setPosition( pos );
}
......@@ -57,6 +57,11 @@ class ClipWorkflow : public QObject
\return A pointer to a constant clip instance.
*/
const Clip* getClip() const;
/**
\brief Stop this workflow.
*/
void stop();
void setPosition( float pos );
private:
static void lock( ClipWorkflow* clipWorkflow, void** pp_ret );
......@@ -80,7 +85,7 @@ class ClipWorkflow : public QObject
public slots:
void pauseAfterPlaybackStarted();
void pausedMediaPlayer();
void setPosition();
void setPositionAfterPlayback();
void endReached();
};
......
......@@ -45,6 +45,7 @@ void MainWorkflow::startRender()
{
m_currentFrame = 0;
emit frameChanged( 0 );
m_length = m_tracks[0]->getLength();
m_tracks[0]->startRender();
}
......@@ -55,3 +56,17 @@ unsigned char* MainWorkflow::getOutput()
emit frameChanged( m_currentFrame );
return ret;
}
void MainWorkflow::setPosition( float pos )
{
qint64 frame = (float)m_length * pos;
qDebug() << "Setting current frame to " << frame << '(' << m_length << '*' << pos << ')';
m_tracks[0]->setPosition( pos );
m_currentFrame = frame;
emit frameChanged( frame );
}
qint64 MainWorkflow::getLength() const
{
return m_length;
}
......@@ -42,9 +42,23 @@ class MainWorkflow : public QObject
void startRender();
unsigned char* getOutput();
/**
\brief Set the workflow position
\param pos: The position in vlc position
*/
void setPosition( float pos );
/**
\return Returns the global length of the workflow
in frames.
*/
qint64 getLength() const;
private:
TrackWorkflow** m_tracks;
qint64 m_currentFrame;
qint64 m_length;
signals:
void frameChanged( qint64 currentFrame );
......
......@@ -26,11 +26,12 @@
unsigned char* TrackWorkflow::blackOutput = NULL;
TrackWorkflow::TrackWorkflow() : m_isRendering( false )
TrackWorkflow::TrackWorkflow()
{
m_condMutex = new QMutex;
m_waitCondition = new QWaitCondition;
m_mediaPlayer = new LibVLCpp::MediaPlayer();
m_currentLock = new QReadWriteLock();
if ( TrackWorkflow::blackOutput == NULL )
{
TrackWorkflow::blackOutput = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 3];
......@@ -43,6 +44,7 @@ void TrackWorkflow::addClip( Clip* clip, qint64 start )
qDebug() << "Inserting clip at frame nb" << start;
ClipWorkflow* cw = new ClipWorkflow( clip, m_condMutex, m_waitCondition );
m_clips.insert( start, cw );
computeLength();
}
void TrackWorkflow::startRender()
......@@ -54,6 +56,7 @@ void TrackWorkflow::startRender()
// qDebug() << "Next clip is less than" << nbFrameBeforePreload<< "frame ahead";
m_clips.begin().value()->initialize( m_mediaPlayer );
// qDebug() << "Waiting for the first clip to be ready";
//We wait to be sure the ClipWorkflow will be ready when we really start to render.
while ( m_clips.begin().value()->isReady() == false )
usleep( 150 );
if ( m_current.key() == 0 )
......@@ -61,7 +64,6 @@ void TrackWorkflow::startRender()
m_current = m_clips.begin();
// qDebug() << "Clip workflow is at first frame";
m_current.value()->startRender();
m_isRendering = true;
}
}
}
......@@ -100,13 +102,18 @@ bool TrackWorkflow::checkNextClip( qint64 currentFrame )
return true;
}
qint64 TrackWorkflow::getLength() const
void TrackWorkflow::computeLength()
{
if ( m_clips.count() == 0 )
return 0;
m_length = 0;
QMap<qint64, ClipWorkflow*>::const_iterator it = m_clips.end() - 1;
qDebug() << "Last clip Uuid : " << it.value()->getClip()->getUuid();
return ( it.key() + it.value()->getClip()->getLength() );
m_length = (it.key() + it.value()->getClip()->getLength() );
}
qint64 TrackWorkflow::getLength() const
{
return m_length;
}
unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
......@@ -114,6 +121,8 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
unsigned char* ret = TrackWorkflow::blackOutput;
bool clipsRemaining;
QReadLocker lock( m_currentLock );
// qDebug() << "Frame nb" << m_currentFrame;
clipsRemaining = checkNextClip( currentFrame );
if ( m_current == m_clips.end() )
......@@ -137,3 +146,93 @@ unsigned char* TrackWorkflow::getOutput( qint64 currentFrame )
}
return ret;
}
void TrackWorkflow::setPosition( float pos )
{
qint64 frame = (float)m_length * pos;
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
const QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
QMap<qint64, ClipWorkflow*>::iterator next = m_clips.end();
QWriteLocker lock( m_currentLock );
qDebug() << m_length;
if ( frame > m_length )
{
qDebug() << "setting position after the end of this track";
if ( m_current != end )
{
m_current.value()->stop();
m_current = end;
return ;
}
}
//Locate the new clip workflow
while ( it != end )
{
if ( it.key() <= frame &&
( it.key() + it.value()->getClip()->getLength() ) > frame )
{
qDebug() << "Found new current clip workflow";
break;
}
else if ( next == m_clips.end() && it.key() > frame )
{
// If this clip doesn't match, but starts AFTER the frame we aim,
// we can assume that it's the next clip.
// We can break, and put it to end() in order to simulate the
// normal end of the loop.
next = it;
if ( next != m_clips.begin() )
{
qDebug() << "Next clip isn't the first one";
next = next - 1; //Since the iterator must point to the previous video
}
else
{
next = end;
qDebug() << "Next clip is the first of the track";
}
// in order to checkNextClip() to work.
it = end;
break ;
}
++it;
}
if ( it == m_clips.end() )
{
qDebug() << "No clip matched. Utilisation du Clip precedent le clip suivant la frame selectionnee";
if ( m_current != end )
m_current.value()->stop();
m_current = next;
}
else if ( it == m_current )
{
qDebug() << "Changing the position of the current clip";
//We're changing the position of the current clip
// qDebug() << "frame =" << frame << " key = "<< it.key() <<
it.value()->setPosition( (float)( frame - it.key() ) / (float)(it.value()->getClip()->getLength()) );
//Awaking renderers to avoid them to be stuck inside of the lock...
qDebug() << "Waking all renderer threads";
m_waitCondition->wakeAll();
}
else
{
qDebug() << "Switching to other Clip";
if ( m_current != end )
{
m_current.value()->stop();
// m_waitCondition->wakeAll();
}
it.value()->initialize( m_mediaPlayer );
while ( it.value()->isReady() == false )
usleep( 150 );
it.value()->startRender();
m_current = it;
qDebug() << "Switched current clip workflow";
}
//Don't forget to wake the renderer so they can process the events
}
......@@ -27,6 +27,7 @@
#include <QMutex>
#include <QWaitCondition>
#include <QMap>
#include <QReadWriteLock>
#include "ClipWorkflow.h"
#include "VLCMediaPlayer.h"
......@@ -47,23 +48,46 @@ class TrackWorkflow : public QObject
unsigned char* getOutput( qint64 currentFrame );
qint64 getLength() const;
/**
\brief Set the track workflow position
\param pos: The new pos in VLC position
*/
void setPosition( float pos );
//FIXME: this won't be reliable as soon as we change the fps from the configuration
static const unsigned int nbFrameBeforePreload = 60;
static unsigned char* blackOutput;
private:
/**
* \return true if at least one video remains, false otherwise (IE end of this track)
* \brief Check if there's a ClipWorkflow that's comming soon. If so, it preload it to avoid
freeze when switching video.
This does NOT search for the next current clip !
* \return true if at least one video remains, false otherwise (IE end of this track)
*/
bool checkNextClip( qint64 currentFrame );
void computeLength();
private:
QMap<qint64, ClipWorkflow*> m_clips;
/**
* \brief An iterator that "point" the current ClipWorkflow used.
*
* This holds the current ClipWorkflow, and the current starting frame
* of this ClipWorkflow.
* If the track is empty at a T time, this iterator still points to the last
* ClipWorkflow used. However, if the next video occurs to be the first one
* in the Track, this iterators is equal to m_clips.end();
*/
QMap<qint64, ClipWorkflow*>::iterator m_current;
QMutex* m_condMutex;
QReadWriteLock* m_currentLock;
QWaitCondition* m_waitCondition;
LibVLCpp::MediaPlayer* m_mediaPlayer;
bool m_isRendering;
/**
\brief The track length in frames.
*/
qint64 m_length;
public:
void addClip( Clip*, qint64 start );
......
......@@ -54,7 +54,7 @@ void ClipPreviewWidget::setPosition( float newPos )
{
if ( m_clipLoaded == false || m_videoStopped == true )
return ;
m_mediaPlayer->setPosition( newPos / 1000.0 );
m_mediaPlayer->setPosition( newPos );
}
void ClipPreviewWidget::togglePlayPause( bool forcePause )
......
......@@ -154,7 +154,8 @@ void PreviewWidget::seekSliderMoved( int )
return;
}
m_endReached = false;
m_currentPreviewRenderer->setPosition( (float)m_ui->seekSlider->value() );
//Putting back the slider value into vlc position
m_currentPreviewRenderer->setPosition( (float)m_ui->seekSlider->value() / 1000.0f );
}
void PreviewWidget::seekSliderReleased()
......
......@@ -84,8 +84,9 @@ void RenderPreviewWidget::startPreview( Media* )
m_isRendering = true;
}
void RenderPreviewWidget::setPosition( float /*newPos*/ )
void RenderPreviewWidget::setPosition( float newPos )
{
m_mainWorkflow->setPosition( newPos );
}
void RenderPreviewWidget::togglePlayPause( bool /*forcePause*/ )
......
......@@ -30,7 +30,6 @@
#include "Workflow/MainWorkflow.h"
#include "GenericPreviewWidget.h"
//TODO: This should really share a common interface with ClipPreviewWorkflow
class RenderPreviewWidget : public GenericPreviewWidget
{
Q_OBJECT
......@@ -41,6 +40,13 @@ class RenderPreviewWidget : public GenericPreviewWidget
~RenderPreviewWidget();
virtual void startPreview( Media* );
/**
\brief Set the preview position
\param newPos : The new position in vlc position (between
0 and 1)
*/
virtual void setPosition( float newPos );
virtual void togglePlayPause( bool forcePause );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment