sylware / nyanmp (public) (License: AGPLv3) (since 2020-02-12) (hash sha1)
intended to become a collection of media players for gnu/linux based on ffmpeg, alsa, vulkan, x11, wayland, etc.
List of commits:
Subject Hash Author Date (UTC)
npv:bugs, finer-grained locking, pthread_cond, etc 8bd06c28483adc9986b8b51612e609115948943d Sylvain BERTRAND 2020-05-26 23:59:16
npv: fix obvious multithread bug db4f3801c2185b8da1d9fb3f4b3da3d2ab92ea13 Sylvain BERTRAND 2020-05-24 21:42:08
remove old commented code d3701c5734aceda5c46cd5f60281cc524c55e4a3 Sylvain BERTRAND 2020-05-24 19:29:04
npv: video: handle latency spikes on main thread f629068cb27b47530058f81fc2b065b0786b4afa Sylvain BERTRAND 2020-05-24 18:11:07
npv: media pipeline 30efa7c8f2574c676d9d41b8bf5678d5725b8721 Sylvain BERTRAND 2020-05-24 17:40:23
alsa-lib warning 54b6dc9b912bb9509ba35405f15a623632adf784 Sylvain BERTRAND 2020-05-19 14:32:04
npv: proper handling of snd_pcm_drain() db7959bdd5f7ed921773aef42984b1c982575ad4 Sylvain BERTRAND 2020-05-15 15:00:13
proper handling of snd_pcm_drain() ae2c6458f893e77cd352fe9225e123bdf077e33f Sylvain BERTRAND 2020-05-15 14:46:30
after network testing: need an input thread 0c26bffd3c2268cfb9f7d8e43c7aba2fbf7fec16 Sylvain BERTRAND 2020-05-13 23:11:20
spin on futex waiting in threaded scaler e90420f459c608cbcbae423b3c487598a83de359 Sylvain BERTRAND 2020-05-13 21:05:48
npa tidying and npv addition, usable on our system 443ff39347c8b599dfaafff612caed84287f1a70 Sylvain BERTRAND 2020-05-13 15:12:15
here we go d5a2b11f4d73ec5365a340163f451fa8a123d728 Sylvain BERTRAND 2020-02-12 18:50:57
Commit 8bd06c28483adc9986b8b51612e609115948943d - npv:bugs, finer-grained locking, pthread_cond, etc
Author: Sylvain BERTRAND
Author date (UTC): 2020-05-26 23:59
Committer name: Sylvain BERTRAND
Committer date (UTC): 2020-05-26 23:59
Parent(s): db4f3801c2185b8da1d9fb3f4b3da3d2ab92ea13
Signer:
Signing key:
Signing status: N
Tree: 377fd66305abfad5815f5fc58871d0f9cd8ca39a
File Lines added Lines deleted
npv/TODO 6 5
npv/thdsws/local/code.frag.c 44 27
npv/thdsws/main.c 0 6
npv/thdsws/namespace/main.c 0 2
npv/thdsws/public/code.frag.c 31 26
npv/video/local/code.frag.c 7 8
npv/video/local/state.frag.c 2 0
npv/video/main.c 1 2
npv/video/namespace/ffmpeg.h 3 1
npv/video/public/code.frag.c 23 14
npv/video/public/state.frag.h 1 0
File npv/TODO changed (mode: 100644) (index 7fec801..ae774ef)
1 do first:make seek/end/etc work again
2
1 3 not ordered: not ordered:
2 - make seek/end/etc work again
3 4 - better/smoother/less drop/(correct?) video frame display strategy - better/smoother/less drop/(correct?) video frame display strategy
4 5 - xcb(resize)/vulkan swapchain loss or "not optimal" ? (state re-factoring) - xcb(resize)/vulkan swapchain loss or "not optimal" ? (state re-factoring)
5 6 - x11 map/unmap handling to: - x11 map/unmap handling to:
 
... ... not ordered:
18 19 - "buffering" indicator - "buffering" indicator
19 20 - subtitles - subtitles
20 21 - osd (On Screen Display) - osd (On Screen Display)
21 - use vulkan shaders (no glsl or hlsl), compute or not, in order to perform some yuvX pixel
22 formats to srgb format conversions. do NOT use the vulkan yuvX samplers as
23 they are mostly dirty hack tricks built into spirv translaters.
22 - use vulkan shaders (no glsl or hlsl), compute or not, in order to perform
23 some yuvX pixel formats to srgb format conversions. do NOT use the vulkan
24 yuvX samplers as they are mostly dirty hack tricks built into spirv
25 translaters.
24 26 - vulkan thingy for better quality down/up scaling? - vulkan thingy for better quality down/up scaling?
25 - actually off-loading alsa output and vulkan output to their thread?
File npv/thdsws/local/code.frag.c changed (mode: 100644) (index 2028789..cc7d041)
1 1 struct thdsws_ctx_private_t { struct thdsws_ctx_private_t {
2 atomic_u32 futex;
2 pthread_mutex_t mutex;
3 u8 state;
4 pthread_cond_t have_fr_to_scale;
3 5 struct SwsContext *sws; struct SwsContext *sws;
4 6 }; };
5 /* futex syscall does not have a libc wrapper */
6 static long futex(atomic_u32 *uaddr, long futex_op, long val)
7 /*NSPC*/
8 static void state_lock(struct thdsws_ctx_private_t *ctx_priv)
7 9 { {
8 return syscall(SYS_futex, uaddr, futex_op, val, 0, 0, 0);
10 int r;
11
12 r = pthread_mutex_lock(&ctx_priv->mutex);
13 if (r != 0)
14 FATALTS("unable to lock the state\n");
15 }
16 /*NSPC*/
17 static void state_unlock(struct thdsws_ctx_private_t *ctx_priv)
18 {
19 int r;
20
21 r = pthread_mutex_unlock(&ctx_priv->mutex);
22 if (r != 0)
23 FATALTS("unable to unlock the state\n");
9 24 } }
10 25 static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_priv) static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_priv)
11 26 { {
 
... ... static void do_work(struct thdsws_ctx_t *ctx, struct thdsws_ctx_private_t *ctx_p
24 39 (uint8_t*const*)&ctx->scale.dst_slice, (uint8_t*const*)&ctx->scale.dst_slice,
25 40 (int*)&ctx->scale.dst_stride); (int*)&ctx->scale.dst_stride);
26 41 } }
42 #define IDLE 0
43 #define RUNNING 1
27 44 static void worker(struct thdsws_ctx_t *ctx, static void worker(struct thdsws_ctx_t *ctx,
28 45 struct thdsws_ctx_private_t *ctx_priv) struct thdsws_ctx_private_t *ctx_priv)
29 46 { {
30 long r;
31 u32 futex_val;
32
33 errno = 0;
34 r = futex(&ctx_priv->futex, FUTEX_WAIT, IDLE);
35 if (r == -1) {
36 if (errno == EINTR || errno == EAGAIN) /* SIGSTOP/SIGCONT/etc */
37 return;
38 FATALTSW("unable to wait on futex:%s\n", strerror(errno));
47 /* on entry the state must be locked */
48 if (ctx_priv->state == RUNNING) {
49 state_unlock(ctx_priv);
50 do_work(ctx, ctx_priv);
51 state_lock(ctx_priv);
52 ctx_priv->state = IDLE;
39 53 } }
54 /* state == IDLE */
55 loop { /* spurious IDLE protection */
56 int r;
40 57
41 /* r == 0 */
42
43 /* internet says, double check for any spurious wakeup evt */
44 futex_val = atomic_load(&ctx_priv->futex);
45 if (futex_val == IDLE)
46 /* spurious wakeup */
47 return;
48 do_work(ctx, ctx_priv);
49 /*
50 * XXX: the only location where the futex gets this value, apart from
51 * _before_ the worker thread creation
52 */
53 atomic_store(&ctx_priv->futex, IDLE);
58 /* while waiting the mutex is unlocked */
59 r = pthread_cond_wait(&ctx_priv->have_fr_to_scale,
60 &ctx_priv->mutex);
61 /* on exit the mutex is locked */
62 if (r != 0)
63 FATALTSW("an error occured while waiting for a frame\n");
64 if (ctx_priv->state != IDLE)
65 break;
66 /* state == IDLE */
67 }
54 68 } }
69 #undef IDLE
70 #undef RUNNING
55 71 static void *worker_entry(void *arg) static void *worker_entry(void *arg)
56 72 { {
57 73 int r; int r;
 
... ... static void *worker_entry(void *arg)
70 86 ctx = arg; ctx = arg;
71 87 ctx_priv = ctx->private; ctx_priv = ctx->private;
72 88
73 loop worker(ctx, ctx_priv);
89 state_lock(ctx_priv);
90 loop worker(ctx, ctx_priv); /* state must be locked on entry */
74 91 } }
File npv/thdsws/main.c changed (mode: 100644) (index 25b44dd..1a7d68c)
11 11 #include <stdatomic.h> #include <stdatomic.h>
12 12 #include <unistd.h> #include <unistd.h>
13 13 #include <time.h> #include <time.h>
14 #include <sys/syscall.h>
15 #include <linux/futex.h>
16 14 #include "npv/c_fixing.h" #include "npv/c_fixing.h"
17 15 #include "npv/global.h" #include "npv/global.h"
18 16 #include "npv/thdsws/public.h" #include "npv/thdsws/public.h"
 
22 20 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
23 21 #define FATALTS(fmt, ...) FATAL("scaler:" fmt, ##__VA_ARGS__) #define FATALTS(fmt, ...) FATAL("scaler:" fmt, ##__VA_ARGS__)
24 22 #define FATALTSW(fmt, ...) FATAL("scaler worker:" fmt, ##__VA_ARGS__) #define FATALTSW(fmt, ...) FATAL("scaler worker:" fmt, ##__VA_ARGS__)
25 #define IDLE 0
26 #define BUSY 1
27 23 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
28 24 #include "npv/thdsws/local/code.frag.c" #include "npv/thdsws/local/code.frag.c"
29 25 #include "npv/thdsws/public/code.frag.c" #include "npv/thdsws/public/code.frag.c"
30 26 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
31 27 #undef FATALTS #undef FATALTS
32 28 #undef FATALTSW #undef FATALTSW
33 #undef IDLE
34 #undef BUSY
35 29 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
36 30 #define CLEANUP #define CLEANUP
37 31 #include "npv/namespace/ffmpeg.h" #include "npv/namespace/ffmpeg.h"
File npv/thdsws/namespace/main.c changed (mode: 100644) (index c964ffe..9b7fb3d)
1 1 #ifndef CLEANUP #ifndef CLEANUP
2 #define futex thdsws_futex
3 2 #define worker_entry thdsws_worker_entry #define worker_entry thdsws_worker_entry
4 3 #define worker thdsws_worker #define worker thdsws_worker
5 4 #define do_work thdsws_do_work #define do_work thdsws_do_work
6 5 #else #else
7 #undef futex
8 6 #undef worker_entry #undef worker_entry
9 7 #undef worker #undef worker
10 8 #undef do_work #undef do_work
File npv/thdsws/public/code.frag.c changed (mode: 100644) (index 2fb1bb9..92102bb)
1 #define RUNNING 1
1 2 static void thdsws_run(struct thdsws_ctx_t *ctx) static void thdsws_run(struct thdsws_ctx_t *ctx)
2 3 { {
4 int r;
3 5 struct thdsws_ctx_private_t *ctx_priv; struct thdsws_ctx_private_t *ctx_priv;
4 6
5 7 ctx_priv = ctx->private; ctx_priv = ctx->private;
6 atomic_store(&ctx_priv->futex, BUSY);
7 loop {
8 long r;
9 8
10 errno = 0;
11 r = futex(&ctx_priv->futex, FUTEX_WAKE, 1);
12 if (r == -1) {
13 if (errno == EAGAIN || errno == EINTR)
14 continue;
15 FATALTS("unable to wakeup the worker threads:%s\n", strerror(errno));
16 }
17 if (r == 1)
18 break;
19 /*
20 * r == 0 ,
21 * can happen if the worker thread is still initing and not
22 * waiting on the futex yet or the worker thread did change its
23 * state, but it is not waiting no the futex yet
24 */
25 }
9 state_lock(ctx_priv);
10 if (ctx_priv->state == RUNNING)
11 FATALTS("the worker thread is already running, did you forget to wait for it to idle\n");
12 ctx_priv->state = RUNNING;
13 state_unlock(ctx_priv);
14 r = pthread_cond_signal(&ctx_priv->have_fr_to_scale);
15 if (r != 0)
16 FATALTS("unable to signal the worker thread a frame is to be scaled\n");
26 17 } }
18 #undef RUNNING
19 #define RUNNING 1
27 20 static bool thdsws_is_busy(struct thdsws_ctx_t *ctx) static bool thdsws_is_busy(struct thdsws_ctx_t *ctx)
28 21 { {
29 22 struct thdsws_ctx_private_t *ctx_priv; struct thdsws_ctx_private_t *ctx_priv;
30 u32 futex_val;
23 bool r;
31 24
32 25 ctx_priv = ctx->private; ctx_priv = ctx->private;
33
34 futex_val = atomic_load(&ctx_priv->futex);
35 if (futex_val == IDLE)
36 return false;
37 return true;
26 state_lock(ctx_priv);
27 if (ctx_priv->state == RUNNING)
28 r = true;
29 else
30 r = false;
31 state_unlock(ctx_priv);
32 return r;
38 33 } }
34 #undef RUNNING
35 #define IDLE 0
39 36 static struct thdsws_ctx_t *thdsws_init_once(void) static struct thdsws_ctx_t *thdsws_init_once(void)
40 37 { {
41 38 int r; int r;
 
... ... static struct thdsws_ctx_t *thdsws_init_once(void)
52 49 FATALTS("unable to allocate memory for private context\n"); FATALTS("unable to allocate memory for private context\n");
53 50 ctx->private = ctx_priv; ctx->private = ctx_priv;
54 51
55 atomic_init(&ctx_priv->futex, IDLE);
52 r = pthread_mutex_init(&ctx_priv->mutex, 0);
53 if (r != 0)
54 FATALTS("unable to create the state mutex\n");
55 r = pthread_cond_init(&ctx_priv->have_fr_to_scale, 0);
56 if (r != 0)
57 FATALTS("unable to create waiting condition\n");
56 58
57 59 r = pthread_attr_init(&attr); r = pthread_attr_init(&attr);
58 60 if (r != 0) if (r != 0)
 
... ... static struct thdsws_ctx_t *thdsws_init_once(void)
62 64 if (r != 0) if (r != 0)
63 65 FATALTS("unable to set the worker thread attribute to detach mode\n"); FATALTS("unable to set the worker thread attribute to detach mode\n");
64 66
67 /* be really sure the entry state is correct _before_ thd creation */
68 ctx_priv->state = IDLE;
65 69 r = pthread_create(&worker, &attr, &worker_entry, ctx); r = pthread_create(&worker, &attr, &worker_entry, ctx);
66 70 if (r != 0) if (r != 0)
67 71 FATALTS("unable to create the worker thread\n"); FATALTS("unable to create the worker thread\n");
68 72 pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
69 73 return ctx; return ctx;
70 74 } }
75 #undef IDLE
71 76 #define TIME_UNIT_NS 1000000 /* 1ms */ #define TIME_UNIT_NS 1000000 /* 1ms */
72 77 #define TIMEOUT_UNITS_N 100 /* 100 * 1 ms = 100 ms */ #define TIMEOUT_UNITS_N 100 /* 100 * 1 ms = 100 ms */
73 78 static void thdsws_wait_for_idle(struct thdsws_ctx_t *ctx) static void thdsws_wait_for_idle(struct thdsws_ctx_t *ctx)
File npv/video/local/code.frag.c changed (mode: 100644) (index f43e609..5a0a591)
... ... static void init_once_local(void)
12 12 blit_l[i].viewport.height = -1; blit_l[i].viewport.height = -1;
13 13 ++i; ++i;
14 14 } }
15 receive_fr = avutil_video_fr_ref_alloc();
15 16 } }
16 17 static void scaler_img_create(avutil_video_fr_ref_t *fr) static void scaler_img_create(avutil_video_fr_ref_t *fr)
17 18 { {
 
... ... static void dec_a_grow(void)
243 244 /* extract a fr ref, shift the a, push it back at the e, and unref its bufs */ /* extract a fr ref, shift the a, push it back at the e, and unref its bufs */
244 245 static void fr_drop(u16 fr) static void fr_drop(u16 fr)
245 246 { {
246 struct dec_fr_priv_t *fr_priv;
247 struct dec_fr_priv_t *priv_save;
247 248 avutil_video_fr_ref_t *save; avutil_video_fr_ref_t *save;
248 249
249 fr_priv = dec_frs_p.priv_a[fr];
250 if (!fr_priv->was_qed_to_pe)
250 priv_save = dec_frs_p.priv_a[fr];
251 if (!priv_save->was_qed_to_pe)
251 252 WARNINGV("dropping undisplayed frame\n"); WARNINGV("dropping undisplayed frame\n");
252 253 save = dec_frs_p.a[fr]; save = dec_frs_p.a[fr];
253 254 avutil_video_fr_unref(save); avutil_video_fr_unref(save);
255 memset(priv_save, 0, sizeof(*priv_save));
254 256 if (dec_frs_p.n > 1) { if (dec_frs_p.n > 1) {
255 257 u16 e; u16 e;
256 258
 
... ... static void fr_drop(u16 fr)
261 263
262 264 memmove(&dec_frs_p.priv_a[fr], &dec_frs_p.priv_a[fr + 1], memmove(&dec_frs_p.priv_a[fr], &dec_frs_p.priv_a[fr + 1],
263 265 sizeof(*dec_frs_p.priv_a) * (e - (fr + 1))); sizeof(*dec_frs_p.priv_a) * (e - (fr + 1)));
264 memset(dec_frs_p.priv_a[e - 1], 0, sizeof(**dec_frs_p.priv_a));
265 } else
266 memset(dec_frs_p.priv_a[0], 0, sizeof(**dec_frs_p.priv_a));
266 dec_frs_p.priv_a[e - 1] = priv_save;
267 }
267 268 dec_frs_p.n--; dec_frs_p.n--;
268 269 } }
269 270 static void frs_drop(s64 now) static void frs_drop(s64 now)
 
... ... static void start_scaling(avutil_video_fr_ref_t *fr,
525 526 scaler_p.ctx->scale.dst_slice = scaler_p.img.data; scaler_p.ctx->scale.dst_slice = scaler_p.img.data;
526 527 scaler_p.ctx->scale.dst_stride = scaled_line_bytes_n; scaler_p.ctx->scale.dst_stride = scaled_line_bytes_n;
527 528 thdsws_run(scaler_p.ctx); thdsws_run(scaler_p.ctx);
528 dec_frs_p.being_scaled.fr = fr;
529 dec_frs_p.being_scaled.fr_priv = fr_priv;
530 529 } }
531 530 static void timer_ack(void) static void timer_ack(void)
532 531 { {
File npv/video/local/state.frag.c changed (mode: 100644) (index 90ad001..bc28f4d)
... ... struct dec_fr_priv_t {
6 6 }; };
7 7 /*===========================================================================*/ /*===========================================================================*/
8 8 static pthread_mutex_t dec_ctx_mutex_l; static pthread_mutex_t dec_ctx_mutex_l;
9 /*NSPC*/
10 static avutil_video_fr_ref_t *receive_fr;
9 11 static avcodec_codec_t *dec_l; static avcodec_codec_t *dec_l;
10 12 static struct vk_mem_rqmts_t tmp_mem_rqmts_l; static struct vk_mem_rqmts_t tmp_mem_rqmts_l;
11 13 static struct { static struct {
File npv/video/main.c changed (mode: 100644) (index 0cbd7e2..0db8fe4)
46 46 #define WARNINGVVK(fmt, ...) WARNINGVK("video:" fmt, ##__VA_ARGS__) #define WARNINGVVK(fmt, ...) WARNINGVK("video:" fmt, ##__VA_ARGS__)
47 47 #define IF_FATALVVK(fmt, ...) IF_FATALVK("video:" fmt, ##__VA_ARGS__) #define IF_FATALVVK(fmt, ...) IF_FATALVK("video:" fmt, ##__VA_ARGS__)
48 48
49 /* 4ms + ~5ms "scaling" ~ 100 frs per sec */
50 #define TIMER_INTERVAL_NSECS_N 4000000
49 #define TIMER_INTERVAL_NSECS_N 4000000 /* 4ms should be enough? */
51 50 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
52 51 #include "npv/video/local/state.frag.c" #include "npv/video/local/state.frag.c"
53 52 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
File npv/video/namespace/ffmpeg.h changed (mode: 100644) (index 36c42f1..8b25218)
1 1 #ifndef CLEANUP #ifndef CLEANUP
2 #define avutil_video_fr_ref_t AVFrame
2 #define avutil_video_fr_ref_t AVFrame
3 #define avutil_video_fr_ref_move av_frame_move_ref
3 4 /*============================================================================*/ /*============================================================================*/
4 5 #else #else
5 6 #undef avutil_video_fr_ref_t #undef avutil_video_fr_ref_t
7 #undef avutil_video_fr_ref_move
6 8 #endif #endif
File npv/video/public/code.frag.c changed (mode: 100644) (index e7b22d9..386bb83)
... ... static void timer_start(void)
82 82 static u8 dec_fr_try_receive(void) static u8 dec_fr_try_receive(void)
83 83 { {
84 84 int r; int r;
85 u16 fr;
86 85
87 if (dec_frs_p.eof_receive)
88 return EOF_DEC;
89 if (dec_frs_p.n == dec_frs_p.n_max)
90 dec_a_grow();
91 fr = dec_frs_p.n;
92 r = avcodec_receive_video_fr(dec_ctx_p, dec_frs_p.a[fr]);
86 dec_ctx_lock();
87 r = avcodec_receive_video_fr(dec_ctx_p, receive_fr);
88 dec_ctx_unlock();
93 89 if (r == AVUTIL_AVERROR(EAGAIN)) if (r == AVUTIL_AVERROR(EAGAIN))
94 90 return AGAIN; return AGAIN;
95 91 else if (r == 0) { else if (r == 0) {
96 memset(dec_frs_p.priv_a[fr], 0, sizeof(**dec_frs_p.priv_a));
92 u16 last;
93
94 dec_frs_lock();
95 if (dec_frs_p.n == dec_frs_p.n_max)
96 dec_a_grow();
97 last = dec_frs_p.n;
98 avutil_video_fr_ref_move(dec_frs_p.a[last], receive_fr);
99 memset(dec_frs_p.priv_a[last], 0, sizeof(**dec_frs_p.priv_a));
97 100 ++dec_frs_p.n; ++dec_frs_p.n;
101 dec_frs_unlock();
98 102 return HAVE_FR; return HAVE_FR;
99 103 } else if (r == AVUTIL_AVERROR_EOF) { } else if (r == AVUTIL_AVERROR_EOF) {
100 104 POUTVFF("last decoder frame reached (receiving)\n"); POUTVFF("last decoder frame reached (receiving)\n");
105 dec_frs_lock();
101 106 dec_frs_p.eof_receive = true; dec_frs_p.eof_receive = true;
107 dec_frs_unlock();
102 108 return EOF_DEC; return EOF_DEC;
103 109 } }
104 110 FATALVFF("error while receiving frame from the decoder\n"); FATALVFF("error while receiving frame from the decoder\n");
 
... ... static void dec_frs_receive_avail(void) { loop
113 119 { {
114 120 u8 r; u8 r;
115 121
116 dec_frs_lock();
117 dec_ctx_lock();
118 122 r = dec_fr_try_receive(); r = dec_fr_try_receive();
119 dec_ctx_unlock();
120 dec_frs_unlock();
121 123 if (r == HAVE_FR) if (r == HAVE_FR)
122 124 continue; continue;
123 125 else if (r == AGAIN || r == EOF_DEC) else if (r == AGAIN || r == EOF_DEC)
 
... ... static void dec_frs_unlock(void)
174 176 #define TS_FROM_CLK_OK 0 #define TS_FROM_CLK_OK 0
175 177 #define READY 0 #define READY 0
176 178 #define NOT_READY 1 #define NOT_READY 1
177 /* XXX: we do want to lock the frs q the least amount of time as possible */
179 /*
180 * XXX: we do want to lock the frs q the least amount of time as possible. but
181 * the main thd seems to have too much latency for the video output. may
182 * need to move the video output to its own thd in the end.
183 */
178 184 static void timer_evt(void) static void timer_evt(void)
179 185 { {
180 186 u8 r; u8 r;
 
... ... static void timer_evt(void)
207 213 return; return;
208 214 scaler_is_busy = thdsws_is_busy(scaler_p.ctx); scaler_is_busy = thdsws_is_busy(scaler_p.ctx);
209 215 if (!scaler_is_busy) { if (!scaler_is_busy) {
216 /* the fr which was scaled may not be the selected one */
210 217 if (dec_frs_p.being_scaled.fr != NO_FR) { if (dec_frs_p.being_scaled.fr != NO_FR) {
211 218 dec_frs_p.being_scaled.fr_priv->is_scaled = true; dec_frs_p.being_scaled.fr_priv->is_scaled = true;
212 219 dec_frs_p.being_scaled.fr = NO_FR; dec_frs_p.being_scaled.fr = NO_FR;
213 220 } }
214 221 } }
215 if (!fr_priv->is_scaled) {
222 if (!fr_priv->is_scaled) { /* the selected fr */
216 223 if (scaler_is_busy) if (scaler_is_busy)
217 224 return; return;
218 225 start_scaling(fr, fr_priv, &scaler_dims_changed); start_scaling(fr, fr_priv, &scaler_dims_changed);
226 dec_frs_p.being_scaled.fr = fr;
227 dec_frs_p.being_scaled.fr_priv = fr_priv;
219 228 return; return;
220 229 } }
221 230 r = swpchn_next_img(&swpchn_img); r = swpchn_next_img(&swpchn_img);
File npv/video/public/state.frag.h changed (mode: 100644) (index 7918f89..1517464)
... ... static struct {
30 30 } dec_frs_p; } dec_frs_p;
31 31 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
32 32 static struct { static struct {
33 pthread_mutex_t mutex;
33 34 struct { struct {
34 35 struct vk_img_t *vk; struct vk_img_t *vk;
35 36 struct vk_subrsrc_layout_t layout; struct vk_subrsrc_layout_t layout;
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/sylware/nyanmp

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/sylware/nyanmp

Clone this repository using git:
git clone git://git.rocketgit.com/user/sylware/nyanmp

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main