WorkflowRenderer.h 12.7 KB
Newer Older
1
/*****************************************************************************
2
 * WorkflowRenderer.h: Render the main workflow
3
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
4
 * Copyright (C) 2008-2010 VideoLAN
5
 *
6
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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 24
#ifndef WORKFLOWRENDERER_H
#define WORKFLOWRENDERER_H
25

26
#include "GenericRenderer.h"
27
#include "ISourceRenderer.h"
28
#include "MainWorkflow.h"
29

30 31
#include <QObject>

32 33 34 35 36 37
namespace Backend
{
    class IBackend;
    class IMemorySource;
}

38 39 40 41 42 43
class   Clip;

class   QWidget;
class   QWaitCondition;
class   QMutex;

44
class   WorkflowRenderer : public GenericRenderer
45 46
{
    Q_OBJECT
47
    Q_DISABLE_COPY( WorkflowRenderer )
48 49

    public:
50 51 52 53
        /**
         *  \brief  This struct will be the type of the callback parameter
         *          in the lock / unlock callbacks
         */
54 55
        struct  EsHandler
        {
56
            WorkflowRenderer*   self; ///< The 'this' pointer will be passed in this field
57
            //Fixme: this should go away I guess...
58
            double              fps; ///< The fps to use for this rendering session.
59
        };
60

61
        WorkflowRenderer( Backend::IBackend *backend );
62
        ~WorkflowRenderer();
63

64 65 66 67 68
        /**
         *  \brief      Initialize the renderer.
         *
         *  This will set the imem string, instantiate EsHandlers, connect signals.
         */
69
        void                initializeRenderer();
70 71 72 73 74 75 76 77 78 79 80
        /**
         *  \brief          Play or pause the media.
         *
         *  When this method is called :
         *      - if the render has not started and forcePause is false, the render is started
         *      - if the render has not started and forcePause is true, nothing happens.
         *      - if the render has started and is not paused, the render will pause
         *      - if the render has started, and is paused, the render will unpause if
         *          forcePause is false.
         *  \param  forcePause  Will force the pause if true.
         *  \sa     stop()
81 82
         *  \warning    Do NOT call this method from a constructor as it calls some
         *              virtual methods.
83
         */
84
        virtual void        togglePlayPause( bool forcePause );
85
        /**
86 87 88 89
         *  \brief Stop the mainworkflow, but not the renderer.
         *
         *  In order to provide premanent feedback (ie stay in paused mode when not
         *  playing, we have to never stop the renderer.
90
         *  \sa togglePlayPause( bool );
91
         *  \sa killRenderer();
92
         */
93
        virtual void        stop();
94 95 96 97 98 99 100

        /**
         *  \brief  Set the output volume.
         *  \param  volume the volume (int)
         *  \return 0 if the volume was set, -1 if it was out of range
         *  \sa     getVolume()
         */
101
        virtual void        setVolume( int volume );
102 103 104 105 106 107 108 109

        /**
         *  \brief   Return the volume
         *  \return  The Return the volume the audio level (int)
         *  \sa     setVolume( int )
         */
        virtual int         getVolume() const;

110 111 112 113
        /**
         *  \brief Render the next frame
         *  \sa     previousFrame()
         */
114
        virtual void        nextFrame();
115 116 117 118
        /**
         *  \brief  Render the previous frame
         *  \sa     nextFrame();
         */
119
        virtual void        previousFrame();
120 121 122 123 124
        /**
         * \brief   Return the length in milliseconds
         * \return  The length of the underlying rendered target in milliseconds
         *  \sa     getLength()
         */
125
        virtual qint64      getLengthMs() const;
126

127
        virtual qint64      length() const;
128

129 130 131 132
        /**
         *  \brief  Return the current frame number
         *  \return The current frame
         */
133
        virtual qint64      getCurrentFrame() const;
134 135 136 137
        /**
         *  \brief Return the number of frames per second
         *  \return     The current fps
         */
138
        virtual float       getFps() const;
139

140
        void                saveProject( QXmlStreamWriter &project ) const;
141
        void                loadProject( const QDomElement& project );
142
    private:
143 144 145 146
        /**
         *  \brief          This is a subpart of the togglePlayPause( bool ) method
         *  \sa             togglePlayPause( bool );
         */
147
        void                internalPlayPause( bool forcePause );
148 149 150 151 152 153 154 155
        /**
         *  \brief          This is a subpart of the togglePlayPause( bool ) method
         *
         *  It starts the render by launching the media player that will query the
         *  lock and unlock callbacks, thus querying the MainWorkflow for frames and
         *  audio samples
         *  \sa             togglePlayPause( bool );
         */
156 157
        virtual void        startPreview();

158
    protected:
159 160 161 162 163 164 165 166 167
        /**
         *  \brief          Will return a pointer to the function/static method to use
         *                  as the imem lock callback.
         *  This method is provided to allow renderers to inherit from this class,
         *  without having to reimplement the initializeRenderer() method, that uses
         *  both getLockCallback() and getUnlockCallback()
         *  \return         A pointer to the lock function.
         *  \sa             getUnlockCallback()
         */
168
        virtual Backend::ISourceRenderer::MemoryInputLockCallback getLockCallback();
169 170 171 172 173 174 175 176 177
        /**
         *  \brief          Will return a pointer to the function/static method to use
         *                  as the imem unlock callback.
         *  This method is provided to allow renderers to inherit from this class,
         *  without having to reimplement the initializeRenderer() method, that uses
         *  both getLockCallback() and getUnlockCallback()
         *  \return         A pointer to the unlock function.
         *  \sa             getLockCallback()
         */
178
        virtual Backend::ISourceRenderer::MemoryInputUnlockCallback getUnlockCallback();
179 180 181 182 183
        /**
         *  \brief              Lock callback for imem module
         *
         *  This callback will query the MainWorkflow for a frame or an audio sample
         *  \param  data        The callback data, this is most likely to be an EsHandler
184
         *  \param  cookie      The input identifier.
185 186 187 188 189 190
         *  \param  dts         Unused, but provided by imem
         *  \param  pts         The pts for the buffer that will be provided
         *  \param  flags       Unused but provided by imem
         *  \param  bufferSize  The size of the buffer that will be provided
         *  \param  buffer      The buffer itself.
         */
191 192
        static int          lock(void *data, const char* cookie, int64_t *dts, int64_t *pts,
                                unsigned int *flags, size_t *bufferSize, const void **buffer );
193 194 195 196 197 198 199
        /**
         *  \brief  "Subcallback", for video frame injection
         *
         *  \param  pts         The pts for the buffer that will be provided
         *  \param  bufferSize  The size of the buffer that will be provided
         *  \param  buffer      The buffer itself.
         */
200
        int                 lockVideo(void *handler, int64_t *pts,
201
                                       size_t *bufferSize, const void **buffer );
202 203 204 205 206 207 208
        /**
         *  \brief  "Subcallback", for audio sample injection
         *
         *  \param  pts         The pts for the buffer that will be provided
         *  \param  bufferSize  The size of the buffer that will be provided
         *  \param  buffer      The buffer itself.
         */
209
        int                 lockAudio( EsHandler *handler, int64_t *pts,
210
                                       size_t *bufferSize, const void **buffer );
211 212 213 214
        /**
         *  \brief  unlock callback for the imem module
         *
         *  \param  data        The callback data, this is most likely to be an EsHandler
215
         *  \param  cookie      The imem cookie.
216 217 218
         *  \param  buffSize    The size of the buffer
         *  \param  buffer      The buffer to be released
         */
219
        static void         unlock( void *data, const char* cookie, size_t buffSize, void *buffer );
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
        /**
         *  \brief  Return the renderer specific width
         *
         *  The render width can changed depending on the render target.
         *  This getter will be used to initialized the MainWorkflow with the
         *  appropriate width.
         *  \return The video width for the underlying WorkflowRenderer
         */
        virtual quint32     width() const;
        /**
         *  \brief  Return the renderer specific height
         *
         *  The render width can changed depending on the render target.
         *  This getter will be used to initialized the MainWorkflow with the
         *  appropriate height.
         *  \return The video height for the underlying WorkflowRenderer
         */
        virtual quint32     height() const;
238 239 240 241 242 243 244 245 246 247 248 249
        /**
         *  \return         The output fps for this specific render.
         *
         *  The output fps may change according to the rendering target.
         *  IE the output may be different when previewing and when rendering to a file.
         *  This method has to be reimplemented in the underlying WorkflowRenderer, to
         *  adjust itself to the specific renderer fps.
         *  \warning        This may be confused with getFps(), and therefore, one of the
         *                  two should be modified.
         */
        virtual float       outputFps() const;

250 251
        const QString       aspectRatio() const;

252 253 254
        /**
         *  \brief          Configure the production chain.
         */
255
        void                setupRenderer( quint32 width, quint32 height, double fps );
256
        /**
257
         *  \brief          Check for parameters modification.
258 259
         *  \return         true if some render parameters has changed.
         */
260
        bool                paramsHasChanged( quint32 width, quint32 height,
261
                                                  double fps, QString aspect );
262

263
    protected:
264
        MainWorkflow*       m_mainWorkflow;
265
        Backend::IMemorySource* m_source;
266
        bool                m_stopping;
267
        float               m_outputFps;
268
        QString             m_aspectRatio;
269 270 271 272 273 274
        /**
         *  \brief          This isn't exactly the current PTS.
         *                  It's the number of frame rendered since the render has started.
         */
        qint64              m_pts;
        qint64              m_audioPts;
275

276
    private:
277 278 279 280
        /**
         *  \brief          When there's no sound to play, this is the buffer that'll
         *                  be injected
         */
281
        quint8              *m_silencedAudioBuffer;
282
        EsHandler*          m_esHandler;
283 284 285
        quint32             m_nbChannels;
        quint32             m_rate;
        /**
286
         *  \brief          Used in permanent rendering mode, to know if some operations
287 288 289
         *                  has to be performed.
         */
        qint64              m_oldLength;
290

291 292
        quint32             *m_effectFrame;

293 294
        static const quint8     VideoCookie = '0';
        static const quint8     AudioCookie = '1';
295

296
    public slots:
297 298 299
        /**
         *  \brief          The current frame just changed because of the timeline cursor
         */
300
        void                timelineCursorChanged( qint64 newFrame );
301 302 303
        /**
         *  \brief          The current frame just changed because of the timeline ruler
         */
304
        void                rulerCursorChanged( qint64 newFrame );
305 306 307
        /**
         *  \brief          The current frame just changed because of the preview widget
         */
308
        void                previewWidgetCursorChanged( qint64 newFrame );
309 310

    private slots:
311 312 313 314 315 316 317
        /**
         *  \brief          Used to launch "permanent playback", as soon as the length
         *                  first changed to a non zero value.
         *
         *  If the length comes to a 0 value again, the permanent playback will be stoped.
         */
        void                mainWorkflowLenghtChanged( qint64 newLength );
318 319
};

320
#endif // WORKFLOWRENDERER_H