Reduces GPU usage when encoding is not active. Does not perform color
conversion, frame staging, or frame downloading unless encoding is
explicitly active.
During packet interleaving (for outputs), ensure that if two packets
coincide with the same timestamp, that the video packet always comes
first instead of the audio packet.
This fix is required to make FLV demux properly with certain demuxers;
some FLV demuxers expect the video packet before the audio packet when
two packets coincide with the same timestamps.
(This commit also modifies the obs-outputs module)
The first video packet video offset (the value used to set the starting
point of video data) would be set to the DTS value of the first video
packet. However, when b-frames are used, the first DTS value will be
negative. This was originally done because FLV muxing requires that the
first packet's DTS start from 0. Unfortunately, this would also
effectively cause the first packet's PTS/DTS value to be shifted forward
by the negative amount, which would cause video sync to be off by a
video frame or two.
This fixes it to start at the PTS value instead and preserve any
negative offsets. Additionally, the FLV muxing code has been fixed to
ensure that it adjusts the starting video DTS to 0, and now correctly
adjusts the first audio packet's timestamp according to that DTS as well
(which it didn't do before).
Instead of logging the relative encoded count (which is susceptible to
integer overflow), log the output frame count instead. If there's an
issue with encoding, it'll show up when all encoding stops regardless.
This reverts commit 4e3e67bb8c.
The way this is handled will erroneously report 0 frames encoded when
frames have actually been properly encoded, which is best avoided.
Additionally, and overflow would be generated for drawn frames where
none occurred before. The encoded value should probably not even be
present in the log for the output due to the way it's handled.
I believe the issue with the next to impossible frame count to be an integer underflow, as in order to achieve those you'd have to have recorded for at least 345 days with 144 fps. So this commit fixes them by using a normal integer first and then deciding on the result if it should be used or be replaced with a 0.
When an output fails to connect and it's already been prematurely
stopped, the event to mark the output as stopped would not be signaled,
causing obs_output_destroy to lock up indefinitely while waiting for the
event to be signaled.
Rather than have the back-end try to determine whether the output can or
cannot stop, allow the stop callback to continue in the plugin either
way and let the plugin itself make that determination.
This fixes a bug where the back-end wouldn't have data active while
connecting, therefore the stop callback wouldn't be called, and once
connected it wouldn't know that it was supposed to stop. In other words
trying to call obs_output_stop on an output that was in a state of
connecting would do nothing and the output would never stop.
When frames are skipped the skipped frame count would increment, but the
total frame count would not increment, causing the percentage
calculation to fail.
Additionally, the skipped frames log reporting has been moved to
media-io/video-io.c instead of each output.
Captions do something unusual with encoder packets: they reallocate them
due to appending extra h.264 data. Due to the way allocations are
handled with core encoder packets (they now store a reference in their
data), instead of modifying the encoder data directly, create a new
encoder packet instead and release the old packet.
When an output's context data is being created, it cannot register any
hotkeys because the output has not initialized its reference counting
capability. This is due to the fact that when a hotkey is registered,
it creates a weak reference to the source/output/service/encoder.
The solution to this is to make sure the output's reference counter data
is created before calling the create callback.
Allow outputs to force a stop even when already in the process of
stopping. If for example a stream is heavily congested and taking a
very long time to stop, this allows frontends to give the users the
option to forcibly stop the stream to make it stop as quickly as
possible.
(Note: This commit also modifies coreaudio-encoder, win-capture, and
win-mf modules)
This reduces logging to the user's log file. Most of the things
specified are not useful for examining log files, and make reading log
files more painful.
The things that are useful to log should be up to the front-end to
implement. The core and core plugins should have minimal mandatory
logging.
This fixes an design flaw where a delayed output would schedule a
stop even while in the process of reconnecting instead of just shutting
down right away.
When obs_output_actual_stop is called on shutdown, it should wait for
the output to fully stop before doing anything, and then it should wait
for the data capture to end. The service should not be removed until
after the output has stopped, otherwise it could result in a possible
memory leak on stop. Packets should be freed last.
(Note: This commit also modifies obs-ffmpeg and obs-outputs)
API Changed:
obs_output_info::void (*stop)(void *data);
To:
obs_output_info::void (*stop)(void *data, uint64_t ts);
This fixes the long-time design flaw where obs_output_stop and the
output 'stop' callback would just shut down the output without
considering the timing of when obs_output_stop was used, discarding any
possible buffering and causing the output to get cut off at an
unexpected timing.
The 'stop' callback of obs_output_info now takes a timestamp with the
expectation that the output will use that timestamp to stop output data
in accordance to that timing. obs_output_stop now records the timestamp
at the time that the function is called and calls the 'stop' callback
with that timestamp. If needed, obs_output_force_stop will still stop
the output immediately without buffering.
On outputs that use already-active video/audio encoder, the audio
pruning to sync up audio packets with video packets doesn't always get
called (for example if the video pruning function was called). Always
prune excess starting audio packets.
If audio buffering is very high, the audio packets built up in the
interleaved buffer would be significantly before the first video packet,
causing the offset between the starting video/audio packet pairs to be
significantly off, leading to desync.
This issue was not spotted until recently because it only happens when
streaming/recording with same encoders while audio buffering is very
high.
When starting a multi-track output, attempt to pair the video encoder
with one of the audio encoders to ensure that the video and audio
encoders start as close together in time as possible. This ensures the
best possible audio/video syncing point when using multi-track audio
output.
When using multi-track audio, encoders cannot be paired like they can
when only using a single audio track with video, so it has to choose the
best point in the interleaved buffer as the "starting point", and if the
encoders start up at different times, it has to prune that data and wait
to start the output on the next video keyframe. When the audio encoders
started up, there was the case where the encoders would take some time
to load, and it would cause the pruning code to wait for the next
keyframe to ensure startup syncing.
Starting the audio encoders before starting the video encoder should
reduce the possibility of that happening in a multi-track scenario.
In a multi-track scenario it was not taking in to consideration the
possibility of secondary audio tracks, which could have caused desync on
some of the audio tracks.
Problem:
When an output is started with encoders that have already been started
by another output, and it starts in between the window in between where
the first audio packets start coming in and where the first video packet
comes in, the output would get audio packets with timestamps potentially
much later than the first video frame when the first video frame finally
comes in. The audio/video encoders will almost always have a differing
delay.
Solution:
Detect that starting window, and if within that starting window, wait
for a new keyframe from video instead of trying to sync up video.
Additional Notes:
In these cases where an output starts with already-active encoders, this
patch also reduces the potential sync offset between the first video
frame and the first audio frame. Before, it would sync the first video
frame with the first audio frames right after that, but now it syncs
with the closest audio frame in the interleaved array, which halves the
potential sync difference between the first video frame and the first
audio frame of already-active encoders. (So now the potential sync
difference is roughly 11.6 milliseconds at 44.1khz audio, where it was
23.2 before)
API changed from:
obs_source_info::get_name(void)
obs_output_info::get_name(void)
obs_encoder_info::get_name(void)
obs_service_info::get_name(void)
API changed to:
obs_source_info::get_name(void *type_data)
obs_output_info::get_name(void *type_data)
obs_encoder_info::get_name(void *type_data)
obs_service_info::get_name(void *type_data)
This allows the type data to be used when getting the name of the
object (useful for plugin wrappers primarily).
NOTE: Though a parameter was added, this is backward-compatible with
older plugins due to calling convention. The new parameter will simply
be ignored by older plugins, and the stack (if used) will be cleaned up
by the caller.