some code cleanup and changes in ffmpeg decoder thread
This commit is contained in:
1 parent
1e9a6f0d3d
commit
ad2fb1ddc5
1 file changed
+96
-80
@@ -214,33 +214,34 @@ namespace Vocaluxe.Lib.Video
|
|||||||
|
|
||||||
class Decoder
|
class Decoder
|
||||||
{
|
{
|
||||||
private IntPtr _instance = IntPtr.Zero;
|
private IntPtr _instance = IntPtr.Zero; // acinerella instance
|
||||||
private IntPtr _videodecoder = IntPtr.Zero;
|
private IntPtr _videodecoder = IntPtr.Zero; // acinerella video decoder instance
|
||||||
private IntPtr _package = IntPtr.Zero;
|
|
||||||
private Stopwatch _Timer = new Stopwatch();
|
private Stopwatch _LoopTimer = new Stopwatch();
|
||||||
private CLOSEPROC _Closeproc;
|
private CLOSEPROC _Closeproc; // delegate for stream closing
|
||||||
private int _StreamID;
|
private int _StreamID; // stream ID for stream closing
|
||||||
private string _FileName;
|
private string _FileName; // current video file name
|
||||||
|
|
||||||
private FileStream _fs;
|
private FileStream _fs; // video file stream
|
||||||
private TAc_read_callback _rc;
|
private TAc_read_callback _rc; // read callback for acinerella
|
||||||
private TAc_seek_callback _sc;
|
private TAc_seek_callback _sc; // seek callback for acinerella
|
||||||
|
|
||||||
private bool _FileOpened = false;
|
private bool _FileOpened = false;
|
||||||
|
|
||||||
private float _VideoTimeBase = 0f;
|
private float _VideoTimeBase = 0f; // frame time
|
||||||
private float _VideoTime = 0f;
|
private float _VideoDecoderTime = 0f; // time of last decoded frame
|
||||||
private float _ActualVideoTime = 0f;
|
private float _CurrentVideoTime = 0f; // current video position
|
||||||
private bool _waiting = false;
|
private bool _BufferFull = false; // buffer is full, waiting for free frame slot
|
||||||
private bool _skip = false;
|
|
||||||
|
private bool _skip = false; // do skip
|
||||||
private float _Time = 0f;
|
private float _Time = 0f;
|
||||||
private float _Gap = 0f;
|
private float _Gap = 0f;
|
||||||
private float _Start = 0f;
|
private float _Start = 0f;
|
||||||
private bool _Loop = false;
|
private bool _Loop = false;
|
||||||
private float _Duration = 0f;
|
private float _Duration = 0f;
|
||||||
private float _VideoSkipTime = 0f;
|
private float _VideoSkipTime = 0f; // = VideoGap
|
||||||
private float _NegativeSkipTime = 0f;
|
private float _SkipTime = 0f; // = Start + VideoGap
|
||||||
private float _SkipTime = 0f;
|
|
||||||
private bool _Paused = false;
|
private bool _Paused = false;
|
||||||
private bool _NoMoreFrames = false;
|
private bool _NoMoreFrames = false;
|
||||||
private bool _Finished = false;
|
private bool _Finished = false;
|
||||||
@@ -292,15 +293,16 @@ namespace Vocaluxe.Lib.Video
|
|||||||
get { return _Paused; }
|
get { return _Paused; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_Paused = value;
|
|
||||||
lock (MutexSyncSignals)
|
lock (MutexSyncSignals)
|
||||||
{
|
{
|
||||||
|
_Paused = value;
|
||||||
if (_Paused)
|
if (_Paused)
|
||||||
_Timer.Stop();
|
{
|
||||||
|
_LoopTimer.Stop();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_Timer.Start();
|
_LoopTimer.Start();
|
||||||
EventDecode.Set();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,7 +331,7 @@ namespace Vocaluxe.Lib.Video
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
_FileName = FileName;
|
_FileName = FileName;
|
||||||
_thread.Priority = ThreadPriority.Highest;
|
_thread.Priority = ThreadPriority.Normal;
|
||||||
_thread.Name = Path.GetFileName(FileName);
|
_thread.Name = Path.GetFileName(FileName);
|
||||||
_thread.Start();
|
_thread.Start();
|
||||||
return true;
|
return true;
|
||||||
@@ -347,12 +349,12 @@ namespace Vocaluxe.Lib.Video
|
|||||||
{
|
{
|
||||||
lock (MutexSyncSignals)
|
lock (MutexSyncSignals)
|
||||||
{
|
{
|
||||||
_SetTime += _Timer.ElapsedMilliseconds / 1000f;
|
_SetTime += _LoopTimer.ElapsedMilliseconds / 1000f;
|
||||||
VideoTime = _SetTime;
|
VideoTime = _SetTime;
|
||||||
|
|
||||||
_Timer.Stop();
|
_LoopTimer.Stop();
|
||||||
_Timer.Reset();
|
_LoopTimer.Reset();
|
||||||
_Timer.Start();
|
_LoopTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -361,12 +363,12 @@ namespace Vocaluxe.Lib.Video
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Time - _SetTime >= 0 || _SetTime > Time)
|
if (_SetTime != Time)
|
||||||
{
|
{
|
||||||
lock (MutexSyncSignals)
|
lock (MutexSyncSignals)
|
||||||
{
|
{
|
||||||
_SetTime = Time;
|
_SetTime = Time;
|
||||||
VideoTime = _VideoTime;
|
VideoTime = _CurrentVideoTime;
|
||||||
}
|
}
|
||||||
UploadNewFrame(ref frame);
|
UploadNewFrame(ref frame);
|
||||||
EventDecode.Set();
|
EventDecode.Set();
|
||||||
@@ -394,17 +396,14 @@ namespace Vocaluxe.Lib.Video
|
|||||||
private void DoSkip()
|
private void DoSkip()
|
||||||
{
|
{
|
||||||
string extension = Path.GetExtension(_FileName); //just a workaround for the mkv-search-bug in ffmpeg
|
string extension = Path.GetExtension(_FileName); //just a workaround for the mkv-search-bug in ffmpeg
|
||||||
lock (MutexSyncSignals)
|
|
||||||
{
|
_VideoSkipTime = _Gap;
|
||||||
_VideoSkipTime = _Gap;
|
_SkipTime = _Start + _Gap;
|
||||||
_NegativeSkipTime = _Start + _Gap;
|
_BeforeLoop = false;
|
||||||
_SkipTime = _Start + _Gap;
|
|
||||||
_BeforeLoop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_SkipTime > 0 && extension != ".mkv")
|
if (_SkipTime > 0 && extension != ".mkv")
|
||||||
{
|
{
|
||||||
_VideoTime = _SkipTime;
|
_VideoDecoderTime = _SkipTime;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CAcinerella.ac_seek(_videodecoder, -1, (Int64)(_SkipTime * 1000f));
|
CAcinerella.ac_seek(_videodecoder, -1, (Int64)(_SkipTime * 1000f));
|
||||||
@@ -417,7 +416,7 @@ namespace Vocaluxe.Lib.Video
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_VideoTime = 0f;
|
_VideoDecoderTime = 0f;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (extension != ".mkv")
|
if (extension != ".mkv")
|
||||||
@@ -429,7 +428,10 @@ namespace Vocaluxe.Lib.Video
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ActualVideoTime = _VideoTime;
|
lock (MutexSyncSignals)
|
||||||
|
{
|
||||||
|
_CurrentVideoTime = _VideoDecoderTime;
|
||||||
|
}
|
||||||
|
|
||||||
lock (MutexFramebuffer)
|
lock (MutexFramebuffer)
|
||||||
{
|
{
|
||||||
@@ -440,46 +442,41 @@ namespace Vocaluxe.Lib.Video
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_waiting = false;
|
_BufferFull = false;
|
||||||
|
_skip = false;
|
||||||
|
EventDecode.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Execute()
|
private void Execute()
|
||||||
{
|
{
|
||||||
DoOpen();
|
DoOpen();
|
||||||
|
EventDecode.Set();
|
||||||
|
|
||||||
while (!_terminated)
|
while (!_terminated)
|
||||||
{
|
{
|
||||||
if (EventDecode.WaitOne(1) || !_waiting)
|
if (EventDecode.WaitOne(10))
|
||||||
{
|
|
||||||
if (_skip)
|
|
||||||
{
|
|
||||||
DoSkip();
|
|
||||||
_skip = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_waiting)
|
|
||||||
{
|
|
||||||
DoDecode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_waiting)
|
|
||||||
Copy();
|
|
||||||
}
|
|
||||||
if (!_terminated)
|
|
||||||
{
|
{
|
||||||
lock (MutexSyncSignals)
|
lock (MutexSyncSignals)
|
||||||
{
|
{
|
||||||
_Time = _SetTime;
|
_Time = _SetTime;
|
||||||
if (_SetSkip)
|
if (_SetSkip)
|
||||||
_skip = true;
|
_skip = true;
|
||||||
|
|
||||||
_SetSkip = false;
|
_SetSkip = false;
|
||||||
_Gap = _SetGap;
|
_Gap = _SetGap;
|
||||||
_Start = _SetStart;
|
_Start = _SetStart;
|
||||||
_Loop = _SetLoop;
|
_Loop = _SetLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_skip)
|
||||||
|
DoSkip();
|
||||||
|
|
||||||
|
if (!_BufferFull)
|
||||||
|
DoDecode();
|
||||||
|
|
||||||
|
if (_BufferFull)
|
||||||
|
Copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DoFree();
|
DoFree();
|
||||||
@@ -545,7 +542,7 @@ namespace Vocaluxe.Lib.Video
|
|||||||
if (Videodecoder.stream_info.video_info.frames_per_second > 0)
|
if (Videodecoder.stream_info.video_info.frames_per_second > 0)
|
||||||
_VideoTimeBase = 1f / (float)Videodecoder.stream_info.video_info.frames_per_second;
|
_VideoTimeBase = 1f / (float)Videodecoder.stream_info.video_info.frames_per_second;
|
||||||
|
|
||||||
_VideoTime = 0f;
|
_VideoDecoderTime = 0f;
|
||||||
_Time = 0f;
|
_Time = 0f;
|
||||||
|
|
||||||
for (int i = 0; i < _FrameBuffer.Length; i++)
|
for (int i = 0; i < _FrameBuffer.Length; i++)
|
||||||
@@ -564,14 +561,14 @@ namespace Vocaluxe.Lib.Video
|
|||||||
if (!_FileOpened)
|
if (!_FileOpened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_Paused || _NoMoreFrames)
|
if (_Paused || _NoMoreFrames || _BufferFull)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((_NegativeSkipTime < 0f) && (_Time + _NegativeSkipTime >= 0f))
|
if ((_SkipTime < 0f) && (_Time + _SkipTime >= 0f))
|
||||||
_NegativeSkipTime = 0f;
|
_SkipTime = 0f;
|
||||||
|
|
||||||
float myTime = _Time + _VideoSkipTime;
|
float myTime = _Time + _VideoSkipTime;
|
||||||
float TimeDifference = myTime - _VideoTime;
|
float TimeDifference = myTime - _VideoDecoderTime;
|
||||||
|
|
||||||
bool DropFrame = false;
|
bool DropFrame = false;
|
||||||
if (TimeDifference >= (FRAMEDROPCOUNT - 1) * _VideoTimeBase)
|
if (TimeDifference >= (FRAMEDROPCOUNT - 1) * _VideoTimeBase)
|
||||||
@@ -634,7 +631,6 @@ namespace Vocaluxe.Lib.Video
|
|||||||
|
|
||||||
lock (MutexSyncSignals)
|
lock (MutexSyncSignals)
|
||||||
{
|
{
|
||||||
_ActualVideoTime = 0f;
|
|
||||||
_Start = 0f;
|
_Start = 0f;
|
||||||
_Gap = 0f;
|
_Gap = 0f;
|
||||||
_SetTime = 0f;
|
_SetTime = 0f;
|
||||||
@@ -655,6 +651,7 @@ namespace Vocaluxe.Lib.Video
|
|||||||
private void Copy()
|
private void Copy()
|
||||||
{
|
{
|
||||||
int num = -1;
|
int num = -1;
|
||||||
|
|
||||||
lock (MutexFramebuffer)
|
lock (MutexFramebuffer)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _FrameBuffer.Length; i++)
|
for (int i = 0; i < _FrameBuffer.Length; i++)
|
||||||
@@ -667,24 +664,38 @@ namespace Vocaluxe.Lib.Video
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (num == -1)
|
if (num == -1)
|
||||||
_waiting = true;
|
{
|
||||||
|
_BufferFull = true;
|
||||||
|
EventDecode.Reset();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TAc_decoder Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder));
|
TAc_decoder Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder));
|
||||||
|
|
||||||
_VideoTime = (float)Videodecoder.timecode;
|
_VideoDecoderTime = (float)Videodecoder.timecode;
|
||||||
_FrameBuffer[num].time = _VideoTime;
|
_FrameBuffer[num].time = _VideoDecoderTime;
|
||||||
|
|
||||||
if (Videodecoder.buffer != IntPtr.Zero)
|
if (Videodecoder.buffer != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Marshal.Copy(Videodecoder.buffer, _FrameBuffer[num].data, 0, _Width * _Height * 4);
|
Marshal.Copy(Videodecoder.buffer, _FrameBuffer[num].data, 0, _Width * _Height * 4);
|
||||||
|
|
||||||
_FrameBuffer[num].displayed = false;
|
_FrameBuffer[num].displayed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_waiting = false;
|
int numfull = 0;
|
||||||
|
for (int i = 0; i < _FrameBuffer.Length; i++)
|
||||||
|
{
|
||||||
|
if (!_FrameBuffer[i].displayed)
|
||||||
|
numfull++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numfull < _FrameBuffer.Length)
|
||||||
|
_BufferFull = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_BufferFull)
|
||||||
|
EventDecode.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UploadNewFrame(ref STexture frame)
|
private void UploadNewFrame(ref STexture frame)
|
||||||
@@ -707,8 +718,13 @@ namespace Vocaluxe.Lib.Video
|
|||||||
{
|
{
|
||||||
CDraw.UpdateTexture(ref frame, ref _FrameBuffer[num].data);
|
CDraw.UpdateTexture(ref frame, ref _FrameBuffer[num].data);
|
||||||
}
|
}
|
||||||
_ActualVideoTime = _FrameBuffer[num].time;
|
|
||||||
|
lock (MutexSyncSignals)
|
||||||
|
{
|
||||||
|
_CurrentVideoTime = _FrameBuffer[num].time;
|
||||||
|
}
|
||||||
_Finished = false;
|
_Finished = false;
|
||||||
|
EventDecode.Set();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -716,7 +732,6 @@ namespace Vocaluxe.Lib.Video
|
|||||||
_Finished = true;
|
_Finished = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventDecode.Set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FindFrame()
|
private int FindFrame()
|
||||||
@@ -728,27 +743,28 @@ namespace Vocaluxe.Lib.Video
|
|||||||
{
|
{
|
||||||
float td = _SetTime + _VideoSkipTime - _FrameBuffer[i].time;
|
float td = _SetTime + _VideoSkipTime - _FrameBuffer[i].time;
|
||||||
|
|
||||||
|
if (td > _VideoTimeBase * 2 || td < -1f * _VideoTimeBase * (_FrameBuffer.Length + 1))
|
||||||
|
{
|
||||||
|
_FrameBuffer[i].displayed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_FrameBuffer[i].displayed && (td < diff) && (td > _VideoTimeBase))
|
if (!_FrameBuffer[i].displayed && (td < diff) && (td > _VideoTimeBase))
|
||||||
{
|
{
|
||||||
diff = Math.Abs(_FrameBuffer[i].time - _SetTime - _VideoSkipTime);
|
diff = Math.Abs(_FrameBuffer[i].time - _SetTime - _VideoSkipTime);
|
||||||
Result = i;
|
Result = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (td > _VideoTimeBase * 2)
|
|
||||||
_FrameBuffer[i].displayed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Result != -1)
|
if (Result != -1)
|
||||||
|
{
|
||||||
_FrameBuffer[Result].displayed = true;
|
_FrameBuffer[Result].displayed = true;
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoFree()
|
private void DoFree()
|
||||||
{
|
{
|
||||||
if (_package != IntPtr.Zero)
|
|
||||||
CAcinerella.ac_free_package(_package);
|
|
||||||
|
|
||||||
if (_videodecoder != IntPtr.Zero)
|
if (_videodecoder != IntPtr.Zero)
|
||||||
CAcinerella.ac_free_decoder(_videodecoder);
|
CAcinerella.ac_free_decoder(_videodecoder);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user