Fix drawing bug with async video sources

Before, async video sources would flicker because they were only being
drawn when they were updated.  So when updated, they'd draw that frame,
then it would stop drawing it until it updated again.  This fixes that
issue and they should now draw properly.

Also, fix a few other minor bugs and issues relating to async video,
and make it so that non-async video filters can be properly applied to
them.

For the purposes of testing, change the 'test-random' source to an async
video source that updates every quarter of a second with a new random
face.

Also fix a bug where non-async video sources wouldn't have filter
effects applied properly.
This commit is contained in:
jp9000
2014-04-13 02:22:28 -07:00
parent bc33b09ba9
commit 2451b80ef6
5 changed files with 156 additions and 98 deletions

View File

@@ -1,8 +1,13 @@
#include <stdlib.h>
#include <util/threading.h>
#include <util/platform.h>
#include <obs.h>
struct random_tex {
texture_t texture;
obs_source_t source;
os_event_t stop_signal;
pthread_t thread;
bool initialized;
};
static const char *random_getname(const char *locale)
@@ -16,19 +21,18 @@ static void random_destroy(void *data)
struct random_tex *rt = data;
if (rt) {
gs_entercontext(obs_graphics());
if (rt->initialized) {
os_event_signal(rt->stop_signal);
pthread_join(rt->thread, NULL);
}
texture_destroy(rt->texture);
os_event_destroy(rt->stop_signal);
bfree(rt);
gs_leavecontext();
}
}
static void *random_create(obs_data_t settings, obs_source_t source)
static inline void fill_texture(uint32_t *pixels)
{
struct random_tex *rt = bzalloc(sizeof(struct random_tex));
uint32_t *pixels = bmalloc(20*20*4);
size_t x, y;
for (y = 0; y < 20; y++) {
@@ -41,53 +45,62 @@ static void *random_create(obs_data_t settings, obs_source_t source)
pixels[y*20 + x] = pixel;
}
}
}
gs_entercontext(obs_graphics());
static void *video_thread(void *data)
{
struct random_tex *rt = data;
uint32_t pixels[20*20];
uint64_t cur_time = os_gettime_ns();
rt->texture = gs_create_texture(20, 20, GS_RGBA, 1,
(const void**)&pixels, 0);
bfree(pixels);
struct source_frame frame = {
.data = {[0] = (uint8_t*)pixels},
.linesize = {[0] = 20*4},
.width = 20,
.height = 20,
.format = VIDEO_FORMAT_BGRX
};
if (!rt->texture) {
while (os_event_try(rt->stop_signal) == EAGAIN) {
fill_texture(pixels);
frame.timestamp = cur_time;
obs_source_output_video(rt->source, &frame);
os_sleepto_ns(cur_time += 250000000);
}
return NULL;
}
static void *random_create(obs_data_t settings, obs_source_t source)
{
struct random_tex *rt = bzalloc(sizeof(struct random_tex));
rt->source = source;
if (os_event_init(&rt->stop_signal, OS_EVENT_TYPE_MANUAL) != 0) {
random_destroy(rt);
return NULL;
}
gs_leavecontext();
if (pthread_create(&rt->thread, NULL, video_thread, rt) != 0) {
random_destroy(rt);
return NULL;
}
rt->initialized = true;
UNUSED_PARAMETER(settings);
UNUSED_PARAMETER(source);
return rt;
}
static void random_video_render(void *data, effect_t effect)
{
struct random_tex *rt = data;
eparam_t image = effect_getparambyname(effect, "image");
effect_settexture(effect, image, rt->texture);
gs_draw_sprite(rt->texture, 0, 0, 0);
}
static uint32_t random_getwidth(void *data)
{
struct random_tex *rt = data;
return texture_getwidth(rt->texture);
}
static uint32_t random_getheight(void *data)
{
struct random_tex *rt = data;
return texture_getheight(rt->texture);
}
struct obs_source_info test_random = {
.id = "random",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO,
.output_flags = OBS_SOURCE_ASYNC_VIDEO,
.getname = random_getname,
.create = random_create,
.destroy = random_destroy,
.video_render = random_video_render,
.getwidth = random_getwidth,
.getheight = random_getheight
};