Hi,
i found deadlock in v4l2 h264 encoder nonblocking api. I need to stop encoder, at any time, and the data to enter the encoder does not come immediately. For this abort and usleep. Reproduced if you start several times and stop in the middle using ctrl-c
bt
(gdb) bt
#0 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x55a33e3848) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
#1 __pthread_cond_wait_common (abstime=0x0, mutex=0x55a33e37f0, cond=0x55a33e3820) at pthread_cond_wait.c:502
#2 __pthread_cond_wait (cond=0x55a33e3820, mutex=0x55a33e37f0) at pthread_cond_wait.c:655
#3 0x0000007fa390ffdc in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libnvos.so
#4 0x0000007fa0e6db08 in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so
#5 0x0000007fa0e27c34 in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite.so
#6 0x0000007fa0eb4e2c in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
#7 0x0000007fa0ea76fc in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
#8 0x0000007fa0eab810 in ?? () from /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
#9 0x0000007fa0e9f960 in TegraV4L2_Ioctl () from /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
#10 0x0000007fa387ae78 in plugin_ioctl () from /usr/lib/aarch64-linux-gnu/libv4l/plugins/nv/libv4l2_nvvideocodec.so
#11 0x0000007fa42a15c0 in v4l2_ioctl () from /usr/lib/aarch64-linux-gnu/libv4l2.so.0
#12 0x0000005588624f60 in NvV4l2ElementPlane::setStreamStatus(bool) ()
#13 0x000000558862b4d4 in NvV4l2Element::abort() ()
#14 0x00000055885eb5f0 in encoder_proc_nonblocking(context_t&, bool) ()
#15 0x00000055885eec1c in encode_proc(context_t&, int, char**) ()
#16 0x00000055885ef500 in main ()
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7fa38af9b0 (LWP 18395) "EncCapPlane" __pthread_cond_wait (cond=0x55a33e3820, mutex=0x55a33e37f0) at pthread_cond_wait.c:655
2 Thread 0x7fa34ea1d0 (LWP 18396) "video_encode" 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x55a338b788)
at ../sysdeps/unix/sysv/linux/futex-internal.h:88
3 Thread 0x7fa2ce91d0 (LWP 18397) "video_encode" 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x55a338b758)
at ../sysdeps/unix/sysv/linux/futex-internal.h:88
4 Thread 0x7f9e83f1d0 (LWP 18398) "V4L2_EncThread" 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0,
futex_word=0x55a33a830c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
5 Thread 0x7f9e03e1d0 (LWP 18399) "EncPollThread" 0x0000007fa43c19c8 in futex_abstimed_wait_cancelable (private=0, abstime=0x0, expected=0,
futex_word=0x558864c2b8 <ctx+568>) at ../sysdeps/unix/sysv/linux/futex-internal.h:205
6 Thread 0x7f97fff1d0 (LWP 18400) "NVMVidEncInputT" 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0,
futex_word=0x55a33e38bc) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
7 Thread 0x7f977fe1d0 (LWP 18401) "V4L2_EncThread" 0x0000007fa43bf22c in futex_wait_cancelable (private=<optimized out>, expected=0,
futex_word=0x55a33e27bc) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
part
info proc mapping
0x7fa0e5b000 0x7fa0e8a000 0x2f000 0x0 /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so
0x7fa0e8a000 0x7fa0e9a000 0x10000 0x2f000 /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so
0x7fa0e9a000 0x7fa0e9b000 0x1000 0x2f000 /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so
0x7fa0e9b000 0x7fa0e9d000 0x2000 0x30000 /usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so
0x7fa0e9d000 0x7fa0ec9000 0x2c000 0x0 /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
0x7fa0ec9000 0x7fa0ed8000 0xf000 0x2c000 /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
0x7fa0ed8000 0x7fa0ed9000 0x1000 0x2b000 /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
0x7fa0ed9000 0x7fa0eda000 0x1000 0x2c000 /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
jetson tx2 8Gb
l4t # R32 (release), REVISION: 4.3, GCID: 21589087, BOARD: t186ref, EABI: aarch64, DATE: Fri Jun 26 04:34:27 UTC 2020
./video_encode source.yuv 1280 720 H264 dst.h264 --blocking-mode 0
Patch video_encode sample
# diff -ruN samples/01_video_encode/video_encode_main.cpp.orig samples/01_video_encode/video_encode_main.cpp
--- samples/01_video_encode/video_encode_main.cpp.orig 2020-07-15 17:28:23.281784416 +0300
+++ samples/01_video_encode/video_encode_main.cpp 2020-07-15 18:24:35.215037494 +0300
@@ -35,6 +35,8 @@
#include <string.h>
#include <fcntl.h>
#include <poll.h>
+#include <unistd.h>
+#include <signal.h>
#include "nvbuf_utils.h"
#include "video_encode.h"
@@ -547,6 +549,7 @@
ctx->endf = 0;
ctx->num_output_buffers = 6;
ctx->num_frames_to_encode = -1;
+ ctx->stop = false;
}
/**
@@ -814,12 +817,21 @@
{
/* Call SetPollInterrupt */
ctx.enc->SetPollInterrupt();
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
/* Since buffers have been queued, issue a post to start polling and
then wait here */
sem_post(&ctx.pollthread_sema);
sem_wait(&ctx.encoderthread_sema);
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
+
/* Already end of file, no more queue-dequeue for output plane */
if (eos)
goto check_capture_buffers;
@@ -849,6 +861,11 @@
abort(&ctx);
return -1;
}
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
+
/* Get the parsed encoder runtime parameters */
if (ctx.runtime_params_str &&
@@ -859,6 +876,12 @@
if (ctx.runtime_params_str)
get_next_runtime_param_change_frame(&ctx);
}
+ usleep(500);
+
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
/* Read yuv frame data from input file */
if (read_video_frame(ctx.in_file, *outplane_buffer) < 0 || ctx.num_frames_to_encode == 0)
@@ -1006,6 +1029,11 @@
abort(&ctx);
return -1;
}
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
+
if(ctx.num_frames_to_encode > 0)
{
ctx.num_frames_to_encode--;
@@ -1043,6 +1071,11 @@
abort(&ctx);
return -1;
}
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
+
/* Invoke encoder capture-plane deque buffer callback */
capture_dq_continue = encoder_capture_plane_dq_callback(&v4l2_capture_buf, capplane_buffer, NULL,
@@ -1053,6 +1086,11 @@
ctx.got_eos = true;
return 0;
}
+ if (ctx.stop) {
+ ctx.enc->abort();
+ break;
+ }
+
}
}
@@ -2071,6 +2109,18 @@
return -error;
}
+/* create encoder context. */
+context_t ctx;
+
+void hdnl(int sig) {
+ cerr << "siganal " << sig << endl;
+ if (ctx.enc) {
+ cerr << "abort " << endl;
+ ctx.stop = true;
+ }
+}
+
+
/**
* Start of video Encode application.
*
@@ -2080,11 +2130,10 @@
int
main(int argc, char *argv[])
{
- /* create encoder context. */
- context_t ctx;
int ret = 0;
/* save encode iterator number */
int iterator_num = 0;
+ signal(SIGINT, &hdnl);
do
{
--- samples/01_video_encode/video_encode.h.orig 2020-07-15 18:41:31.816189379 +0300
+++ samples/01_video_encode/video_encode.h 2020-07-15 17:56:28.885867902 +0300
@@ -158,6 +158,7 @@
sem_t encoderthread_sema; // Encoder thread waits on this to be signalled to continue q/dq loop
pthread_t enc_pollthread; // Polling thread, created if running in non-blocking mode.
pthread_t enc_capture_loop; // Encoder capture thread
+ bool stop;
} context_t;