libobs: Don't use source flags for async buffering

(This commit also modifies the decklink, linux-v4l2, mac-avcapture,
obs-ffmpeg, and win-dshow modules)

Originally, async buffering for sources was supposed to be a
user-controllable flag.  However, that turned out to be less than ideal
because sources (such as the win-dshow plugin) were programmed with
automatic control over their buffering (such as automatically detecting
USB 2.0 capture devices and then enabling in those cases).

The fact that it was a flag caused a design flaw to where buffering
values would be overwritten when a source is loaded from save data.

Because of that, this flag is being deprecated and replaced with a
specific function to enable unbuffered mode instead.
This commit is contained in:
jp9000 2017-05-13 23:32:40 -07:00
parent d64542e10b
commit d13fa96851
9 changed files with 30 additions and 30 deletions

View File

@ -608,6 +608,7 @@ struct obs_source {
bool async_flip; bool async_flip;
bool async_active; bool async_active;
bool async_update_texture; bool async_update_texture;
bool async_unbuffered;
struct obs_source_frame *async_preload_frame; struct obs_source_frame *async_preload_frame;
DARRAY(struct async_frame) async_cache; DARRAY(struct async_frame) async_cache;
DARRAY(struct obs_source_frame*)async_frames; DARRAY(struct obs_source_frame*)async_frames;

View File

@ -27,7 +27,7 @@ static bool ready_deinterlace_frames(obs_source_t *source, uint64_t sys_time)
uint64_t frame_offset = 0; uint64_t frame_offset = 0;
size_t idx = 1; size_t idx = 1;
if ((source->flags & OBS_SOURCE_FLAG_UNBUFFERED) != 0) { if (source->async_unbuffered) {
while (source->async_frames.num > 2) { while (source->async_frames.num > 2) {
da_erase(source->async_frames, 0); da_erase(source->async_frames, 0);
remove_async_frame(source, next_frame); remove_async_frame(source, next_frame);

View File

@ -2602,7 +2602,7 @@ static bool ready_async_frame(obs_source_t *source, uint64_t sys_time)
uint64_t frame_time = next_frame->timestamp; uint64_t frame_time = next_frame->timestamp;
uint64_t frame_offset = 0; uint64_t frame_offset = 0;
if ((source->flags & OBS_SOURCE_FLAG_UNBUFFERED) != 0) { if (source->async_unbuffered) {
while (source->async_frames.num > 1) { while (source->async_frames.num > 1) {
da_erase(source->async_frames, 0); da_erase(source->async_frames, 0);
remove_async_frame(source, next_frame); remove_async_frame(source, next_frame);
@ -4020,3 +4020,17 @@ enum obs_monitoring_type obs_source_get_monitoring_type(
return obs_source_valid(source, "obs_source_get_monitoring_type") ? return obs_source_valid(source, "obs_source_get_monitoring_type") ?
source->monitoring_type : OBS_MONITORING_TYPE_NONE; source->monitoring_type : OBS_MONITORING_TYPE_NONE;
} }
void obs_source_set_async_unbuffered(obs_source_t *source, bool unbuffered)
{
if (!obs_source_valid(source, "obs_source_set_async_unbuffered"))
return;
source->async_unbuffered = unbuffered;
}
bool obs_source_async_unbuffered(const obs_source_t *source)
{
return obs_source_valid(source, "obs_source_async_unbuffered") ?
source->async_unbuffered : false;
}

View File

@ -834,8 +834,8 @@ EXPORT bool obs_source_active(const obs_source_t *source);
*/ */
EXPORT bool obs_source_showing(const obs_source_t *source); EXPORT bool obs_source_showing(const obs_source_t *source);
/** Specifies that async video frames should be played as soon as possible */ /** Unused flag */
#define OBS_SOURCE_FLAG_UNBUFFERED (1<<0) #define OBS_SOURCE_FLAG_UNUSED_1 (1<<0)
/** Specifies to force audio to mono */ /** Specifies to force audio to mono */
#define OBS_SOURCE_FLAG_FORCE_MONO (1<<1) #define OBS_SOURCE_FLAG_FORCE_MONO (1<<1)
@ -1100,6 +1100,10 @@ EXPORT uint64_t obs_source_get_audio_timestamp(const obs_source_t *source);
EXPORT void obs_source_get_audio_mix(const obs_source_t *source, EXPORT void obs_source_get_audio_mix(const obs_source_t *source,
struct obs_source_audio_mix *audio); struct obs_source_audio_mix *audio);
EXPORT void obs_source_set_async_unbuffered(obs_source_t *source,
bool unbuffered);
EXPORT bool obs_source_async_unbuffered(const obs_source_t *source);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Transition-specific functions */ /* Transition-specific functions */
enum obs_transition_target { enum obs_transition_target {

View File

@ -31,12 +31,7 @@ static DeckLinkDeviceDiscovery *deviceEnum = nullptr;
static void decklink_enable_buffering(DeckLink *decklink, bool enabled) static void decklink_enable_buffering(DeckLink *decklink, bool enabled)
{ {
obs_source_t *source = decklink->GetSource(); obs_source_t *source = decklink->GetSource();
uint32_t flags = obs_source_get_flags(source); obs_source_set_async_unbuffered(source, !enabled);
if (enabled)
flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
else
flags |= OBS_SOURCE_FLAG_UNBUFFERED;
obs_source_set_flags(source, flags);
} }
static void *decklink_create(obs_data_t *settings, obs_source_t *source) static void *decklink_create(obs_data_t *settings, obs_source_t *source)

View File

@ -912,11 +912,8 @@ fail:
static void v4l2_update_source_flags(struct v4l2_data *data, static void v4l2_update_source_flags(struct v4l2_data *data,
obs_data_t *settings) obs_data_t *settings)
{ {
uint32_t flags = obs_source_get_flags(data->source); obs_source_set_async_unbuffered(data->source,
flags = (obs_data_get_bool(settings, "buffering")) !obs_data_get_bool(settings, "buffering"));
? flags & ~OBS_SOURCE_FLAG_UNBUFFERED
: flags | OBS_SOURCE_FLAG_UNBUFFERED;
obs_source_set_flags(data->source, flags);
} }
/** /**

View File

@ -645,13 +645,7 @@ static inline bool update_frame(av_capture *capture,
static void av_capture_enable_buffering(av_capture *capture, bool enabled) static void av_capture_enable_buffering(av_capture *capture, bool enabled)
{ {
obs_source_t *source = capture->source; obs_source_set_async_unbuffered(capture->source, !enabled);
uint32_t flags = obs_source_get_flags(source);
if (enabled)
flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
else
flags |= OBS_SOURCE_FLAG_UNBUFFERED;
obs_source_set_flags(source, flags);
} }
static const char *av_capture_getname(void*) static const char *av_capture_getname(void*)

View File

@ -273,14 +273,14 @@ static void ffmpeg_source_update(void *data, obs_data_t *settings)
input_format = NULL; input_format = NULL;
s->is_looping = obs_data_get_bool(settings, "looping"); s->is_looping = obs_data_get_bool(settings, "looping");
obs_source_set_flags(s->source, OBS_SOURCE_FLAG_UNBUFFERED); obs_source_set_async_unbuffered(s->source, true);
} else { } else {
input = (char *)obs_data_get_string(settings, "input"); input = (char *)obs_data_get_string(settings, "input");
input_format = (char *)obs_data_get_string(settings, input_format = (char *)obs_data_get_string(settings,
"input_format"); "input_format");
s->is_looping = false; s->is_looping = false;
obs_source_set_flags(s->source, 0); obs_source_set_async_unbuffered(s->source, false);
} }
s->input = input ? bstrdup(input) : NULL; s->input = input ? bstrdup(input) : NULL;

View File

@ -753,12 +753,7 @@ inline void DShowInput::SetupBuffering(obs_data_t *settings)
else else
useBuffering = bufType == BufferingType::On; useBuffering = bufType == BufferingType::On;
if (useBuffering) obs_source_set_async_unbuffered(source, !useBuffering);
flags &= ~OBS_SOURCE_FLAG_UNBUFFERED;
else
flags |= OBS_SOURCE_FLAG_UNBUFFERED;
obs_source_set_flags(source, flags);
} }
static DStr GetVideoFormatName(VideoFormat format); static DStr GetVideoFormatName(VideoFormat format);