v4l2: drop frames for those dequeued buffer with error flag
Some frames are dequeued with error flag, which may cause AV unsync if decoder does not drop them as soon as possible. So add "output-error-dequeued" and "capture-error-dequeued" signal for v4l2 to drop such frames. Fixes #3031 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5479>
This commit is contained in:
parent
3f0808a910
commit
bf87ad72e4
@ -80,6 +80,15 @@ enum _GstV4l2BufferState
|
||||
BUFFER_STATE_QUEUED = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
OUTPUT_ERROR_DEQUEUED,
|
||||
CAPTURE_ERROR_DEQUEUED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint gst_v4l2_buffer_pool_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void gst_v4l2_buffer_pool_complete_release_buffer (GstBufferPool * bpool,
|
||||
GstBuffer * buffer, gboolean queued);
|
||||
|
||||
@ -1279,6 +1288,16 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
|
||||
GST_LOG_OBJECT (pool, "dequeueing a buffer");
|
||||
|
||||
res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group);
|
||||
|
||||
if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {
|
||||
if (V4L2_TYPE_IS_OUTPUT (obj->type))
|
||||
g_signal_emit (pool, gst_v4l2_buffer_pool_signals[OUTPUT_ERROR_DEQUEUED],
|
||||
0, (guint) group->buffer.timestamp.tv_sec);
|
||||
else
|
||||
g_signal_emit (pool, gst_v4l2_buffer_pool_signals[CAPTURE_ERROR_DEQUEUED],
|
||||
0, (guint) group->buffer.timestamp.tv_sec);
|
||||
}
|
||||
|
||||
if (res == GST_V4L2_FLOW_LAST_BUFFER)
|
||||
goto eos;
|
||||
if (res != GST_FLOW_OK)
|
||||
@ -1765,6 +1784,14 @@ gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
|
||||
bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
|
||||
bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
|
||||
|
||||
gst_v4l2_buffer_pool_signals[OUTPUT_ERROR_DEQUEUED] =
|
||||
g_signal_new ("output-error-dequeued", G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||
|
||||
gst_v4l2_buffer_pool_signals[CAPTURE_ERROR_DEQUEUED] =
|
||||
g_signal_new ("capture-error-dequeued", G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (v4l2bufferpool_debug, "v4l2bufferpool", 0,
|
||||
"V4L2 Buffer Pool");
|
||||
GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
|
||||
|
@ -180,6 +180,16 @@ gst_v4l2_video_dec_close (GstVideoDecoder * decoder)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_v4l2_video_dec_drop_frame (GstVideoDecoder * decoder, guint frame_number)
|
||||
{
|
||||
GstVideoCodecFrame *frame =
|
||||
gst_video_decoder_get_frame (decoder, frame_number);
|
||||
|
||||
if (frame)
|
||||
gst_video_decoder_drop_frame (decoder, frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_dec_start (GstVideoDecoder * decoder)
|
||||
{
|
||||
@ -538,6 +548,9 @@ use_acquired_caps:
|
||||
if (!active)
|
||||
goto activate_failed;
|
||||
|
||||
g_signal_connect_swapped (self->v4l2capture->pool, "capture-error-dequeued",
|
||||
G_CALLBACK (gst_v4l2_video_dec_drop_frame), decoder);
|
||||
|
||||
return TRUE;
|
||||
|
||||
not_negotiated:
|
||||
@ -1004,6 +1017,9 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||
if (!gst_buffer_pool_set_active (pool, TRUE))
|
||||
goto activate_failed;
|
||||
|
||||
g_signal_connect_swapped (self->v4l2output->pool, "output-error-dequeued",
|
||||
G_CALLBACK (gst_v4l2_video_dec_drop_frame), decoder);
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
|
||||
processed ? frame->system_frame_number : 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user