From 7e8a8a5b764a92c492aca2867dd442d5b798827e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 3 Aug 2025 01:41:15 +0200 Subject: [PATCH] Recherche / preparation for FrOSCon talk The topic of this talk was ''Video output from a Linux desktop application'' after extended research we built a demo application in four flavours (XVideo, SDL, OpenGL legacy / modern). This research project was set off by our immediate needs for a setup to show computed video pixel data in a viewer window in the GUI; the investigated technologies should work at present and in the near term future (yet leaving out Vulkan and Wayland) --- src/stage/output/xv-displayer.cpp | 12 +- src/stage/output/xv-displayer.hpp | 2 - src/stage/widget/video-display-widget.cpp | 2 - .../engine/worker/dummy-image-generator.hpp | 1 + wiki/thinkPad.ichthyo.mm | 850 +++++++++++++++++- 5 files changed, 845 insertions(+), 22 deletions(-) diff --git a/src/stage/output/xv-displayer.cpp b/src/stage/output/xv-displayer.cpp index 4390c0aab..999901577 100644 --- a/src/stage/output/xv-displayer.cpp +++ b/src/stage/output/xv-displayer.cpp @@ -26,6 +26,8 @@ //#include "lib/format-cout.hpp" #include +#include +#include namespace stage { namespace output { @@ -144,8 +146,9 @@ namespace output { if (gotPort) { - XGCValues values; - memset(&values, 0, sizeof(XGCValues)); +// XGCValues values; +// memset(&values, 0, sizeof(XGCValues)); +///////////////////////////////////////////////////////////////TODO actually pass these to XCreateGC to set line width or fill colour etc. gc = XCreateGC( display, window, 0, NULL ); xvImage = ( XvImage * ) XvShmCreateImage( display, grabbedPort, FORMAT_ID_YUY2, 0, videoWidth, videoHeight, &shmInfo ); @@ -167,8 +170,8 @@ namespace output { } XSync( display, false ); - shmctl( shmInfo.shmid, IPC_RMID, 0 ); - } + shmctl( shmInfo.shmid, IPC_RMID, 0 ); // mark the segment as deleted + } // -- it will be retained until the last client calls shmdt() } } else @@ -233,6 +236,7 @@ namespace output { XvShmPutImage (display, grabbedPort, window, gc, xvImage, 0, 0, videoWidth, videoHeight, org_x, org_y, destW, destH, false); + XFlush (display); } } diff --git a/src/stage/output/xv-displayer.hpp b/src/stage/output/xv-displayer.hpp index ecac3e346..9cc1ae048 100644 --- a/src/stage/output/xv-displayer.hpp +++ b/src/stage/output/xv-displayer.hpp @@ -29,8 +29,6 @@ #include "stage/gtk-base.hpp" #include -#include -#include #include #include diff --git a/src/stage/widget/video-display-widget.cpp b/src/stage/widget/video-display-widget.cpp index 0190aeb40..eb5e8702d 100644 --- a/src/stage/widget/video-display-widget.cpp +++ b/src/stage/widget/video-display-widget.cpp @@ -71,11 +71,9 @@ namespace widget { { REQUIRE (videoWidth > 0); REQUIRE (videoHeight > 0); - /* ///////////////////////////////TICKET #1403 : temporarily disabled XV for experimentation with Pixbuf (but XV works and is usable) displayer_ = make_unique (*this, videoWidth, videoHeight); if (displayer_->usable()) return; - */ displayer_ = make_unique (*this, videoWidth, videoHeight); if (displayer_->usable()) return; diff --git a/src/steam/engine/worker/dummy-image-generator.hpp b/src/steam/engine/worker/dummy-image-generator.hpp index cf8f7c358..a9f741b3f 100644 --- a/src/steam/engine/worker/dummy-image-generator.hpp +++ b/src/steam/engine/worker/dummy-image-generator.hpp @@ -21,6 +21,7 @@ ** dummy playback service. ** ** @todo obsolete since 2010, can be removed once we have a real player in the UI + ** @todo revived in 2025 for research of video output techniques; this is test code. ** @see stage::controller::PlaybackController ** @see steam::play::DummyPlayerService ** diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 217bd36a3..571f215f3 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -36349,6 +36349,10 @@ + + + + @@ -130333,7 +130337,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -130402,6 +130407,42 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...was aber normalerweise passiert bei der Behandlung des »Expose«-Events von X +

+ +
+
+ + + + + +
@@ -130612,7 +130653,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -130659,6 +130701,20 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + @@ -151816,8 +151872,22 @@ std::cout << tmpl.render({"what", "World"}) << s - + + + + + +

+ was ich hier angebe, ist eine Grenz-Version; viele der Unterseiten wurden schon länger nicht geändert, und der letzte Capture in Archive.org liegt schon mehrere Jahre zurück; daher wird dann die nächst-neuere Version geliefert, die typischerweise aus 2021 stammt und bereits auf GTK-4 bezogen ist +

+ +
+ +
+ + +
@@ -152992,7 +153062,7 @@ std::cout << tmpl.render({"what", "World"}) << s - + @@ -153022,6 +153092,101 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + + +

+ #include <gtkmm.h> +

+

+ #include <iostream> +

+

+ +

+

+ class MyApp +

+

+   : public Gtk::Application +

+

+   { +

+

+   protected: +

+

+     // install into the default startup handler +

+

+     void +

+

+     on_startup()  override +

+

+       { +

+

+         Gtk::Application::on_startup (); +

+

+         Glib::signal_timeout ().connect (sigc::ptr_fun (&MyApp::on_timeout), 1000); +

+

+       } +

+

+     +

+

+     static bool +

+

+     on_timeout() +

+

+       { +

+

+         std::cout << "Periodic task executed" << std::endl; +

+

+         return true; // Return true to continue calling this function +

+

+       } +

+

+   }; +

+

+ +

+

+ int main (int argc, char *argv[]) +

+

+   { +

+

+     auto app = MyApp::create (); +

+

+     return app->run (argc, argv); +

+

+   } +

+ +
+ + +
+
@@ -155449,6 +155614,15 @@ std::cout << tmpl.render({"what", "World"}) << s
+ + + + + + + + +
@@ -159501,6 +159675,31 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + + + + + + + + + + + + +

+ wichtiger Hinweis: OpenColorIO LUT statt ICC-Profilen  verwenden! +

+ +
+
+
+
+
+
+
@@ -159567,6 +159766,10 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + +
@@ -159584,13 +159787,36 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - + + + + + + + + +

+ ...er ist inzwischen sehr tief in Ardour eingestiegen; xjadeo hat er schon „viele Jahre nicht mehr angeschaut“ — da hatte er vor langer Zeit mal beim konsolidieren geholfen; viel von dem Wissen ist dann in Ardour's video-Anzeige in der Timeline eingeflossen. +

+

+ +

+

+ Nach dem letzten Event, im »le Sucre« an der confluence  von Rhône und Saône, sind dann Frank Neumeier, ich, Robin und Jörg Nettingsmeyer zusammen spät nachts quer durch Lyon zurück ins Hotel gewandert +

+ +
+
+
- + + + + @@ -159602,6 +159828,14 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + + + + + + @@ -159900,6 +160134,40 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo

+ + + + + + +

+ In die Pipeline gehören im Besonderen auch Operationen, die spezifisch sind für ein bestimmtes Ausgabe-System... +

+
    +
  • + für XV: das Skalieren und Umrechnen in den Ausgabe-Farbraum +
  • +
  • + für XGL: die Matrix-Operationen um die Textur für die Ausgabe aufzubereiten +
  • +
+

+ Allerdings gibt es Schritte, die sind dann an die konkrete Ausgabe-Verbindung gebunden und insofern Zustands-behaftet: +

+
    +
  • + XV: die shared-memory operationen und Kommunikation mit dem X-Server und flush +
  • +
  • + XGL auch hier erzeugt man ja einen Grafix-Kontext +
  • +
+ +
+ + +
+
@@ -160713,11 +160981,79 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ XSync leert die Event-Queue. Wenn sie leer ist, wird per IO nach weiteren Events gesucht. Was so gesammelt wurde, wird als Batch an den XServer gegeben und blockend gewartet, bis dieser diese Events abgearbeitet hat. Zwischenzeitlich können weitere Events aufgelaufen sein; diese kann man dann einfach wegwerfen (discard = true) oder in der Queue lassen (discard = false) ohne sie zu bearbeiten +

+ +
+ +
+
+ + + + + + + + + + + + + + + + + +

+ war verlinkt von einer Stackoverflow-Antwort zum Thema "redraw unter X" +

+

+ https://stackoverflow.com/a/17035752/444796 +

+ +
+
+ + + +
+
+
+
@@ -161012,7 +161348,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
- + @@ -161038,8 +161374,8 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - - + + @@ -161398,9 +161734,12 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - + - + + + + @@ -161419,6 +161758,10 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + + @@ -161439,8 +161782,8 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - - + + @@ -161448,6 +161791,485 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + + + + + + + + + + + + + + + + + +

+ Das war praktisch der Anfang der Diskussion, Benny sagte, die Einleitung wirke steif, und hat einige Vorschläge im Chat skizziert +

+ +
+
+ + + + +

+ ...aus dem, was ich geschrieben habe, aber nur der 2. Hälfte, und Benny's Formulierung, die um einiges glatter wirkt, da sie mehr an weithin aktzeptierte Formulierungen anknüpft. Das halte ich aber nun auch für besser, da es ja nur zum Thema hinführen soll. +

+ +
+
+
+ + + + + + +

+ "is established" ist zweifellos eine viel dezentere und neutralere Formulierung, aber weicht eben auch einer Aussage in der Sache aus. Das ist immer wieder der Konflikt zwischen uns Beiden; ich mache die Aussage in der Sache ja, weil ich einen Gedankengang entwickle, anstatt nur bekannte Umstände möglichst geläufig anzusprechen; damit ist meine Formulierung meist schwierig und herausfordernd. Nachdem dann Benny einmal alles geglättet hat, stößt er dann auf die Kernaussage und sagt: das ist jetzt aber komisch, wie kommst Du da drauf? Und in der Tat, nachdem der ganze Gedankengang in der Sache weg ist, ist die Aussage, bei der der Gedankengang ankommen sollte, nur noch beliebig und far fetched. +

+

+ +

+

+ Da ich diese Erfahrung in der Zusammenarbeit mit Benny nun schon oft gemacht habe, weiß ich, daß ich an zentralen Stellen den Konflikt suchen muß. Denn letztlich bin ich es, der einen Gedanken sieht und einen Entwurf macht. Würde Benny, auf seine Weise, etwas Entsprechendes tun, ich wäre der letzte das anzugreifen...! +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ siehe deutsche Wikipedia +

+ +
+
+ + + + +

+ siehe englische Wikipedia +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ TODO this commit requires a review +

+
    
+
'essence' does not work here. Don't know why, probably gramatical; but I
+
know what you'd like too say.
+
The problem with my suggestion, 'core', ist that core has several meanings.
+
One meaning refers to responsibility or location. So making an insigificant
+
code modification in this area; which is noot the meaning you intended with
+
'essence'. However 'core' can also mean 'essence'....so this is ambiguous using
+
core.
+
    
+
    'fundamental operation of the code base' might be better suited; but everyone
+
    gets 'core' immediately.
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...will sagen, er hat den generischen Ausdruck gewählt, den ich ganz bewußt nicht genommen habe, der eigentlichen Aussage wegen. Das hatten wir schon mehrfach. +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ A complex integration process is also +

+

+ required for large and intricately structured systems: changes will first be accommodated within a subsystem, +

+

+ which is followed by joining subsystem branches into a new state of integration +

+ +
+
+ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ebenso hier: das meiste ist sehr gut, +

+

+ aber manches versteht Benny anscheinend nicht +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ was für einen native speaker schwierig zu verstehen ist, läßt er nicht gelten +

+ +
+ + + + + +

+ interessanterweise beharrt er darauf, +

+

+ das sei rein grammatikalisch +

+ +
+
+ + + + +

+ Das passiert uns immer wieder mal, bei der Arbeit an einem Text. Und es handelt sich immer um Gedanken, die man sehr wohl im Englischen ausdrücken kann (siehe die Übersetzung philosophischer Werke, daher habe ich es ja) aber die Engländer und Amerikaner der Tendenz nach nicht gebrauchen; und das liegt wohl mehr in ihrer eigenen Kultur: die Esssenz, der Wesenskern, ein Begriff der diesen trifft — so etwas ist ihnen suspekt, das erscheint ihnen wie ein "Label" das man künstlich draufklebt +

+ +
+ +
+ + +
+
+ + + + +
+ + + + + + + + + +

+ Dieser gegenwärtige Trend ist kein Pendelschlag in die andere Richtung, und es geht nicht darum, die bewährten alten Methoden gegen Neuerungen zu positionieren. Allerdings laufen die propagierten Methoden im Grunde auf eine Restauration hinaus; es werden wieder mal Tools und Technologien propagiert, allerdings unter dem Thema einer aggressiven Beschleunigung und Steigerung +

+ +
+
+ + + + + + + + + + +

+ Rein der Sache nach wäre auch nicht mehr notwendig; was derzeit an Argumenten vorgebracht wird ist vor allem dummes Zeug, formuliert von Leuten, die keine Erfahrung haben, und wieder einem naiven Technik-Glauben anhängen.... +

+ +
+
+ + + + +

+ ich vermute aber, dahinter steht eine ernst zu nehmende Tendenz: Industrialisierung +

+ +
+ +
+ + + + + + + + + + +

+ und impliziert eine Gegenposition — ohne sie direkt zu bezeichnen +

+ +
+ + + +

+ Ich würde diese Gegenposition wie folgt charakerisieren: „egal was von Deiner Industrialisierung zu halten ist — Erfahrung brauchst Du trotzdem, Entscheidungen wirst Du weiterhin treffen müssen, und den Grenzen Deiner Fähigkeiten entgehst Du nicht“ +

+ +
+
+
+ +