Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
VLMC
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
luyikei
VLMC
Commits
2cf157ac
Commit
2cf157ac
authored
Jun 01, 2009
by
Hugo Beauzee-Luyssen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored TrackWorkflow
parent
3467724d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
224 additions
and
285 deletions
+224
-285
src/Workflow/ClipWorkflow.cpp
src/Workflow/ClipWorkflow.cpp
+71
-26
src/Workflow/ClipWorkflow.h
src/Workflow/ClipWorkflow.h
+40
-5
src/Workflow/MainWorkflow.cpp
src/Workflow/MainWorkflow.cpp
+0
-2
src/Workflow/TrackWorkflow.cpp
src/Workflow/TrackWorkflow.cpp
+110
-204
src/Workflow/TrackWorkflow.h
src/Workflow/TrackWorkflow.h
+3
-48
No files found.
src/Workflow/ClipWorkflow.cpp
View file @
2cf157ac
...
...
@@ -24,41 +24,51 @@
#include "ClipWorkflow.h"
ClipWorkflow
::
ClipWorkflow
(
Clip
::
Clip
*
clip
,
QMutex
*
renderMutex
,
QMutex
*
condMutex
,
QWaitCondition
*
waitCond
)
:
int
g_debugId
=
0
;
ClipWorkflow
::
ClipWorkflow
(
Clip
::
Clip
*
clip
)
:
m_clip
(
clip
),
m_buffer
(
NULL
),
m_renderMutex
(
renderMutex
),
m_condMutex
(
condMutex
),
m_waitCond
(
waitCond
),
m_usingBackBuffer
(
false
),
m_mediaPlayer
(
NULL
),
m_state
(
ClipWorkflow
::
Stopped
)
m_state
(
ClipWorkflow
::
Stopped
),
m_requiredState
(
ClipWorkflow
::
None
)
{
m_buffer
=
new
unsigned
char
[
VIDEOHEIGHT
*
VIDEOWIDTH
*
4
];
m_backBuffer
=
new
unsigned
char
[
VIDEOHEIGHT
*
VIDEOWIDTH
*
4
];
m_stateLock
=
new
QReadWriteLock
;
m_requiredStateLock
=
new
QMutex
;
m_condMutex
=
new
QMutex
;
m_waitCond
=
new
QWaitCondition
;
m_backBufferLock
=
new
QReadWriteLock
;
this
->
debugId
=
g_debugId
++
;
}
ClipWorkflow
::~
ClipWorkflow
()
{
delete
[]
m_buffer
;
delete
[]
m_backBuffer
;
delete
m_stateLock
;
delete
m_requiredStateLock
;
delete
m_backBufferLock
;
}
unsigned
char
*
ClipWorkflow
::
getOutput
()
{
QMutexLocker
lock
(
m_renderMutex
);
return
m_buffer
;
QReadLocker
lock
(
m_backBufferLock
);
if
(
m_usingBackBuffer
==
true
)
return
m_buffer
;
return
m_backBuffer
;
}
void
ClipWorkflow
::
checkStateChange
()
{
QMutexLocker
lock
(
m_requiredStateLock
);
QWriteLocker
lock2
(
m_stateLock
);
QWriteLocker
lock2
(
m_stateLock
);
if
(
m_requiredState
!=
ClipWorkflow
::
None
)
{
qDebug
()
<<
"
Changing state"
;
qDebug
()
<<
"
Setting required state : "
<<
m_requiredState
;
m_state
=
m_requiredState
;
m_requiredState
=
ClipWorkflow
::
None
;
}
...
...
@@ -66,29 +76,42 @@ void ClipWorkflow::checkStateChange()
void
ClipWorkflow
::
lock
(
ClipWorkflow
*
clipWorkflow
,
void
**
pp_ret
)
{
//In any case, we give vlc a buffer to render in...
//If we don't, segmentation fault will catch us and eat our brains !! ahem...
// qDebug() << "Locking in ClipWorkflow::lock";
clipWorkflow
->
m_renderMutex
->
lock
();
// qDebug() << clipWorkflow->getState();
*
pp_ret
=
clipWorkflow
->
m_buffer
;
QReadLocker
lock
(
clipWorkflow
->
m_backBufferLock
);
if
(
clipWorkflow
->
m_usingBackBuffer
)
*
pp_ret
=
clipWorkflow
->
m_backBuffer
;
else
*
pp_ret
=
clipWorkflow
->
m_buffer
;
}
void
ClipWorkflow
::
unlock
(
ClipWorkflow
*
c
lipWorkflo
w
)
void
ClipWorkflow
::
unlock
(
ClipWorkflow
*
cw
)
{
c
lipWorkflow
->
m_renderMutex
->
unlock
();
c
w
->
m_stateLock
->
lockForWrite
();
clipWorkflow
->
checkStateChange
();
clipWorkflow
->
m_stateLock
->
lockForRead
();
if
(
clipWorkflow
->
m_state
==
Rendering
)
if
(
cw
->
m_state
==
Rendering
)
{
QMutexLocker
lock
(
clipWorkflow
->
m_condMutex
);
clipWorkflow
->
m_stateLock
->
unlock
();
clipWorkflow
->
m_waitCond
->
wait
(
clipWorkflow
->
m_condMutex
);
cw
->
m_state
=
Sleeping
;
cw
->
m_stateLock
->
unlock
();
QMutexLocker
lock
(
cw
->
m_condMutex
);
cw
->
m_waitCond
->
wait
(
cw
->
m_condMutex
);
{
QWriteLocker
lock2
(
cw
->
m_backBufferLock
);
cw
->
m_usingBackBuffer
=
!
cw
->
m_usingBackBuffer
;
}
cw
->
m_stateLock
->
lockForWrite
();
cw
->
m_state
=
Rendering
;
}
else
qDebug
()
<<
clipWorkflow
->
m_state
;
clipWorkflow
->
m_stateLock
->
unlock
();
{
qDebug
()
<<
"UnLocking. State = "
<<
cw
->
m_state
<<
"Debug Id = "
<<
cw
->
debugId
;
}
cw
->
m_stateLock
->
unlock
();
cw
->
checkStateChange
();
// qDebug() << "UnLocking in ClipWorkflow::unlock";
}
...
...
@@ -96,6 +119,7 @@ void ClipWorkflow::setVmem()
{
char
buffer
[
32
];
qDebug
()
<<
"Setting vmem from clip "
<<
this
->
debugId
;
//TODO: it would be good if we somehow backup the old media parameters to restore it later.
m_clip
->
getParent
()
->
getVLCMedia
()
->
addOption
(
":vout=vmem"
);
m_clip
->
getParent
()
->
getVLCMedia
()
->
setDataCtx
(
this
);
...
...
@@ -146,6 +170,7 @@ void ClipWorkflow::pausedMediaPlayer()
{
disconnect
(
m_mediaPlayer
,
SIGNAL
(
paused
()
),
this
,
SLOT
(
pausedMediaPlayer
()
)
);
setState
(
Ready
);
qDebug
()
<<
"Set Ready state"
;
}
bool
ClipWorkflow
::
isReady
()
const
...
...
@@ -168,7 +193,6 @@ bool ClipWorkflow::isStopped() const
ClipWorkflow
::
State
ClipWorkflow
::
getState
()
const
{
QReadLocker
lock
(
m_stateLock
);
return
m_state
;
}
...
...
@@ -199,6 +223,8 @@ void ClipWorkflow::stop()
qDebug
()
<<
"Stopped media player"
;
m_mediaPlayer
=
NULL
;
setState
(
Stopped
);
QMutexLocker
lock
(
m_requiredStateLock
);
m_requiredState
=
ClipWorkflow
::
None
;
qDebug
()
<<
"Changed state"
;
}
...
...
@@ -215,6 +241,7 @@ bool ClipWorkflow::isRendering() const
void
ClipWorkflow
::
setState
(
State
state
)
{
qDebug
()
<<
"Setting state : "
<<
state
;
QWriteLocker
lock
(
m_stateLock
);
m_state
=
state
;
}
...
...
@@ -225,3 +252,21 @@ void ClipWorkflow::queryStateChange( State newState )
QMutexLocker
lock
(
m_requiredStateLock
);
m_requiredState
=
newState
;
}
void
ClipWorkflow
::
wake
()
{
m_waitCond
->
wakeAll
();
}
QReadWriteLock
*
ClipWorkflow
::
getStateLock
()
{
return
m_stateLock
;
}
void
ClipWorkflow
::
reinitialize
()
{
QWriteLocker
lock
(
m_stateLock
);
m_state
=
Stopped
;
queryStateChange
(
None
);
}
src/Workflow/ClipWorkflow.h
View file @
2cf157ac
...
...
@@ -49,11 +49,13 @@ class ClipWorkflow : public QObject
Initializing
,
Ready
,
Rendering
,
Sleeping
,
Stopping
,
EndReached
,
StopRequired
,
};
int
debugId
;
ClipWorkflow
(
Clip
*
clip
,
QMutex
*
renderMutex
,
QMutex
*
condMutex
,
QWaitCondition
*
waitCond
);
ClipWorkflow
(
Clip
*
clip
);
virtual
~
ClipWorkflow
();
/**
...
...
@@ -89,6 +91,9 @@ class ClipWorkflow : public QObject
/**
* Returns the current workflow state.
* Be carrefull, as this function is NOT thread safe, and return the
* state without locking the state.
* It's your job to do it, by calling the getStateLock() method.
*/
State
getState
()
const
;
...
...
@@ -120,23 +125,53 @@ class ClipWorkflow : public QObject
*/
void
queryStateChange
(
State
newState
);
/**
* This method will wake the renderer thread for one iteration.
*/
void
wake
();
/**
* This returns the QReadWriteLock that protects the ClipWorkflow's state.
* It should be use to lock the value when checking states from outside this
* class.
*/
QReadWriteLock
*
getStateLock
();
/**
* Put back the ClipWorkflow in its initial state.
*/
void
reinitialize
();
private:
static
void
lock
(
ClipWorkflow
*
clipWorkflow
,
void
**
pp_ret
);
static
void
unlock
(
ClipWorkflow
*
clipWorkflow
);
void
setVmem
();
void
setState
(
State
state
);
/**
* Don't ever call this method from anywhere else than the unlock() method
*/
void
checkStateChange
();
private:
Clip
*
m_clip
;
unsigned
char
*
m_buffer
;
unsigned
char
*
m_backBuffer
;
/**
* This allow the render procedure to know in which buffer it should render.
* If true, then the render occurs in the back buffer, which means the
* returned buffer much be the "front" buffer.
* In other term :
* - When m_usingBackBuffer == false, lock() will return m_buffer, and getOutput() m_backBuffer
* - When m_usingBackBuffer == true, lock() will return m_backBuffer, and getOutput() m_buffer
*/
bool
m_usingBackBuffer
;
QReadWriteLock
*
m_backBufferLock
;
LibVLCpp
::
MediaPlayer
*
m_mediaPlayer
;
QMutex
*
m_renderMutex
;
QMutex
*
m_condMutex
;
QWaitCondition
*
m_waitCond
;
LibVLCpp
::
MediaPlayer
*
m_mediaPlayer
;
State
m_state
;
QReadWriteLock
*
m_stateLock
;
State
m_requiredState
;
...
...
src/Workflow/MainWorkflow.cpp
View file @
2cf157ac
...
...
@@ -50,7 +50,6 @@ void MainWorkflow::startRender()
m_currentFrame
=
0
;
emit
frameChanged
(
0
);
m_length
=
m_tracks
[
0
]
->
getLength
();
m_tracks
[
0
]
->
startRender
();
}
unsigned
char
*
MainWorkflow
::
getOutput
()
...
...
@@ -67,7 +66,6 @@ void MainWorkflow::setPosition( float pos )
if
(
m_renderStarted
==
false
)
return
;
qint64
frame
=
(
float
)
m_length
*
pos
;
m_tracks
[
0
]
->
requirePositionChanged
(
pos
);
m_currentFrame
=
frame
;
emit
frameChanged
(
frame
);
//Do not emit a signal for the RenderWidget, since it's the one that triggered that call...
...
...
src/Workflow/TrackWorkflow.cpp
View file @
2cf157ac
...
...
@@ -26,13 +26,9 @@
unsigned
char
*
TrackWorkflow
::
blackOutput
=
NULL
;
TrackWorkflow
::
TrackWorkflow
()
:
m_requiredPosition
(
-
1.0
f
)
TrackWorkflow
::
TrackWorkflow
()
{
m_condMutex
=
new
QMutex
;
m_waitCondition
=
new
QWaitCondition
;
m_mediaPlayer
=
new
LibVLCpp
::
MediaPlayer
();
m_renderMutex
=
new
QMutex
;
m_requiredPositionLock
=
new
QMutex
;
if
(
TrackWorkflow
::
blackOutput
==
NULL
)
{
//TODO: this ain't free !
...
...
@@ -43,38 +39,17 @@ TrackWorkflow::TrackWorkflow() : m_requiredPosition( -1.0f )
TrackWorkflow
::~
TrackWorkflow
()
{
delete
m_condMutex
;
delete
m_waitCondition
;
delete
m_mediaPlayer
;
delete
m_renderMutex
;
}
void
TrackWorkflow
::
addClip
(
Clip
*
clip
,
qint64
start
)
{
qDebug
()
<<
"Inserting clip at frame nb"
<<
start
;
ClipWorkflow
*
cw
=
new
ClipWorkflow
(
clip
,
m_renderMutex
,
m_condMutex
,
m_waitCondition
);
ClipWorkflow
*
cw
=
new
ClipWorkflow
(
clip
);
m_clips
.
insert
(
start
,
cw
);
computeLength
();
}
void
TrackWorkflow
::
startRender
()
{
m_current
=
m_clips
.
end
();
if
(
m_clips
.
size
()
<=
0
)
return
;
//If the first frame is to be render soon, we should play it now.
if
(
m_clips
.
begin
().
key
()
<
TrackWorkflow
::
nbFrameBeforePreload
)
{
m_clips
.
begin
().
value
()
->
initialize
(
m_mediaPlayer
);
if
(
m_current
.
key
()
==
0
)
{
m_current
=
m_clips
.
begin
();
m_current
.
value
()
->
startRender
();
}
}
}
void
TrackWorkflow
::
computeLength
()
{
if
(
m_clips
.
count
()
==
0
)
...
...
@@ -88,227 +63,158 @@ qint64 TrackWorkflow::getLength() const
return
m_length
;
}
bool
TrackWorkflow
::
checkNextClip
(
qint64
currentFrame
)
unsigned
char
*
TrackWorkflow
::
renderClip
(
ClipWorkflow
*
cw
,
bool
needRepositioning
,
float
pos
)
{
QMap
<
qint64
,
ClipWorkflow
*>::
iterator
next
;
const
QMap
<
qint64
,
ClipWorkflow
*>::
const_iterator
end
=
m_clips
.
end
();
unsigned
char
*
ret
=
TrackWorkflow
::
blackOutput
;
//Picking next clip :
if
(
m_current
==
end
)
{
//Checking if there is a clip in the first place...
if
(
m_clips
.
count
()
==
0
)
return
false
;
next
=
m_clips
.
begin
();
}
else
{
next
=
m_clips
.
begin
()
+
1
;
if
(
next
==
end
)
return
false
;
}
cw
->
getStateLock
()
->
lockForRead
();
//If it's about to be used, initialize it
if
(
next
.
key
()
==
currentFrame
+
TrackWorkflow
::
nbFrameBeforePreload
)
{
//Don't do anything if the current media player is still in use
//But for it to be in use, we should have a current media :
if
(
m_current
!=
end
&&
m_current
.
value
()
->
isRendering
()
==
false
)
qDebug
()
<<
"Preloading media"
;
next
.
value
()
->
initialize
(
m_mediaPlayer
);
}
//This ClipWorkflow must start at this frame :
else
if
(
next
.
key
()
==
currentFrame
)
if
(
cw
->
getState
()
==
ClipWorkflow
::
Rendering
)
{
qDebug
()
<<
"Starting rendering"
;
m_current
=
next
;
m_current
.
value
()
->
startRender
();
//The rendering state meens... whell it means that the frame is
//beeing rendered, so we wait.
cw
->
getStateLock
()
->
unlock
();
while
(
cw
->
isRendering
()
==
true
)
{
// qDebug() << "Waiting for complete render. State == " << cw->getState();
usleep
(
100
);
}
cw
->
getStateLock
()
->
lockForRead
();
//This way we can trigger the appropriate if just below.
}
return
true
;
}
unsigned
char
*
TrackWorkflow
::
getOutput
(
qint64
currentFrame
)
{
unsigned
char
*
ret
=
TrackWorkflow
::
blackOutput
;
bool
clipsRemaining
;
QMutexLocker
lock
(
m_requiredPositionLock
);
if
(
m_requiredPosition
>=
0.0
f
)
//If frame has been rendered :
if
(
cw
->
getState
()
==
ClipWorkflow
::
Sleeping
)
{
setPosition
(
m_requiredPosition
);
m_requiredPosition
=
-
1.0
f
;
cw
->
getStateLock
()
->
unlock
();
ret
=
cw
->
getOutput
();
if
(
needRepositioning
==
true
)
{
cw
->
setPosition
(
pos
);
}
cw
->
wake
();
}
checkStop
();
// qDebug() << "Frame nb" << currentFrame;
clipsRemaining
=
checkNextClip
(
currentFrame
);
//This is true only before the first render.
if
(
m_current
==
m_clips
.
end
()
)
else
if
(
cw
->
getState
()
==
ClipWorkflow
::
Stopped
)
{
// qDebug() << "m_current == m_clips.end()";
//If the track was empty, then its end is reached
if
(
clipsRemaining
==
false
)
emit
endReached
();
//Else, we return a black screen.
return
TrackWorkflow
::
blackOutput
;
cw
->
getStateLock
()
->
unlock
();
cw
->
initialize
(
m_mediaPlayer
);
cw
->
startRender
();
qDebug
()
<<
"Render started for clip"
<<
cw
->
debugId
;
}
//We proceed to the render only if the ClipWorkflow is in rendering mode.
if
(
m_current
.
value
()
->
isRendering
()
==
true
)
else
if
(
cw
->
getState
()
==
ClipWorkflow
::
Ready
||
cw
->
getState
()
==
ClipWorkflow
::
Initializing
)
{
m_waitCondition
->
wakeAll
();
// qDebug() << "Is rendering == true";
ret
=
m_current
.
value
()
->
getOutput
();
return
ret
;
//If the state is Initializing, then the workflow will wait.
//Otherwise, it will start directly.
cw
->
getStateLock
()
->
unlock
();
cw
->
startRender
();
qDebug
()
<<
"Started render for clip"
<<
cw
->
debugId
;
}
else
if
(
m_current
.
value
()
->
getState
()
==
ClipWorkflow
::
EndReached
||
m_current
.
value
()
->
getState
()
==
ClipWorkflow
::
StopRequired
)
else
{
//First, we stop the current ClipWorkflow so that it won't
//enter the lock/unlock cycle anymore.
qDebug
()
<<
"Stopping"
;
m_current
.
value
()
->
stop
();
//Then, if there's no remaining clip, end of track is reached.
if
(
clipsRemaining
==
false
)
emit
endReached
();
qDebug
()
<<
"Unexpected ClipWorkflow::State when rendering:"
<<
cw
->
getState
();
cw
->
getStateLock
()
->
unlock
();
}
// else
// qDebug() << "Uncoherent state : " << m_current.value()->getState();
return
ret
;
}
void
TrackWorkflow
::
initializeClipWorkflow
(
ClipWorkflow
*
cw
)
void
TrackWorkflow
::
preloadClip
(
ClipWorkflow
*
cw
)
{
//>Launching the initialization
cw
->
initialize
(
m_mediaPlayer
);
cw
->
startRender
();
}
cw
->
getStateLock
()
->
lockForRead
();
void
TrackWorkflow
::
stopClipWorkflow
(
ClipWorkflow
*
cw
)
{
if
(
cw
->
getState
()
!=
ClipWorkflow
::
Stopped
&&
cw
->
getState
()
!=
ClipWorkflow
::
StopRequired
)
if
(
cw
->
getState
()
==
ClipWorkflow
::
Stopped
)
{
cw
->
queryStateChange
(
ClipWorkflow
::
StopRequired
);
//Since state change won't be immediate, we add the clip workflow to a lookup list
m_toStop
.
enqueue
(
cw
)
;
cw
->
getStateLock
()
->
unlock
(
);
cw
->
initialize
(
m_mediaPlayer
);
return
;
}
cw
->
getStateLock
()
->
unlock
();
}
void
TrackWorkflow
::
setPosition
(
float
pos
)
void
TrackWorkflow
::
stopClipWorkflow
(
ClipWorkflow
*
cw
)
{
qDebug
()
<<
"Setting 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
=
end
;
cw
->
getStateLock
()
->
lockForRead
();
if
(
frame
>
m_length
)
if
(
cw
->
getState
()
==
ClipWorkflow
::
Stopped
)
{
if
(
m_current
!=
end
)
{
stopClipWorkflow
(
m_current
.
value
()
);
m_current
=
end
;
qDebug
()
<<
"After end of current track"
;
return
;
}
cw
->
getStateLock
()
->
unlock
();
return
;
}
//Locate the new clip workflow
while
(
it
!=
en
d
)
if
(
cw
->
getState
()
==
ClipWorkflow
::
Sleeping
||
cw
->
getState
()
==
ClipWorkflow
::
Ready
||
cw
->
getState
()
==
ClipWorkflow
::
EndReache
d
)
{
if
(
it
.
key
()
<=
frame
&&
(
it
.
key
()
+
it
.
value
()
->
getClip
()
->
getLength
()
)
>
frame
)
{
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
()
)
{
next
=
next
-
1
;
//Since the iterator must point to the previous video
}
else
{
next
=
end
;
}
// in order to checkNextClip() to work.
it
=
end
;
break
;
}
++
it
;
qDebug
()
<<
"Stopping from sleeping / ready / endreached state for clip "
<<
cw
->
debugId
;
cw
->
getStateLock
()
->
unlock
();
cw
->
queryStateChange
(
ClipWorkflow
::
Stopping
);
cw
->
wake
();
cw
->
stop
();
}
//No clip was found, just adjusing the current clip. (Render will be black though)
if
(
it
==
end
)
else
if
(
cw
->
getState
()
==
ClipWorkflow
::
Rendering
)
{
qDebug
()
<<
"In black zone"
;
//We should use the next clip, however, we use the clip just before
//the next.
//We also stop the current clip if it was started.
if
(
m_current
!=
end
)
{
stopClipWorkflow
(
m_current
.
value
()
);
}
//TODO: it seems that m_current may be equal to next... check if that could be a problem...
m_current
=
next
;
qDebug
()
<<
"Stopping from rendering state for clip"
<<
cw
->
debugId
;
cw
->
getStateLock
()
->
unlock
();
while
(
cw
->
isRendering
()
==
true
)
usleep
(
100
);
qDebug
()
<<
"Rendering completed"
<<
cw
->
debugId
;
cw
->
queryStateChange
(
ClipWorkflow
::
Stopping
);
cw
->
wake
();
cw
->
stop
();
qDebug
()
<<
"Mediaplayer Stop asked for clip"
<<
cw
->
debugId
;
}
// If the clip found is the current, we just change the position of the
// media player
else
if
(
it
==
m_current
)
else
if
(
cw
->
getState
()
==
ClipWorkflow
::
Initializing
)
{
qDebug
()
<<
"Using current clip with new position"
;
qDebug
()
<<
it
.
value
()
->
getState
();
//The clip may have been stoped (if we reached end but came back at it)
if
(
it
.
value
()
->
isStopped
()
)
{
initializeClipWorkflow
(
it
.
value
()
);
}
it
.
value
()
->
setPosition
(
(
float
)(
frame
-
it
.
key
()
)
/
(
float
)(
it
.
value
()
->
getClip
()
->
getLength
())
);
//Awaking renderers to avoid them to be stuck inside of the lock...
m_waitCondition
->
wakeAll
();
qDebug
()
<<
"Stopping from initializing state for clip"
<<
cw
->
debugId
;
cw
->
getStateLock
()
->
unlock
();
while
(
cw
->
isReady
()
==
false
)
usleep
(
20
);
cw
->
stop
();
}
// Else, we found a clip that is not the current one.
else
{
qDebug
()
<<
"Using other clip"
;
//First, we stop the current workflow.
if
(
m_current
!=
end
)
{
stopClipWorkflow
(
m_current
.
value
()
);
}
//We initialize the new workflow
initializeClipWorkflow
(
it
.
value
()
);
//And this is now our current clip
m_current
=
it
;
//TODO: we doesn't take the new position in count :/
qDebug
()
<<
"Unexpected ClipWorkflow::State when stopping :"
<<
cw
->
getState
();
cw
->
getStateLock
()
->
unlock
();
}
}
void
TrackWorkflow
::
requirePositionChanged
(
float
pos
)
unsigned
char
*
TrackWorkflow
::
getOutput
(
qint64
currentFrame
)
{
QMutexLocker
lock
(
m_requiredPositionLock
);
m_requiredPosition
=
pos
;
}
unsigned
char
*
ret
=
TrackWorkflow
::
blackOutput
;
QMap
<
qint64
,
ClipWorkflow
*>::
iterator
it
=
m_clips
.
begin
();
QMap
<
qint64
,
ClipWorkflow
*>::
iterator
end
=
m_clips
.
end
();
static
qint64
lastFrame
=
0
;
bool
needRepositioning
;
void
TrackWorkflow
::
checkStop
()
{
while
(
m_toStop
.
isEmpty
()
==
false
)
needRepositioning
=
(
abs
(
currentFrame
-
lastFrame
)
>
3
)
?
true
:
false
;
while
(
it
!=
end
)
{
ClipWorkflow
*
cw
=
m_toStop
.
head
();
if
(
cw
->
getState
()
==
ClipWorkflow
::
StopRequired
)
qint64
start
=
it
.
key
();
ClipWorkflow
*
cw
=
it
.
value
();
//Is the clip supposed to render now ?
if
(
start
<=
currentFrame
&&
currentFrame
<=
start
+
cw
->
getClip
()
->
getLength
()
)
{
qDebug
()
<<
"Stopping from queue"
;
cw
->
stop
();
m_toStop
.
dequeue
();
if
(
needRepositioning
==
true
)