ClipWorkflow.cpp 8.08 KB
Newer Older
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*****************************************************************************
 * ClipWorkflow.cpp : Clip workflow. Will extract a single frame from a VLCMedia
 *****************************************************************************
 * Copyright (C) 2008-2009 the VLMC team
 *
 * Authors: Hugo Beauzee-Luyssen <hugo@vlmc.org>
 *
 * 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.
 *****************************************************************************/

23
#include <QtDebug>
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
24

25
#include "vlmc.h"
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
26
#include "ClipWorkflow.h"
27
#include "Pool.hpp"
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
28

29
30
31
int     g_debugId = 0;

ClipWorkflow::ClipWorkflow( Clip::Clip* clip ) :
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
32
33
                m_clip( clip ),
                m_buffer( NULL ),
34
                //m_usingBackBuffer( false ),
35
                m_mediaPlayer(NULL),
36
37
                m_state( ClipWorkflow::Stopped ),
                m_requiredState( ClipWorkflow::None )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
38
{
39
    m_buffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
40
//    m_backBuffer = new unsigned char[VIDEOHEIGHT * VIDEOWIDTH * 4];
41
42
    m_stateLock = new QReadWriteLock;
    m_requiredStateLock = new QMutex;
43
44
    m_condMutex = new QMutex;
    m_waitCond = new QWaitCondition;
45
//    m_backBufferLock = new QReadWriteLock;
46
47

    this->debugId = g_debugId++;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
48
49
50
51
}

ClipWorkflow::~ClipWorkflow()
{
52
    delete[] m_buffer;
53
//    delete[] m_backBuffer;
54
    delete m_stateLock;
55
    delete m_requiredStateLock;
56
//    delete m_backBufferLock;
57
}
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
58

59
unsigned char*    ClipWorkflow::getOutput()
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
60
{
61
62
//    QReadLocker     lock( m_backBufferLock );
//    if ( m_usingBackBuffer == true )
63
        return m_buffer;
64
//    return m_backBuffer;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
65
66
}

67
68
69
void    ClipWorkflow::checkStateChange()
{
    QMutexLocker    lock( m_requiredStateLock );
70
    QWriteLocker    lock2( m_stateLock );
71
72
    if ( m_requiredState != ClipWorkflow::None )
    {
73
//        qDebug() << "Changed state from" << m_state << "to state" << m_requiredState;
74
75
76
77
78
        m_state = m_requiredState;
        m_requiredState = ClipWorkflow::None;
    }
}

79
void    ClipWorkflow::lock( ClipWorkflow* cw, void** pp_ret )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
80
{
81
//    QReadLocker lock( cw->m_backBufferLock );
82

83
84
85
86
87
88
//    if ( cw->m_usingBackBuffer )
//    {
//        *pp_ret = cw->m_backBuffer;
//    }
//    else
//    {
89
        *pp_ret = cw->m_buffer;
90
//        qDebug() << "Clip workflow locking";
91
//    }
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
92
93
}

94
void    ClipWorkflow::unlock( ClipWorkflow* cw )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
95
{
96
    cw->m_stateLock->lockForWrite();
97

98
    if ( cw->m_state == Rendering )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
99
    {
100
101
102
103
        cw->m_state = Sleeping;
        cw->m_stateLock->unlock();

        QMutexLocker    lock( cw->m_condMutex );
104
//            qDebug() << "Entering condwait";
105

106
        cw->m_waitCond->wait( cw->m_condMutex );
107
//            qDebug() << "Leaved condwait";
108
109
        cw->m_stateLock->lockForWrite();
        cw->m_state = Rendering;
110
111
112
113
//        {
//            QWriteLocker    lock2( cw->m_backBufferLock );
//            cw->m_usingBackBuffer = !cw->m_usingBackBuffer;
//        }
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
114
    }
115
116
    cw->m_stateLock->unlock();
    cw->checkStateChange();
117
118
}

119
void    ClipWorkflow::setVmem()
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
120
121
122
{
    char        buffer[32];

123
124
125
126
127
128
    m_vlcMedia->addOption( ":no-audio" );
    m_vlcMedia->addOption( ":vout=vmem" );
    m_vlcMedia->setDataCtx( this );
    m_vlcMedia->setLockCallback( reinterpret_cast<LibVLCpp::Media::lockCallback>( &ClipWorkflow::lock ) );
    m_vlcMedia->setUnlockCallback( reinterpret_cast<LibVLCpp::Media::unlockCallback>( &ClipWorkflow::unlock ) );
    m_vlcMedia->addOption( ":vmem-chroma=RV24" );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
129

130
    sprintf( buffer, ":vmem-width=%i", VIDEOWIDTH );
131
    m_vlcMedia->addOption( buffer );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
132

133
    sprintf( buffer, ":vmem-height=%i", VIDEOHEIGHT );
134
    m_vlcMedia->addOption( buffer );
135
136

    sprintf( buffer, "vmem-pitch=%i", VIDEOWIDTH * 3 );
137
    m_vlcMedia->addOption( buffer );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
138
139
}

140
void    ClipWorkflow::initialize()
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
141
{
142
    setState( Initializing );
143
    m_vlcMedia = new LibVLCpp::Media( m_clip->getParent()->getFileInfo()->absoluteFilePath() );
144
    setVmem();
145
146
    m_mediaPlayer = Pool<LibVLCpp::MediaPlayer>::getInstance()->get();
    m_mediaPlayer->setMedia( m_vlcMedia );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
147

148
    connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ), Qt::DirectConnection );
149
    connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ), Qt::DirectConnection );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
150
151
152
    m_mediaPlayer->play();
}

153
void    ClipWorkflow::setPositionAfterPlayback()
154
{
155
    disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ) );
156
    connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( pauseAfterPlaybackStarted() ), Qt::DirectConnection );
157
158
159
    m_mediaPlayer->setPosition( m_clip->getBegin() );
}

160
void    ClipWorkflow::pauseAfterPlaybackStarted()
161
{
162
163
    disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( pauseAfterPlaybackStarted() ) );
    disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( pauseAfterPlaybackStarted() ) );
164

165
166
167
168
169
170
171
172
    connect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( pausedMediaPlayer() ), Qt::DirectConnection );
    m_mediaPlayer->pause();

}

void    ClipWorkflow::pausedMediaPlayer()
{
    disconnect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( pausedMediaPlayer() ) );
173
    setState( Ready );
174
175
}

176
bool    ClipWorkflow::isReady() const
177
{
178
179
    QReadLocker lock( m_stateLock );
    return m_state == ClipWorkflow::Ready;
180
}
181
182
183

bool    ClipWorkflow::isEndReached() const
{
184
185
186
187
188
189
190
191
192
193
194
195
196
    QReadLocker lock( m_stateLock );
    return m_state == ClipWorkflow::EndReached;
}

bool    ClipWorkflow::isStopped() const
{
    QReadLocker lock( m_stateLock );
    return m_state == ClipWorkflow::Stopped;
}

ClipWorkflow::State     ClipWorkflow::getState() const
{
    return m_state;
197
}
198
199
200

void    ClipWorkflow::startRender()
{
201
    while ( isReady() == false )
202
        SleepMS( 1 );
203
    m_mediaPlayer->play();
204
    setState( Rendering );
205
}
206

207
void    ClipWorkflow::clipEndReached()
208
{
209
    setState( EndReached );
210
}
211

212
Clip*     ClipWorkflow::getClip()
213
214
215
{
    return m_clip;
}
216
217
218

void            ClipWorkflow::stop()
{
219
220
221
222
223
224
225
226
    if ( m_mediaPlayer )
    {
        m_mediaPlayer->stop();
        disconnect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ) );
        m_mediaPlayer = NULL;
        setState( Stopped );
        QMutexLocker    lock( m_requiredStateLock );
        m_requiredState = ClipWorkflow::None;
227
        delete m_vlcMedia;
228
229
230
    }
    else
        qDebug() << "ClipWorkflow has already been stopped";
231
232
233
234
235
236
}

void            ClipWorkflow::setPosition( float pos )
{
    m_mediaPlayer->setPosition( pos );
}
237

238
bool            ClipWorkflow::isRendering() const
239
{
240
241
    QReadLocker lock( m_stateLock );
    return m_state == ClipWorkflow::Rendering;
242
}
243

244
void            ClipWorkflow::setState( State state )
245
{
246
247
    QWriteLocker    lock( m_stateLock );
    m_state = state;
248
}
249
250
251
252
253
254

void            ClipWorkflow::queryStateChange( State newState )
{
    QMutexLocker    lock( m_requiredStateLock );
    m_requiredState = newState;
}
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

void            ClipWorkflow::wake()
{
    m_waitCond->wakeAll();
}

QReadWriteLock* ClipWorkflow::getStateLock()
{
    return m_stateLock;
}

void            ClipWorkflow::reinitialize()
{
    QWriteLocker    lock( m_stateLock );
    m_state = Stopped;
    queryStateChange( None );
}
272
273
274
275
276

void            ClipWorkflow::pause()
{
    m_mediaPlayer->pause();
    setState( Paused );
277
278
    QMutexLocker    lock( m_requiredStateLock );
    m_requiredState = ClipWorkflow::None;
279
280
281
282
283
284
285
}

void            ClipWorkflow::unpause()
{
    //Since VLC will detect that the media player is paused and unpause it, we can do this safely
    m_mediaPlayer->pause();
    setState( ClipWorkflow::Rendering );
286
287
    QMutexLocker    lock( m_requiredStateLock );
    m_requiredState = ClipWorkflow::None;
288
}