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: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
npv:fixing the fix 2043d3ae57ff8b4c26acfd1ee2ff8958cb887ab8 Sylvain BERTRAND 2020-07-17 19:11:14
npv:fixing minor annoyances 2b1895f92933d41a7eb6b7638a94f526e1b5e7cd Sylvain BERTRAND 2020-07-17 19:03:47
npv:spurious namespace tag 65b5c4970e0c0b651ff8d9d61ce2ab0654a039fd Sylvain BERTRAND 2020-06-06 23:22:19
npv:namespace cleanup, don't need that many short identifiers 86d95bbd53a6c9264a44ae98038db9bf4d195e29 Sylvain BERTRAND 2020-06-06 22:44:11
npv:aspect ratio handling 946f160f000a6def790ea64cde5fd31a284f2bd7 Sylvain BERTRAND 2020-06-05 22:21:40
npv:vulkan refactoring to prepare resize handling e6ce6ebf7540d3e7ac2587400e3c0b5289369d19 Sylvain BERTRAND 2020-06-03 17:48:39
npv: x11 wm sugar, fullscreen 7801421eea4849e855916665ede8e9b325520118 Sylvain BERTRAND 2020-06-02 13:39:16
npa: fix initial scheduling bd228fb06dda312888dc6425ebc08dfb2c1d06ae Sylvain BERTRAND 2020-06-02 10:17:42
npv: x11 fixes and more sugar 043ef16cabacaddada9c322fa39871048ef95aae Sylvain BERTRAND 2020-06-01 22:18:22
npv:x11 sugar acd88647f348333fee796a6062963e9cea847d2f Sylvain BERTRAND 2020-05-30 21:26:47
npv: video timer names 8ab20e0c91538f9f84c09c78ee2d5242b5b74607 Sylvain BERTRAND 2020-05-30 17:14:56
npv:less worse pause support, some cleanup ded1666c8970d67bba8f5d0d2ee25230403bc9c3 Sylvain BERTRAND 2020-05-30 16:26:21
Commit 6d34403c2c49bfa6ccf8e7a72e35a69e6f0527c5 - npv:osd:timer, will add more if pertinent
Author: Sylvain BERTRAND
Author date (UTC): 2020-08-28 22:47
Committer name: Sylvain BERTRAND
Committer date (UTC): 2020-08-28 22:47
Parent(s): 510ca39ee6a9ac9fcd646484793b7556eaa5972f
Signer:
Signing key:
Signing status: N
Tree: 0713c31ffe2128bbb893cf7ba34d7c30ee6f6fc1
File Lines added Lines deleted
npv/ABBREVIATIONS 2 0
npv/README 2 1
npv/config.h 12 2
npv/local/code.frag.c 4 154
npv/main.c 2 0
npv/make-template.sh 4 3
npv/video/local/code.frag.c 10 5
npv/video/osd/ABBREVIATIONS 3 0
npv/video/osd/local/code.frag.c 553 0
npv/video/osd/local/state.frag.c 45 0
npv/video/osd/main.c 71 0
npv/video/osd/namespace/main.c 22 0
npv/video/osd/namespace/public.h 14 0
npv/video/osd/public.h 24 0
npv/video/osd/public/code.frag.c 176 0
npv/video/public/code.frag.c 3 0
File npv/ABBREVIATIONS changed (mode: 100644) (index 04e6181..a59704c)
... ... nr(s) : NumbeR(S)
53 53 num : NUMerator num : NUMerator
54 54 out : OUTput out : OUTput
55 55 param(s) : PARAMeter(S) param(s) : PARAMeter(S)
56 pix(s) : PIXel(S)
56 57 pcm : Pulse Coded Modulation pcm : Pulse Coded Modulation
57 58 pkt(s) : PacKeT(S) pkt(s) : PacKeT(S)
58 59 priv : PRIVate priv : PRIVate
 
... ... ptr(s) : PoinTeR(S)
60 61 q(ed) : Queue(D) q(ed) : Queue(D)
61 62 resp : RESPonse resp : RESPonse
62 63 ref : REFerence ref : REFerence
64 rop : Raster OPeration
63 65 s : Start s : Start
64 66 scr : SCReen scr : SCReen
65 67 sec(s) : SECond(S) sec(s) : SECond(S)
File npv/README changed (mode: 100644) (index 03fd272..1b7d893)
5 5 BUILDING: BUILDING:
6 6 configure the key bindings and more in "config.h". see configure the key bindings and more in "config.h". see
7 7 make-template.sh: this is a "one compilation unit" project. just make-template.sh: this is a "one compilation unit" project. just
8 compile main.c and link the compiler output file to your ffmpeg libs,
8 compile main.c and link the compiler output file to your ffmpeg libs
9 (we favor the static libs), freetype2 lib (we favor the static lib),
9 10 your alsa lib (we should make this dynamically loaded). the vulkan your alsa lib (we should make this dynamically loaded). the vulkan
10 11 loader lib and x11 xcb libs will be dynamically loaded. you have to loader lib and x11 xcb libs will be dynamically loaded. you have to
11 12 define the preprocessor macro static as empty or "static". you will define the preprocessor macro static as empty or "static". you will
File npv/config.h changed (mode: 100644) (index 375df09..e28b352)
2 2 #define NPV_CONFIG_H #define NPV_CONFIG_H
3 3 #include <stdlib.h> #include <stdlib.h>
4 4 #include "npv/c_fixing.h" #include "npv/c_fixing.h"
5 /* NotoSansSymbols2 is the only one with the play and pause symbols */
6 STATIC u8 *npv_faces[] = {
7 "/share/fonts/noto/NotoMono-Regular.ttf",
8 "/share/fonts/noto/NotoSansSymbols-Regular.ttf",
9 "/share/fonts/noto/NotoSansSymbols2-Regular.ttf",
10 "/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf",
11 "/usr/share/fonts/truetype/noto/NotoSansSymbols-Regular.ttf",
12 "/usr/share/fonts/truetype/noto/NotoSansSymbols2-Regular.ttf",
13 0
14 };
5 15 /* we don't use a xkb state machine, only bear 8bits truncated raw keycodes */ /* we don't use a xkb state machine, only bear 8bits truncated raw keycodes */
6 16 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
7 17 STATIC void npv_cmd_quit(void); STATIC void npv_cmd_quit(void);
 
... ... STATIC void npv_cmd_fastforward_big(void);
12 22 STATIC void npv_cmd_vol_up(void); STATIC void npv_cmd_vol_up(void);
13 23 STATIC void npv_cmd_vol_down(void); STATIC void npv_cmd_vol_down(void);
14 24 STATIC void npv_cmd_mute(void); STATIC void npv_cmd_mute(void);
15 STATIC void npv_cmd_info(void);
25 STATIC void npv_cmd_osd_timer_toggle(void);
16 26 STATIC void npv_cmd_pause(void); STATIC void npv_cmd_pause(void);
17 27 STATIC void npv_cmd_fullscreen_toggle(void); STATIC void npv_cmd_fullscreen_toggle(void);
18 28 /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
 
... ... struct npv_x11_bind_t npv_x11_binds[] = {
39 49 X11_BIND(0x6f, "arrow up", npv_cmd_vol_up), X11_BIND(0x6f, "arrow up", npv_cmd_vol_up),
40 50 X11_BIND(0x74, "arrow down", npv_cmd_vol_down), X11_BIND(0x74, "arrow down", npv_cmd_vol_down),
41 51 X11_BIND(0x48, "f6", npv_cmd_mute), X11_BIND(0x48, "f6", npv_cmd_mute),
42 X11_BIND(0x43, "f1", npv_cmd_info),
52 X11_BIND(0x43, "f1", npv_cmd_osd_timer_toggle),
43 53 X11_BIND(0x5f, "f11", npv_cmd_fullscreen_toggle) X11_BIND(0x5f, "f11", npv_cmd_fullscreen_toggle)
44 54 }; };
45 55 #undef X11_BIND #undef X11_BIND
File npv/local/code.frag.c changed (mode: 100644) (index 407220a..70847d5)
... ... STATIC void opts_parse(int argc, u8 **args, u8 **url, bool* start_fullscreen,
430 430 STATIC void init_once(u8 *url, bool start_fullscreen, double initial_vol, STATIC void init_once(u8 *url, bool start_fullscreen, double initial_vol,
431 431 u16 win_width, u16 win_height, u8 *pcm_str, u16 win_width, u16 win_height, u8 *pcm_str,
432 432 avcodec_params_t **audio_codec_params, avcodec_params_t **audio_codec_params,
433 avcodec_params_t **video_codec_params)
433 avcodec_params_t **video_codec_params,
434 u8 **faces)
434 435 { {
435 436 avutil_rational_t *audio_st_tb; avutil_rational_t *audio_st_tb;
436 437 avutil_rational_t *video_st_tb; avutil_rational_t *video_st_tb;
 
... ... STATIC void init_once(u8 *url, bool start_fullscreen, double initial_vol,
442 443 /* before audio_st_idx_p is actually used */ /* before audio_st_idx_p is actually used */
443 444 npv_audio_init_once(pcm_str); npv_audio_init_once(pcm_str);
444 445 npv_video_init_once(); /* before video_st_idx_p is actually used */ npv_video_init_once(); /* before video_st_idx_p is actually used */
446 npv_video_osd_init_once(faces);
445 447 npv_clk_init_once(); npv_clk_init_once();
446 448 npv_pipeline_init_once(); npv_pipeline_init_once();
447 449
 
... ... STATIC void prepare(double initial_vol, u8 pkts_prefill_percent,
497 499
498 500 evt_add_all_fds(); evt_add_all_fds();
499 501 } }
500 /*==== while waiting for the osd -- start ====================================*/
501 STATIC u8 *duration_estimate_to_str(enum AVDurationEstimationMethod m)
502 {
503 switch (m) {
504 case AVFMT_DURATION_FROM_PTS:
505 return "from PTS(Presentation TimeStamp)";
506 case AVFMT_DURATION_FROM_STREAM:
507 return "from stream";
508 case AVFMT_DURATION_FROM_BITRATE:
509 return "from bitrate";
510 default:
511 return "unkwown";
512 }
513 }
514 STATIC u8 *ts_to_str(int64_t ts, avutil_rational_t time_base,
515 int64_t *remaining)
516 {
517 static u8 str[sizeof("~S00:00:00.000 remains S9223372036854775807 time base units")];
518 bool is_neg;
519 int64_t hours_n;
520 int64_t mins_n;
521 int64_t secs_n;
522 int64_t msecs_n;
523 int64_t one_hour; /* in ffmpeg time_base units */
524 int64_t one_min; /* in ffmpeg time_base units */
525 int64_t one_sec; /* in ffmpeg time_base units */
526 int64_t one_msec; /* in ffmpeg time_base units */
527
528 if (ts < 0) {
529 ts = -ts;
530 is_neg = true;
531 } else
532 is_neg = false;
533
534 one_hour = INT64_C(3600) * (int64_t)time_base.den
535 / (int64_t)time_base.num;
536 one_min = INT64_C(60) * (int64_t)time_base.den
537 / (int64_t)time_base.num;
538 one_sec = (int64_t)time_base.den / (int64_t)time_base.num;
539 one_msec = one_sec / INT64_C(1000);
540
541 hours_n = ts / one_hour;
542
543 *remaining = ts % one_hour;
544 mins_n = *remaining / one_min;
545
546 *remaining = *remaining % one_min;
547 secs_n = *remaining / one_sec;
548
549 *remaining = *remaining % one_sec;
550 msecs_n = *remaining / one_msec;
551
552 /* account for all rounding errors */
553 *remaining = ts - (hours_n * one_hour + mins_n * one_min
554 + secs_n * one_sec + msecs_n * one_msec);
555 if (!is_neg)
556 snprintf(str, sizeof(str), "%02"PRId64":%02"PRId64":%02"PRId64".%03"PRId64, hours_n, mins_n, secs_n, msecs_n);
557 else {
558 str[0] = '-';
559 snprintf(str + 1, sizeof(str) - 1, "%02"PRId64":%02"PRId64":%02"PRId64".%03"PRId64, hours_n, mins_n, secs_n, msecs_n);
560 }
561 return str;
562 }
563 #define RED if (stdout_is_tty) pout("\x1b[38;2;255;0;0m")
564 #define GREEN if (stdout_is_tty) pout("\x1b[38;2;0;255;0m")
565 #define BLUE if (stdout_is_tty) pout("\x1b[38;2;0;0;255m")
566 #define PURPLE if (stdout_is_tty) pout("\x1b[38;2;255;0;255m")
567 #define RESTORE if (stdout_is_tty) pout("\x1b[39;49m");
568 #define TS_FROM_CLK_OK 0
569 /* we don't lock anything as an act of faith */
570 STATIC void npv_cmd_info(void)
571 {
572 int ri;
573 u8 r8;
574 s64 audio_now;
575 bool stdout_is_tty;
576 u8 *ts_str;
577 int64_t remaining;
578 u8 duration_str[sizeof("S9223372036854775807")];
579
580 ri = isatty(1);
581 if (ri == 0)
582 stdout_is_tty = false;
583 else
584 stdout_is_tty = true;
585
586 RESTORE;
587 GREEN;pout("================================================================================\n");RESTORE;
588 PURPLE;pout("%s\n", npv_fmt_ctx_p->url);RESTORE;
589
590 r8 = npv_clk_get_audio_st_ts(&audio_now);
591 if (r8 != TS_FROM_CLK_OK) {
592 pout("information unavailable at the time of the command due to an unavailable audio clock\n");
593 return;
594 }
595 ts_str = ts_to_str(audio_now, npv_audio_st_p.tb, &remaining);
596 RED;pout("%s", ts_str);RESTORE;
597 if (remaining != 0)
598 pout(" remaining %"PRId64" time base units", remaining);
599 else
600 pout("\n");
601 pout("\t%"PRId64" stream time base units (%d/%d seconds)\n",
602 audio_now, npv_audio_st_p.tb.num, npv_audio_st_p.tb.den);
603 BLUE;pout("--------------------------------------------------------------------------------\n");RESTORE;
604 pout("format:");
605 if (npv_fmt_ctx_p->duration == AV_NOPTS_VALUE) {
606 pout("duration is not provided\n");
607 } else {
608 snprintf(duration_str, sizeof(duration_str), "%"PRId64,
609 npv_fmt_ctx_p->duration);
610 ts_str = ts_to_str(npv_fmt_ctx_p->duration, AV_TIME_BASE_Q,
611 &remaining);
612 pout("duration=");RED;pout("%s", ts_str);RESTORE;
613 if (remaining != 0)
614 pout(" remaining %"PRId64" av_time_base units\n",
615 remaining);
616 else
617 pout("\n");
618 pout("\t%s av_time_base units (1/%d seconds)\n\testimation method is %s\n",
619 duration_str, AV_TIME_BASE, duration_estimate_to_str(
620 npv_fmt_ctx_p->duration_estimation_method));
621 }
622 BLUE;pout("--------------------------------------------------------------------------------\n");RESTORE;
623 pout("stream:audio_id=%d", npv_audio_st_p.id);
624 if (npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->duration == AV_NOPTS_VALUE) {
625 pout(";duration is not provided\n");
626 } else {
627 snprintf(duration_str, sizeof(duration_str), "%"PRId64,
628 npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->duration);
629 ts_str = ts_to_str(
630 npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->duration,
631 npv_audio_st_p.tb, &remaining);
632 pout(";duration=");RED;pout("%s\n", ts_str);RESTORE;
633 if (remaining != 0)
634 pout(" remaining %"PRId64" stream time base units\n",
635 remaining);
636 else
637 pout("\n");
638 pout("\t%s stream time base units (%d/%d seconds)\n",
639 duration_str, npv_audio_st_p.tb.num,
640 npv_audio_st_p.tb.den);
641 }
642 BLUE;pout("--------------------------------------------------------------------------------\n");RESTORE;
643 GREEN;pout("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");RESTORE;
644 }
645 #undef TS_FROM_CLK_OK
646 #undef RED
647 #undef GREEN
648 #undef BLUE
649 #undef PURPLE
650 #undef RESTORE
651 /*==== while waiting for the osd -- end ======================================*/
652 502 STATIC void npv_cmd_quit(void) STATIC void npv_cmd_quit(void)
653 503 { {
654 504 exit_ok("quit command received\n"); exit_ok("quit command received\n");
 
... ... int main(int argc, u8 **args)
847 697 &pcm_str, &initial_vol, &pcm_str, &initial_vol,
848 698 &npv_pipeline_limits_p.pkts.prefill.percent); &npv_pipeline_limits_p.pkts.prefill.percent);
849 699 init_once(url, start_fullscreen, initial_vol, win_width, win_height, init_once(url, start_fullscreen, initial_vol, win_width, win_height,
850 pcm_str, &audio_codec_params, &video_codec_params);
700 pcm_str, &audio_codec_params, &video_codec_params, npv_faces);
851 701 prepare(initial_vol, npv_pipeline_limits_p.pkts.prefill.percent, prepare(initial_vol, npv_pipeline_limits_p.pkts.prefill.percent,
852 702 audio_codec_params, video_codec_params); audio_codec_params, video_codec_params);
853 703
File npv/main.c changed (mode: 100644) (index 1e9ab6e..2089b02)
37 37 #include "npv/audio/filt/public.h" #include "npv/audio/filt/public.h"
38 38 #include "npv/audio/public.h" #include "npv/audio/public.h"
39 39 #include "npv/video/public.h" #include "npv/video/public.h"
40 #include "npv/video/osd/public.h"
40 41 #include "npv/xcb/public.h" #include "npv/xcb/public.h"
41 42 #include "npv/vk/public.h" #include "npv/vk/public.h"
42 43 #include "npv/thdsws/public.h" #include "npv/thdsws/public.h"
 
66 67 #include "npv/fmt/main.c" #include "npv/fmt/main.c"
67 68 #include "npv/audio/main.c" #include "npv/audio/main.c"
68 69 #include "npv/audio/filt/main.c" #include "npv/audio/filt/main.c"
70 #include "npv/video/osd/main.c"
69 71 #include "npv/video/main.c" #include "npv/video/main.c"
70 72 #include "npv/xcb/main.c" #include "npv/xcb/main.c"
71 73 #include "npv/vk/main.c" #include "npv/vk/main.c"
File npv/make-template.sh changed (mode: 100755) (index b95910a..6417689)
1 1 #!/bin/sh #!/bin/sh
2 2 cc main.c -lc -ldl -D_GNU_SOURCE -DSTATIC=static -I../ \ cc main.c -lc -ldl -D_GNU_SOURCE -DSTATIC=static -I../ \
3 3 $(pkg-config --cflags xcb) \ $(pkg-config --cflags xcb) \
4 $(pkg-config --cflags --libs libavcodec libavdevice libavfilter \
5 libavformat libavutil libpostproc libswresample libswscale \
6 alsa) \
4 $(pkg-config --cflags --libs alsa) \
5 $(pkg-config --cflags --libs --static freetype2 libavcodec libavdevice \
6 libavfilter libavformat libavutil libpostproc libswresample \
7 libswscale) \
7 8 -o /tmp/npv -o /tmp/npv
File npv/video/local/code.frag.c changed (mode: 100644) (index 0ccccd2..9c78014)
... ... STATIC u8 send_to_pe(u32 swpchn_img)
598 598 STATIC void start_scaling(avutil_video_fr_ref_t *fr, STATIC void start_scaling(avutil_video_fr_ref_t *fr,
599 599 struct dec_fr_priv_t *fr_priv, bool *scaler_dims_changed) struct dec_fr_priv_t *fr_priv, bool *scaler_dims_changed)
600 600 { {
601 u32 scaled_line_bytes_n;
602
603 601 if (scaler_p.ctx->cfg.width != fr->width if (scaler_p.ctx->cfg.width != fr->width
604 602 || scaler_p.ctx->cfg.height != fr->height) { || scaler_p.ctx->cfg.height != fr->height) {
605 603 if (scaler_p.img.vk != 0) if (scaler_p.img.vk != 0)
 
... ... STATIC void start_scaling(avutil_video_fr_ref_t *fr,
615 613 *scaler_dims_changed = true; *scaler_dims_changed = true;
616 614 scaler_p.ctx->cfg.width = fr->width; scaler_p.ctx->cfg.width = fr->width;
617 615 scaler_p.ctx->cfg.height = fr->height; scaler_p.ctx->cfg.height = fr->height;
616 npv_video_osd_update_dimensions(scaler_p.img.data,
617 (u16)fr->width, (u16)fr->height,
618 (u32)scaler_p.img.layout.row_pitch);
618 619 } else } else
619 620 *scaler_dims_changed = false; *scaler_dims_changed = false;
620 621 scaler_p.ctx->cfg.src_fmt = fr->fmt; scaler_p.ctx->cfg.src_fmt = fr->fmt;
621 622 scaler_p.ctx->cfg.dst_fmt = AVUTIL_PIX_FMT_RGB32; scaler_p.ctx->cfg.dst_fmt = AVUTIL_PIX_FMT_RGB32;
622 623 scaler_p.ctx->cfg.flags = SWS_POINT; /* | SWS_PRINT_INFO */ scaler_p.ctx->cfg.flags = SWS_POINT; /* | SWS_PRINT_INFO */
623 624
624 scaled_line_bytes_n = (u32)scaler_p.img.layout.row_pitch;
625 625 scaler_p.ctx->scale.src_slices = fr->data; scaler_p.ctx->scale.src_slices = fr->data;
626 626 scaler_p.ctx->scale.src_strides = fr->linesize; scaler_p.ctx->scale.src_strides = fr->linesize;
627 627 scaler_p.ctx->scale.dst_slice = scaler_p.img.data; scaler_p.ctx->scale.dst_slice = scaler_p.img.data;
628 scaler_p.ctx->scale.dst_stride = scaled_line_bytes_n;
628 scaler_p.ctx->scale.dst_stride = (u32)scaler_p.img.layout.row_pitch;
629 629 npv_thdsws_run(scaler_p.ctx); npv_thdsws_run(scaler_p.ctx);
630 630 scaler_p.img.fr = fr; scaler_p.img.fr = fr;
631 /*
632 * saved pixs for restoration are now irrelevant since we did
633 * overwrite everything
634 */
635 npv_video_osd_clear_dirty();
631 636 } }
632 637 STATIC void timer_ack(void) STATIC void timer_ack(void)
633 638 { {
 
... ... STATIC void timer_ack(void)
637 642 exps_n = 0; exps_n = 0;
638 643 r = read(timer_fd_p, &exps_n, sizeof(exps_n)); r = read(timer_fd_p, &exps_n, sizeof(exps_n));
639 644 if (r == -1) if (r == -1)
640 fatal("unable to read the number of timer expirations\n");
645 warning("unable to read the number of timer expirations\n");
641 646 } }
File npv/video/osd/ABBREVIATIONS added (mode: 100644) (index 0000000..4dac451)
1 bg(s) : BitmapGlyph(S)
2 g(s) : Glyph(S)
3 GLOBAL:max : MAXimum
File npv/video/osd/local/code.frag.c added (mode: 100644) (index 0000000..3fe63eb)
1 STATIC void fatal(void *fmt, ...)
2 {
3 va_list ap;
4
5 npv_perr("osd:");
6 va_start(ap, fmt);
7 npv_vfatal(fmt, ap);
8 va_end(ap);
9 exit(EXIT_FAILURE);
10 }
11 STATIC void warning(void *fmt, ...)
12 {
13 va_list ap;
14
15 npv_perr("osd:");
16 va_start(ap, fmt);
17 npv_vwarning(fmt,ap);
18 va_end(ap);
19 }
20 STATIC void pout(void *fmt, ...)
21 {
22 va_list ap;
23
24 npv_pout("osd:");
25 va_start(ap, fmt);
26 npv_vpout(fmt, ap);
27 va_end(ap);
28 }
29 /*NSPC*/
30 STATIC void cache_nodes_release(void)
31 {
32 u8 i;
33
34 i = 0;
35 loop {
36 if (i == GS_N)
37 break;
38 if (cache_l.gs[i].node != 0) {
39 FTC_Node_Unref(cache_l.gs[i].node, cache_l.manager);
40 cache_l.gs[i].node = 0;
41 }
42 ++i;
43 }
44 }
45 /*NSPC*/
46 STATIC void finalizer(void *object)
47 {
48 FT_Face f;
49 FT_Face *f_ptr;
50
51 f = object;
52 f_ptr = f->generic.data; /* we need to zero our pointer */
53 *f_ptr = 0;
54 }
55 /*NSPC*/
56 STATIC void face_lookup(FT_Face *f, u8 i)
57 {
58 FT_Error ft_r;
59
60 if (cache_l.faces.ft[i] != 0) {
61 *f = cache_l.faces.ft[i];
62 return;
63 }
64 ft_r = FTC_Manager_LookupFace(cache_l.manager, &cache_l.faces.ids[i],
65 f);
66 if (ft_r != FT_Err_Ok)
67 fatal("freetype:cache_l:unable to lookup for face %s\n", cache_l.faces.files[i]);
68 }
69 /*NSPC*/
70 STATIC void gs_init_once(void)
71 {
72 u8 i;
73
74 cache_l.gs[G_PERCENT_SIGN].unicode = 0x25;
75 cache_l.gs[G_SOLIDUS].unicode = 0x2f;
76 cache_l.gs[G_0].unicode = 0x30;
77 cache_l.gs[G_1].unicode = 0x31;
78 cache_l.gs[G_2].unicode = 0x32;
79 cache_l.gs[G_3].unicode = 0x33;
80 cache_l.gs[G_4].unicode = 0x34;
81 cache_l.gs[G_5].unicode = 0x35;
82 cache_l.gs[G_6].unicode = 0x36;
83 cache_l.gs[G_7].unicode = 0x37;
84 cache_l.gs[G_8].unicode = 0x38;
85 cache_l.gs[G_9].unicode = 0x39;
86 cache_l.gs[G_COLON].unicode = 0x3a;
87 cache_l.gs[G_QUESTION_MARK].unicode = 0x3f;
88 cache_l.gs[G_MINUS].unicode = 0x2212;
89 cache_l.gs[G_PLAY].unicode = 0x23f5;
90 cache_l.gs[G_PAUSE].unicode = 0x23f8;
91 cache_l.gs[G_BLACK_LOWER_RIGHT_TRIANGLE].unicode= 0x25e2;
92
93 i = 0;
94 loop {
95 u8 j;
96
97 if (i == GS_N)
98 break;
99 j = 0;
100 loop {
101 FT_Face f;
102
103 if (j == cache_l.faces.n) {
104 warning("freetype:unable to find a valid glyph index for our glyph %u\n", i);
105 cache_l.gs[i].face_id = 0;
106 break;
107 }
108 face_lookup(&f, j);
109 cache_l.gs[i].idx = FT_Get_Char_Index(f,
110 cache_l.gs[i].unicode);
111 if (cache_l.gs[i].idx != 0) {
112 cache_l.gs[i].face_id = j;
113 break;
114 }
115 ++j;
116 }
117 ++i;
118 }
119 }
120 STATIC void out_tt_interpreters(FT_UInt iv)
121 {
122 if ((TT_INTERPRETER_VERSION_35 & iv) != 0)
123 pout("freetype:truetype:hinting interpreter version 35 available\n");
124 if ((TT_INTERPRETER_VERSION_38 & iv) != 0)
125 pout("freetype:truetype:hinting interpreter version 38 available\n");
126 if ((TT_INTERPRETER_VERSION_40 & iv) != 0)
127 pout("freetype:truetype:hinting interpreter version 40 available\n");
128 }
129 STATIC u8 *hinting_engine_str(FT_Int32 he)
130 {
131 if (he == FT_HINTING_FREETYPE)
132 return "freetype";
133 else if (he == FT_HINTING_ADOBE)
134 return "adobe";
135 else
136 return "unknown";
137 }
138 /* the id is the idx in the faces/fonts arrays */
139 STATIC FT_Error face_requester(FTC_FaceID face_id, FT_Library lib,
140 FT_Pointer unused, FT_Face *aface)
141 {
142 FT_Error ft_r;
143 u8 *id;
144
145 id = face_id;
146 if (id == 0) {
147 warning("freetype:cache_l:requester:no face id\n");
148 return FT_Err_Invalid_Argument;
149 }
150 /* presume ptr equality means the same */
151 if (lib != library_l) {
152 warning("freetype:cache_l:requester:wrong lib\n");
153 return FT_Err_Invalid_Library_Handle;
154 }
155 if (cache_l.faces.ft[*id] != NULL)
156 goto exit;
157 ft_r = FT_New_Face(lib, cache_l.faces.files[*id], -1,
158 &cache_l.faces.ft[*id]);
159 if (ft_r != FT_Err_Ok) {
160 warning("freetype:unable to load the face(s) %s:%d\n", cache_l.faces.files[*id], ft_r);
161 return ft_r;
162 }
163 pout("freetype:face %s has %ld faces\n", cache_l.faces.files[*id], cache_l.faces.ft[*id]->num_faces);
164 ft_r = FT_Done_Face(cache_l.faces.ft[*id]);
165 if (ft_r != FT_Err_Ok) {
166 warning("freetype:unable to unload the face(s) %s:%d\n", cache_l.faces.files[*id], ft_r);
167 return ft_r;
168 }
169 pout("freetype:opening face 0 of %s\n", cache_l.faces.files[*id]);
170 ft_r = FT_New_Face(lib, cache_l.faces.files[*id], 0,
171 &cache_l.faces.ft[*id]);
172 if (ft_r != FT_Err_Ok) {
173 warning("freetype:unable to open the face 0 from %s:%d\n", cache_l.faces.files[*id], ft_r);
174 return ft_r;
175 }
176 /* install finalizer, to know when the cache let it go */
177 cache_l.faces.ft[*id]->generic.finalizer = finalizer;
178 cache_l.faces.ft[*id]->generic.data = &cache_l.faces.ft[*id];
179
180 pout("freetype:face 0 of %s:\n", cache_l.faces.files[*id]);
181 pout("freetype:\tnumber of glyphs = %ld\n", cache_l.faces.ft[*id]->num_glyphs);
182 pout("freetype:\tfamily name=%s\n", cache_l.faces.ft[*id]->family_name);
183 if (cache_l.faces.ft[*id]->style_name != 0)
184 pout("freetype:\tstyle name=%s\n", cache_l.faces.ft[*id]->style_name);
185 exit:
186 *aface = cache_l.faces.ft[*id];
187 return FT_Err_Ok;
188 }
189 /*NSPC*/
190 STATIC void timer_baseline_compute(void)
191 {
192 FT_Int max;
193 u8 i;
194 /*
195 * get the max distance, in n of lines, from the baseline, _excluded_,
196 * of the _rendered_ gs: play/pause, 0..9 and colon
197 */
198 max = cache_l.gs[G_PLAY].bg->top;
199 if (cache_l.gs[G_PAUSE].bg->top > max)
200 max = cache_l.gs[G_PAUSE].bg->top;
201 i = G_0;
202 loop {
203 if (i > G_COLON)
204 break;
205 if (cache_l.gs[i].bg->top > max)
206 max = cache_l.gs[i].bg->top;
207 ++i;
208 }
209 pout("timer:baseline:max top=%d\n", max);
210 timer_baseline_l = (u16)max;
211 }
212 /*NSPC*/
213 STATIC u32 digit_advance_max(void)
214 {
215 u8 i;
216 u32 max;
217 u16 max_i;
218 u16 max_f;
219
220 max = cache_l.gs[G_0].bg->root.advance.x;
221 max_i = (u16)(max >> 16);
222 max_f = (u16)(max & 0xffff);
223 i = G_1;
224 loop {
225 u32 digit_advance;
226 u16 digit_advance_i;
227 u16 digit_advance_f;
228
229 if (i > G_9)
230 break;
231 digit_advance = (u32)(cache_l.gs[i].bg->root.advance.x);
232 digit_advance_i = (u16)(digit_advance >> 16);
233 digit_advance_f = (u16)(digit_advance & 0xffff);
234 if (digit_advance_i > max_i) {
235 max_i = digit_advance_i;
236 max_f = digit_advance_f;
237 } else if (digit_advance_i == max_i) {
238 if (digit_advance_f > max_f) {
239 max_i = digit_advance_i;
240 max_f = digit_advance_f;
241 }
242 }
243 ++i;
244 }
245 return max;
246 }
247 /* template:S100% where S is the a volume symbol */
248 /*NSPC*/
249 STATIC void volume_pen_start_location_compute(u16 width, u16 height)
250 {
251 u16 steps;
252 u16 indicator_start_column;
253 s16 indicator_width; /* we can start as a negative number */
254 u32 advance;
255 u16 advance_i;
256 u16 advance_f;
257 /*
258 * we must take into account the "full" width of the left glyph, namely
259 * the volume symbol, and the "full" width of the right glyph, namely
260 * the percent glyph
261 */
262 /*
263 * we add or remove some colums, that depends on the "left" position of
264 * the glyph bitmap from the pen position: if the left border of the
265 * bitmap is "before" the pen position ("left" is <0), we add some
266 * colmuns. if the left border of the bitmap is "after" the pen
267 * position ("left is >=0), we remove some columns. (yes, this is
268 * excessive brain f*ckage)
269 */
270 indicator_width = (s16)(-cache_l.gs[G_PERCENT_SIGN].bg->left);
271 advance = (u32)cache_l.gs[G_PERCENT_SIGN].bg->root.advance.x;
272 advance_i = (u16)(advance >> 16);
273 advance_f = (u16)(advance & 0xffff);
274 indicator_width += (s16)(advance_i + (advance_f != 0 ? 1 : 0));
275 /* for the digits, we account only the advance width */
276 advance = (u32)cache_l.gs[G_1].bg->root.advance.x;
277 advance_i = (u16)(advance >> 16);
278 advance_f = (u16)(advance & 0xffff);
279 indicator_width += (s16)(advance_i + (advance_f != 0 ? 1 : 0));
280 advance = digit_advance_max();
281 advance_i = (u16)(advance >> 16);
282 advance_f = (u16)(advance & 0xffff);
283 indicator_width += 2 * (advance_i + (advance_f != 0 ? 1 : 0));
284 /* we must account of the "full width of the last symbol */
285 indicator_width += (s16)cache_l.gs[G_PERCENT_SIGN].bg->left;
286 /* divided by 3, because the bitmap is lcd decimated, see freetype doc*/
287 indicator_width += (s16)(cache_l.gs[G_PERCENT_SIGN].bg->bitmap.width
288 / 3);
289 volume_l.baseline = height / 2; /* ~ middle of the screen */
290 /*
291 * should be "enough", and we re-adjust the start pen position based
292 * on the columns we did add or remove
293 */
294 volume_l.start_column = (width - (u16)indicator_width) / 2;
295 volume_l.start_column = (u16)((s16)volume_l.start_column
296 - (s16)cache_l.gs[G_PERCENT_SIGN].bg->left);
297 }
298 /*
299 * in order:
300 * - fmt
301 * - audio st (we are audio driven)
302 * - video st
303 */
304 /*NSPC*/
305 STATIC bool duration_resolve(int64_t *duration, avutil_rational_t *tb)
306 {
307 if (npv_fmt_ctx_p->duration != AV_NOPTS_VALUE) {
308 *duration = npv_fmt_ctx_p->duration;
309 memcpy(tb, &AV_TIME_BASE_Q, sizeof(*tb));
310 return true;
311 }
312 if (npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->duration != AV_NOPTS_VALUE) {
313 *duration =
314 npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->duration;
315 memcpy(tb, &(npv_fmt_ctx_p->streams[npv_audio_st_p.idx]->tb),
316 sizeof(*tb));
317 return true;
318 }
319 if (npv_fmt_ctx_p->streams[npv_video_st_p.idx]->duration != AV_NOPTS_VALUE) {
320 *duration =
321 npv_fmt_ctx_p->streams[npv_video_st_p.idx]->duration;
322 memcpy(tb, &(npv_fmt_ctx_p->streams[npv_video_st_p.idx]->tb),
323 sizeof(*tb));
324 return true;
325 }
326 return false;
327 }
328 /*NSPC*/
329 STATIC u8 *timer_to_gs(int64_t ts, avutil_rational_t tb)
330 {
331 /* P = Play, S = minus Sign */
332 static u8 gs[sizeof(TIMER_TMPL)];
333 u8 i;
334 bool is_neg;
335 int64_t remaining;
336 int64_t hours_n;
337 int64_t hours_d;
338 int64_t hours_dx;
339 int64_t mins_n;
340 int64_t secs_n;
341 int64_t msecs_n;
342 int64_t one_hour; /* in ffmpeg time_base units */
343 int64_t one_min; /* in ffmpeg time_base units */
344 int64_t one_sec; /* in ffmpeg time_base units */
345 int64_t one_msec; /* in ffmpeg time_base units */
346 int64_t duration;
347 avutil_rational_t duration_tb;
348
349 i = 0;
350 if (npv_paused_p)
351 gs[i++] = G_PAUSE;
352 else
353 gs[i++] = G_PLAY;
354
355 if (ts < 0) {
356 ts = -ts;
357 is_neg = true;
358 gs[i++] = G_MINUS;
359 } else
360 is_neg = false;
361
362 one_hour = INT64_C(3600) * (int64_t)tb.den / (int64_t)tb.num;
363 one_min = INT64_C(60) * (int64_t)tb.den / (int64_t)tb.num;
364 one_sec = (int64_t)tb.den / (int64_t)tb.num;
365 one_msec = one_sec / INT64_C(1000);
366
367 hours_n = ts / one_hour;
368 if (hours_n >= 100) {
369 gs[i++] = G_QUESTION_MARK;
370 gs[i++] = G_QUESTION_MARK;
371 } else {
372 gs[i++] = hours_n / 10 + G_0;
373 gs[i++] = hours_n % 10 + G_0;
374 }
375 gs[i++] = G_COLON;
376
377 remaining = ts % one_hour;
378 mins_n = remaining / one_min;
379 gs[i++] = mins_n / 10 + G_0;
380 gs[i++] = mins_n % 10 + G_0;
381
382 gs[i++] = G_COLON;
383
384 remaining = remaining % one_min;
385 secs_n = remaining / one_sec;
386 gs[i++] = secs_n / 10 + G_0;
387 gs[i++] = secs_n % 10 + G_0;
388
389 gs[i++] = G_SOLIDUS;
390 /*--------------------------------------------------------------------*/
391 /* duration */
392 if (!duration_resolve(&duration, &duration_tb)) {
393 gs[i++] = G_QUESTION_MARK;
394 gs[i++] = G_QUESTION_MARK;
395 gs[i++] = G_COLON;
396 gs[i++] = G_QUESTION_MARK;
397 gs[i++] = G_QUESTION_MARK;
398 gs[i++] = G_COLON;
399 gs[i++] = G_QUESTION_MARK;
400 gs[i++] = G_QUESTION_MARK;
401 goto exit;
402 }
403 one_hour = INT64_C(3600) * (int64_t)duration_tb.den
404 / (int64_t)duration_tb.num;
405 one_min = INT64_C(60) * (int64_t)duration_tb.den
406 / (int64_t)duration_tb.num;
407 one_sec = (int64_t)duration_tb.den / (int64_t)duration_tb.num;
408 one_msec = one_sec / INT64_C(1000);
409
410 hours_n = duration / one_hour;
411 if (hours_n >= 100) {
412 gs[i++] = G_QUESTION_MARK;
413 gs[i++] = G_QUESTION_MARK;
414 } else {
415 gs[i++] = hours_n / 10 + G_0;
416 gs[i++] = hours_n % 10 + G_0;
417 }
418 gs[i++] = G_COLON;
419
420 remaining = duration % one_hour;
421 mins_n = remaining / one_min;
422 gs[i++] = mins_n / 10 + G_0;
423 gs[i++] = mins_n % 10 + G_0;
424
425 gs[i++] = G_COLON;
426
427 remaining = remaining % one_min;
428 secs_n = remaining / one_sec;
429 gs[i++] = secs_n / 10 + G_0;
430 gs[i++] = secs_n % 10 + G_0;
431 /*--------------------------------------------------------------------*/
432 exit:
433 gs[i] = GS_N; /* perfect hash ! (ahah) */
434 return gs;
435 }
436 /*NSPC*/
437 struct pen_t {
438 s16 x;
439 s16 y;
440 };
441 /* FT_BitmapGlyph is a ptr */
442 #define BLEND 0
443 /*NSPC*/
444 static void g_x(bool mode, FT_BitmapGlyph gb, struct pen_t *p)
445 {
446 u8 *fr_row;
447 u8 *gb_row;
448 u8 *gb_rows_end; /* ptr on the row past the last one */
449 s16 x;
450 s16 y;
451
452 gb_row = gb->bitmap.buffer;
453 gb_rows_end = gb->bitmap.buffer + gb->bitmap.rows * gb->bitmap.pitch;
454 /* if top is 0, the bitmap top line is the baseline */
455 y = p->y - gb->top;
456 loop {
457 u8 *png_column;
458 u8 *gb_column;
459 u8 *gb_columns_end; /* ptr on the column past the last one */
460
461 if (gb_row == gb_rows_end)
462 break;
463 gb_column = gb_row;
464 /* fu... "decimation" */
465 gb_columns_end = gb_row + gb->bitmap.width;
466 x = p->x + gb->left;
467 loop {
468
469 if (gb_column == gb_columns_end)
470 break;
471 if (x >= 0 && y >= 0 && x < restore_l.width
472 && y < restore_l.height) {
473 u8 p;
474 u8 *scaler_pix;
475 u8 *restore_pix;
476 u32 offset;
477
478 offset = restore_l.line_bytes_n * y + (3 + 1)
479 * x;
480 scaler_pix = (u8*)restore_l.scaler_pixs
481 + offset;
482 restore_pix = (u8*)restore_l.pixs + offset;
483 /*
484 * the img is sRGB encoded, we "cheat" here,
485 * using glyph bitmap linear RGB
486 */
487 p = 0;
488 loop {
489 if (p == 3)
490 break;
491 if (gb_column[p] != 0) {
492 if (mode == BLEND) {
493 restore_pix[p] =
494 scaler_pix[p];
495 scaler_pix[p] =
496 gb_column[p];
497 } else /* RESTORE */
498 scaler_pix[p] =
499 restore_pix[p];
500 }
501 ++p;
502 }
503 /*
504 * don't know how vulkan hw will interpret the
505 * alpha channel
506 */
507 if (gb_column[0] != 0 || gb_column[1] != 0
508 || gb_column[2] != 0 ) {
509 if (mode == BLEND) {
510 restore_pix[3] = scaler_pix[3];
511 scaler_pix[3] = 0xff;
512 } else /* RESTORE */
513 scaler_pix[3] = restore_pix[3];
514 }
515 }
516 gb_column += 3;
517 ++x;
518 }
519 gb_row += gb->bitmap.pitch;
520 ++y;
521 }
522 }
523 #undef BLEND
524 #define BLEND 0
525 /*NSPC*/
526 STATIC void rop_x(u8 mode, u8 *gs)
527 {
528 struct pen_t pen;
529 u8 i;
530
531 if (mode == BLEND)
532 memcpy(restore_l.timer_gs, gs, sizeof(TIMER_TMPL));
533 pen.x = 0;
534 pen.y = timer_baseline_l;
535 i = 0;
536 loop {
537 FT_BitmapGlyph bg;
538 u32 advance_x;
539 s16 advance_x_i;
540 u16 advance_x_f;
541
542 if (gs[i] == GS_N)
543 break;
544 bg = cache_l.gs[gs[i]].bg;
545 g_x(mode, bg, &pen);
546 advance_x = bg->root.advance.x;
547 advance_x_i = advance_x >> 16;
548 advance_x_f = advance_x & 0xffff;
549 pen.x += advance_x_i + (s16)(advance_x_f != 0 ? 1 : 0);
550 ++i;
551 }
552 }
553 #undef BLEND
File npv/video/osd/local/state.frag.c added (mode: 100644) (index 0000000..0c599bb)
1 STATIC FT_Library library_l;
2 STATIC struct {
3 /*
4 * use caches, coze we will probably share fonts with libass,
5 * if libass is still properly coded and have a clean set of
6 * dependencies
7 */
8 FTC_Manager manager;
9 FTC_ImageCache img_cache;
10 struct {
11 u8 **files;
12 FT_Face *ft;
13 u8 *ids;
14 u8 n;
15 } faces;
16
17 struct {
18 FT_ULong unicode;
19
20 u8 face_id;
21 FT_UInt idx;
22 FT_BitmapGlyph bg;
23 FTC_Node node;
24 } gs[GS_N];
25 } cache_l;
26 /*NSPC*/
27 STATIC u16 timer_baseline_l;
28 /*NSPC*/
29 STATIC struct {
30 u16 baseline;
31 u16 start_column;
32 } volume_l;
33 /* only used to restore pixels from a paused img */
34 /*NSPC*/
35 STATIC struct {
36 void *scaler_pixs;
37 void *pixs;
38 s16 width;
39 s16 height;
40 u32 line_bytes_n;
41 u8 timer_gs[sizeof(TIMER_TMPL)];
42 bool dirty;
43 } restore_l;
44 /*NSPC*/
45 STATIC bool timer_on;
File npv/video/osd/main.c added (mode: 100644) (index 0000000..49a4390)
1 #ifndef NPV_VIDEO_OSD_MAIN_C
2 #define NPV_VIDEO_OSD_MAIN_C
3 #include <stdint.h>
4 #include <stdarg.h>
5
6 #include <ft2build.h>
7 #include FT_FREETYPE_H
8 #include FT_CACHE_H
9 #include FT_MODULE_H
10 #include FT_DRIVER_H
11 #include FT_LCD_FILTER_H
12
13 #include "npv/c_fixing.h"
14 /*----------------------------------------------------------------------------*/
15 #include "npv/namespace/ffmpeg.h"
16 #include "npv/video/osd/namespace/public.h"
17 #include "npv/video/osd/namespace/main.c"
18 /*----------------------------------------------------------------------------*/
19 #define G_PERCENT_SIGN 0
20 #define G_SOLIDUS 1
21 #define G_0 2
22 #define G_1 3
23 #define G_2 4
24 #define G_3 5
25 #define G_4 6
26 #define G_5 7
27 #define G_6 8
28 #define G_7 9
29 #define G_8 10
30 #define G_9 11
31 #define G_COLON 12
32 #define G_QUESTION_MARK 13
33 #define G_MINUS 14
34 #define G_PLAY 15
35 #define G_PAUSE 16
36 #define G_BLACK_LOWER_RIGHT_TRIANGLE 17
37 #define GS_N 18
38 #define TIMER_TMPL "PS00:00:00/00:00:00"
39 /*----------------------------------------------------------------------------*/
40 #include "npv/video/osd/local/state.frag.c"
41 /*----------------------------------------------------------------------------*/
42 #include "npv/video/osd/local/code.frag.c"
43 #include "npv/video/osd/public/code.frag.c"
44 /*----------------------------------------------------------------------------*/
45 #undef G_PERCENT_SIGN
46 #undef G_SOLIDUS
47 #undef G_0
48 #undef G_1
49 #undef G_2
50 #undef G_3
51 #undef G_4
52 #undef G_5
53 #undef G_6
54 #undef G_7
55 #undef G_8
56 #undef G_9
57 #undef G_COLON
58 #undef G_QUESTION_MARK
59 #undef G_MINUS
60 #undef G_PLAY
61 #undef G_PAUSE
62 #undef G_BLACK_LOWER_RIGHT_TRIANGLE
63 #undef GS_N
64 #undef TIMER_TMPL
65 /*----------------------------------------------------------------------------*/
66 #define CLEANUP
67 #include "npv/namespace/ffmpeg.h"
68 #include "npv/video/osd/namespace/public.h"
69 #include "npv/video/osd/namespace/main.c"
70 #undef CLEANUP
71 #endif
File npv/video/osd/namespace/main.c added (mode: 100644) (index 0000000..1d192fe)
1 #ifndef CLEANUP
2 #define cache npv_video_osd_cache
3 #define face_requester npv_video_osd_face_requester
4 #define fatal npv_video_osd_fatal
5 #define hinting_engine_str npv_video_osd_hinting_engine_str
6 #define library npv_video_osd_library
7 #define out_tt_interpreters npv_video_osd_out_tt_interpreters
8 #define pout npv_video_osd_pout
9 #define timer_on npv_video_osd_timer_on
10 #define warning npv_video_osd_warning
11 /*----------------------------------------------------------------------------*/
12 #else
13 #undef cache
14 #undef face_requester
15 #undef fatal
16 #undef hinting_engine_str
17 #undef library
18 #undef out_tt_interpreters
19 #undef pout
20 #undef timer_on
21 #undef warning
22 #endif
File npv/video/osd/namespace/public.h added (mode: 100644) (index 0000000..2cc1041)
1 #ifndef CLEANUP
2 #define clear_dirty npv_video_osd_clear_dirty
3 #define init_once npv_video_osd_init_once
4 #define rop_blend npv_video_osd_rop_blend
5 #define rop_restore npv_video_osd_rop_restore
6 #define update_dimensions npv_video_osd_update_dimensions
7 /*----------------------------------------------------------------------------*/
8 #else
9 #undef clear_dirty
10 #undef init_once
11 #undef update_dimensions
12 #undef rop_blend
13 #undef rop_restore
14 #endif
File npv/video/osd/public.h added (mode: 100644) (index 0000000..fd39f5e)
1 #ifndef NPV_VIDEO_OSD_PUBLIC_H
2 #define NPV_VIDEO_OSD_PUBLIC_H
3 #include <stdint.h>
4
5 #include <ft2build.h>
6 #include FT_FREETYPE_H
7 #include FT_GLYPH_H /* TODO: temporary for gb_get */
8
9 #include "npv/c_fixing.h"
10 /*----------------------------------------------------------------------------*/
11 #include "npv/video/osd/namespace/public.h"
12 /*----------------------------------------------------------------------------*/
13 STATIC void clear_dirty(void);
14 STATIC void init_once(u8 **faces_files);
15 STATIC void init_once(u8 **faces_files);
16 STATIC void update_dimensions(void *scaler_pixs, u16 width, u16 height,
17 u32 line_bytes_n);
18 STATIC void rop_blend(s64 now);
19 STATIC void rop_restore(void);
20 /*----------------------------------------------------------------------------*/
21 #define CLEANUP
22 #include "npv/video/osd/namespace/public.h"
23 #undef CLEANUP
24 #endif
File npv/video/osd/public/code.frag.c added (mode: 100644) (index 0000000..c06e9ab)
1 STATIC void init_once(u8 **faces_files)
2 {
3 FT_Error ft_r;
4 /* adobe or legacy freetype */
5 FT_UInt cff;
6 FT_UInt type1;
7 FT_UInt t1cid;
8 /* the different versions of freetype truetype hinters */
9 FT_UInt tt_interpreters;
10 u8 id; /* face cache_l id, idx in the arrays */
11
12 memset(&cache_l, 0, sizeof(cache_l));
13 ft_r = FT_Init_FreeType(&library_l);
14 if (ft_r != FT_Err_Ok)
15 fatal("freetype:unable to get a freetype2 library_l handle:%d\n", ft_r);
16 ft_r = FTC_Manager_New(library_l, 0, 0, 0, face_requester, 0,
17 &cache_l.manager);
18 if (ft_r != 0)
19 fatal("freetype:unable to new a cache_l manager\n");
20 ft_r = FTC_ImageCache_New(cache_l.manager, &cache_l.img_cache);
21 if (ft_r != 0)
22 fatal("freetype:unable to new a image cache_l\n");
23 /* ccf, type1 and t1cid hinting engines */
24 ft_r = FT_Property_Get(library_l, "cff", "hinting-engine", &cff);
25 if (ft_r != FT_Err_Ok)
26 warning("freetype:no cff module or no hinting engine property\n");
27 else
28 pout("freetype:ccf:using the %s hinting engine\n", hinting_engine_str(cff));
29 ft_r = FT_Property_Get(library_l, "type1", "hinting-engine", &type1);
30 if (ft_r != FT_Err_Ok)
31 warning("freetype:no type1 module or no hinting engine property\n");
32 else
33 pout("freetype:type1:using the %s hinting engine\n", hinting_engine_str(type1));
34 ft_r = FT_Property_Get(library_l, "t1cid", "hinting-engine", &t1cid);
35 if (ft_r != FT_Err_Ok)
36 warning("freetype:no t1cid module or no hinting engine property\n");
37 else
38 pout("freetype:t1cid:using the %s hinting engine\n", hinting_engine_str(t1cid));
39 /* truetype various hinting engines */
40 ft_r = FT_Property_Get(library_l, "truetype", "interpreter-version",
41 &tt_interpreters);
42 if (ft_r != FT_Err_Ok)
43 warning("freetype:no truetype module or no truetype hinting interpreter version\n");
44 else {
45 pout("freetype:truetype:hinting interpreters 0x%x\n", tt_interpreters);
46 out_tt_interpreters(tt_interpreters);
47 }
48 /* we leave all defaults for the various hinting engines */
49 /*
50 * the lcd filtering stuff (_rendering_ and _not hinting_) must be
51 * explicitely enabled, if available
52 */
53 ft_r = FT_Library_SetLcdFilter(library_l, FT_LCD_FILTER_DEFAULT);
54 if (ft_r != FT_Err_Ok)
55 warning("freetype:no lcd filtering in this freetype library_l:%d\n", ft_r);
56 else
57 pout("freetype:default lcd filtering enabled\n");
58 /*====================================================================*/
59 /* prepare our side of the font cache */
60 cache_l.faces.files = faces_files;
61 id = 0;
62 loop { /* count the font files */
63 if (cache_l.faces.files[id] == 0)
64 break;
65 pout("font file:%s\n", cache_l.faces.files[id]);
66 ++id;
67 }
68 pout("%u font files provided\n", id);
69 cache_l.faces.n = id;
70 cache_l.faces.ft = calloc(cache_l.faces.n, sizeof(*cache_l.faces.ft));
71 if (cache_l.faces.ft == 0)
72 fatal("unable to allocate an array of %u freetype sets of faces\n", cache_l.faces.n);
73 /*--------------------------------------------------------------------*/
74 /* freetype cache wants face id pointers to be uniq in memory... */
75 cache_l.faces.ids = calloc(cache_l.faces.n, sizeof(*cache_l.faces.ids));
76 if (cache_l.faces.ids == 0)
77 fatal("unable to allocate an array of %u ids\n", cache_l.faces.n);
78 id = 0;
79 loop {
80 if (id == cache_l.faces.n)
81 break;
82 cache_l.faces.ids[id] = id; /* we did miss something */
83 ++id;
84 }
85 /*====================================================================*/
86 gs_init_once();
87 memset(&restore_l, 0, sizeof(restore_l));
88 timer_on = false;
89 }
90 STATIC void update_dimensions(void *scaler_pixs, u16 width, u16 height,
91 u32 line_bytes_n)
92 {
93 FT_Error ft_r;
94 FT_Face f;
95 FTC_ScalerRec scaler_rec;
96 u8 i;
97
98 cache_nodes_release();
99 /*
100 * choices which may end up in the config file:
101 * XXX: ascender in most font files ~ em height
102 * XXX: ascender ~ 1/16 height
103 * XXX: em box height/width ratio ~ 4/3
104 */
105 scaler_rec.height = height / 16;
106 scaler_rec.width = scaler_rec.height * 3 / 4;
107 pout("scaler:em to %ux%u pixels\n", scaler_rec.width, scaler_rec.height);
108 i = 0;
109 loop {
110 FT_Glyph g;
111
112 if (i == GS_N)
113 break;
114 memset(&scaler_rec, 0, sizeof(scaler_rec));
115 /* XXX: freetype cache wants ids with uniq ptrs */
116 scaler_rec.face_id =
117 &(cache_l.faces.ids[cache_l.gs[i].face_id]);
118 scaler_rec.height = height / 16;
119 scaler_rec.width = scaler_rec.height * 3 / 4;
120 scaler_rec.pixel = 1;
121 ft_r = FTC_ImageCache_LookupScaler(cache_l.img_cache,
122 &scaler_rec, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD,
123 cache_l.gs[i].idx, &g, &cache_l.gs[i].node);
124 if (ft_r != FT_Err_Ok)
125 fatal("freetype:cache_l:failed to look for glyph %u with our target size:0x%02x\n", i, ft_r);
126 if (g->format != FT_GLYPH_FORMAT_BITMAP)
127 fatal("freetype:the glyph %u was not rendered in bitmap\n", i);
128 cache_l.gs[i].bg = (FT_BitmapGlyph)g;
129 ++i;
130 }
131 timer_baseline_compute();
132 volume_pen_start_location_compute(width, height);
133 restore_l.scaler_pixs = scaler_pixs;
134 free(restore_l.pixs);
135 restore_l.pixs = calloc(4, (u32)height * line_bytes_n);
136 restore_l.width = width;
137 restore_l.height = height;
138 restore_l.line_bytes_n = line_bytes_n;
139 restore_l.dirty = false;
140 }
141 #define BLEND 0
142 STATIC void rop_blend(s64 now)
143 {
144 u8 *timer_gs;
145
146 if (!timer_on || restore_l.dirty)
147 return;
148 timer_gs = timer_to_gs(now,
149 npv_fmt_ctx_p->streams[npv_video_st_p.idx]->tb);
150 rop_x(BLEND, timer_gs);
151 restore_l.dirty = true;
152 }
153 #undef BLEND
154 #define RESTORE 1
155 STATIC void rop_restore(void)
156 {
157 if (!restore_l.dirty)
158 return;
159 rop_x(RESTORE, restore_l.timer_gs);
160 restore_l.dirty = false;
161 }
162 #undef RESTORE
163 STATIC void clear_dirty(void)
164 {
165 restore_l.dirty = false;
166 }
167 STATIC void npv_cmd_osd_timer_toggle(void)
168 {
169 if (timer_on) {
170 timer_on = false;
171 pout("timer off\n");
172 } else {
173 timer_on = true;
174 pout("timer on\n");
175 }
176 }
File npv/video/public/code.frag.c changed (mode: 100644) (index b2604be..abea91c)
... ... STATIC void timer_evt(void)
232 232 start_scaling(fr, fr_priv, &scaler_dims_changed); start_scaling(fr, fr_priv, &scaler_dims_changed);
233 233 return; return;
234 234 } }
235 if (npv_paused_p)
236 npv_video_osd_rop_restore();
237 npv_video_osd_rop_blend(now);
235 238 loop { /* because the swpchn can change, aka "the win changed" */ loop { /* because the swpchn can change, aka "the win changed" */
236 239 r = swpchn_next_img(&swpchn_img); r = swpchn_next_img(&swpchn_img);
237 240 if (r == NOT_READY) if (r == NOT_READY)
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