Commit Graph

699 Commits (11106c2fce391d522c5bed9a3379c09a3a964b2b)

Author SHA1 Message Date
jp9000 11106c2fce libobs: Redesign/optimize frame encoding handling
Previously, the design for the interaction between the encoder thread
and the graphics thread was that the encoder thread would signal to the
graphics thread when to start drawing each frame.  The original idea
behind this was to prevent mutually cascading stalls of encoding or
graphics rendering (i.e., if rendering took too long, then encoding
would have to catch up, then rendering would have to catch up again, and
so on, cascading upon each other).  The ultimate goal was to prevent
encoding from impacting graphics and vise versa.

However, eventually it was realized that there were some fundamental
flaws with this design.

1. Stray frame duplication.  You could not guarantee that a frame would
   render on time, so sometimes frames would unintentionally be lost if
   there was any sort of minor hiccup or if the thread took too long to
   be scheduled I'm guessing.

2. Frame timing in the rendering thread was less accurate.  The only
   place where frame timing was accurate was in the encoder thread, and
   the graphics thread was at the whim of thread scheduling.  On higher
   end computers it was typically fine, but it was just generally not
   guaranteed that a frame would be rendered when it was supposed to be
   rendered.

So the solution (originally proposed by r1ch and paibox) is to instead
keep the encoding and graphics threads separate as usual, but instead of
the encoder thread controlling the graphics thread, the graphics thread
now controls the encoder thread.  The encoder thread keeps a limited
cache of frames, then the graphics thread copies frames in to the cache
and increments a semaphore to schedule the encoder thread to encode that
data.

In the cache, each frame has an encode counter.  If the frame cache is
full (e.g., the encoder taking too long to return frames), it will not
cache a new frame, but instead will just increment the counter on the
last frame in the cache to schedule that frame to encode again, ensuring
that frames are on time and reducing CPU usage by lowering video
complexity.  If the graphics thread takes too long to render a frame,
then it will add that frame with the count value set to the total amount
of frames that were missed (actual legitimately duplicated frames).

Because the cache gives many frames of breathing room for the encoder to
encode frames, this design helps improve results especially when using
encoding presets that have higher complexity and CPU usage, minimizing
the risk of needlessly skipped or duplicated frames.

I also managed to sneak in what should be a bit of an optimization to
reduce copying of frame data, though how much of an optimization it
ultimately ends up being is debatable.

So to sum it up, this commit increases accuracy of frame timing,
completely removes stray frame duplication, gives better results for
higher complexity encoding presets, and potentially optimizes the frame
pipeline a tiny bit.
2014-12-31 04:03:47 -08:00
jp9000 11dd7912ce libobs: Fix bug with frame output handling
The boolean variables which stored whether frames have been
rendered/downloaded/converted/etc were not being reset when video
restarted, causing frames to not be sent in the correct order whenever
video was reset.  This could lead to minor desync of video/audio.
2014-12-31 04:03:46 -08:00
jp9000 244280335b libobs: Fix potential crash on output stop
In certain circumstances where the output was stopping, and where data
took a long enough time to send (such as when using an encoding preset
that causes high CPU usage), the output would sometimes still send data
even after it was stopped, typically causing the output to crash.
2014-12-31 04:03:45 -08:00
jp9000 8e1549820b libobs/media-io: Add frame copying function 2014-12-31 04:03:45 -08:00
jp9000 5d0551eb27 libobs/media-io: Add #pragma once to video-frame.h 2014-12-31 04:03:44 -08:00
jp9000 caa6251054 libobs: Fix force mono channel count
I unintentionally made it use obs_source::sample_info instead of using
the actual target channel count, which is designated by the OBS output
sampler info.  obs_source::sample_info is actually used to indicate the
currently set sampler information for incoming samples.  So if a source
is outputting 5.1 channel 48khz audio, and OBS is running at stereo
44.1khz, then the obs_source::sample_info value would be set to
5.1/48khz, not the other way around.  It indicates what the source
itself is running at, not what OBS is running at.

I suppose the variable needs a better name because even I used it
incorrectly despite actually having been the one who wrote it.
2014-12-28 03:51:06 -08:00
jp9000 ce6a1146cc libobs: Remove inline on a function
The copy_audio_data function really shouldn't be inlined because it's
being called twice.  It's somewhat unnecessary, I think I left it inline
by accident.
2014-12-28 01:51:55 -08:00
jp9000 63c43b649d libobs: Add flag to force source audio to mono
This flag is actually useful under a number of circumstances, and has
been requested a number of times.
2014-12-28 01:51:55 -08:00
jp9000 c431ac6aa5 libobs: Refactor source volume transition design
This changes the way source volume handles transitioning between being
active and inactive states.

The previous way that transitioning handled volume was that it set the
presentation volume of the source and all of its sub-sources to 0.0 if
the source was inactive, and 1.0 if active.  Transition sources would
then also set the presentation volume for sub-sources to whatever their
transitioning volume was.  However, the problem with this is that the
design didn't take in to account if the source or its sub-sources were
active anywhere else, so because of that it would break if that ever
happened, and I didn't realize that when I was designing it.

So instead, this completely overhauls the design of handling
transitioning volume.  Each frame, it'll go through all sources and
check whether they're active or inactive and set the base volume
accordingly.  If transitions are currently active, it will actually walk
the active source tree and check whether the source is in a
transitioning state somewhere.

 - If the source is a sub-source of a transition, and it's not active
   outside of the transition, then the transition will control the
   volume of the source.

 - If the source is a sub-source of a transition, but it's also active
   outside of the transition, it'll defer to whichever is louder.

This also adds a new callback to the obs_source_info structure for
transition sources, get_transition_volume, which is called to get the
transitioning volume of a sub-source.
2014-12-28 01:51:43 -08:00
jp9000 10f8988667 libobs: Keep transition reference counter
The reason to keep a reference counter for transitions is due to an
optimization I'm planning on when calculating transition volumes.  I'm
planning on walking the source tree to be able to calculate the current
base volume of a source, but *only* if there are transitions active,
because the only time that the volume can be anything other than 1.0
or 0.0 is when there are active transitions, which may change the base
volume of a source.
2014-12-28 01:04:29 -08:00
jp9000 6eab6ceff5 (API Change) libobs: Add _FLAG to source flags
Changes OBS_SOURCE_UNBUFFERED to OBS_SOURCE_FLAG_UNBUFFERED to make
naming a bit better for source flags.
2014-12-28 01:04:28 -08:00
jp9000 fb09db432f libobs: Save/load source audio sync and flags
When a source is being saved, include the audio sync as well as the
flags.
2014-12-28 01:04:28 -08:00
jp9000 48210d41a6 libobs: Do not set presentation volume on children
When the presentation volume is set for a source, it's set for all of
its children and their children.  The original intention for doing this
was to be able to use it for transitioning, but honestly it's just bad
design, and I feel there are better ways to handle transitioning volume.
2014-12-28 01:04:27 -08:00
jp9000 fb6f8721e2 libobs: Add 'audio_sync' source signal
Adds a signal is called when the sync offset has changed for a source.
2014-12-28 01:04:27 -08:00
jp9000 e29a1fd367 libobs: Prevent infinite source recursion
Changed the design from using obs_source::enum_refs to just simply
preventing infinite source recursion in general, rather than allowing it
through the enum_refs variable.  obs_source_add_child has been changed
so that it now returns a boolean, and if the function fails, it means
that the child cannot be added due to that potential recursion.
2014-12-28 01:04:26 -08:00
jp9000 1ed4c2a920 libobs: Remove unused audio level source vars
These variables are no longer used by sources anymore, as they were
removed in favor of the new source audio control handlers.
2014-12-28 01:04:26 -08:00
jp9000 c72284f387 libobs: Fix a few warnings
Two integers are needlessly converted to floating points for what should
be an integer operation.  One of those floats is then used for another
integer operation later, where the original integer value should have
been used.  So essentially there was an int -> float -> int conversion
going on, which could lead to potential loss of data due to floating
point precision.

There were also some general 64bit -> 32bit conversion warnings.
2014-12-28 01:03:10 -08:00
jp9000 5875434afa libobs: Implement obs_source_active
..Apparently I left this function unimplemented.  This function just
returns whether a source is currently active or not.
2014-12-24 15:55:38 -08:00
jp9000 78c2129f31 libobs: Fix export declaration name
obs_encoder_getdisplayname declaration was not changed to match the
definition (obs_encoder_get_display_name) when the API consistency
update occurred.
2014-12-24 15:55:37 -08:00
Jim 9f3ab85d2b Merge pull request #311 from fryshorts/audio-analyzer-move
libobs: Move audio level calculations
2014-12-21 11:56:02 -08:00
jp9000 1a95004fe8 libobs: Fix bug when SEI not present
If an encoder did not possess any SEI data, it would never send data at
all because the sent_first_packet wasn't set despite the first packet
being sent.
2014-12-21 10:14:23 -08:00
jp9000 9f97b02c32 libobs: Add function to determine AVC keyframes
Added obs_avc_keyframe that returns whether an avc packet is a keyframe
or not.  This function is particularly useful for when writing custom
encoder plugins.
2014-12-21 10:14:22 -08:00
jp9000 f8e56a4e1e libobs: Expose NAL enums in obs-avc.h
I encountered some cases where I needed to use these enumerations
outside of the file, so this allows other modules to use AVC
enumerations without having to redefine them each time.  Especially
useful for custom encoder modules.
2014-12-21 10:14:21 -08:00
jp9000 923916ecce libobs: Use extern "C" on export headers if C++
I neglected to surround some files with extern "C", so if something
written with C++ used the files it would cause function exports to not
be mangled by it correctly.
2014-12-21 10:14:21 -08:00
jp9000 c52406c178 libobs/media-io: Fix recursive lock in video
In certain cases the video thread could end up trying to lock itself
recursively.  This just allows the mutexes to safely be locked
recursively.
2014-12-21 10:14:19 -08:00
jp9000 817a724dea libobs: Add NV12_Reverse shader 2014-12-21 10:14:18 -08:00
jp9000 488cd84f6f libobs: Set version to 0.7.0 2014-12-15 01:55:18 -08:00
jp9000 c88220552f (API Change) libobs: Add bicubic/lanczos scaling
This adds bicubic and lanczos scaling capability to libobs to improve
scaling quality and sharpness when the output resolution has to be
scaled relative to the base resolution.  Bilinear is also available,
although bilinear has rather poor quality and causes scaling to appear
blurry.

If the output resolution is close to the base resolution, then bilinear
is used instead as an optimization, as there's no need to use these
shaders if scaling is not in use.

The Bicubic and Lanczos effects are also exposed via exported function
to allow the ability to use those shaders in plugin modules if desired.

The API change adds a variable 'scale_type' to the obs_video_info
structure that allows the user interface to choose what type of scaling
filter should be used.
2014-12-15 01:55:12 -08:00
fryshorts 73883e6fa8 libobs: Remove volume level signal from obs_source
Remove the calculation of volume levels and the corresponding signal
from obs_source since this is now handled in the volume meter.
Code that is interested in the volume levels can either use the
volmeter provided from obs_audio_controls or use the audio_data signal
to gain access to the raw audio data.
2014-12-14 18:39:54 +01:00
fryshorts c0e6324278 libobs: Signal own levels in volmeter
Signal updated volume levels when they become available in the volume
meter. The frequency of the updates can be adjusted by setting a
different update interval.
2014-12-14 18:39:54 +01:00
fryshorts 94445ddba2 libobs: Remove audio levels handler from volmeter
Remove the the signal handler for the volume_level signal of audio
sources from the volume meter in anticipation of using the levels
calculated in the volume meter itself.
2014-12-14 18:39:54 +01:00
fryshorts 6e0c1533fc libobs: Add level calculations to volmeter
Use the new audio_data signal from sources to calculate the volume
levels in the volume meter.
2014-12-14 18:39:54 +01:00
fryshorts 63399bbfd8 libobs: Add peak hold property to volmeter
Add a property to the volume meter that specifies the time for which
peak value should be held until it is reset.
2014-12-14 18:39:54 +01:00
fryshorts e0ce484b81 libobs: Add update interval property to volmeter
Add a property to the volume meter that specifies the length of the
interval in which the audio data should be sampled before the
audio_levels signal is emitted.
2014-12-14 18:39:28 +01:00
fryshorts 984dd53389 libobs: Add data signal to audio sources
This adds a new signal to (audio) sources which is emitted whenever new
audio data is received from the source. This enables other code that is
interested in the raw audio data to directly access it when it becomes
available.
2014-12-13 14:10:45 +01:00
jp9000 b07862286a (API Change) Add colorspace info to obs_video_info
This was an important change because we were originally using an
hard-coded 709/partial range color matrix for the output, which was
causing problems for people wanting to use different formats or color
spaces.  This will now automatically generate the color matrix depending
on the format, color space, and range, or use an identity matrix if the
video format is RGB instead of YUV.
2014-12-11 19:51:30 -08:00
jp9000 59c4731aa6 libobs/media-io: Add colorspace to video info
This is useful for keeping track of what the current colorspace/range is
if a YUV format is being used.
2014-12-11 19:47:51 -08:00
jp9000 a69524a271 libobs: Add obs_property_list_insert_* functions
These functions allow you to insert items at a specific index in a list
instead of being forced to always append to the end.
2014-12-09 14:21:02 -08:00
jp9000 ca8a9fb5a7 libobs: Fix conversion shader D3D display bug
Just for a quick background: D3D's fmod intrinsic is very imprecise.
Naturally floating points aren't precise at all, and when the numbers
you're dealing with become very large, it can often be off by 0.1 or
more.

However, apparently 0.1 isn't enough of an offset to ensure a proper
value when using the fmod intrinsic and then flooring the value.  0.2
seems to fix the issue and make the image display properly.
2014-12-09 14:21:01 -08:00
jp9000 87ac9c91bc libobs: Add flush to video pipeline
On certain GPUs, if you don't flush and the window is minimized it can
endlessly accumulate memory due to what I'm assuming are driver design
flaws (though I can't know for sure).  The flush seems to prevent this
from happening, at least from my tests.  It would be nice if this
weren't necessary.
2014-12-07 23:15:13 -08:00
Jim fe6622c653 Merge pull request #306 from fryshorts/volume-meter-improvements
Volume meter improvements
2014-12-07 22:51:21 -08:00
fryshorts 014a333807 obs/libobs: Use new volume meter api
This replaces the old code for the audio meter that was using
calculations in two different places with the new audio meter api.
The source signal will now emit simple levels instead of dB values,
in order to avoid dB conversion and calculation in the source.
The GUI on the other hand now expects simple position values from
the volume meter api with no knowledge about dB calculus either.
That way all code that handles those conversions is in one place,
with the option to easily add new mappings that can be used
everywhere.
2014-12-04 21:58:35 +01:00
fryshorts 1b034569f0 libobs: Add Logarithmic fader type
This adds the conversion function used by the old obs based on a
logarithmic scale.
2014-12-04 21:58:35 +01:00
fryshorts 119d77e176 libobs: Add IEC 60-268-18 compliant fader type
This adds a new fader type that implements a position/dB mapping
as specified in IEC 60-268-18.
2014-12-04 21:58:34 +01:00
fryshorts 46686ec556 libobs: Add volume meter object
This adds a volume meter object to libobs that can be used by the GUI
or plugins to convert the raw audio level data from sources to values
that can easily be used to display the audio data.
The volume meter object will use the same mapping functions as the
fader object to map dB levels to a scale.
2014-12-04 21:58:34 +01:00
Nicolas F 486b1082d2 libobs: Use FFmpeg for image loading by default 2014-12-04 15:38:58 +01:00
jp9000 346bcd7e48 libobs: Fix microsoft compiler issue
In older versions of visual studio 2013 microsoft's WORTHLESS C compiler
has a bug where it will, almost at random, not be able to handle having
variables declared in the middle of a function and give the warning:
"illegal use of this type as an expression".  It was fixed in recent
VS2013 updates, but I'm not about to force everyone to update to it.
2014-11-27 11:05:36 -08:00
jp9000 c8dfce886b libobs: Fix warnings assigning values to vec3
Because a vec3 structure can contain a __m128 variable and not the
expected three floats x, y, and z, you must use vec3_set when
setting a value for a vec3 structure to ensure that it uses the proper
intrinsics internally if necessary.
2014-11-27 00:07:49 -08:00
jp9000 8922f2503f libobs: Fix double -> float conversion warning 2014-11-27 00:07:49 -08:00
jp9000 e3e79dcdc5 libobs: Fix windows warnings with C library macro
The macro INFINITY apparently will trigger a warning with microsoft's
compiler despite being a C standard library macro.
2014-11-27 00:07:48 -08:00