some code cleanup and changes in ffmpeg decoder thread

This commit is contained in:
Alexander Eckart committed 2012-03-10 09:30:23 +01:00
1 parent 1e9a6f0d3d
commit ad2fb1ddc5
1 file changed
+96 -80
+96 -80
View File
@@ -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);