mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
decklinkvideosink: Don't schedule too late frames in prepare()
Otherwise we will overflow the internal buffer of the hardware with useless frames and run into an error. This is necessary until this bug in basesink is fixed: https://bugzilla.gnome.org/show_bug.cgi?id=742916
This commit is contained in:
parent
7b979703f8
commit
92fa187d11
2 changed files with 54 additions and 14 deletions
|
@ -272,6 +272,7 @@ gst_decklink_video_sink_prepare (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
GstClockTime timestamp, duration;
|
||||
GstClockTime running_time, running_time_duration;
|
||||
gint i;
|
||||
GstClock *clock;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Preparing buffer %p", buffer);
|
||||
|
||||
|
@ -280,6 +281,57 @@ gst_decklink_video_sink_prepare (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||
duration = GST_BUFFER_DURATION (buffer);
|
||||
if (duration == GST_CLOCK_TIME_NONE) {
|
||||
duration =
|
||||
gst_util_uint64_scale_int (GST_SECOND, self->info.fps_d,
|
||||
self->info.fps_n);
|
||||
}
|
||||
running_time =
|
||||
gst_segment_to_running_time (&GST_BASE_SINK_CAST (self)->segment,
|
||||
GST_FORMAT_TIME, timestamp);
|
||||
running_time_duration =
|
||||
gst_segment_to_running_time (&GST_BASE_SINK_CAST (self)->segment,
|
||||
GST_FORMAT_TIME, timestamp + duration) - running_time;
|
||||
|
||||
// FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=742916
|
||||
// We need to drop late buffers here immediately instead of
|
||||
// potentially overflowing the internal queue of the hardware
|
||||
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
||||
if (clock) {
|
||||
GstClockTime clock_running_time, latency;
|
||||
|
||||
clock_running_time = gst_element_get_base_time (GST_ELEMENT_CAST (self));
|
||||
if (clock_running_time != GST_CLOCK_TIME_NONE) {
|
||||
clock_running_time = gst_clock_get_time (clock) - clock_running_time;
|
||||
latency = gst_base_sink_get_latency (GST_BASE_SINK_CAST (self));
|
||||
|
||||
if (clock_running_time > running_time + running_time_duration + latency) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Late buffer: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (clock_running_time),
|
||||
GST_TIME_ARGS (running_time + running_time_duration));
|
||||
|
||||
if (self->last_render_time == GST_CLOCK_TIME_NONE
|
||||
|| (self->last_render_time < clock_running_time
|
||||
&& clock_running_time - self->last_render_time >= GST_SECOND)) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Rendering frame nonetheless because we had none for more than 1s");
|
||||
running_time = clock_running_time;
|
||||
running_time_duration = 0;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (self, "Dropping frame");
|
||||
gst_object_unref (clock);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_unref (clock);
|
||||
}
|
||||
self->last_render_time = running_time;
|
||||
|
||||
ret = self->output->output->CreateVideoFrame (self->info.width,
|
||||
self->info.height, self->info.stride[0], bmdFormat8BitYUV,
|
||||
bmdFrameFlagDefault, &frame);
|
||||
|
@ -304,20 +356,6 @@ gst_decklink_video_sink_prepare (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
}
|
||||
gst_video_frame_unmap (&vframe);
|
||||
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||
duration = GST_BUFFER_DURATION (buffer);
|
||||
if (duration == GST_CLOCK_TIME_NONE) {
|
||||
duration =
|
||||
gst_util_uint64_scale_int (GST_SECOND, self->info.fps_d,
|
||||
self->info.fps_n);
|
||||
}
|
||||
running_time =
|
||||
gst_segment_to_running_time (&GST_BASE_SINK_CAST (self)->segment,
|
||||
GST_FORMAT_TIME, timestamp);
|
||||
running_time_duration =
|
||||
gst_segment_to_running_time (&GST_BASE_SINK_CAST (self)->segment,
|
||||
GST_FORMAT_TIME, timestamp + duration) - running_time;
|
||||
|
||||
convert_to_internal_clock (self, &running_time, &running_time_duration);
|
||||
|
||||
GST_LOG_OBJECT (self, "Scheduling video frame %p at %" GST_TIME_FORMAT
|
||||
|
@ -507,6 +545,7 @@ gst_decklink_video_sink_change_state (GstElement * element,
|
|||
gst_element_post_message (element,
|
||||
gst_message_new_clock_provide (GST_OBJECT_CAST (element),
|
||||
self->output->clock, TRUE));
|
||||
self->last_render_time = GST_CLOCK_TIME_NONE;
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
|
||||
GstClock *clock, *audio_clock;
|
||||
|
|
|
@ -56,6 +56,7 @@ struct _GstDecklinkVideoSink
|
|||
|
||||
GstClockTime internal_base_time;
|
||||
GstClockTime external_base_time;
|
||||
GstClockTime last_render_time;
|
||||
|
||||
GstDecklinkOutput *output;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue