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: 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
npv: tidy mutex locking 1962092d9675f76604414086200e88f6c857346f Sylvain BERTRAND 2020-09-15 00:51:12
npv: less incorrect reprogramming of blits b319e79f4f1b79670f6eef754142cc65c891ad4b Sylvain BERTRAND 2020-09-12 15:14:27
npv:fix osd restoration 8c64f703eca6b8c54b4cb5c95231dd02aa394135 Sylvain BERTRAND 2020-08-29 20:36:12
npv:osd:solo compilation modulo a few warnings 7805bd8f34f913b1535cc81c5be2a3132bd7e0e5 Sylvain BERTRAND 2020-08-29 14:51:35
npv: cleanup and color component fix 44f294e1de96c7974740f1187ebdbe12204884ae Sylvain BERTRAND 2020-08-28 23:48:18
npv:osd:timer, will add more if pertinent 6d34403c2c49bfa6ccf8e7a72e35a69e6f0527c5 Sylvain BERTRAND 2020-08-28 22:47:18
npv/npa: document properly snd_pcm_drain behavior 510ca39ee6a9ac9fcd646484793b7556eaa5972f Sylvain BERTRAND 2020-08-26 17:36:29
npv:remove locale layout dependent key binds f69bbbe529045b4243ece8957c838cb1465352da Sylvain BERTRAND 2020-08-24 21:27:08
npv: global seek based on audio timeline only 3c8fd60fa0a67143fa16ac90565bfcc35a193b6b Sylvain BERTRAND 2020-08-24 18:41:16
npv:_reasonable_ "pedanticage" of the code c5f2644d6eba84bcbcc9b0599c41e1f6733ea95c Sylvain BERTRAND 2020-08-20 16:25:50
npa:some amount of pedanticage 554bd5b07b1a82eabb2622cbf565031bf7af5c6d Sylvain BERTRAND 2020-08-18 19:33:47
hacking again on it after a rather long time cc09df4f340c9f906e0de9520d2c803ea6936769 Sylvain BERTRAND 2020-08-16 18:14:14
npv:fix initial volume not being stored ef66775061157e5af7d6938d06f38e6e7d06a873 Sylvain BERTRAND 2020-08-15 16:59:23
Commit 2b7347be805d17a2b6f06e276e897c51431b9c6c - npv: fix filter time base handling, prepare discontinuity support
Author: Sylvain BERTRAND
Author date (UTC): 2020-09-22 17:38
Committer name: Sylvain BERTRAND
Committer date (UTC): 2020-09-22 17:38
Parent(s): a9b52940ff2d567dc6c26b28d86eab54f5876819
Signing key:
Tree: 1e321b874ec0cbb9b3c6157adf8f029d6f2426e0
File Lines added Lines deleted
npa/TODO 1 0
npv/audio/filt/local/code.frag.c 11 7
npv/audio/filt/local/state.frag.c 0 1
npv/audio/filt/namespace/main.c 0 2
npv/audio/filt/public.h 3 1
npv/audio/filt/public/code.frag.c 5 4
npv/audio/filt/public/state.frag.h 2 0
npv/audio/local/code.frag.c 2 1
npv/clk/local/state.frag.c 1 1
npv/clk/main.c 1 0
npv/clk/public.h 2 2
npv/clk/public/code.frag.c 20 29
npv/local/code.frag.c 21 20
npv/main.c 1 0
npv/namespace/ffmpeg.h 2 0
npv/pipeline/local/code.frag.c 38 44
npv/pipeline/namespace/main.c 5 1
npv/video/local/code.frag.c 6 3
File npa/TODO changed (mode: 100644) (index 35ff3e5..70b2a25)
1 1 not ordered: not ordered:
2 - port npv proper usage of filter time base
2 3 - port npv dynamic audio reconfiguration - port npv dynamic audio reconfiguration
3 4 - port npv initial ffmpeg audio parameter override code - port npv initial ffmpeg audio parameter override code
4 5 - we were lied to: presentation/decoding timestamps from a demuxer can be - we were lied to: presentation/decoding timestamps from a demuxer can be
File npv/audio/filt/local/code.frag.c changed (mode: 100644) (index 432cf92..7ce8f1f)
... ... STATIC bool is_recfg_required(avutil_audio_set_ref_t *src_set)
34 34 return true; return true;
35 35 return false; return false;
36 36 } }
37 STATIC void abufsrc_cfg(int chans_n, uint64_t chans_layout, int rate,
38 enum avutil_audio_fr_fmt_t fmt, bool print_info)
37 STATIC void abufsrc_cfg(avutil_rational_t tb, int chans_n,
38 uint64_t chans_layout, int rate, enum avutil_audio_fr_fmt_t fmt,
39 bool print_info)
39 40 { {
40 41 int r; int r;
41 avutil_rational_t time_base;
42 42 u8 chans_layout_str[STR_SZ]; /* should be overkill */ u8 chans_layout_str[STR_SZ]; /* should be overkill */
43 43
44 44 abufsrc_l.this = avfilter_get_by_name("abuffer"); abufsrc_l.this = avfilter_get_by_name("abuffer");
 
... ... STATIC void abufsrc_cfg(int chans_n, uint64_t chans_layout, int rate,
65 65 AVUTIL_OPT_SEARCH_CHILDREN); AVUTIL_OPT_SEARCH_CHILDREN);
66 66 if (r < 0) if (r < 0)
67 67 fatal("audio buffer source context:unable to set the decoder channel layout option\n"); fatal("audio buffer source context:unable to set the decoder channel layout option\n");
68 r = avutil_opt_set_q(abufsrc_l.ctx, "time_base", tb,
69 AVUTIL_OPT_SEARCH_CHILDREN);
70 if (r < 0)
71 fatal("audio buffer source context:unable to set the time base option\n");
68 72 r = avfilter_init_str(abufsrc_l.ctx, 0); r = avfilter_init_str(abufsrc_l.ctx, 0);
69 73 if (r < 0) if (r < 0)
70 74 fatal("audio buffer source context:unable to initialize\n"); fatal("audio buffer source context:unable to initialize\n");
 
... ... STATIC void abufsink_cfg(void)
136 140 abufsink_l = avfilter_get_by_name("abuffersink"); abufsink_l = avfilter_get_by_name("abuffersink");
137 141 if (abufsink_l == 0) if (abufsink_l == 0)
138 142 fatal("audio buffer sink:could not find the filter\n"); fatal("audio buffer sink:could not find the filter\n");
139 abufsink_ctx_l = avfilter_graph_alloc_filt(graph_l, abufsink_l,
143 filt_p.abufsink_ctx = avfilter_graph_alloc_filt(graph_l, abufsink_l,
140 144 "sink_abuf"); "sink_abuf");
141 if (abufsink_ctx_l == 0)
145 if (filt_p.abufsink_ctx == 0)
142 146 fatal("audio buffer sink context:could not allocate the instance in the filter graph\n"); fatal("audio buffer sink context:could not allocate the instance in the filter graph\n");
143 r = avfilter_init_str(abufsink_ctx_l, 0);
147 r = avfilter_init_str(filt_p.abufsink_ctx, 0);
144 148 if (r < 0) if (r < 0)
145 149 fatal("audio buffer sink context:unable to initialize\n"); fatal("audio buffer sink context:unable to initialize\n");
146 150 } }
 
... ... STATIC void init_once_local(void)
152 156 vol_l = 0; vol_l = 0;
153 157 afmt_ctx_l = 0; afmt_ctx_l = 0;
154 158 afmt_l = 0; afmt_l = 0;
155 abufsink_ctx_l = 0;
156 159 abufsink_l = 0; abufsink_l = 0;
157 160 /* floating point strs are localized... erk... */ /* floating point strs are localized... erk... */
158 161 snprintf(double_zero_l10n_str_l, sizeof(double_zero_l10n_str_l), snprintf(double_zero_l10n_str_l, sizeof(double_zero_l10n_str_l),
 
... ... STATIC void init_once_public(double initial_vol)
166 169 filt_p.pcm_written_ufrs_n = 0; filt_p.pcm_written_ufrs_n = 0;
167 170 filt_p.vol = initial_vol; filt_p.vol = initial_vol;
168 171 filt_p.muted = false; filt_p.muted = false;
172 filt_p.abufsink_ctx = 0;
169 173 } }
File npv/audio/filt/local/state.frag.c changed (mode: 100644) (index a2b7830..5e2e6d9)
... ... STATIC const avfilter_filt_t *vol_l;
15 15 STATIC u8 double_zero_l10n_str_l[sizeof("xxx.xx")]; STATIC u8 double_zero_l10n_str_l[sizeof("xxx.xx")];
16 16 STATIC avfilter_filt_ctx_t *afmt_ctx_l; STATIC avfilter_filt_ctx_t *afmt_ctx_l;
17 17 STATIC const avfilter_filt_t *afmt_l; STATIC const avfilter_filt_t *afmt_l;
18 STATIC avfilter_filt_ctx_t *abufsink_ctx_l;
19 18 STATIC const avfilter_filt_t *abufsink_l; STATIC const avfilter_filt_t *abufsink_l;
File npv/audio/filt/namespace/main.c changed (mode: 100644) (index 83e3c2d..476c07a)
1 1 #ifndef CLEANUP #ifndef CLEANUP
2 2 #define abufsink_cfg npv_audio_filt_abufsink_cfg #define abufsink_cfg npv_audio_filt_abufsink_cfg
3 #define abufsink_ctx_l npv_audio_filt_abufsink_ctx_l
4 3 #define abufsink_l npv_audio_filt_abufsink_l #define abufsink_l npv_audio_filt_abufsink_l
5 4 #define abufsrc_cfg npv_audio_filt_abufsrc_cfg #define abufsrc_cfg npv_audio_filt_abufsrc_cfg
6 5 #define abufsrc_l npv_audio_filt_abufsrc_l #define abufsrc_l npv_audio_filt_abufsrc_l
 
27 26 /*============================================================================*/ /*============================================================================*/
28 27 #else #else
29 28 #undef abufsink_cfg #undef abufsink_cfg
30 #undef abufsink_ctx_l
31 29 #undef abufsink_l #undef abufsink_l
32 30 #undef abufsrc_cfg #undef abufsrc_cfg
33 31 #undef abufsrc_l #undef abufsrc_l
File npv/audio/filt/public.h changed (mode: 100644) (index 9ff44ce..2e06c71)
7 7 #include <stdbool.h> #include <stdbool.h>
8 8 #include <libavutil/frame.h> #include <libavutil/frame.h>
9 9 #include <libavutil/samplefmt.h> #include <libavutil/samplefmt.h>
10 #include <libavfilter/avfilter.h>
10 11 #include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
11 12 #include "npv/c_fixing.h" #include "npv/c_fixing.h"
12 13 #include "npv/global.h" #include "npv/global.h"
 
19 20 #include "npv/audio/filt/public/state.frag.h" #include "npv/audio/filt/public/state.frag.h"
20 21 /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
21 22 STATIC void init_once(double initial_vol); STATIC void init_once(double initial_vol);
22 STATIC void cfg(int src_chans_n, uint64_t src_chans_layout, int src_rate,
23 STATIC void cfg(avutil_rational_t tb,
24 int src_chans_n, uint64_t src_chans_layout, int src_rate,
23 25 enum avutil_audio_fr_fmt_t src_fmt, enum avutil_audio_fr_fmt_t src_fmt,
24 26 bool muted, double vol, bool muted, double vol,
25 27 int dst_chans_n, uint64_t dst_chans_layout, int dst_rate, int dst_chans_n, uint64_t dst_chans_layout, int dst_rate,
File npv/audio/filt/public/code.frag.c changed (mode: 100644) (index 77bd9c9..7cb3f17)
... ... STATIC u8 filt_set_get(void)
81 81 * the last dec set should switch the filt in draining mode, and * the last dec set should switch the filt in draining mode, and
82 82 * filt_p.set won't matter. * filt_p.set won't matter.
83 83 */ */
84 r = avfilter_bufsink_get_audio_set(abufsink_ctx_l, filt_p.set);
84 r = avfilter_bufsink_get_audio_set(filt_p.abufsink_ctx, filt_p.set);
85 85 if (r >= 0) { if (r >= 0) {
86 86 filt_p.pcm_written_ufrs_n = 0; filt_p.pcm_written_ufrs_n = 0;
87 87 return HAVE_FILT_SET; return HAVE_FILT_SET;
 
... ... STATIC void init_once(double initial_vol)
104 104 init_once_local(); init_once_local();
105 105 init_once_public(initial_vol); init_once_public(initial_vol);
106 106 } }
107 STATIC void cfg(int src_chans_n, uint64_t src_chans_layout, int src_rate,
107 STATIC void cfg(avutil_rational_t tb,
108 int src_chans_n, uint64_t src_chans_layout, int src_rate,
108 109 enum avutil_audio_fr_fmt_t src_fmt, enum avutil_audio_fr_fmt_t src_fmt,
109 110 bool muted, double vol, bool muted, double vol,
110 111 int dst_chans_n, uint64_t dst_chans_layout, int dst_rate, int dst_chans_n, uint64_t dst_chans_layout, int dst_rate,
 
... ... STATIC void cfg(int src_chans_n, uint64_t src_chans_layout, int src_rate,
119 120 graph_l = avfilter_graph_alloc(); graph_l = avfilter_graph_alloc();
120 121 if (graph_l == 0) if (graph_l == 0)
121 122 fatal("unable to create filter graph\n"); fatal("unable to create filter graph\n");
122 abufsrc_cfg(src_chans_n, src_chans_layout, src_rate, src_fmt,
123 abufsrc_cfg(tb, src_chans_n, src_chans_layout, src_rate, src_fmt,
123 124 print_info); print_info);
124 125 /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
125 126 abufsrc_l.key.chans_n = src_chans_n; abufsrc_l.key.chans_n = src_chans_n;
 
... ... STATIC void cfg(int src_chans_n, uint64_t src_chans_layout, int src_rate,
136 137 r = avfilter_link(vol_ctx_l, 0, afmt_ctx_l, 0); r = avfilter_link(vol_ctx_l, 0, afmt_ctx_l, 0);
137 138 if (r < 0) if (r < 0)
138 139 fatal("unable to connect the volume filter to the audio format filter\n"); fatal("unable to connect the volume filter to the audio format filter\n");
139 r = avfilter_link(afmt_ctx_l, 0, abufsink_ctx_l, 0);
140 r = avfilter_link(afmt_ctx_l, 0, filt_p.abufsink_ctx, 0);
140 141 if (r < 0) if (r < 0)
141 142 fatal("unable to connect the audio format filter to the audio buffer sink filter\n"); fatal("unable to connect the audio format filter to the audio buffer sink filter\n");
142 143 r = avfilter_graph_config(graph_l, 0); r = avfilter_graph_config(graph_l, 0);
File npv/audio/filt/public/state.frag.h changed (mode: 100644) (index 1144830..2e885e0)
... ... STATIC struct {
9 9
10 10 double vol; double vol;
11 11 bool muted; bool muted;
12 /* we will need query some output props from the filte */
13 avfilter_filt_ctx_t *abufsink_ctx;
12 14 } filt_p; } filt_p;
File npv/audio/local/code.frag.c changed (mode: 100644) (index 3f827fe..e10e8bd)
... ... STATIC u8 dec_set_filter(void)
686 686 /* FILT_RECFG_REQUIRED */ /* FILT_RECFG_REQUIRED */
687 687 pcm2ff_strict(npv_audio_pcm_p, &dst_chans_n, &dst_chans_layout, pcm2ff_strict(npv_audio_pcm_p, &dst_chans_n, &dst_chans_layout,
688 688 &dst_rate, &dst_fmt, PRINT_INFO); &dst_rate, &dst_fmt, PRINT_INFO);
689 filt_cfg(new_chans_n, new_chans_layout, new_rate, new_fmt,
689 filt_cfg(st_p.tb,
690 new_chans_n, new_chans_layout, new_rate, new_fmt,
690 691 filt_p.muted, filt_p.vol, filt_p.muted, filt_p.vol,
691 692 dst_chans_n, dst_chans_layout, dst_rate, dst_fmt, dst_chans_n, dst_chans_layout, dst_rate, dst_fmt,
692 693 PRINT_INFO); PRINT_INFO);
File npv/clk/local/state.frag.c changed (mode: 100644) (index 209a0de..e125745)
... ... STATIC struct {
24 24 */ */
25 25 snd_pcm_ufrs_t written_ufrs_n; snd_pcm_ufrs_t written_ufrs_n;
26 26
27 s64 audio_st_ts; /* ff audio st tb units */
27 s64 audio_filt_ts; /* in ff audio filt tb units */
28 28 } ref; } ref;
29 29 struct { struct {
30 30 snd_pcm_status_t *status; snd_pcm_status_t *status;
File npv/clk/main.c changed (mode: 100644) (index aeeccfb..edc559f)
12 12 #include <libavformat/avformat.h> #include <libavformat/avformat.h>
13 13 #include "npv/c_fixing.h" #include "npv/c_fixing.h"
14 14 #include "npv/audio/public.h" #include "npv/audio/public.h"
15 #include "npv/audio/filt/public.h"
15 16 #include "npv/video/public.h" #include "npv/video/public.h"
16 17 /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
17 18 #include "npv/namespace/alsa.h" #include "npv/namespace/alsa.h"
File npv/clk/public.h changed (mode: 100644) (index bae0b52..cf3cfbe)
7 7 #include "npv/namespace/alsa.h" #include "npv/namespace/alsa.h"
8 8 /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
9 9 STATIC void npv_clk_init_once(void); STATIC void npv_clk_init_once(void);
10 STATIC u8 npv_clk_get_audio_st_ts(s64 *ts);
10 STATIC u8 npv_clk_get_audio_filt_ts(s64 *ts);
11 11 STATIC u8 npv_clk_get_video_st_ts(s64 *ts); STATIC u8 npv_clk_get_video_st_ts(s64 *ts);
12 STATIC void npv_clk_ref_time_point_update(s64 audio_ts,
12 STATIC void npv_clk_ref_time_point_update(s64 audio_filt_ts,
13 13 snd_pcm_ufrs_t written_ufrs_n); snd_pcm_ufrs_t written_ufrs_n);
14 14 STATIC void npv_clk_invalidate(void); STATIC void npv_clk_invalidate(void);
15 15 STATIC void npv_clk_pause(void); STATIC void npv_clk_pause(void);
File npv/clk/public/code.frag.c changed (mode: 100644) (index c8a4604..84aafba)
... ... STATIC void npv_clk_init_once(void)
15 15 npv_clk_l.paused = false; npv_clk_l.paused = false;
16 16 } }
17 17 #define NO_REF_TIME_POINT 1 #define NO_REF_TIME_POINT 1
18 STATIC u8 npv_clk_get_audio_st_ts(s64 *ts)
18 STATIC u8 npv_clk_get_audio_filt_ts(s64 *ts)
19 19 { {
20 20 int r; int r;
21 21 snd_pcm_audio_tstamp_config_t ac; snd_pcm_audio_tstamp_config_t ac;
 
... ... STATIC u8 npv_clk_get_audio_st_ts(s64 *ts)
24 24 f64 ref_ns; f64 ref_ns;
25 25 f64 ref_status_ns; f64 ref_status_ns;
26 26 f64 ref_delay_frs_n; f64 ref_delay_frs_n;
27 f64 ref_audio_ts;
28 f64 audio_tb_num;
29 f64 audio_tb_den;
27 f64 ref_audio_filt_ts;
28 avutil_rational_t audio_filt_tb;
29 f64 audio_filt_tb_num;
30 f64 audio_filt_tb_den;
30 31 f64 audio_rate_num; f64 audio_rate_num;
31 32 unsigned int audio_rate_num_ui; unsigned int audio_rate_num_ui;
32 33 f64 audio_rate_den; f64 audio_rate_den;
 
... ... STATIC u8 npv_clk_get_audio_st_ts(s64 *ts)
53 54 snd_pcm_status_get_audio_htstamp(npv_clk_l.ref.status, &hts); snd_pcm_status_get_audio_htstamp(npv_clk_l.ref.status, &hts);
54 55 ref_status_ns = (f64)hts.tv_sec * 1e9 + (f64)hts.tv_nsec; ref_status_ns = (f64)hts.tv_sec * 1e9 + (f64)hts.tv_nsec;
55 56
56 ref_audio_ts = (f64)npv_clk_l.ref.audio_st_ts;
57 ref_audio_filt_ts = (f64)npv_clk_l.ref.audio_filt_ts;
57 58 ref_delay_frs_n = (f64)snd_pcm_status_get_delay(npv_clk_l.ref.status); ref_delay_frs_n = (f64)snd_pcm_status_get_delay(npv_clk_l.ref.status);
58 audio_tb_num = (f64)npv_audio_st_p.tb.num;
59 audio_tb_den = (f64)npv_audio_st_p.tb.den;
59 /* we are writting the output of the filt to the audio pcm */
60 audio_filt_tb = avfilter_bufsink_tb_get(npv_audio_filt_p.abufsink_ctx);
61 audio_filt_tb_num = (f64)audio_filt_tb.num;
62 audio_filt_tb_den = (f64)audio_filt_tb.den;
60 63 /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
61 64 r = snd_pcm_hw_params_current(npv_audio_pcm_p, npv_clk_pcm_hw_params_l); r = snd_pcm_hw_params_current(npv_audio_pcm_p, npv_clk_pcm_hw_params_l);
62 65 if (r != 0) if (r != 0)
 
... ... STATIC u8 npv_clk_get_audio_st_ts(s64 *ts)
74 77 ref_ns = ref_status_ns + (ref_delay_frs_n - written_frs_n) ref_ns = ref_status_ns + (ref_delay_frs_n - written_frs_n)
75 78 * audio_rate_den * 1e9 / audio_rate_num; * audio_rate_den * 1e9 / audio_rate_num;
76 79 /* basic linear interpolation */ /* basic linear interpolation */
77 now_audio_ts = audio_tb_den * 1e-9 * (now_ns - ref_ns) / audio_tb_num
78 + ref_audio_ts;
80 now_audio_ts = audio_filt_tb_den * 1e-9 * (now_ns - ref_ns)
81 / audio_filt_tb_num + ref_audio_filt_ts;
79 82 *ts = (s64)lrint(now_audio_ts); *ts = (s64)lrint(now_audio_ts);
80 83 return TS_RETURNED; return TS_RETURNED;
81 84 } }
82 85 #undef NO_REF_TIME_POINT #undef NO_REF_TIME_POINT
83 86 STATIC u8 npv_clk_get_video_st_ts(s64 *ts) STATIC u8 npv_clk_get_video_st_ts(s64 *ts)
84 87 { {
85 f64 audio_tb_num;
86 f64 audio_tb_den;
87 f64 video_tb_num;
88 f64 video_tb_den;
89 f64 now_audio_ts;
90 s64 now_audio_ts_s64;
91 f64 now_video_ts;
88 avutil_rational_t audio_filt_tb;
89 s64 now_audio_filt_ts;
92 90 u8 r; u8 r;
93 91
94 audio_tb_num = (f64)npv_audio_st_p.tb.num;
95 audio_tb_den = (f64)npv_audio_st_p.tb.den;
96 video_tb_num = (f64)npv_video_st_p.tb.num;
97 video_tb_den = (f64)npv_video_st_p.tb.den;
98
99 r = npv_clk_get_audio_st_ts(&now_audio_ts_s64);
92 audio_filt_tb = avfilter_bufsink_tb_get(npv_audio_filt_p.abufsink_ctx);
93 r = npv_clk_get_audio_filt_ts(&now_audio_filt_ts);
100 94 if (r != TS_RETURNED) if (r != TS_RETURNED)
101 95 return r; return r;
102 now_audio_ts = (f64)now_audio_ts_s64;
103 /* basic conversion */
104 now_video_ts = audio_tb_num * video_tb_den * now_audio_ts
105 / (audio_tb_den * video_tb_num);
106 *ts = (s64)lrint(now_video_ts);
96 *ts = avutil_rescale_q(now_audio_filt_ts, audio_filt_tb,
97 npv_video_st_p.tb);
107 98 return TS_RETURNED; return TS_RETURNED;
108 99 } }
109 STATIC void npv_clk_ref_time_point_update(s64 audio_ts,
100 STATIC void npv_clk_ref_time_point_update(s64 audio_filt_ts,
110 101 snd_pcm_ufrs_t written_ufrs_n) snd_pcm_ufrs_t written_ufrs_n)
111 102 { {
112 103 int r; int r;
 
... ... STATIC void npv_clk_ref_time_point_update(s64 audio_ts,
119 110 r = snd_pcm_status(npv_audio_pcm_p, npv_clk_l.ref.status); r = snd_pcm_status(npv_audio_pcm_p, npv_clk_l.ref.status);
120 111 if (r < 0) if (r < 0)
121 112 npv_clk_fatal("unable to sample timing information for reference time point\n"); npv_clk_fatal("unable to sample timing information for reference time point\n");
122 npv_clk_l.ref.audio_st_ts = audio_ts;
113 npv_clk_l.ref.audio_filt_ts = audio_filt_ts;
123 114 npv_clk_l.ref.written_ufrs_n = written_ufrs_n; npv_clk_l.ref.written_ufrs_n = written_ufrs_n;
124 115 npv_clk_l.ref_valid = true; npv_clk_l.ref_valid = true;
125 116 } }
File npv/local/code.frag.c changed (mode: 100644) (index 6ad6944..13f11e5)
... ... STATIC void seek_x(s64 delta)
621 621 { {
622 622 int a; int a;
623 623 u8 r; u8 r;
624 s64 new_audio_ts;
625 s64 new_video_ts;
626 s64 audio_now;
624 s64 now_audio_filt_ts;
625 avutil_rational_t audio_filt_tb;
626 s64 new_audio_filt_ts;
627 s64 new_audio_st_ts;
628 s64 now_audio_st_ts;
627 629
628 630 if (npv_audio_draining_p) { if (npv_audio_draining_p) {
629 631 warning("seek:audio is draining, seeking disable\n"); warning("seek:audio is draining, seeking disable\n");
 
... ... STATIC void seek_x(s64 delta)
636 638
637 639 seek_lock(); seek_lock();
638 640
639 r = npv_clk_get_audio_st_ts(&audio_now);
641 r = npv_clk_get_audio_filt_ts(&now_audio_filt_ts);
640 642 if (r != TS_FROM_CLK_OK) { if (r != TS_FROM_CLK_OK) {
641 643 warning("seek:audio:clock timestamp unavailable, ignoring command\n"); warning("seek:audio:clock timestamp unavailable, ignoring command\n");
642 644 seek_unlock(); seek_unlock();
643 645 return; return;
644 646 } }
645 647 (void)snd_pcm_drop(npv_audio_pcm_p); (void)snd_pcm_drop(npv_audio_pcm_p);
646 /*
647 * XXX: a set of sts can share the same id for seeking. if they share
648 * the same id then the tbs should be the same.
649 */
648 /* XXX: a set of sts can share the same id for seeking */
650 649 /*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
651 new_audio_ts = audio_now + delta * npv_audio_st_p.tb.den
652 / npv_audio_st_p.tb.num;
653 /* rewind capping if possible */
654 if (npv_audio_st_p.start_time != AV_NOPTS_VALUE)
655 if (new_audio_ts < npv_audio_st_p.start_time)
656 new_audio_ts = npv_audio_st_p.start_time;
657 pout("trying to seek to %"PRId64" audio stream time base units\n", new_audio_ts);
658 a = avformat_seek_pkt(npv_fmt_ctx_p, npv_audio_st_p.id, new_audio_ts,
650 audio_filt_tb = avfilter_bufsink_tb_get(npv_audio_filt_p.abufsink_ctx);
651 new_audio_filt_ts = now_audio_filt_ts + delta * audio_filt_tb.den
652 / audio_filt_tb.num;
653 new_audio_st_ts = avutil_rescale_q(new_audio_filt_ts, audio_filt_tb,
654 npv_audio_st_p.tb);
655 pout("trying to seek to %"PRId64" audio filter time base units/%"PRId64" audio stream time base units\n", new_audio_filt_ts, new_audio_st_ts);
656 a = avformat_seek_pkt(npv_fmt_ctx_p, npv_audio_st_p.id, new_audio_st_ts,
659 657 0); 0);
660 658 if (a < 0) { if (a < 0) {
661 pout("unable to seek to %"PRId64" audio stream time base units\n", new_audio_ts);
659 pout("unable to seek to %"PRId64" audio filter time base units/%"PRId64" audio stream time base units\n", new_audio_filt_ts, new_audio_st_ts);
662 660 goto try_restore_audio; goto try_restore_audio;
663 661 } }
664 pout("global seek using audio seek to %"PRId64" audio stream time base units\n", new_audio_ts);
662 pout("global seek using audio seek to %"PRId64" audio filter time base units/%"PRId64" audio stream time base units\n", new_audio_filt_ts, new_audio_st_ts);
665 663 flush: flush:
666 664 npv_video_dec_flush(); npv_video_dec_flush();
667 665 npv_audio_dec_flush(); npv_audio_dec_flush();
 
... ... flush:
682 680 return; return;
683 681
684 682 try_restore_audio: try_restore_audio:
685 a = avformat_seek_pkt(npv_fmt_ctx_p, npv_audio_st_p.id, audio_now, 0);
683 now_audio_st_ts = avutil_rescale_q(now_audio_filt_ts, audio_filt_tb,
684 npv_audio_st_p.tb);
685 a = avformat_seek_pkt(npv_fmt_ctx_p, npv_audio_st_p.id, now_audio_st_ts,
686 0);
686 687 if (a < 0) /* we don't send an application error */ if (a < 0) /* we don't send an application error */
687 exit_ok("unable to restore audio to %"PRId64" audio stream time base units\n", audio_now);
688 exit_ok("unable to restore audio to %"PRId64" audio filter time base units/%"PRId64" audio stream time base units\n", now_audio_filt_ts, now_audio_st_ts);
688 689 goto flush; goto flush;
689 690 } }
690 691 #undef TS_FROM_CLK_OK #undef TS_FROM_CLK_OK
File npv/main.c changed (mode: 100644) (index 1bb6e6e..ffef877)
27 27 #include <libavformat/avformat.h> #include <libavformat/avformat.h>
28 28 #include <libavutil/samplefmt.h> #include <libavutil/samplefmt.h>
29 29 #include <libavutil/mathematics.h> #include <libavutil/mathematics.h>
30 #include <libavfilter/buffersink.h>
30 31 #include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
31 32 /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
32 33 #include "npv/c_fixing.h" #include "npv/c_fixing.h"
File npv/namespace/ffmpeg.h changed (mode: 100644) (index 44451b6..1e1b61b)
35 35 #define avcodec_pkt_ref_alloc av_packet_alloc #define avcodec_pkt_ref_alloc av_packet_alloc
36 36 #define avcodec_pkt_ref_t AVPacket #define avcodec_pkt_ref_t AVPacket
37 37 #define avcodec_pkt_unref av_packet_unref #define avcodec_pkt_unref av_packet_unref
38 #define avfilter_bufsink_tb_get av_buffersink_get_time_base
38 39 #define avfilter_filt_t AVFilter #define avfilter_filt_t AVFilter
39 40 #define avfilter_filt_ctx_t AVFilterContext #define avfilter_filt_ctx_t AVFilterContext
40 41 #define avfilter_filt_graph_t AVFilterGraph #define avfilter_filt_graph_t AVFilterGraph
 
114 115 #undef avcodec_pkt_ref_alloc #undef avcodec_pkt_ref_alloc
115 116 #undef avcodec_pkt_ref_t #undef avcodec_pkt_ref_t
116 117 #undef avcodec_pkt_unref #undef avcodec_pkt_unref
118 #undef avfilter_bufsink_tb_get
117 119 #undef avfilter_filt_t #undef avfilter_filt_t
118 120 #undef avfilter_filt_ctx_t #undef avfilter_filt_ctx_t
119 121 #undef avfilter_filt_graph_t #undef avfilter_filt_graph_t
File npv/pipeline/local/code.frag.c changed (mode: 100644) (index 0fa7a21..52d64ed)
... ... STATIC void *read_thd_entry(void *arg)
80 80 /* /*
81 81 * our alsa audio buf is (rate/4)~0.25s (interactivity like vol processing). * our alsa audio buf is (rate/4)~0.25s (interactivity like vol processing).
82 82 * then we would like to have ~2 times this buf (~double buf) of decoded audio * then we would like to have ~2 times this buf (~double buf) of decoded audio
83 * frs. namely we try to have ~(2 *0.25s) of decoded audio frames. we presume
84 * the audio dec is fine grained enough in order to base our calculation on the
85 * pts-es of 2 sets of audio frs.
83 * frs. namely we try to have ~(2 *0.25s) of decoded audio frs.
84 * due to discontinuity with ts and change of audio properties, we account for
85 * the total amount of us based on the rate and frs n.
86 86 */ */
87 87 STATIC bool have_enough_predecoded_audio_frs(void) STATIC bool have_enough_predecoded_audio_frs(void)
88 88 { {
89 int64_t pts_min;
90 int64_t pts_max;
91 int64_t pts_delta;
92 int64_t pts_delta_limit;
89 u32 set;
90 int64_t total_us;
91 int64_t total_us_threshold;
93 92
94 93 npv_audio_dec_sets_lock(); npv_audio_dec_sets_lock();
95 94 if (npv_audio_dec_sets_p.eof_receive) { if (npv_audio_dec_sets_p.eof_receive) {
 
... ... STATIC bool have_enough_predecoded_audio_frs(void)
100 99 return false; return false;
101 100 } }
102 101 /* from here we have at least 1 sets of audio frs */ /* from here we have at least 1 sets of audio frs */
103 /* we presume the audio sets are in pts order */
104 pts_min = npv_audio_dec_sets_p.a[0]->pts;
105 pts_max = npv_audio_dec_sets_p.a[npv_audio_dec_sets_p.n - 1]->pts;
102 set = 0;
103 total_us = 0;
104 loop {
105 if (set == (npv_audio_dec_sets_p.n - 1))
106 break;
107 total_us += npv_audio_dec_sets_p.a[set]->frs_n * 1000000
108 / npv_audio_dec_sets_p.a[set]->fr_rate;
109 ++set;
110 }
106 111 npv_audio_dec_sets_unlock(); npv_audio_dec_sets_unlock();
107
108 pts_delta = pts_max - pts_min;
109 /* 2 * 0.25s = 500 ms */
110 pts_delta_limit = 500 * npv_audio_st_p.tb.den / npv_audio_st_p.tb.num
111 / 1000;
112 if (pts_delta >= pts_delta_limit)
112 /* 250 * 2 ms */
113 total_us_threshold = 250 * 2 * 1000;
114 if (total_us >= total_us_threshold)
113 115 return true; return true;
114 116 return false; return false;
115 117 } }
116 118 STATIC void audio(void) { loop /* infinite loop */ STATIC void audio(void) { loop /* infinite loop */
117 119 { {
118 120 if (have_enough_predecoded_audio_frs()) { if (have_enough_predecoded_audio_frs()) {
119 wait(250000000); /* (rate/4)~0.25s */
121 /* human ear is sensitive to ~20ms crack, make it 16ms */
122 wait(16000000);
120 123 continue; continue;
121 124 } }
122 125 /* can be long, finer-grained locking is done in there */ /* can be long, finer-grained locking is done in there */
 
... ... STATIC void *audio_thd_entry(void *arg)
139 142 /* unreachable */ /* unreachable */
140 143 } }
141 144 /* /*
142 * same heuristics than for audio. there is some sort of sync due to video fr
143 * dropping based on "audio now" in the main thd
145 * predecoded video frs are expensive from the perspectives of the cpu and the
146 * mem hierarchy.
147 * 1920 * 1080 * 4 bytes = 8MB. I like powers of 2, then 4.
144 148 */ */
145 149 STATIC bool have_enough_predecoded_video_frs(void) STATIC bool have_enough_predecoded_video_frs(void)
146 150 { {
147 int64_t pts_min;
148 int64_t pts_max;
149 int64_t pts_delta;
150 int64_t pts_delta_limit;
151 bool r;
151 152
152 153 npv_video_dec_frs_lock(); npv_video_dec_frs_lock();
153 154 if (npv_video_dec_frs_p.eof_receive) { if (npv_video_dec_frs_p.eof_receive) {
154 npv_video_dec_frs_unlock();
155 return true;
156 } else if (npv_video_dec_frs_p.n == 0) {
157 npv_video_dec_frs_unlock();
158 return false;
159 }
160 /* from here we have at least 1 video fr */
161 /* we presume the video frs are in pts order */
162 pts_min = npv_video_dec_frs_p.a[0]->pts;
163 pts_max = npv_video_dec_frs_p.a[npv_video_dec_frs_p.n - 1]->pts;
155 r = true;
156 } else if (npv_video_dec_frs_p.n < 4) {
157 r = false;
158 } else /* >= 4 */
159 r = true;
164 160 npv_video_dec_frs_unlock(); npv_video_dec_frs_unlock();
165
166 pts_delta = pts_max - pts_min;
167 /* 2 * 0.25s = 500 ms */
168 pts_delta_limit = 500 * npv_video_st_p.tb.den / npv_video_st_p.tb.num
169 / 1000;
170 if (pts_delta >= pts_delta_limit)
171 return true;
172 return false;
161 return r;
173 162 } }
174 163 STATIC void video(void) { loop /* infinite loop */ STATIC void video(void) { loop /* infinite loop */
175 164 { {
176 165 if (have_enough_predecoded_video_frs()) { if (have_enough_predecoded_video_frs()) {
177 wait(250000000); /* (audio rate/4)~0.25s */
166 wait(8000000); /* 60fps or 16ms, let's check every 8ms */
178 167 continue; continue;
179 168 } }
180 /* can be long, finer-grained locking is done in there */
181 npv_video_pkts_send();
169 /*
170 * can be long, finer-grained locking is done in there. filling the dec
171 * bufs should be "faster" than decoding, and we may not have enough
172 * pkts to fill those bufs, then it should exit without filling up
173 * mem.
174 */
175 npv_video_pkts_send(); /* fill the dec bufs */
182 176 npv_video_dec_frs_receive_avail(); npv_video_dec_frs_receive_avail();
183 177 }} }}
184 178 STATIC void *video_thd_entry(void *arg) STATIC void *video_thd_entry(void *arg)
File npv/pipeline/namespace/main.c changed (mode: 100644) (index 35f28c2..df1bddf)
1 1 #ifndef CLEANUP #ifndef CLEANUP
2 2 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
3 3 /* some struct fields */ /* some struct fields */
4 #define sz size
4 #define frs_n nb_samples
5 #define fr_rate sample_rate
6 #define sz size
5 7 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
6 8 #define audio npv_pipeline_audio #define audio npv_pipeline_audio
7 9 #define audio_thd_entry npv_pipeline_audio_thd_entry #define audio_thd_entry npv_pipeline_audio_thd_entry
 
34 36 #undef video_thd_entry #undef video_thd_entry
35 37 #undef wait #undef wait
36 38 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
39 #undef frs_n
40 #undef fr_rate
37 41 #undef sz #undef sz
38 42 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
39 43 #endif #endif
File npv/video/local/code.frag.c changed (mode: 100644) (index 48ef6ab..71655cc)
... ... STATIC void frs_drop(s64 now)
335 335 s64 threshold; s64 threshold;
336 336 u16 fr; u16 fr;
337 337
338 /* audio can be late up to 0.25s, and audio is 'now' */
339 threshold = (250 * st_p.tb.den) / (st_p.tb.num * 1000);
338 /*
339 * https://en.wikipedia.org/wiki/Audio_to_video_synchronization
340 * we need to make room in the dec a of predecoded frs, based on the
341 * previous url (20200922), we abitrary choose -30ms.
342 */
343 threshold = (30 * st_p.tb.den) / (st_p.tb.num * 1000);
340 344 low = now - threshold; low = now - threshold;
341 345 fr = 0; fr = 0;
342 346 loop { loop {
 
... ... STATIC void frs_drop(s64 now)
348 352
349 353 pts = dec_frs_p.a[fr]->pts; pts = dec_frs_p.a[fr]->pts;
350 354 fr_priv = dec_frs_p.priv_a[fr]; fr_priv = dec_frs_p.priv_a[fr];
351
352 355 /* keep the fr the scaler is related to */ /* keep the fr the scaler is related to */
353 356 if ((dec_frs_p.a[fr] != scaler_p.img.fr) && (pts < low)) { if ((dec_frs_p.a[fr] != scaler_p.img.fr) && (pts < low)) {
354 357 if (dec_frs_p.a[fr] == last_fr_sent_to_pe_l) if (dec_frs_p.a[fr] == last_fr_sent_to_pe_l)
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