0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 13:08:50 +02:00

obs-outputs: Fix frame dropping when using ultrafast

x264 on ultrafast won't drop any b-frames, so it might buffer packets a
bit too much in that case.

The frame drop duration calculation now searches for the first valid
video frame within the packets buffer.  Additionally, it no longer
prevents frame dropping for a specific time after dropping frames,
because the first case eliminates the need for that.
This commit is contained in:
jp9000 2017-04-24 09:00:28 -07:00
parent 585b3ed945
commit d1329d1798
2 changed files with 23 additions and 15 deletions

View File

@ -798,7 +798,6 @@ static bool init_connect(struct rtmp_stream *stream)
os_atomic_set_bool(&stream->disconnected, false);
stream->total_bytes_sent = 0;
stream->dropped_frames = 0;
stream->min_drop_dts_usec= 0;
stream->min_priority = 0;
settings = obs_output_get_settings(stream->output);
@ -876,7 +875,6 @@ static inline bool add_packet(struct rtmp_stream *stream,
{
circlebuf_push_back(&stream->packets, packet,
sizeof(struct encoder_packet));
stream->last_dts_usec = packet->dts_usec;
return true;
}
@ -886,7 +884,7 @@ static inline size_t num_buffered_packets(struct rtmp_stream *stream)
}
static void drop_frames(struct rtmp_stream *stream, const char *name,
int highest_priority, int64_t *p_min_dts_usec)
int highest_priority, bool pframes)
{
struct circlebuf new_buf = {0};
uint64_t last_drop_dts_usec = 0;
@ -922,8 +920,8 @@ static void drop_frames(struct rtmp_stream *stream, const char *name,
if (stream->min_priority < highest_priority)
stream->min_priority = highest_priority;
*p_min_dts_usec = last_drop_dts_usec;
if (!num_frames_dropped)
return;
stream->dropped_frames += num_frames_dropped;
#ifdef _DEBUG
@ -934,6 +932,23 @@ static void drop_frames(struct rtmp_stream *stream, const char *name,
#endif
}
static bool find_first_video_packet(struct rtmp_stream *stream,
struct encoder_packet *first)
{
size_t count = stream->packets.size / sizeof(*first);
for (size_t i = 0; i < count; i++) {
struct encoder_packet *cur = circlebuf_data(&stream->packets,
i * sizeof(*first));
if (cur->type == OBS_ENCODER_VIDEO && !cur->keyframe) {
*first = *cur;
return true;
}
}
return false;
}
static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
{
struct encoder_packet first;
@ -942,9 +957,6 @@ static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
const char *name = pframes ? "p-frames" : "b-frames";
int priority = pframes ?
OBS_NAL_PRIORITY_HIGHEST : OBS_NAL_PRIORITY_HIGH;
int64_t *p_min_dts_usec = pframes ?
&stream->pframe_min_drop_dts_usec :
&stream->min_drop_dts_usec;
int64_t drop_threshold = pframes ?
stream->pframe_drop_threshold_usec :
stream->drop_threshold_usec;
@ -955,10 +967,7 @@ static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
return;
}
circlebuf_peek_front(&stream->packets, &first, sizeof(first));
/* do not drop frames if frames were just dropped within this time */
if (first.dts_usec < *p_min_dts_usec)
if (!find_first_video_packet(stream, &first))
return;
/* if the amount of time stored in the buffered packets waiting to be
@ -972,7 +981,7 @@ static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes)
if (buffer_duration_usec > drop_threshold) {
debug("buffer_duration_usec: %" PRId64, buffer_duration_usec);
drop_frames(stream, name, priority, p_min_dts_usec);
drop_frames(stream, name, priority, pframes);
}
}
@ -991,6 +1000,7 @@ static bool add_video_packet(struct rtmp_stream *stream,
stream->min_priority = 0;
}
stream->last_dts_usec = packet->dts_usec;
return add_packet(stream, packet);
}

View File

@ -72,9 +72,7 @@ struct rtmp_stream {
/* frame drop variables */
int64_t drop_threshold_usec;
int64_t min_drop_dts_usec;
int64_t pframe_drop_threshold_usec;
int64_t pframe_min_drop_dts_usec;
int min_priority;
float congestion;