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:
parent
6bf8a0da7a
commit
4699ae8f03
4 changed files with 296 additions and 40 deletions
|
|
@ -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ützlich">
|
<node CREATED="1783984371031" ID="ID_1219649133" MODIFIED="1783984401222" TEXT="das Grundschema von letztem Jahr war nützlich">
|
||||||
<node CREATED="1783984407459" ID="ID_321798557" MODIFIED="1783984427656" TEXT="„muß den GTK-Code gar nicht anschauen“"/>
|
<node CREATED="1783984407459" ID="ID_321798557" MODIFIED="1783984427656" TEXT="„muß den GTK-Code gar nicht anschauen“"/>
|
||||||
<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="⟹ muß nun einen Frame-Callback (cross-Thread) realisieren">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1783985519074" ID="ID_1873813285" MODIFIED="1783985537906" TEXT="⟹ muß 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 ⟶ Setup"/>
|
<node CREATED="1783986006656" ID="ID_1853634036" MODIFIED="1783986020234" TEXT="GtkApp ⟶ Setup"/>
|
||||||
<node CREATED="1783986025918" ID="ID_905927115" MODIFIED="1783986037848" TEXT="Setup ⟹ erzeugt Player"/>
|
<node CREATED="1783986025918" ID="ID_905927115" MODIFIED="1783986037848" TEXT="Setup ⟹ erzeugt Player"/>
|
||||||
|
|
@ -1816,7 +1819,7 @@
|
||||||
<node CREATED="1783986156014" ID="ID_1075245760" MODIFIED="1783986166367" TEXT="Player ⟶ Frame-Signal"/>
|
<node CREATED="1783986156014" ID="ID_1075245760" MODIFIED="1783986166367" TEXT="Player ⟶ Frame-Signal"/>
|
||||||
<node CREATED="1783986171122" ID="ID_931723726" MODIFIED="1783986184677" TEXT="GtkApp ⟶ Player-Stop"/>
|
<node CREATED="1783986171122" ID="ID_931723726" MODIFIED="1783986184677" TEXT="GtkApp ⟶ 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ösung-1 : in der GtkApp">
|
<node COLOR="#5b280f" CREATED="1783986546063" ID="ID_1573759034" MODIFIED="1783986688651" TEXT="Lö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ösung-2 : im Player">
|
<node CREATED="1783986560783" ID="ID_1335290152" MODIFIED="1784076661520" TEXT="Lö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ösung: baue ein Player-Objekt im Start-Hook">
|
<node CREATED="1783986793999" ID="ID_1360252421" MODIFIED="1783986816919" TEXT="Lö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ösung: das EglDisplay wird nun ein weiteres Objekt">
|
<node CREATED="1783986838784" ID="ID_1847977458" MODIFIED="1783986861705" TEXT="Lö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ä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ß 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 ⟹ getrieben vom Timer-Tick">
|
<node CREATED="1784052955974" ID="ID_1491751742" MODIFIED="1784052978769" TEXT="da nun Proactor ⟹ getrieben vom Timer-Tick">
|
||||||
<icon BUILTIN="idea"/>
|
<icon BUILTIN="idea"/>
|
||||||
</node>
|
</node>
|
||||||
|
<node CREATED="1784076700200" ID="ID_1239755482" MODIFIED="1784076707103" TEXT="Datenübergabe / Sichtbarkeit">
|
||||||
|
<node CREATED="1784076715698" ID="ID_102034340" MODIFIED="1784076740355" TEXT="Dispatcher überträgt nur den Trigger über die Thread-Grenzen"/>
|
||||||
|
<node CREATED="1784076755543" ID="ID_1514914957" MODIFIED="1784076772757" TEXT="muß Atomics / Barrieren einführen fü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ß Claude diese „Idee gehabt“ hätte — denn ich hatte die Konversation ja so geführt, daß Claude mir meine Konzept-Ansätze validiert und verfeinert. Dann habe ich das Prinzip formuliert, daß für Async-IO irgendwo eine State-Machine sein muß. Claude hat das aufgegriffen, validiert und verschärft; und damit war offensichtlich geworden, daß man diese State-Flag als Atomic auslegen kann. Das habe ich in dem Moment genauso »offensichtlich« 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äre
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
aber weil es offensichtlich nicht von Claude stammt
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
⟹ das wirft ein Licht darauf, wie dieses <i>scheinbar intelligente »Generieren« funktioniert, </i>auf Basis einer industriellen Daten-Technik, die Plausibilitä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übergänge">
|
||||||
|
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||||
|
<icon BUILTIN="info"/>
|
||||||
|
<node CREATED="1784078717834" ID="ID_17978925" MODIFIED="1784078954065" TEXT="IO beauftragen: FREE ⟶ READ"/>
|
||||||
|
<node CREATED="1784078958419" ID="ID_1531715805" MODIFIED="1784078974343" TEXT="Übergabe an Display: READ ⟶ SHOW"/>
|
||||||
|
<node CREATED="1784078981634" ID="ID_1578413583" MODIFIED="1784079026236" TEXT="Frame-Flip: SHOW ⟶ FREE"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784078466234" ID="ID_424139171" MODIFIED="1784078496653">
|
||||||
|
<richcontent TYPE="NODE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
hier muß auch die <b>Backpressure</b> 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ö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ür beide Threads sichtbar (und unverä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ä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ä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önnte dem Displayer direkt gegeben werden">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Das wä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ß dann ein Datenfeld sein (sinnvollerweise im Displayer)"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784080062495" ID="ID_254917759" MODIFIED="1784080174245" TEXT="die zuletzt genanne Möglichkeit erscheint mir am natürlichsten">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...da ich immer in Zustä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ö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ß ⟹ einzeln allozieren">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...das gilt fü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äre ein riesiges Array auf dem Heap">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Für die Demo ist das die offensichtliche Lösung: man bekommt unique-ownership und Subscript-Operator einfach vom std::unique_ptr. Wenn man den notwendigen Speicher nicht bekommt, dann läuft die Demo eh nicht, also wozu die Umstä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 ⟹ 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 »Buffer«-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 ⟶ 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ß 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 ⟹ 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 »nur« 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 (�� Demo-Code)">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
heißt: hier gibt es keine Möglichkeit, <i>ein Auge zuzudrücken</i>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784131409804" ID="ID_359711423" MODIFIED="1784131419742" TEXT="durch das einmal gewählte Domain-Scoping"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784131432702" ID="ID_1143489272" MODIFIED="1784131440428" TEXT="Lö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 ⟹ λ">
|
||||||
|
<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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue