Fix audio streaming and mac semaphores
...The reason why audio didn't work was because I overwrote the bitrate values. As for semaphores, mac doesn't support unnamed semaphores without using mach semaphores. So, I just implemented a semaphore wrapper for each OS.
This commit is contained in:
@@ -80,7 +80,7 @@ struct audio_output {
|
||||
size_t planes;
|
||||
|
||||
pthread_t thread;
|
||||
event_t stop_event;
|
||||
os_event_t stop_event;
|
||||
|
||||
DARRAY(uint8_t) mix_buffers[MAX_AV_PLANES];
|
||||
|
||||
@@ -437,7 +437,7 @@ static void *audio_thread(void *param)
|
||||
uint64_t prev_time = os_gettime_ns() - buffer_time;
|
||||
uint64_t audio_time;
|
||||
|
||||
while (event_try(audio->stop_event) == EAGAIN) {
|
||||
while (os_event_try(audio->stop_event) == EAGAIN) {
|
||||
os_sleep_ms(AUDIO_WAIT_TIME);
|
||||
|
||||
pthread_mutex_lock(&audio->line_mutex);
|
||||
@@ -590,7 +590,7 @@ int audio_output_open(audio_t *audio, struct audio_output_info *info)
|
||||
goto fail;
|
||||
if (pthread_mutex_init(&out->input_mutex, NULL) != 0)
|
||||
goto fail;
|
||||
if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0)
|
||||
if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0)
|
||||
goto fail;
|
||||
if (pthread_create(&out->thread, NULL, audio_thread, out) != 0)
|
||||
goto fail;
|
||||
@@ -613,7 +613,7 @@ void audio_output_close(audio_t audio)
|
||||
return;
|
||||
|
||||
if (audio->initialized) {
|
||||
event_signal(audio->stop_event);
|
||||
os_event_signal(audio->stop_event);
|
||||
pthread_join(audio->thread, &thread_ret);
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ void audio_output_close(audio_t audio)
|
||||
da_free(audio->mix_buffers[i]);
|
||||
|
||||
da_free(audio->inputs);
|
||||
event_destroy(audio->stop_event);
|
||||
os_event_destroy(audio->stop_event);
|
||||
pthread_mutex_destroy(&audio->line_mutex);
|
||||
bfree(audio);
|
||||
}
|
||||
|
@@ -50,13 +50,13 @@ struct video_output {
|
||||
|
||||
pthread_t thread;
|
||||
pthread_mutex_t data_mutex;
|
||||
event_t stop_event;
|
||||
os_event_t stop_event;
|
||||
|
||||
struct video_data cur_frame;
|
||||
struct video_data next_frame;
|
||||
bool new_frame;
|
||||
|
||||
event_t update_event;
|
||||
os_event_t update_event;
|
||||
uint64_t frame_time;
|
||||
volatile uint64_t cur_video_time;
|
||||
|
||||
@@ -125,13 +125,13 @@ static void *video_thread(void *param)
|
||||
struct video_output *video = param;
|
||||
uint64_t cur_time = os_gettime_ns();
|
||||
|
||||
while (event_try(video->stop_event) == EAGAIN) {
|
||||
while (os_event_try(video->stop_event) == EAGAIN) {
|
||||
/* wait half a frame, update frame */
|
||||
cur_time += (video->frame_time/2);
|
||||
os_sleepto_ns(cur_time);
|
||||
|
||||
video->cur_video_time = cur_time;
|
||||
event_signal(video->update_event);
|
||||
os_event_signal(video->update_event);
|
||||
|
||||
/* wait another half a frame, swap and output frames */
|
||||
cur_time += (video->frame_time/2);
|
||||
@@ -174,9 +174,9 @@ int video_output_open(video_t *video, struct video_output_info *info)
|
||||
goto fail;
|
||||
if (pthread_mutex_init(&out->input_mutex, NULL) != 0)
|
||||
goto fail;
|
||||
if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0)
|
||||
if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0)
|
||||
goto fail;
|
||||
if (event_init(&out->update_event, EVENT_TYPE_AUTO) != 0)
|
||||
if (os_event_init(&out->update_event, OS_EVENT_TYPE_AUTO) != 0)
|
||||
goto fail;
|
||||
if (pthread_create(&out->thread, NULL, video_thread, out) != 0)
|
||||
goto fail;
|
||||
@@ -201,8 +201,8 @@ void video_output_close(video_t video)
|
||||
video_input_free(&video->inputs.array[i]);
|
||||
da_free(video->inputs);
|
||||
|
||||
event_destroy(video->update_event);
|
||||
event_destroy(video->stop_event);
|
||||
os_event_destroy(video->update_event);
|
||||
os_event_destroy(video->stop_event);
|
||||
pthread_mutex_destroy(&video->data_mutex);
|
||||
pthread_mutex_destroy(&video->input_mutex);
|
||||
bfree(video);
|
||||
@@ -342,8 +342,8 @@ bool video_output_wait(video_t video)
|
||||
{
|
||||
if (!video) return false;
|
||||
|
||||
event_wait(video->update_event);
|
||||
return event_try(video->stop_event) == EAGAIN;
|
||||
os_event_wait(video->update_event);
|
||||
return os_event_try(video->stop_event) == EAGAIN;
|
||||
}
|
||||
|
||||
uint64_t video_getframetime(video_t video)
|
||||
@@ -364,8 +364,8 @@ void video_output_stop(video_t video)
|
||||
return;
|
||||
|
||||
if (video->initialized) {
|
||||
event_signal(video->stop_event);
|
||||
os_event_signal(video->stop_event);
|
||||
pthread_join(video->thread, &thread_ret);
|
||||
event_signal(video->update_event);
|
||||
os_event_signal(video->update_event);
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,9 @@
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/time.h>
|
||||
#include <mach/semaphore.h>
|
||||
#else
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#include "bmem.h"
|
||||
@@ -45,7 +48,7 @@ int event_init(event_t *event, enum event_type type)
|
||||
return code;
|
||||
}
|
||||
|
||||
data->manual = (type == EVENT_TYPE_MANUAL);
|
||||
data->manual = (type == OS_EVENT_TYPE_MANUAL);
|
||||
data->signalled = false;
|
||||
*event = data;
|
||||
|
||||
@@ -149,3 +152,84 @@ void event_reset(event_t event)
|
||||
event->signalled = false;
|
||||
pthread_mutex_unlock(&event->mutex);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
struct os_sem_data {
|
||||
semaphore_t sem;
|
||||
task_t task;
|
||||
};
|
||||
|
||||
int os_sem_init(os_sem_t *sem, int value)
|
||||
{
|
||||
semaphore_t new_sem;
|
||||
task_t task = mach_task_self();
|
||||
|
||||
if (semaphore_create(task, &new_sem, 0, value) != KERN_SUCCESS)
|
||||
return -1;
|
||||
|
||||
*sem = bzalloc(sizeof(struct os_sem_data));
|
||||
(*sem)->sem = new_sem;
|
||||
(*sem)->task = task;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_sem_destroy(os_sem_t sem)
|
||||
{
|
||||
if (sem) {
|
||||
semaphore_destroy(sem->task, sem->sem);
|
||||
bfree(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int os_sem_post(os_sem_t sem)
|
||||
{
|
||||
if (!sem) return -1;
|
||||
return (semaphore_signal(sem->sem) == KERN_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
int os_sem_wait(os_sem_t sem)
|
||||
{
|
||||
if (!sem) return -1;
|
||||
return (semaphore_wait(sem->sem) == KERN_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct os_sem_data {
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
int os_sem_init(os_sem_t *sem, int value)
|
||||
{
|
||||
sem_t new_sem;
|
||||
int ret = sem_init(&new_sem, 0, value);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*sem = bzalloc(sizeof(struct os_sem_data));
|
||||
(*sem)->sem = new_sem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_sem_destroy(os_sem_t sem)
|
||||
{
|
||||
if (sem) {
|
||||
semaphore_destroy(&sem->sem);
|
||||
bfree(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int os_sem_post(os_sem_t sem)
|
||||
{
|
||||
if (!sem) return -1;
|
||||
return sem_post(&sem->sem);
|
||||
}
|
||||
|
||||
int os_sem_wait(os_sem_t sem)
|
||||
{
|
||||
if (!sem) return -1;
|
||||
return sem_wait(&sem->sem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -20,27 +20,31 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
struct event_data {
|
||||
struct os_event_data {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
int event_init(event_t *event, enum event_type type)
|
||||
struct os_sem_data {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
int os_event_init(os_event_t *event, enum os_event_type type)
|
||||
{
|
||||
HANDLE handle;
|
||||
struct event_data *data;
|
||||
struct os_event_data *data;
|
||||
|
||||
handle = CreateEvent(NULL, (type == EVENT_TYPE_MANUAL), FALSE, NULL);
|
||||
handle = CreateEvent(NULL, (type == OS_EVENT_TYPE_MANUAL), FALSE, NULL);
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
data = bmalloc(sizeof(struct event_data));
|
||||
data = bmalloc(sizeof(struct os_event_data));
|
||||
data->handle = handle;
|
||||
|
||||
*event = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void event_destroy(event_t event)
|
||||
void os_event_destroy(os_event_t event)
|
||||
{
|
||||
if (event) {
|
||||
CloseHandle(event->handle);
|
||||
@@ -48,7 +52,7 @@ void event_destroy(event_t event)
|
||||
}
|
||||
}
|
||||
|
||||
int event_wait(event_t event)
|
||||
int os_event_wait(os_event_t event)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
@@ -62,7 +66,7 @@ int event_wait(event_t event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_timedwait(event_t event, unsigned long milliseconds)
|
||||
int os_event_timedwait(os_event_t event, unsigned long milliseconds)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
@@ -78,7 +82,7 @@ int event_timedwait(event_t event, unsigned long milliseconds)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_try(event_t event)
|
||||
int os_event_try(os_event_t event)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
@@ -94,7 +98,7 @@ int event_try(event_t event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_signal(event_t event)
|
||||
int os_event_signal(os_event_t event)
|
||||
{
|
||||
if (!event)
|
||||
return EINVAL;
|
||||
@@ -105,10 +109,44 @@ int event_signal(event_t event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void event_reset(event_t event)
|
||||
void os_event_reset(os_event_t event)
|
||||
{
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
ResetEvent(event->handle);
|
||||
}
|
||||
|
||||
int os_sem_init(os_sem_t *sem, int value)
|
||||
{
|
||||
HANDLE handle = CreateSemaphore(NULL, (LONG)value, 0x7FFFFFFF, NULL);
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
*sem = bzalloc(sizeof(struct os_sem_data));
|
||||
(*sem)->handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_sem_destroy(os_sem_t sem)
|
||||
{
|
||||
if (sem) {
|
||||
CloseHandle(sem->handle);
|
||||
bfree(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int os_sem_post(os_sem_t sem)
|
||||
{
|
||||
if (!sem) return -1;
|
||||
return ReleaseSemaphore(sem->handle, 1, NULL) ? 0 : -1;
|
||||
}
|
||||
|
||||
int os_sem_wait(os_sem_t sem)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
if (!sem) return -1;
|
||||
ret = WaitForSingleObject(sem->handle, INFINITE);
|
||||
return (ret == WAIT_OBJECT_0) ? 0 : -1;
|
||||
}
|
||||
|
@@ -28,11 +28,9 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "../../deps/w32-pthreads/pthread.h"
|
||||
#include "../../deps/w32-pthreads/semaphore.h"
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -46,21 +44,28 @@ static inline void pthread_mutex_init_value(pthread_mutex_t *mutex)
|
||||
*mutex = init_val;
|
||||
}
|
||||
|
||||
enum event_type {
|
||||
EVENT_TYPE_AUTO,
|
||||
EVENT_TYPE_MANUAL
|
||||
enum os_event_type {
|
||||
OS_EVENT_TYPE_AUTO,
|
||||
OS_EVENT_TYPE_MANUAL
|
||||
};
|
||||
|
||||
struct event_data;
|
||||
typedef struct event_data *event_t;
|
||||
struct os_event_data;
|
||||
struct os_sem_data;
|
||||
typedef struct os_event_data *os_event_t;
|
||||
typedef struct os_sem_data *os_sem_t;
|
||||
|
||||
EXPORT int event_init(event_t *event, enum event_type type);
|
||||
EXPORT void event_destroy(event_t event);
|
||||
EXPORT int event_wait(event_t event);
|
||||
EXPORT int event_timedwait(event_t event, unsigned long milliseconds);
|
||||
EXPORT int event_try(event_t event);
|
||||
EXPORT int event_signal(event_t event);
|
||||
EXPORT void event_reset(event_t event);
|
||||
EXPORT int os_event_init(os_event_t *event, enum os_event_type type);
|
||||
EXPORT void os_event_destroy(os_event_t event);
|
||||
EXPORT int os_event_wait(os_event_t event);
|
||||
EXPORT int os_event_timedwait(os_event_t event, unsigned long milliseconds);
|
||||
EXPORT int os_event_try(os_event_t event);
|
||||
EXPORT int os_event_signal(os_event_t event);
|
||||
EXPORT void os_event_reset(os_event_t event);
|
||||
|
||||
EXPORT int os_sem_init(os_sem_t *sem, int value);
|
||||
EXPORT void os_sem_destroy(os_sem_t sem);
|
||||
EXPORT int os_sem_post(os_sem_t sem);
|
||||
EXPORT int os_sem_wait(os_sem_t sem);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Reference in New Issue
Block a user