Prototype: settle wiring and configuration of UringVideoPlayer and EglDisplay

This implies a basic decision regarding the buffer and state data to use,
and how this can be defined, parameterised and passed between threads.

I decided to place separation of domains first and to prefer
using a functional callback over using a shared data structure.
This commit is contained in:
Fischlurch 2026-07-15 18:56:37 +02:00
parent 6bf8a0da7a
commit 4699ae8f03
4 changed files with 296 additions and 40 deletions

View file

@ -1171,7 +1171,7 @@
</p> </p>
</body> </body>
</html></richcontent> </html></richcontent>
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1783953478348" ID="ID_186490339" MODIFIED="1783954023236" STYLE="fork" TEXT="with release-on-write / acquire-on-read"> <node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1783953478348" ID="ID_186490339" MODIFIED="1784076975728" STYLE="fork" TEXT="with release-on-write / acquire-on-read">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head/> <head/>
<body> <body>
@ -1183,6 +1183,7 @@
</body> </body>
</html></richcontent> </html></richcontent>
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/> <edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
<arrowlink COLOR="#0c8e99" DESTINATION="ID_1043516833" ENDARROW="Default" ENDINCLINATION="556;-26;" ID="Arrow_ID_1416969408" STARTARROW="None" STARTINCLINATION="1283;82;"/>
<icon BUILTIN="wizard"/> <icon BUILTIN="wizard"/>
</node> </node>
</node> </node>
@ -1787,7 +1788,7 @@
<node CREATED="1783984352027" ID="ID_1602724940" MODIFIED="1783984359484" TEXT="Aufbau der Application-Shell"> <node CREATED="1783984352027" ID="ID_1602724940" MODIFIED="1783984359484" TEXT="Aufbau der Application-Shell">
<node CREATED="1783984371031" ID="ID_1219649133" MODIFIED="1783984401222" TEXT="das Grundschema von letztem Jahr war n&#xfc;tzlich"> <node CREATED="1783984371031" ID="ID_1219649133" MODIFIED="1783984401222" TEXT="das Grundschema von letztem Jahr war n&#xfc;tzlich">
<node CREATED="1783984407459" ID="ID_321798557" MODIFIED="1783984427656" TEXT="&#x201e;mu&#xdf; den GTK-Code gar nicht anschauen&#x201c;"/> <node CREATED="1783984407459" ID="ID_321798557" MODIFIED="1783984427656" TEXT="&#x201e;mu&#xdf; den GTK-Code gar nicht anschauen&#x201c;"/>
<node CREATED="1783985102373" ID="ID_734300736" MODIFIED="1783985128117" TEXT="Aber: die Ablaufsteuerung liegt jetzt nicht mehr (komplett) in GTK"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783985102373" ID="ID_734300736" MODIFIED="1784076612700" TEXT="Aber: die Ablaufsteuerung liegt jetzt nicht mehr (komplett) in GTK">
<icon BUILTIN="messagebox_warning"/> <icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783985519074" ID="ID_1873813285" MODIFIED="1783985537906" TEXT="&#x27f9; mu&#xdf; nun einen Frame-Callback (cross-Thread) realisieren"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783985519074" ID="ID_1873813285" MODIFIED="1783985537906" TEXT="&#x27f9; mu&#xdf; nun einen Frame-Callback (cross-Thread) realisieren">
<icon BUILTIN="messagebox_warning"/> <icon BUILTIN="messagebox_warning"/>
@ -1807,7 +1808,9 @@
<node CREATED="1783985399747" ID="ID_720330070" MODIFIED="1783985405923" TEXT="Locks niemals auf der Senderseite"/> <node CREATED="1783985399747" ID="ID_720330070" MODIFIED="1783985405923" TEXT="Locks niemals auf der Senderseite"/>
</node> </node>
</node> </node>
<node CREATED="1783985980271" ID="ID_1205516934" MODIFIED="1783985994016" TEXT="Konstruktions-Problem: Verdrahtung"> </node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1783985980271" FOLDED="true" ID="ID_1205516934" MODIFIED="1784076663250" TEXT="Konstruktions-Problem: Verdrahtung">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1783985998296" ID="ID_602134117" MODIFIED="1783986005435" TEXT="die Verdrahtung ist jetzt kreuzweise"> <node CREATED="1783985998296" ID="ID_602134117" MODIFIED="1783986005435" TEXT="die Verdrahtung ist jetzt kreuzweise">
<node CREATED="1783986006656" ID="ID_1853634036" MODIFIED="1783986020234" TEXT="GtkApp &#x27f6; Setup"/> <node CREATED="1783986006656" ID="ID_1853634036" MODIFIED="1783986020234" TEXT="GtkApp &#x27f6; Setup"/>
<node CREATED="1783986025918" ID="ID_905927115" MODIFIED="1783986037848" TEXT="Setup &#x27f9; erzeugt Player"/> <node CREATED="1783986025918" ID="ID_905927115" MODIFIED="1783986037848" TEXT="Setup &#x27f9; erzeugt Player"/>
@ -1816,7 +1819,7 @@
<node CREATED="1783986156014" ID="ID_1075245760" MODIFIED="1783986166367" TEXT="Player &#x27f6; Frame-Signal"/> <node CREATED="1783986156014" ID="ID_1075245760" MODIFIED="1783986166367" TEXT="Player &#x27f6; Frame-Signal"/>
<node CREATED="1783986171122" ID="ID_931723726" MODIFIED="1783986184677" TEXT="GtkApp &#x27f6; Player-Stop"/> <node CREATED="1783986171122" ID="ID_931723726" MODIFIED="1783986184677" TEXT="GtkApp &#x27f6; Player-Stop"/>
</node> </node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1783986532114" ID="ID_1245562739" MODIFIED="1783986543992" TEXT="Knackpunkt: wo sitzt der Dispatcher?"> <node COLOR="#435e98" CREATED="1783986532114" ID="ID_1245562739" MODIFIED="1784076460564" TEXT="Knackpunkt: wo sitzt der Dispatcher?">
<icon BUILTIN="help"/> <icon BUILTIN="help"/>
<node COLOR="#5b280f" CREATED="1783986546063" ID="ID_1573759034" MODIFIED="1783986688651" TEXT="L&#xf6;sung-1 : in der GtkApp"> <node COLOR="#5b280f" CREATED="1783986546063" ID="ID_1573759034" MODIFIED="1783986688651" TEXT="L&#xf6;sung-1 : in der GtkApp">
<icon BUILTIN="button_cancel"/> <icon BUILTIN="button_cancel"/>
@ -1824,7 +1827,8 @@
<node CREATED="1783986584944" ID="ID_478484131" MODIFIED="1783986600350" TEXT="bleibt damit Interna der GTK-App"/> <node CREATED="1783986584944" ID="ID_478484131" MODIFIED="1783986600350" TEXT="bleibt damit Interna der GTK-App"/>
<node CREATED="1783986603534" ID="ID_1364662813" MODIFIED="1783986612304" TEXT="Nachteil: Verdrahtung nicht offensichtlich"/> <node CREATED="1783986603534" ID="ID_1364662813" MODIFIED="1783986612304" TEXT="Nachteil: Verdrahtung nicht offensichtlich"/>
</node> </node>
<node CREATED="1783986560783" ID="ID_1335290152" MODIFIED="1783986686480" TEXT="L&#xf6;sung-2 : im Player"> <node CREATED="1783986560783" ID="ID_1335290152" MODIFIED="1784076661520" TEXT="L&#xf6;sung-2 : im Player">
<arrowlink COLOR="#308bd6" DESTINATION="ID_1751781345" ENDARROW="Default" ENDINCLINATION="95;-7;" ID="Arrow_ID_309586658" STARTARROW="None" STARTINCLINATION="77;235;"/>
<icon BUILTIN="back"/> <icon BUILTIN="back"/>
<node CREATED="1783986627477" ID="ID_281071387" MODIFIED="1783986637023" TEXT="Vorteil: Verdrahtung offensichtlich und einfach"/> <node CREATED="1783986627477" ID="ID_281071387" MODIFIED="1783986637023" TEXT="Vorteil: Verdrahtung offensichtlich und einfach"/>
<node CREATED="1783986637869" ID="ID_1603304" MODIFIED="1783986655939" TEXT="Nachteil : GTK-spezifisches Detail leaked"/> <node CREATED="1783986637869" ID="ID_1603304" MODIFIED="1783986655939" TEXT="Nachteil : GTK-spezifisches Detail leaked"/>
@ -1861,7 +1865,6 @@
</node> </node>
</node> </node>
</node> </node>
</node>
<node CREATED="1783986793999" ID="ID_1360252421" MODIFIED="1783986816919" TEXT="L&#xf6;sung: baue ein Player-Objekt im Start-Hook"> <node CREATED="1783986793999" ID="ID_1360252421" MODIFIED="1783986816919" TEXT="L&#xf6;sung: baue ein Player-Objekt im Start-Hook">
<node CREATED="1783986820215" ID="ID_360250150" MODIFIED="1783986836070" TEXT="das tritt an die Stelle wo bisher der EglContext stand"/> <node CREATED="1783986820215" ID="ID_360250150" MODIFIED="1783986836070" TEXT="das tritt an die Stelle wo bisher der EglContext stand"/>
<node CREATED="1783986838784" ID="ID_1847977458" MODIFIED="1783986861705" TEXT="L&#xf6;sung: das EglDisplay wird nun ein weiteres Objekt"> <node CREATED="1783986838784" ID="ID_1847977458" MODIFIED="1783986861705" TEXT="L&#xf6;sung: das EglDisplay wird nun ein weiteres Objekt">
@ -1870,11 +1873,237 @@
<node CREATED="1783986866318" ID="ID_623423104" MODIFIED="1783986874503" TEXT="alles per Konstruktor-Verdrahtung"/> <node CREATED="1783986866318" ID="ID_623423104" MODIFIED="1783986874503" TEXT="alles per Konstruktor-Verdrahtung"/>
</node> </node>
</node> </node>
<node CREATED="1784076499094" ID="ID_1786219220" MODIFIED="1784076516947" TEXT="Player per Konstruktur-Initialisierung">
<node CREATED="1784076561463" ID="ID_1248489844" MODIFIED="1784076582686" TEXT="l&#xe4;uft im GUI-Thread">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1784076539919" ID="ID_1751781345" MODIFIED="1784076661520" TEXT="erzeuge hier den Dispatcher">
<linktarget COLOR="#308bd6" DESTINATION="ID_1751781345" ENDARROW="Default" ENDINCLINATION="95;-7;" ID="Arrow_ID_309586658" SOURCE="ID_1335290152" STARTARROW="None" STARTINCLINATION="77;235;"/>
</node>
<node CREATED="1784076520970" ID="ID_1201489587" MODIFIED="1784076537887" TEXT="mu&#xdf; auch die EGL-Initialisierung in den Konstruktor bringen"/>
<node CREATED="1784076675289" ID="ID_1648662317" MODIFIED="1784076685507" TEXT="unmittelbar hier den Thread starten"/>
</node>
</node> </node>
<node CREATED="1783644425567" ID="ID_238189215" MODIFIED="1783644429274" TEXT="Flow-Steuerung"> <node CREATED="1783644425567" ID="ID_238189215" MODIFIED="1783644429274" TEXT="Flow-Steuerung">
<node CREATED="1784052955974" ID="ID_1491751742" MODIFIED="1784052978769" TEXT="da nun Proactor &#x27f9; getrieben vom Timer-Tick"> <node CREATED="1784052955974" ID="ID_1491751742" MODIFIED="1784052978769" TEXT="da nun Proactor &#x27f9; getrieben vom Timer-Tick">
<icon BUILTIN="idea"/> <icon BUILTIN="idea"/>
</node> </node>
<node CREATED="1784076700200" ID="ID_1239755482" MODIFIED="1784076707103" TEXT="Daten&#xfc;bergabe / Sichtbarkeit">
<node CREATED="1784076715698" ID="ID_102034340" MODIFIED="1784076740355" TEXT="Dispatcher &#xfc;bertr&#xe4;gt nur den Trigger &#xfc;ber die Thread-Grenzen"/>
<node CREATED="1784076755543" ID="ID_1514914957" MODIFIED="1784076772757" TEXT="mu&#xdf; Atomics / Barrieren einf&#xfc;hren f&#xfc;r die Datensicherheit"/>
<node BACKGROUND_COLOR="#accdc3" COLOR="#010101" CREATED="1784076776201" ID="ID_1043516833" MODIFIED="1784076975728" STYLE="fork" TEXT="Vorschlag von Claude: die State-Machine als Atomic implementieren">
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
<linktarget COLOR="#0c8e99" DESTINATION="ID_1043516833" ENDARROW="Default" ENDINCLINATION="556;-26;" ID="Arrow_ID_1416969408" SOURCE="ID_186490339" STARTARROW="None" STARTINCLINATION="1283;82;"/>
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#fefc4e" COLOR="#351d75" CREATED="1784076979882" ID="ID_1843330900" MODIFIED="1784078228911" TEXT="Bemerkenswert: das hat sich durch die Konversation so ergeben">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...es war nicht so, da&#223; Claude diese &#8222;Idee gehabt&#8220; h&#228;tte &#8212; denn ich hatte die Konversation ja so gef&#252;hrt, da&#223; Claude mir meine Konzept-Ans&#228;tze validiert und verfeinert. Dann habe ich das Prinzip formuliert, da&#223; f&#252;r Async-IO irgendwo eine State-Machine sein mu&#223;. Claude hat das aufgegriffen, validiert und versch&#228;rft; und damit war offensichtlich geworden, da&#223; man diese State-Flag als Atomic auslegen kann. Das habe ich in dem Moment genauso &#187;offensichtlich&#171; gesehen, und Claude hat es ebenso formuliert.
</p>
<p>
Warum ich hier nochmal nachzeichne, wie das zustandegekommen ist:
</p>
<ul>
<li>
weil ich allein da nicht draufgekommen w&#228;re
</li>
<li>
aber weil es offensichtlich nicht von Claude stammt
</li>
</ul>
<p>
&#10233; das wirft ein Licht darauf, wie dieses <i>scheinbar intelligente &#187;Generieren&#171; funktioniert, </i>auf Basis einer industriellen Daten-Technik, die Plausibilit&#228;ten integriert und interpoliert.
</p>
</body>
</html>
</richcontent>
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="back"/>
</node>
<node COLOR="#435e98" CREATED="1784079033427" ID="ID_1573408699" MODIFIED="1784079050907" TEXT="Zustands&#xfc;berg&#xe4;nge">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="info"/>
<node CREATED="1784078717834" ID="ID_17978925" MODIFIED="1784078954065" TEXT="IO beauftragen: FREE &#x27f6; READ"/>
<node CREATED="1784078958419" ID="ID_1531715805" MODIFIED="1784078974343" TEXT="&#xdc;bergabe an Display: READ &#x27f6; SHOW"/>
<node CREATED="1784078981634" ID="ID_1578413583" MODIFIED="1784079026236" TEXT="Frame-Flip: SHOW &#x27f6; FREE"/>
</node>
<node CREATED="1784078466234" ID="ID_424139171" MODIFIED="1784078496653">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
hier mu&#223; auch die <b>Backpressure</b>&#160;beachtet und realisiert werden
</p>
</body>
</html>
</richcontent>
<node CREATED="1784078502730" ID="ID_846472947" MODIFIED="1784078534574" TEXT="darf nur weitergehen, nachdem der vorherige Frame aufgegriffen wurde"/>
<node CREATED="1784078681486" ID="ID_1106864388" MODIFIED="1784078714572" TEXT="und darf nur neue IO beauftragen wenn der Zielpuffer vom Consumer freigegeben werden"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1784079572400" ID="ID_1393056375" MODIFIED="1784079586917" TEXT="wie bekommt der EglDisplayer die Daten?">
<node CREATED="1784079589221" ID="ID_1308906754" MODIFIED="1784079609606" TEXT="Optionen">
<node CREATED="1784079611026" ID="ID_870843631" MODIFIED="1784079835110" TEXT="Buffer-Ring k&#xf6;nnte global sichtbar sein">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Sofern er aus dem GUI-Thread alloziert wird, also bevor der Proactor-Thread startet, ist die Position f&#252;r beide Threads sichtbar (und unver&#228;nderlich)
</p>
</body>
</html>
</richcontent>
<node CREATED="1784079641676" ID="ID_595831960" MODIFIED="1784079776456" TEXT="eine currentFrameNr ebenso">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Diese w&#228;re dann ebenfalls teil der cross-Trade-Synchronisation (ebenfalls bewirkt durch release-Semantik auf dem State-Atomic)
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1784079653178" ID="ID_1804993764" MODIFIED="1784079727230" TEXT="oder der Displayer hat intern seine eigene FrameNr">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...nur als lokale Variable, die er jeweils hochz&#228;hlt, wenn er einen Trigger bekommt (Nachteil: duplizierter State, dessen Konsistenz sich nur implizit ergibt und nicht offensichtlich ist)
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1784079838160" ID="ID_1763616932" MODIFIED="1784080020991" TEXT="k&#xf6;nnte dem Displayer direkt gegeben werden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Das w&#228;re dann ein Pointer (const void *); seine Sichtbarkeit ergibt sich auch hier aus dem atomic-State
</p>
</body>
</html>
</richcontent>
<node CREATED="1784079873496" ID="ID_714454620" MODIFIED="1784079881936" TEXT="kann aber nicht per Dispatcher erfolgen"/>
<node CREATED="1784079882711" ID="ID_102892347" MODIFIED="1784079907595" TEXT="mu&#xdf; dann ein Datenfeld sein (sinnvollerweise im Displayer)"/>
</node>
</node>
<node CREATED="1784080062495" ID="ID_254917759" MODIFIED="1784080174245" TEXT="die zuletzt genanne M&#xf6;glichkeit erscheint mir am nat&#xfc;rlichsten">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...da ich immer in Zust&#228;ndigkeiten denke, ist es mir unsympatisch, einen Satz gemeinsamer Zustands-Variablen zu verwenden
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1784080203172" ID="ID_952531619" MODIFIED="1784080213143" TEXT="daraus ergibt sich die Datenstruktur">
<node CREATED="1784080214847" ID="ID_1165930889" MODIFIED="1784080245515" TEXT="und zwar geh&#xf6;ren damit die Buffer dem Proactor-Thread"/>
<node CREATED="1784080390813" ID="ID_1044489570" MODIFIED="1784080418199" TEXT="Allocation und Ownership">
<node CREATED="1784080461760" ID="ID_1762147278" MODIFIED="1784080535764" TEXT="Buffer sehr gro&#xdf; &#x27f9; einzeln allozieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...das gilt f&#252;r ein Prod-System, in dem der Speicher framentiert ist, und man vermutlich Buffer-Pools hat
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1784080449077" ID="ID_1803805054" MODIFIED="1784080659901" TEXT="einfach w&#xe4;re ein riesiges Array auf dem Heap">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
F&#252;r die Demo ist das die offensichtliche L&#246;sung: man bekommt unique-ownership und Subscript-Operator einfach vom std::unique_ptr. Wenn man den notwendigen Speicher nicht bekommt, dann l&#228;uft die Demo eh nicht, also wozu die Umst&#228;nde?
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="back"/>
</node>
</node>
<node CREATED="1784082520499" ID="ID_299429653" MODIFIED="1784082523281" TEXT="Buffer-Typ">
<node COLOR="#5b280f" CREATED="1784082524138" ID="ID_1665124664" MODIFIED="1784132193492" TEXT="der Einfachheit halber &#x27f9; definiert vom EglDisplay">
<icon BUILTIN="button_cancel"/>
<node CREATED="1784082547951" ID="ID_1261536746" MODIFIED="1784082582921" TEXT="ist ein std::array aus 8bit-Pixeln"/>
<node COLOR="#5b280f" CREATED="1784082595689" ID="ID_1135557355" MODIFIED="1784132191641" TEXT="verwende diese Typedef aber auch als &#xbb;Buffer&#xab;-Abstraktion">
<icon BUILTIN="stop-sign"/>
<node CREATED="1784132084657" ID="ID_845039951" MODIFIED="1784132129048" TEXT="hier beginnt der Knoten">
<arrowlink COLOR="#b92b54" DESTINATION="ID_1404935910" ENDARROW="Default" ENDINCLINATION="101;8;" ID="Arrow_ID_1619759457" STARTARROW="None" STARTINCLINATION="53;82;"/>
<icon BUILTIN="broken-line"/>
</node>
</node>
<node BACKGROUND_COLOR="#e7d8b6" CREATED="1784132196542" ID="ID_1214331051" MODIFIED="1784132240994" TEXT="besser: Globale Konfig &#x27f6; Template-Paramter">
<icon BUILTIN="yes"/>
</node>
</node>
<node CREATED="1784083148598" ID="ID_504827142" MODIFIED="1784083164848" TEXT="Problem: Anordnung der Daten-Definition im Code">
<node CREATED="1784083166480" ID="ID_1404935910" MODIFIED="1784132116787" TEXT="mu&#xdf; hierzu auch das Enum definieren">
<linktarget COLOR="#b92b54" DESTINATION="ID_1404935910" ENDARROW="Default" ENDINCLINATION="101;8;" ID="Arrow_ID_1619759457" SOURCE="ID_845039951" STARTARROW="None" STARTINCLINATION="53;82;"/>
</node>
<node CREATED="1784083179322" ID="ID_275541270" MODIFIED="1784083198899" TEXT="und zum Buffer den atomic-state packen"/>
<node CREATED="1784083201959" ID="ID_697343104" MODIFIED="1784083233397" TEXT="Alignment beachten &#x27f9; besser separater Ring von State-Flags"/>
<node CREATED="1784083236834" ID="ID_1267317279" MODIFIED="1784131541424" TEXT="wie kann dann der Zugriff erfolgen?">
<arrowlink COLOR="#5a94d9" DESTINATION="ID_169121010" ENDARROW="Default" ENDINCLINATION="135;0;" ID="Arrow_ID_84801803" STARTARROW="None" STARTINCLINATION="76;6;"/>
</node>
<node CREATED="1784131317769" ID="ID_1516225282" MODIFIED="1784131336237" TEXT="das Anordnungs-Problem ist eine Sackgasse">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1784131338269" ID="ID_1521754743" MODIFIED="1784131354300" TEXT="es ist zwar &#xbb;nur&#xab; ein Problem der Code-Anordnung"/>
<node CREATED="1784131354971" ID="ID_458757211" MODIFIED="1784131366411" TEXT="diese ist jedoch festgelegt">
<node CREATED="1784131367993" ID="ID_55736035" MODIFIED="1784131407585" TEXT="durch die Forderung nach Lesbarkeit (&#xd83e;&#xdc32; Demo-Code)">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
hei&#223;t: hier gibt es keine M&#246;glichkeit, <i>ein Auge zuzudr&#252;cken</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1784131409804" ID="ID_359711423" MODIFIED="1784131419742" TEXT="durch das einmal gew&#xe4;hlte Domain-Scoping"/>
</node>
</node>
</node>
<node CREATED="1784131432702" ID="ID_1143489272" MODIFIED="1784131440428" TEXT="L&#xf6;sung: Zugriff vom Datentyp trennen">
<node CREATED="1784131442690" ID="ID_656100547" MODIFIED="1784131483235" TEXT="dadurch bleibt das Scoping unbedingt erhalten"/>
<node CREATED="1784131484193" ID="ID_169121010" MODIFIED="1784131533952" TEXT="Zugriff als Funktion darstellen &#x27f9; &#x3bb;">
<linktarget COLOR="#5a94d9" DESTINATION="ID_169121010" ENDARROW="Default" ENDINCLINATION="135;0;" ID="Arrow_ID_84801803" SOURCE="ID_1267317279" STARTARROW="None" STARTINCLINATION="76;6;"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1783644430659" ID="ID_269686877" MODIFIED="1783644452555" TEXT="Aufrabe: Vorlauf steuern"> <node CREATED="1783644430659" ID="ID_269686877" MODIFIED="1783644452555" TEXT="Aufrabe: Vorlauf steuern">
<node CREATED="1783644529049" ID="ID_486151338" MODIFIED="1783644875737" TEXT="zwei Phasen (Chase/Lock)"> <node CREATED="1783644529049" ID="ID_486151338" MODIFIED="1783644875737" TEXT="zwei Phasen (Chase/Lock)">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>

View file

@ -21,18 +21,25 @@
using std::unique_ptr; using std::unique_ptr;
//-----------------hard-coded-config-- //-----------------hard-coded-config--
const size_t RING_SIZ = 5;
const uint VIDEO_WIDTH = 320;
const uint VIDEO_HEIGHT = 240;
//-----------------hard-coded-config-- //-----------------hard-coded-config--
class UringVideoPlayer class UringVideoPlayer
{ {
using VideoDisplay = EglDisplay<uint8_t, VIDEO_WIDTH,VIDEO_HEIGHT>;
using Buffer = VideoDisplay::Buffer;
Glib::Dispatcher dispatchFrame_; Glib::Dispatcher dispatchFrame_;
EglDisplay videoDisplayer_; VideoDisplay videoDisplayer_;
std::thread proactorThread_; std::thread proactorThread_;
public: public:
UringVideoPlayer (Gtk::Window& appWindow) UringVideoPlayer (Gtk::Window& appWindow)
: videoDisplayer_{appWindow, dispatchFrame_} : videoDisplayer_{appWindow, dispatchFrame_, [this]{ return retrieveCurrFrame(); }}
, proactorThread_{[this]{ playVideo(); }} , proactorThread_{[this]{ playVideo(); }}
{ } { }
@ -42,7 +49,15 @@ class UringVideoPlayer
void void
playVideo() playVideo()
{ {
// allocate buffer data structure
// initialise URing
// ++ proactor-loop ++
}
Buffer*
retrieveCurrFrame()
{
///////OOO threadsafe hand-over of current frame data
} }
}; };
@ -50,7 +65,7 @@ class UringVideoPlayer
unique_ptr<UringVideoPlayer> unique_ptr<UringVideoPlayer>
launchPlayer (Gtk::Window& appWindow) launchPlayer (Gtk::Window& appWindow)
{ {
appWindow.resize (EglDisplay::VIDEO_WIDTH, EglDisplay::VIDEO_HEIGHT); appWindow.resize (VIDEO_WIDTH, VIDEO_HEIGHT);
auto player = std::make_unique<UringVideoPlayer> (appWindow); auto player = std::make_unique<UringVideoPlayer> (appWindow);

View file

@ -14,10 +14,11 @@
#include "commons.hpp" #include "commons.hpp"
#include "gtk-uring-app.hpp" #include "gtk-uring-app.hpp"
#include <iostream> #include <functional>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <string> #include <string>
#include <array>
#include <set> #include <set>
// for low-level access -> X-Window // for low-level access -> X-Window
@ -35,8 +36,27 @@ using std::string;
/** /**
* Connection and drawing context used for EGL based video display. * Connection and drawing context used for EGL based video display.
*/ */
template<typename PIX, uint WIDTH, uint HEIGHT>
class EglDisplay class EglDisplay
{ {
public:
using Buffer = std::array<PIX, WIDTH*HEIGHT * 3 >;
using PixFeed = std::function<Buffer*()>;
EglDisplay(Gtk::Window& appWindow
,Glib::Dispatcher& dispatchFrame
,PixFeed frameCallback
)
: retrieveFrame_{frameCallback}
{
openDisplay (appWindow);
dispatchFrame.connect([this]{ displayFrame(); });
}
void cleanUp();
private:
/** EGL / X11 connection. */ /** EGL / X11 connection. */
EGLDisplay display_{nullptr}; EGLDisplay display_{nullptr};
EGLSurface surface_{nullptr}; EGLSurface surface_{nullptr};
@ -50,20 +70,9 @@ class EglDisplay
float scaleX_{1}; float scaleX_{1};
float scaleY_{1}; float scaleY_{1};
public: /** Callback functor to access current pixel data */
// hard wired here (should be dynamic in real-world usage) PixFeed retrieveFrame_{};
constexpr static uint VIDEO_WIDTH {320};
constexpr static uint VIDEO_HEIGHT{240};
EglDisplay(Gtk::Window& appWindow, Glib::Dispatcher& dispatchFrame)
{
openDisplay (appWindow);
dispatchFrame.connect([this]{ displayFrame(); });
}
void cleanUp();
private:
void openDisplay (Gtk::Window&); void openDisplay (Gtk::Window&);
void displayFrame(); void displayFrame();
}; };
@ -71,8 +80,9 @@ class EglDisplay
template<typename PIX, uint WIDTH, uint HEIGHT>
void void
EglDisplay::openDisplay (Gtk::Window& appWindow) EglDisplay<PIX,WIDTH,HEIGHT>::openDisplay (Gtk::Window& appWindow)
{ {
std::cout << "Open display-connection through EGL..." << std::endl; std::cout << "Open display-connection through EGL..." << std::endl;
@ -262,7 +272,7 @@ EglDisplay::openDisplay (Gtk::Window& appWindow)
/* === setup a fixed geometry to hold that texture === */ /* === setup a fixed geometry to hold that texture === */
glDisable (GL_DEPTH_TEST); // we do not need 3D layering / positioning glDisable (GL_DEPTH_TEST); // we do not need 3D layering / positioning
glViewport (0, 0, VIDEO_WIDTH, VIDEO_HEIGHT); // Origin in the middle of the window (note Y points upwards) glViewport (0, 0, WIDTH, HEIGHT); // Origin in the middle of the window (note Y points upwards)
// Note: this demo uses a fixed-size window and hard-coded video size; // Note: this demo uses a fixed-size window and hard-coded video size;
// a real-world implementation would have to place the video frame // a real-world implementation would have to place the video frame
@ -301,28 +311,28 @@ EglDisplay::openDisplay (Gtk::Window& appWindow)
glEnableVertexAttribArray (0); // activate attribute #1 ≙ input argument `position` in vertexShader glEnableVertexAttribArray (0); // activate attribute #1 ≙ input argument `position` in vertexShader
glEnableVertexAttribArray (1); // activate attribute #2 ≙ input argument `texCoord` in vertexShader glEnableVertexAttribArray (1); // activate attribute #2 ≙ input argument `texCoord` in vertexShader
std::cout << "Successfully established OpenGL display ("<<VIDEO_WIDTH<<"x"<<VIDEO_HEIGHT<<"px) within GTK-Window." << std::endl; std::cout << "Successfully established OpenGL display ("<<WIDTH<<"x"<<HEIGHT<<"px) within GTK-Window." << std::endl;
} }
template<typename PIX, uint WIDTH, uint HEIGHT>
void void
EglDisplay::displayFrame() EglDisplay<PIX,WIDTH,HEIGHT>::displayFrame()
{ {
uint frameNr = imgGen_.getFrameNr();
uint fps = imgGen_.getFps();
if (0 == frameNr % fps)
std::cout << "tick ... " << imgGen_.getFrameNr() << std::endl;
// compute a buffer with RGB data and bind it into the prepared texture... auto currFrame = retrieveFrame_();
const void* buffer = imgGen_.buildNext().data(); if (not currFrame) return;
// pick up current buffer with RGB data
// and send it to the GPU (into the prepared texture)...
glTexImage2D (GL_TEXTURE_2D // the target texture store to work on, here "the" TEXTURE_2D glTexImage2D (GL_TEXTURE_2D // the target texture store to work on, here "the" TEXTURE_2D
,0 // detail level (when using mipmap reduction, which we don't) ,0 // detail level (when using mipmap reduction, which we don't)
,GL_RGB // internal format or features to use for this texture ,GL_RGB // internal format or features to use for this texture
,VIDEO_WIDTH,VIDEO_HEIGHT, /*border*/ 0 ,WIDTH,HEIGHT, /*border*/ 0
,GL_RGB // data layout of the provided pixels ,GL_RGB // data layout of the provided pixels
,GL_UNSIGNED_BYTE // data format / size of the pixels ,GL_UNSIGNED_BYTE // data format / size of the pixels
,buffer ,currFrame
); );
// Draw the quadrilateral // Draw the quadrilateral
@ -333,10 +343,12 @@ EglDisplay::displayFrame()
} }
template<typename PIX, uint WIDTH, uint HEIGHT>
void void
EglDisplay::cleanUp() EglDisplay<PIX,WIDTH,HEIGHT>::cleanUp()
{ {
std::cout << "STOP " << imgGen_.getFrameNr() << " frames displayed." << std::endl; // std::cout << "STOP " << imgGen_.getFrameNr() << " frames displayed." << std::endl;
// detach binding with OpenGL context // detach binding with OpenGL context
eglMakeCurrent (display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent (display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

View file

@ -86,7 +86,7 @@ class GtkUringApp
run() run()
{ {
demoWindow_.button_.signal_clicked().connect( demoWindow_.button_.signal_clicked().connect(
sigc::mem_fun (*this, GtkUringApp::triggerProcessing)); sigc::mem_fun (*this, &GtkUringApp::triggerProcessing));
return Gtk::Application::run (demoWindow_); return Gtk::Application::run (demoWindow_);
} // blocks while application is active } // blocks while application is active