147 lines
3.7 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Klak.Hap
{
internal sealed class Decoder : IDisposable
{
#region Initialization/finalization
public Decoder(StreamReader stream, int width, int height, int videoType)
{
_stream = stream;
// Plugin initialization
_plugin = KlakHap_CreateDecoder(width, height, videoType);
_id = ++_instantiationCount;
KlakHap_AssignDecoder(_id, _plugin);
// By default, start from the first frame.
_time = 0;
// Decoder thread startup
_resume.req = new AutoResetEvent(true);
_resume.ack = new AutoResetEvent(false);
_thread = new Thread(DecoderThread);
_thread.Start();
}
public void Dispose()
{
if (_thread != null)
{
_terminate = true;
_resume.req.Set();
_thread.Join();
_thread = null;
}
if (_plugin != IntPtr.Zero)
{
KlakHap_AssignDecoder(_id, IntPtr.Zero);
KlakHap_DestroyDecoder(_plugin);
_plugin = IntPtr.Zero;
}
}
#endregion
#region Public members
public uint CallbackID { get { return _id; } }
public int BufferSize { get {
return KlakHap_GetDecoderBufferSize(_plugin);
} }
public void UpdateSync(float time)
{
_time = time;
var buffer = _stream.Advance(_time);
if (buffer != null)
KlakHap_DecodeFrame(_plugin, buffer.PluginPointer);
}
public void UpdateAsync(float time)
{
_time = time;
_resume.req.Set();
_resume.ack.WaitOne();
}
public IntPtr LockBuffer()
{
return KlakHap_LockDecoderBuffer(_plugin);
}
public void UnlockBuffer()
{
KlakHap_UnlockDecoderBuffer(_plugin);
}
#endregion
#region Private members
static uint _instantiationCount;
IntPtr _plugin;
uint _id;
Thread _thread;
(AutoResetEvent req, AutoResetEvent ack) _resume;
bool _terminate;
StreamReader _stream;
float _time;
#endregion
#region Thread function
void DecoderThread()
{
while (true)
{
_resume.req.WaitOne();
_resume.ack.Set();
if (_terminate) break;
var buffer = _stream.Advance(_time);
if (buffer == null) continue;
KlakHap_DecodeFrame(_plugin, buffer.PluginPointer);
}
}
#endregion
#region Native plugin entry points
[DllImport("KlakHap")]
internal static extern IntPtr KlakHap_CreateDecoder(int width, int height, int typeID);
[DllImport("KlakHap")]
internal static extern void KlakHap_DestroyDecoder(IntPtr decoder);
[DllImport("KlakHap")]
internal static extern void KlakHap_AssignDecoder(uint id, IntPtr decoder);
[DllImport("KlakHap")]
internal static extern void KlakHap_DecodeFrame(IntPtr decoder, IntPtr input);
[DllImport("KlakHap")]
internal static extern IntPtr KlakHap_LockDecoderBuffer(IntPtr decoder);
[DllImport("KlakHap")]
internal static extern void KlakHap_UnlockDecoderBuffer(IntPtr decoder);
[DllImport("KlakHap")]
internal static extern int KlakHap_GetDecoderBufferSize(IntPtr decoder);
#endregion
}
}