summaryrefslogtreecommitdiff
path: root/drivers/theoraplayer/src/TheoraAsync.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/theoraplayer/src/TheoraAsync.cpp')
-rw-r--r--drivers/theoraplayer/src/TheoraAsync.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/drivers/theoraplayer/src/TheoraAsync.cpp b/drivers/theoraplayer/src/TheoraAsync.cpp
new file mode 100644
index 0000000000..cc3b7a4bf5
--- /dev/null
+++ b/drivers/theoraplayer/src/TheoraAsync.cpp
@@ -0,0 +1,253 @@
+/************************************************************************************
+This source file is part of the Theora Video Playback Library
+For latest info, see http://libtheoraplayer.googlecode.com
+*************************************************************************************
+Copyright (c) 2008-2014 Kresimir Spes (kspes@cateia.com)
+This program is free software; you can redistribute it and/or modify it under
+the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause
+*************************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+#include "TheoraAsync.h"
+#include "TheoraUtil.h"
+
+#ifdef _WINRT
+#include <wrl.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Mutex
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+TheoraMutex::TheoraMutex()
+{
+#ifdef _WIN32
+#ifndef _WINRT // WinXP does not have CreateTheoraMutexEx()
+ mHandle = CreateMutex(0, 0, 0);
+#else
+ mHandle = CreateMutexEx(NULL, NULL, 0, SYNCHRONIZE);
+#endif
+#else
+ mHandle = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init((pthread_mutex_t*)mHandle, 0);
+#endif
+}
+
+TheoraMutex::~TheoraMutex()
+{
+#ifdef _WIN32
+ CloseHandle(mHandle);
+#else
+ pthread_mutex_destroy((pthread_mutex_t*)mHandle);
+ free((pthread_mutex_t*)mHandle);
+ mHandle = NULL;
+#endif
+}
+
+void TheoraMutex::lock()
+{
+#ifdef _WIN32
+ WaitForSingleObjectEx(mHandle, INFINITE, FALSE);
+#else
+ pthread_mutex_lock((pthread_mutex_t*)mHandle);
+#endif
+}
+
+void TheoraMutex::unlock()
+{
+#ifdef _WIN32
+ ReleaseMutex(mHandle);
+#else
+ pthread_mutex_unlock((pthread_mutex_t*)mHandle);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Thread
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _WINRT
+using namespace Windows::Foundation;
+using namespace Windows::System::Threading;
+#endif
+
+#ifdef _WIN32
+unsigned long WINAPI theoraAsyncCall(void* param)
+#else
+void* theoraAsyncCall(void* param)
+#endif
+{
+ TheoraThread* t = (TheoraThread*)param;
+ t->execute();
+#ifdef _WIN32
+ return 0;
+#else
+ pthread_exit(NULL);
+ return NULL;
+#endif
+}
+
+#ifdef _WINRT
+struct TheoraAsyncActionWrapper
+{
+public:
+ IAsyncAction^ mAsyncAction;
+ TheoraAsyncActionWrapper(IAsyncAction^ asyncAction)
+ {
+ mAsyncAction = asyncAction;
+ }
+};
+#endif
+
+TheoraThread::TheoraThread() : mRunning(false), mId(0)
+{
+#ifndef _WIN32
+ mId = (pthread_t*)malloc(sizeof(pthread_t));
+#endif
+}
+
+TheoraThread::~TheoraThread()
+{
+ if (mRunning)
+ {
+ stop();
+ }
+ if (mId != NULL)
+ {
+#ifdef _WIN32
+#ifndef _WINRT
+ CloseHandle(mId);
+#else
+ delete mId;
+#endif
+#else
+ free((pthread_t*)mId);
+#endif
+ mId = NULL;
+ }
+}
+
+void TheoraThread::start()
+{
+ mRunning = true;
+#ifdef _WIN32
+#ifndef _WINRT
+ mId = CreateThread(0, 0, &theoraAsyncCall, this, 0, 0);
+#else
+ mId = new TheoraAsyncActionWrapper(ThreadPool::RunAsync(
+ ref new WorkItemHandler([&](IAsyncAction^ work_item)
+ {
+ execute();
+ }),
+ WorkItemPriority::Normal, WorkItemOptions::TimeSliced));
+#endif
+#else
+ pthread_create((pthread_t*)mId, NULL, &theoraAsyncCall, this);
+#endif
+}
+
+bool TheoraThread::isRunning()
+{
+ bool ret;
+ mRunningMutex.lock();
+ ret = mRunning;
+ mRunningMutex.unlock();
+
+ return ret;
+}
+
+void TheoraThread::join()
+{
+ mRunningMutex.lock();
+ mRunning = false;
+ mRunningMutex.unlock();
+#ifdef _WIN32
+#ifndef _WINRT
+ WaitForSingleObject(mId, INFINITE);
+ if (mId != NULL)
+ {
+ CloseHandle(mId);
+ mId = NULL;
+ }
+#else
+ IAsyncAction^ action = ((TheoraAsyncActionWrapper*)mId)->mAsyncAction;
+ int i = 0;
+ while (action->Status != AsyncStatus::Completed &&
+ action->Status != AsyncStatus::Canceled &&
+ action->Status != AsyncStatus::Error &&
+ i < 100)
+ {
+ _psleep(50);
+ ++i;
+ }
+ if (i >= 100)
+ {
+ i = 0;
+ action->Cancel();
+ while (action->Status != AsyncStatus::Completed &&
+ action->Status != AsyncStatus::Canceled &&
+ action->Status != AsyncStatus::Error &&
+ i < 100)
+ {
+ _psleep(50);
+ ++i;
+ }
+ }
+#endif
+#else
+ pthread_join(*((pthread_t*)mId), 0);
+#endif
+}
+
+void TheoraThread::resume()
+{
+#ifdef _WIN32
+#ifndef _WINRT
+ ResumeThread(mId);
+#else
+ // not available in WinRT
+#endif
+#endif
+}
+
+void TheoraThread::pause()
+{
+#ifdef _WIN32
+#ifndef _WINRT
+ SuspendThread(mId);
+#else
+ // not available in WinRT
+#endif
+#endif
+}
+
+void TheoraThread::stop()
+{
+ if (mRunning)
+ {
+ mRunningMutex.lock();
+ mRunning = false;
+ mRunningMutex.unlock();
+#ifdef _WIN32
+#ifndef _WINRT
+ TerminateThread(mId, 0);
+#else
+ ((TheoraAsyncActionWrapper*)mId)->mAsyncAction->Cancel();
+#endif
+#elif defined(_ANDROID)
+ pthread_kill(*((pthread_t*)mId), 0);
+#else
+ pthread_cancel(*((pthread_t*)mId));
+#endif
+ }
+}
+