ClipRenderer.cpp 7 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 <QtGlobal>
25
#include <QtCore/qmath.h>
26

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

38 39 40
ClipRenderer::ClipRenderer() :
    GenericRenderer(),
    m_clipLoaded( false ),
41
    m_selectedClip( NULL ),
42 43
    m_begin( 0 ),
    m_end( -1 ),
44
    m_mediaChanged( false )
geoff's avatar
geoff committed
45 46 47
{
}

48
ClipRenderer::~ClipRenderer()
geoff's avatar
geoff committed
49
{
50
    stop();
geoff's avatar
geoff committed
51
}
52

53
void
54
ClipRenderer::setClip( Clip* clip )
55
{
56 57 58 59
    // 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 ) )
    {
60
        clipUnloaded( m_selectedClip->uuid() );
61
    }
62
    if ( clip == NULL )
63
    {
64
        m_selectedClip = NULL;
65
        m_clipLoaded = false;
66 67
        return ;
    }
68
    m_selectedClip = clip;
69 70 71 72 73 74 75 76
    if ( clip->length() == 0 )
        return ;
    updateInfos( clip );
}

void
ClipRenderer::updateInfos( Clip* clip )
{
77 78
    m_begin = clip->begin();
    m_end = clip->end();
79 80 81 82
    if ( m_isRendering == true )
        m_mediaChanged = true;
    else
        m_clipLoaded = false;
83 84
}

85 86
void
ClipRenderer::startPreview()
87
{
88
    if ( m_selectedClip == NULL || m_selectedClip->length() == 0 )
89
        return ;
90
    updateInfos( m_selectedClip );
91

92 93 94
    delete m_sourceRenderer;
    m_sourceRenderer = m_selectedClip->getMedia()->source()->createRenderer( m_eventWatcher );
    m_sourceRenderer->setOutputWidget( (void *) static_cast< RenderWidget* >( m_renderWidget )->id() );
95

96 97 98 99 100
    connect( m_eventWatcher, SIGNAL( stopped() ), this, SLOT( __videoStopped() ) );
    connect( m_eventWatcher, SIGNAL( paused() ),  this, SIGNAL( paused() ) );
    connect( m_eventWatcher, SIGNAL( playing() ), this, SIGNAL( playing() ) );
    connect( m_eventWatcher, SIGNAL( volumeChanged() ), this, SIGNAL( volumeChanged() ) );
    connect( m_eventWatcher, SIGNAL( timeChanged( qint64 ) ), this, SLOT( __timeChanged( qint64 ) ) );
101

102
    m_sourceRenderer->start();
103
    m_sourceRenderer->setPosition( (float)m_begin / (float)m_selectedClip->getMedia()->source()->nbFrames() );
104
    m_clipLoaded = true;
105
    m_isRendering = true;
106
    m_paused = false;
107
    m_mediaChanged = false;
108 109
}

110 111
void
ClipRenderer::stop()
112
{
113
    if ( m_clipLoaded == true && m_isRendering == true )
114
    {
115
        m_isRendering = false;
116
        m_sourceRenderer->stop();
117
        m_paused = false;
118 119
        if ( m_mediaChanged == true )
            m_clipLoaded = false;
120 121 122
    }
}

123 124
void
ClipRenderer::togglePlayPause( bool forcePause )
125
{
126
    if ( m_clipLoaded == false )
127
    {
128
        emit frameChanged( 0, Vlmc::Renderer );
129
        startPreview();
130 131
        return ;
    }
132
    if ( m_paused == false && m_isRendering == true )
133
    {
134
        m_sourceRenderer->playPause();
135 136
        m_paused = true;
    }
137
    else if ( forcePause == false )
138
    {
139
        if ( m_isRendering == false )
140
        {
141 142
            m_sourceRenderer->playPause();
            m_sourceRenderer->setPosition( m_begin / ( m_end - m_begin ) );
143
            m_isRendering = true;
144 145
        }
        else
146
            m_sourceRenderer->playPause();
147 148
        m_paused = false;
    }
149
}
150

151 152 153
int
ClipRenderer::getVolume() const
{
154
    return m_sourceRenderer->volume();
155 156
}

157
void ClipRenderer::setVolume( int volume )
158 159
{
    //Returns 0 if the volume was set, -1 if it was out of range
160
    return m_sourceRenderer->setVolume( volume );
161 162
}

163 164
void
ClipRenderer::nextFrame()
165
{
166
    if ( m_isRendering == true )
167
    {
168
        m_sourceRenderer->nextFrame();
169 170 171
    }
}

172 173
void
ClipRenderer::previousFrame()
174
{
175
    if ( m_isRendering == true )
176
    {
177 178
        if ( m_paused == false )
            togglePlayPause( true );
179
        /* FIXME: Implement a better way to render previous frame */
180
        qint64   interval =  static_cast<qint64>( qCeil(1000.0f * 2.0f / m_selectedClip->getMedia()->source()->fps() ) );
181 182
        m_sourceRenderer->setTime( m_sourceRenderer->time() - interval );
        m_sourceRenderer->nextFrame();
183 184 185
    }
}

186
qint64
187
ClipRenderer::length() const
188 189 190 191
{
    return m_end - m_begin;
}

192 193
qint64
ClipRenderer::getLengthMs() const
194
{
195
    if ( m_selectedClip )
196
        return ( qRound64( (qreal)( m_end - m_begin ) / m_selectedClip->getMedia()->source()->fps() * 1000.0 ) );
197 198 199
    return 0;
}

200
void
201
ClipRenderer::clipUnloaded( const QUuid& uuid )
202
{
203
    if ( m_selectedClip != NULL && m_selectedClip->uuid() == uuid )
204
    {
205
        stop();
206
        m_clipLoaded = false;
207
        m_selectedClip = NULL;
208 209 210 211 212
        m_isRendering = false;
        m_paused = false;
    }
}

213 214
qint64
ClipRenderer::getCurrentFrame() const
215
{
216
    if ( m_clipLoaded == false || m_isRendering == false || m_selectedClip == NULL )
217
        return 0;
218
    return qRound64( (qreal)m_sourceRenderer->time() / 1000 *
219
                     (qreal)m_selectedClip->getMedia()->source()->fps() );
220 221
}

222 223
float
ClipRenderer::getFps() const
224
{
225
    if ( m_selectedClip != NULL )
226
        return m_selectedClip->getMedia()->source()->fps();
227 228 229
    return 0.0f;
}

230 231
Clip*
ClipRenderer::getClip()
232
{
233
    return m_selectedClip;
234 235
}

236 237
void
ClipRenderer::previewWidgetCursorChanged( qint64 newFrame )
238 239 240
{
    if ( m_isRendering == true )
    {
241
        newFrame += m_begin;
242
        qint64 nbSeconds = qRound64( (qreal)newFrame / m_selectedClip->getMedia()->source()->fps() );
243
        m_sourceRenderer->setTime( nbSeconds * 1000 );
244 245 246
    }
}

247 248 249 250
/////////////////////////////////////////////////////////////////////
/////SLOTS :
/////////////////////////////////////////////////////////////////////

251 252
void
ClipRenderer::__videoStopped()
253
{
254 255 256
    m_isRendering = false;
    if ( m_mediaChanged == true )
        m_clipLoaded = false;
257
    emit frameChanged( 0, Vlmc::Renderer );
258 259
}

260 261
void
ClipRenderer::__timeChanged( qint64 time )
262
{
263
    float fps = m_selectedClip->getMedia()->source()->fps();
264
    qint64 f = qRound64( (qreal)time / 1000.0 * fps );
265 266 267
    if ( f >= m_end )
        return ;
    f = f - m_begin;
268
    emit frameChanged( f, Vlmc::Renderer );
269 270
}