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:trying to work around nasty live streams 544ddd3381ad56363bb275ae59419e97e8c86895 Sylvain BERTRAND 2021-05-14 15:45:19
npv:spurious braces e8678920198c6795420c54a839b92e5d301b4183 Sylvain BERTRAND 2021-05-06 20:55:38
npv:pts debug tracing, ffmpeg dev tantrum 8c3bf9cf42fc3419b64c232f905c5c580d6a1942 Sylvain BERTRAND 2021-05-06 18:37:35
npa: forgot zero-ing before cmp ceff7a70798b604bdb876a92ba0c446e3ede8a5b Sylvain BERTRAND 2021-04-15 20:15:07
npv: namespace love cb385e293aeb094073963c46022f3c430b6bf9c1 Sylvain BERTRAND 2021-01-16 18:37:11
conservative handling of vulkan linear filtering 7736b342c3566ac3ffa7a83ff1c7985e5595265f Sylvain BERTRAND 2021-01-15 18:18:02
npv: spurious AND faulty image creation flag e7d0d4e9efa15781b323cd092989bc0b95331875 Sylvain BERTRAND 2021-01-15 02:01:16
npa: buffering 9b2ec327646a289dae3e4cbb31b4857bf612d7e2 Sylvain BERTRAND 2020-11-06 17:20:56
npa: tons of love 68a79110ca4a6f5bdb41ed90e421b6f46c1c1877 Sylvain BERTRAND 2020-11-06 15:20:13
npv: spurious unsigned 5b4e039ffd921438a37112f0b4108480366f4d6d Sylvain BERTRAND 2020-11-06 04:31:18
npv: backward discontinuity handling 0fc81a53996993992dd86a96a26afd2aab0ac366 Sylvain BERTRAND 2020-09-25 16:14:26
npv: more monotonic, more pts discontinuity 1ab37ad2a24ca8f9fbf6d51eac8f996bd2eefacf Sylvain BERTRAND 2020-09-25 01:34:41
npv: workaround a mesa bug (which leads to linux state corruption) 780e5bec0b90a9e931778cf68fec62a7c5241c13 Sylvain BERTRAND 2020-09-23 15:57:25
npv: fix filter time base handling, prepare discontinuity support 2b7347be805d17a2b6f06e276e897c51431b9c6c Sylvain BERTRAND 2020-09-22 17:38:46
npv: correct coarse sync of vulkan image acquisition a9b52940ff2d567dc6c26b28d86eab54f5876819 Sylvain BERTRAND 2020-09-20 22:00:32
npv: fix channel layout handling and a tad more 88f74f181a567d108874a936fe3d306d34cfefb7 Sylvain BERTRAND 2020-09-19 23:12:04
npv: dynamic audio filter configuration d8a0ff688ddb2abcde22c01a2ae52ea74e9f0f2f Sylvain BERTRAND 2020-09-19 20:54:04
npv:protection against tantrum of media audio 78589150b7c6f1f3cae49b4b4bc8b572c6d8e6b7 Sylvain BERTRAND 2020-09-18 15:26:17
npv/npa:finish to workaround null channel layout 314788563e01d7ffb364a1775ba68619ee3f6c5c Sylvain BERTRAND 2020-09-15 22:50:57
npv: handle empty channel layout 5b5794fc4d5300b671b684a2f41196f66bd1fc4a Sylvain BERTRAND 2020-09-15 22:11:07
Commit 544ddd3381ad56363bb275ae59419e97e8c86895 - npv:trying to work around nasty live streams
Author: Sylvain BERTRAND
Author date (UTC): 2021-05-14 15:45
Committer name: Sylvain BERTRAND
Committer date (UTC): 2021-05-14 15:45
Parent(s): e8678920198c6795420c54a839b92e5d301b4183
Signer:
Signing key:
Signing status: N
Tree: b511bf163ebbaae2b0e56612c8dcc74093c98f8f
File Lines added Lines deleted
npv/TODO 1 10
npv/config.h 8 5
npv/pipeline/local/code.frag.c 9 2
npv/video/local/code.frag.c 57 45
npv/video/local/state.frag.c 0 4
npv/video/namespace/main.c 0 2
npv/video/public/code.frag.c 3 0
npv/video/public/state.frag.h 5 0
File npv/TODO changed (mode: 100644) (index 1e32934..90608f3)
1 1 not ordered: not ordered:
2 - some live streams can have the audio and video unsynced up to 10 seconds with
3 missing tons of video frames.
4 To support those rare and horrible streams, what seems to be a reasonable
5 work around:
6 - always presume monotonic decoding of frames, monotonic as presentation
7 order, not pts monotonic.
8 - once the array of frames reached a specified limit, do buffer the
9 video demuxed packets.
10 - it would means that outside of transient discontinuity handling,
11 usually based on the audio, only the "too old" frames would be dropped.
2 - try to workaround as much as possible the nasty live streams out there.
12 3 - "buffering" indicator (no)? subtitles (mmmmh...)? - "buffering" indicator (no)? subtitles (mmmmh...)?
13 4 - use vulkan shaders (no glsl or hlsl), compute or not, in order to perform - use vulkan shaders (no glsl or hlsl), compute or not, in order to perform
14 5 some yuvX pixel formats to srgb format conversions. do NOT use the vulkan some yuvX pixel formats to srgb format conversions. do NOT use the vulkan
File npv/config.h changed (mode: 100644) (index 54fc3c1..090af26)
... ... struct npv_x11_bind_t npv_x11_binds[] = {
72 72 #define SEEK_DELTA_BIG (INT64_C(4) * INT64_C(60)) /* 4 minutes */ #define SEEK_DELTA_BIG (INT64_C(4) * INT64_C(60)) /* 4 minutes */
73 73 /*============================================================================*/ /*============================================================================*/
74 74 /* kinky internal settings, modify with care */ /* kinky internal settings, modify with care */
75 /* the count of decoded video frames in the array, it is "expensive" */
75 /*
76 * The targeted count of decoded video frames in the array (while not
77 * resyncing). Decoded frames are "memory expensive".
78 */
76 79 #define DEC_FRS_ARRAY_N_MAX 4 #define DEC_FRS_ARRAY_N_MAX 4
77 80 /* /*
78 81 * video frames are presumed arriving inorder, but once a backward * video frames are presumed arriving inorder, but once a backward
79 * discontinuity is detected, in order to avoid a full and dead locked array of
80 * predecoded video frames, we must drop frames until we resynchronize. To
81 * decide if we found a resynchronzining frame, we define a time window based
82 * on the following value
82 * discontinuity is detected, in order to avoid a full/dead locked array of
83 * predecoded video frames, we unlock the size of array of decoded frames until
84 * we "resynchronize". To decide if we found a resynchronizing frame, we define
85 * a time window based on the following value.
83 86 */ */
84 87 #define DISCONT_BACKWARD_RESYNC_MS 500 #define DISCONT_BACKWARD_RESYNC_MS 500
85 88 #endif #endif
File npv/pipeline/local/code.frag.c changed (mode: 100644) (index bef6d57..aac6b3d)
... ... STATIC bool have_enough_predecoded_video_frs(void)
153 153 npv_video_dec_frs_lock(); npv_video_dec_frs_lock();
154 154 if (npv_video_dec_frs_p.eof_receive) { if (npv_video_dec_frs_p.eof_receive) {
155 155 r = true; r = true;
156 } else if (npv_video_dec_frs_p.n < DEC_FRS_ARRAY_N_MAX) {
156 } else if (npv_video_dec_frs_p.discont_backward.resyncing)
157 /*
158 * We are looking for a "resyncing" fr, and to secure we
159 * receive one, we must decode more frs or the dec frs a
160 * may endup full and dead locked.
161 */
157 162 r = false; r = false;
158 } else /* >= 4 */
163 else if (npv_video_dec_frs_p.n < DEC_FRS_ARRAY_N_MAX) {
164 r = false;
165 } else /* >= DEC_FRS_ARRAY_N_MAX && ! RESYNCING */
159 166 r = true; r = true;
160 167 npv_video_dec_frs_unlock(); npv_video_dec_frs_unlock();
161 168 return r; return r;
File npv/video/local/code.frag.c changed (mode: 100644) (index d6f7e54..20a1a18)
... ... STATIC void init_once_local(void)
76 76 } }
77 77 receive_fr_l = avutil_video_fr_ref_alloc(); receive_fr_l = avutil_video_fr_ref_alloc();
78 78 is_swpchn_sem_fence_submitted_l = false; is_swpchn_sem_fence_submitted_l = false;
79 drop_l.prev_now = AV_NOPTS_VALUE;
80 drop_l.until_resync = false;
81 79 } }
82 80 #undef NONE #undef NONE
83 81 STATIC void scaler_img_create(avutil_video_fr_ref_t *fr) STATIC void scaler_img_create(avutil_video_fr_ref_t *fr)
 
... ... STATIC void fr_drop(u16 fr)
336 334 STATIC void frs_drop(s64 now, avutil_video_fr_ref_t *selected_fr) STATIC void frs_drop(s64 now, avutil_video_fr_ref_t *selected_fr)
337 335 { {
338 336 u16 fr; u16 fr;
339 s64 lo;
340 s64 hi;
341 s64 resync;
342 337
343 338 if (selected_fr == NO_FR) if (selected_fr == NO_FR)
344 goto exit;
345 /* backward discont detected */
346 if (drop_l.prev_now != AV_NOPTS_VALUE && now < drop_l.prev_now)
347 drop_l.until_resync = true;
348 /*====================================================================*/
339 return;
340 #ifdef NPV_DEBUG
341 if (npv_debug_p)
342 npv_perr("DEBUG:%s:selected_fr.pts=%ld\n", __func__, selected_fr->pts);
343 #endif
349 344 /* /*
350 345 * since the frs are supposed inorder, first drop as many of as possible * since the frs are supposed inorder, first drop as many of as possible
351 346 * frs received before the selected one * frs received before the selected one
 
... ... STATIC void frs_drop(s64 now, avutil_video_fr_ref_t *selected_fr)
362 357 } else } else
363 358 ++fr; ++fr;
364 359 } }
365 /*====================================================================*/
366 /*
367 * here, we detected a backward discont, we are looking for a
368 * resynchronizing fr based on a time win. we must drop, inorder,
369 * frs which are out of the time win in order to avoid the dec frs a
370 * being full and locked
371 */
372 if (!drop_l.until_resync)
373 goto exit;
374 resync = (DISCONT_BACKWARD_RESYNC_MS * st_p.tb.den) / (st_p.tb.num
375 * 1000);
376 lo = now - resync;
377 hi = now + resync;
378 fr = 0;
379 loop {
380 if (fr == dec_frs_p.n)
381 break;
382 /* don't touch the scaler fr or selected fr */
383 if (dec_frs_p.a[fr] != scaler_p.img.fr
384 && dec_frs_p.a[fr] != selected_fr) {
385 if (dec_frs_p.a[fr]->pts < lo
386 || hi < dec_frs_p.a[fr]->pts) {
387 if (dec_frs_p.a[fr] == last_fr_sent_to_pe_l)
388 last_fr_sent_to_pe_l = NO_FR;
389 fr_drop(fr); /* do not advance */
390 } else { /* found a resynchronizing fr */
391 drop_l.until_resync = false;
392 break;
393 }
394 } else
395 ++fr;
396 }
397 exit:
398 drop_l.prev_now = now;
399 360 } }
400
401 361 #undef NO_FR #undef NO_FR
402 362 #define NO_FR 0 #define NO_FR 0
403 363 STATIC void select_fr(s64 now, avutil_video_fr_ref_t **selected_fr, STATIC void select_fr(s64 now, avutil_video_fr_ref_t **selected_fr,
 
... ... STATIC void timer_ack(void)
763 723 if (r == -1) if (r == -1)
764 724 warning("unable to read the number of timer expirations\n"); warning("unable to read the number of timer expirations\n");
765 725 } }
726 /*NSPC*/
727 STATIC void discont_backward(s64 now)
728 {
729 s64 lo;
730 s64 hi;
731 s64 resync;
732 u16 fr;
733 /*
734 * Backward discont detected, we will look for a fr reasonably in sync:
735 * we will named this "resyncing".
736 * The issue is the dec frs a may not receive any new fr from the
737 * pipeline which would refuse to add more in order to avoid filling
738 * up memory.
739 * Then, we choose to "take the risk" once a backward discontinuity is
740 * detected, namely let the pipeline increase its hard limit and
741 * potentially fill up huge amount of memory.
742 * This was done to handle some live streams which drops many seconds
743 * of frs and do some backward discontinuity at the same time.
744 * If in normal usage this actually fills up too often the memory,
745 * a tighter strategy would have to be implemented with the shrinking
746 * of the dec frs a.
747 */
748 if (dec_frs_p.discont_backward.prev_now != AV_NOPTS_VALUE
749 && now < dec_frs_p.discont_backward.prev_now)
750 dec_frs_p.discont_backward.resyncing = true;
751 if (dec_frs_p.discont_backward.resyncing)
752 goto exit;
753 #ifdef NPV_DEBUG
754 if (npv_debug_p)
755 npv_perr("DEBUG:%s:running resyncing code\n", __func__);
756 #endif
757 resync = (DISCONT_BACKWARD_RESYNC_MS * st_p.tb.den) / (st_p.tb.num
758 * 1000);
759 lo = now - resync;
760 hi = now + resync;
761 fr = 0;
762 loop {
763 if (fr == dec_frs_p.n)
764 break;
765 if (lo <= dec_frs_p.a[fr]->pts && dec_frs_p.a[fr]->pts <= hi) {
766 /*
767 * We have a fr reasonably in sync in the dec frs a,
768 * let's end this.
769 */
770 dec_frs_p.discont_backward.resyncing = false;
771 break;
772 }
773 ++fr;
774 }
775 exit:
776 dec_frs_p.discont_backward.prev_now = now;
777 }
File npv/video/local/state.frag.c changed (mode: 100644) (index 89f57be..ec8e788)
... ... STATIC struct {
17 17 } blit_l[npv_vk_swpchn_imgs_n_max]; } blit_l[npv_vk_swpchn_imgs_n_max];
18 18 STATIC avutil_video_fr_ref_t *last_fr_sent_to_pe_l; STATIC avutil_video_fr_ref_t *last_fr_sent_to_pe_l;
19 19 STATIC bool is_swpchn_sem_fence_submitted_l; STATIC bool is_swpchn_sem_fence_submitted_l;
20 STATIC struct {
21 s64 prev_now;
22 bool until_resync;
23 } drop_l;
File npv/video/namespace/main.c changed (mode: 100644) (index 885cb2b..0db328f)
13 13 #define dec_a_grow npv_video_dec_a_grow #define dec_a_grow npv_video_dec_a_grow
14 14 #define dec_ctx_mutex_l npv_video_dec_ctx_mutex_l #define dec_ctx_mutex_l npv_video_dec_ctx_mutex_l
15 15 #define dec_l npv_video_dec_l #define dec_l npv_video_dec_l
16 #define drop_l npv_video_drop_l
17 16 #define fatal npv_video_fatal #define fatal npv_video_fatal
18 17 #define fatalff npv_video_fatalff #define fatalff npv_video_fatalff
19 18 #define fatalvk npv_video_fatalvk #define fatalvk npv_video_fatalvk
 
63 62 #undef dec_a_grow #undef dec_a_grow
64 63 #undef dec_ctx_mutex_l #undef dec_ctx_mutex_l
65 64 #undef dec_l #undef dec_l
66 #undef drop_l
67 65 #undef fatal #undef fatal
68 66 #undef fatalff #undef fatalff
69 67 #undef fatalvk #undef fatalvk
File npv/video/public/code.frag.c changed (mode: 100644) (index 921c112..ee905d1)
... ... STATIC void init_once_public(void)
16 16 fatal("unable to create the mutex for the decoder context\n"); fatal("unable to create the mutex for the decoder context\n");
17 17
18 18 dec_frs_p.eof_receive = false; dec_frs_p.eof_receive = false;
19 dec_frs_p.discont_backward.prev_now = AV_NOPTS_VALUE;
20 dec_frs_p.discont_backward.resyncing = false;
19 21 dec_frs_p.n_max = 0; dec_frs_p.n_max = 0;
20 22 dec_frs_p.n = 0; dec_frs_p.n = 0;
21 23 dec_frs_p.a = 0; dec_frs_p.a = 0;
 
... ... STATIC void timer_evt(void)
218 220 } }
219 221 select_fr(now, &fr, &fr_priv); select_fr(now, &fr, &fr_priv);
220 222 frs_drop(now, fr); frs_drop(now, fr);
223 discont_backward(now);
221 224 dec_frs_unlock(); dec_frs_unlock();
222 225 /* unlock ------------------------------------------------------------*/ /* unlock ------------------------------------------------------------*/
223 226 if (fr == NO_FR) if (fr == NO_FR)
File npv/video/public/state.frag.h changed (mode: 100644) (index fb499a9..c771bcb)
... ... STATIC struct {
18 18
19 19 bool eof_receive; /* "receiving" from the dec returned eof */ bool eof_receive; /* "receiving" from the dec returned eof */
20 20
21 struct {
22 s64 prev_now;
23 bool resyncing;
24 } discont_backward;
25
21 26 u16 n_max; u16 n_max;
22 27 u16 n; u16 n;
23 28 /* we did not factor the 2 following fields on purpose */ /* we did not factor the 2 following fields on purpose */
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