ClipRenderer.cpp 7.32 KB
Newer Older
Christophe Courtaut's avatar
Christophe Courtaut committed
1
/*****************************************************************************
2
 * ClipRenderer.cpp: Render from a Clip (mainly for previewing purpose)
Christophe Courtaut's avatar
Christophe Courtaut committed
3
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
4
 * Copyright (C) 2008-2010 VideoLAN
Christophe Courtaut's avatar
Christophe Courtaut committed
5
 *
6
 * Authors: Geoffroy Lacarrière <geoffroylaca@gmail.com>
7
 *          Hugo Beauzée-Luyssen <hugo@beauzee.fr>
Christophe Courtaut's avatar
Christophe Courtaut committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

24
#include <QtDebug>
25
#include <QtGlobal>
26
#include <QtCore/qmath.h>
27

28
#include "Clip.h"
29
#include "ClipRenderer.h"
30
#include "Library.h"
31
#include "Media.h"
32
#include "MainWorkflow.h"
33
#include "VLCMediaPlayer.h"
34
#include "VLCMedia.h"
geoff's avatar
geoff committed
35

36 37 38
ClipRenderer::ClipRenderer() :
    GenericRenderer(),
    m_clipLoaded( false ),
39
    m_vlcMedia( NULL ),
40
    m_selectedClip( NULL ),
41 42
    m_begin( 0 ),
    m_end( -1 ),
43
    m_mediaChanged( false )
geoff's avatar
geoff committed
44
{
45
    connect( m_mediaPlayer,     SIGNAL( stopped() ),            this,   SLOT( __videoStopped() ) );
46 47
    connect( m_mediaPlayer,     SIGNAL( paused() ),             this,   SIGNAL( paused() ) );
    connect( m_mediaPlayer,     SIGNAL( playing() ),            this,   SIGNAL( playing() ) );
48
    connect( m_mediaPlayer,     SIGNAL( volumeChanged() ),      this,   SIGNAL( volumeChanged() ) );
49
    connect( m_mediaPlayer,     SIGNAL( timeChanged( qint64 ) ),this,   SLOT( __timeChanged( qint64 ) ) );
50
    connect( m_mediaPlayer,     SIGNAL( endReached() ),         this,   SLOT( __endReached() ) );
geoff's avatar
geoff committed
51 52
}

53
ClipRenderer::~ClipRenderer()
geoff's avatar
geoff committed
54
{
55 56
    if ( m_vlcMedia )
        delete m_vlcMedia;
57
    stop();
geoff's avatar
geoff committed
58
}
59

60
void
61
ClipRenderer::setClip( Clip* clip )
62
{
63 64 65 66
    // if the clip is different (or NULL) we have to stop playback.
    if ( m_selectedClip != NULL &&
         ( ( clip != NULL && clip->uuid() != m_selectedClip->uuid() ) || clip == NULL ) )
    {
67
        clipUnloaded( m_selectedClip->uuid() );
68
    }
69
    if ( clip == NULL )
70
    {
71
        m_selectedClip = NULL;
72
        m_clipLoaded = false;
73 74
        return ;
    }
75
    m_selectedClip = clip;
76 77 78 79 80 81 82 83
    if ( clip->length() == 0 )
        return ;
    updateInfos( clip );
}

void
ClipRenderer::updateInfos( Clip* clip )
{
84 85
    m_begin = clip->begin();
    m_end = clip->end();
86 87 88 89
    if ( m_isRendering == true )
        m_mediaChanged = true;
    else
        m_clipLoaded = false;
90 91
}

92 93
void
ClipRenderer::startPreview()
94
{
95
    if ( m_selectedClip == NULL || m_selectedClip->length() == 0 )
96
        return ;
97
    updateInfos( m_selectedClip );
98

99
    //If an old media is found, we delete it, and disconnect
100 101
    if ( m_vlcMedia != NULL )
        delete m_vlcMedia;
102
    m_vlcMedia = new LibVLCpp::Media( m_selectedClip->getMedia()->mrl() );
103

104
    m_mediaPlayer->setKeyInput( false );
105
    m_mediaPlayer->setMedia( m_vlcMedia );
106

107
    m_mediaPlayer->play();
108
    m_mediaPlayer->setPosition( (double)m_begin / (double)m_selectedClip->getMedia()->nbFrames() );
109
    m_clipLoaded = true;
110
    m_isRendering = true;
111
    m_paused = false;
112
    m_mediaChanged = false;
113 114
}

115 116
void
ClipRenderer::stop()
117
{
118
    if ( m_clipLoaded == true && m_isRendering == true )
119
    {
120
        m_isRendering = false;
121
        m_mediaPlayer->stop();
122
        m_paused = false;
123 124
        if ( m_mediaChanged == true )
            m_clipLoaded = false;
125 126 127
    }
}

128 129
void
ClipRenderer::togglePlayPause( bool forcePause )
130
{
131
    if ( m_clipLoaded == false )
132
    {
133
        emit frameChanged( 0, Vlmc::Renderer );
134
        startPreview();
135 136
        return ;
    }
137
    if ( m_paused == false && m_isRendering == true )
138
    {
139
        m_mediaPlayer->pause();
140 141
        m_paused = true;
    }
142
    else if ( forcePause == false )
143
    {
144
        if ( m_isRendering == false )
145 146
        {
            m_mediaPlayer->play();
147
            m_mediaPlayer->setPosition( m_begin / ( m_end - m_begin ) );
148
            m_isRendering = true;
149 150 151
        }
        else
            m_mediaPlayer->play();
152 153
        m_paused = false;
    }
154
}
155

156 157 158 159 160 161 162 163 164 165 166 167 168
int
ClipRenderer::getVolume() const
{
    return m_mediaPlayer->getVolume();
}

int
ClipRenderer::setVolume( int volume )
{
    //Returns 0 if the volume was set, -1 if it was out of range
    return m_mediaPlayer->setVolume( volume );
}

169 170
void
ClipRenderer::nextFrame()
171
{
172
    if ( m_isRendering == true )
173
    {
174
        m_mediaPlayer->nextFrame();
175 176 177
    }
}

178 179
void
ClipRenderer::previousFrame()
180
{
181
    if ( m_isRendering == true )
182
    {
183 184
        if ( m_paused == false )
            togglePlayPause( true );
185 186
        /* FIXME: Implement a better way to render previous frame */
        qint64   interval =  static_cast<qint64>( qCeil(1000.0f * 2.0f / m_mediaPlayer->getFps()) );
187
        m_mediaPlayer->setTime( m_mediaPlayer->getTime() - interval );
188
        m_mediaPlayer->nextFrame();
189 190 191
    }
}

192
qint64
193
ClipRenderer::length() const
194 195 196 197
{
    return m_end - m_begin;
}

198 199
qint64
ClipRenderer::getLengthMs() const
200
{
201 202
    if ( m_selectedClip )
        return ( qRound64( (qreal)( m_end - m_begin ) / m_selectedClip->getMedia()->fps() * 1000.0 ) );
203 204 205
    return 0;
}

206
void
207
ClipRenderer::clipUnloaded( const QUuid& uuid )
208
{
209
    if ( m_selectedClip != NULL && m_selectedClip->uuid() == uuid )
210 211 212
    {
        m_mediaPlayer->stop();
        m_clipLoaded = false;
213
        m_selectedClip = NULL;
214 215 216 217 218
        m_isRendering = false;
        m_paused = false;
    }
}

219 220
qint64
ClipRenderer::getCurrentFrame() const
221
{
222
    if ( m_clipLoaded == false || m_isRendering == false || m_selectedClip == NULL )
223
        return 0;
224
    return qRound64( (qreal)m_mediaPlayer->getTime() / 1000 *
225
                     (qreal)m_selectedClip->getMedia()->fps() );
226 227
}

228 229
float
ClipRenderer::getFps() const
230
{
231 232
    if ( m_selectedClip != NULL )
        return m_selectedClip->getMedia()->fps();
233 234 235
    return 0.0f;
}

236 237
Clip*
ClipRenderer::getClip()
238
{
239
    return m_selectedClip;
240 241
}

242 243
void
ClipRenderer::previewWidgetCursorChanged( qint64 newFrame )
244 245 246
{
    if ( m_isRendering == true )
    {
247
        newFrame += m_begin;
248
        qint64 nbSeconds = qRound64( (qreal)newFrame / m_selectedClip->getMedia()->fps() );
249
        m_mediaPlayer->setTime( nbSeconds * 1000 );
250 251 252
    }
}

253 254 255 256
/////////////////////////////////////////////////////////////////////
/////SLOTS :
/////////////////////////////////////////////////////////////////////

257 258
void
ClipRenderer::__videoStopped()
259
{
260
    emit frameChanged( 0, Vlmc::Renderer );
261 262 263
    emit stopped();
}

264 265
void
ClipRenderer::__timeChanged( qint64 time )
266
{
267 268
    float   fps = (qreal)m_mediaPlayer->getFps();
    if ( fps < 0.1f )
269
        fps = m_selectedClip->getMedia()->fps();
270
    qint64 f = qRound64( (qreal)time / 1000.0 * fps );
271 272 273 274 275 276
    if ( f >= m_end )
    {
        __endReached();
        return ;
    }
    f = f - m_begin;
277
    emit frameChanged( f, Vlmc::Renderer );
278 279
}

280 281
void
ClipRenderer::__endReached()
282 283
{
    m_mediaPlayer->stop();
284
    m_isRendering = false;
285 286
    if ( m_mediaChanged == true )
        m_clipLoaded = false;
287
    emit endReached();
288
}