Prototype: establish buffer data structure and initialise URing
- setup a IORING_OP_TIMEOUT to drive the frame loop - use the status mark of buffers ahead to supply new IORING_OP_READ - rely on two running framecount cursors with modulus to map onto buffer slots
This commit is contained in:
parent
2a61def8a4
commit
ae74bd323e
3 changed files with 219 additions and 12 deletions
|
|
@ -897,7 +897,9 @@
|
||||||
<node COLOR="#338800" CREATED="1783644343706" ID="ID_481307677" MODIFIED="1784052427730" TEXT="ein GTK-Rahmen (wie letztes Jahr)">
|
<node COLOR="#338800" CREATED="1783644343706" ID="ID_481307677" MODIFIED="1784052427730" TEXT="ein GTK-Rahmen (wie letztes Jahr)">
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1783644357376" ID="ID_1687423764" MODIFIED="1784052436428" TEXT="ein Proactor-Thread"/>
|
<node COLOR="#338800" CREATED="1783644357376" ID="ID_1687423764" MODIFIED="1784142889926" TEXT="ein Proactor-Thread">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
<node CREATED="1783644382004" ID="ID_222096554" MODIFIED="1783644392847" TEXT="Handler">
|
<node CREATED="1783644382004" ID="ID_222096554" MODIFIED="1783644392847" TEXT="Handler">
|
||||||
<node CREATED="1783644394013" ID="ID_599467746" MODIFIED="1783644398783" TEXT="Completion-Handler"/>
|
<node CREATED="1783644394013" ID="ID_599467746" MODIFIED="1783644398783" TEXT="Completion-Handler"/>
|
||||||
<node CREATED="1783644399671" ID="ID_1684157516" MODIFIED="1783644406037" TEXT="Submission-Handler"/>
|
<node CREATED="1783644399671" ID="ID_1684157516" MODIFIED="1783644406037" TEXT="Submission-Handler"/>
|
||||||
|
|
@ -1012,8 +1014,8 @@
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1783902821732" ID="ID_1465201307" MODIFIED="1783902838122" TEXT="getriggert würde dann der Code, der die OpenGL-Pipeline mit neuen Daten versorgt"/>
|
<node CREATED="1783902821732" ID="ID_1465201307" MODIFIED="1783902838122" TEXT="getriggert würde dann der Code, der die OpenGL-Pipeline mit neuen Daten versorgt"/>
|
||||||
<node CREATED="1783902838536" ID="ID_1259653595" MODIFIED="1783902845946" TEXT="dieser würde mithin im GTK-Thread laufen"/>
|
<node CREATED="1783902838536" ID="ID_1259653595" MODIFIED="1783902845946" TEXT="dieser würde mithin im GTK-Thread laufen"/>
|
||||||
<node CREATED="1783902847135" ID="ID_1990712475" MODIFIED="1783902883778" TEXT="Hinweis auf die VSync-Problematik">
|
<node CREATED="1783902847135" ID="ID_1990712475" MODIFIED="1784140538042" TEXT="Hinweis auf die VSync-Problematik">
|
||||||
<arrowlink COLOR="#347acc" DESTINATION="ID_1393441883" ENDARROW="Default" ENDINCLINATION="154;0;" ID="Arrow_ID_707364611" STARTARROW="None" STARTINCLINATION="140;12;"/>
|
<arrowlink COLOR="#347acc" DESTINATION="ID_1393441883" ENDARROW="Default" ENDINCLINATION="288;0;" ID="Arrow_ID_707364611" STARTARROW="None" STARTINCLINATION="140;12;"/>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#efdeb8" CREATED="1783956967738" ID="ID_1170137190" MODIFIED="1783957012593" TEXT="Wichtige Einsicht: warum nicht jeder Desktop-Frame per Buffer-Flip bedient werden muß">
|
<node BACKGROUND_COLOR="#efdeb8" CREATED="1783956967738" ID="ID_1170137190" MODIFIED="1783957012593" TEXT="Wichtige Einsicht: warum nicht jeder Desktop-Frame per Buffer-Flip bedient werden muß">
|
||||||
<icon BUILTIN="idea"/>
|
<icon BUILTIN="idea"/>
|
||||||
|
|
@ -1406,7 +1408,7 @@
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1783957483612" ID="ID_918051178" MODIFIED="1784136111534" STYLE="fork" TEXT="a Zuckerl: Chrono-to-Kernel-Timespec">
|
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1783957483612" ID="ID_918051178" MODIFIED="1784151801322" STYLE="fork" TEXT="a Zuckerl: Chrono-to-Kernel-Timespec">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -1464,6 +1466,7 @@
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
|
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<linktarget COLOR="#5b8796" DESTINATION="ID_918051178" ENDARROW="Default" ENDINCLINATION="-181;1174;" ID="Arrow_ID_1798992367" SOURCE="ID_546021072" STARTARROW="None" STARTINCLINATION="-274;12;"/>
|
||||||
<icon BUILTIN="wizard"/>
|
<icon BUILTIN="wizard"/>
|
||||||
<icon BUILTIN="edit"/>
|
<icon BUILTIN="edit"/>
|
||||||
</node>
|
</node>
|
||||||
|
|
@ -1714,8 +1717,8 @@
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1783902798597" ID="ID_599725786" MODIFIED="1783902800007" TEXT="eglSwapInterval">
|
<node CREATED="1783902798597" ID="ID_599725786" MODIFIED="1783902800007" TEXT="eglSwapInterval">
|
||||||
<node CREATED="1783902800007" ID="ID_1393441883" MODIFIED="1783902877712" TEXT="damit kann man wohl das Verhlätnis zu VSync steuern">
|
<node CREATED="1783902800007" ID="ID_1393441883" MODIFIED="1784140538042" TEXT="damit kann man wohl das Verhlätnis zu VSync steuern">
|
||||||
<linktarget COLOR="#347acc" DESTINATION="ID_1393441883" ENDARROW="Default" ENDINCLINATION="154;0;" ID="Arrow_ID_707364611" SOURCE="ID_1990712475" STARTARROW="None" STARTINCLINATION="140;12;"/>
|
<linktarget COLOR="#347acc" DESTINATION="ID_1393441883" ENDARROW="Default" ENDINCLINATION="288;0;" ID="Arrow_ID_707364611" SOURCE="ID_1990712475" STARTARROW="None" STARTINCLINATION="140;12;"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1783904509744" ID="ID_1126395932" MODIFIED="1783904513706" TEXT="X11 / Wayland">
|
<node CREATED="1783904509744" ID="ID_1126395932" MODIFIED="1783904513706" TEXT="X11 / Wayland">
|
||||||
|
|
@ -2096,7 +2099,8 @@
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1784083148598" ID="ID_504827142" MODIFIED="1784083164848" TEXT="Problem: Anordnung der Daten-Definition im Code">
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1784083148598" ID="ID_504827142" MODIFIED="1784143583720" TEXT="Problem: Anordnung der Daten-Definition im Code">
|
||||||
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
<node CREATED="1784083166480" ID="ID_1404935910" MODIFIED="1784132116787" TEXT="muß hierzu auch das Enum definieren">
|
<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;"/>
|
<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>
|
||||||
|
|
@ -2126,7 +2130,8 @@
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1784131432702" ID="ID_1143489272" MODIFIED="1784131440428" TEXT="Lösung: Zugriff vom Datentyp trennen">
|
<node COLOR="#338800" CREATED="1784131432702" ID="ID_1143489272" MODIFIED="1784143579660" TEXT="Lösung: Zugriff vom Datentyp trennen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
<node CREATED="1784131442690" ID="ID_656100547" MODIFIED="1784131483235" TEXT="dadurch bleibt das Scoping unbedingt erhalten"/>
|
<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 ⟹ λ">
|
<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;"/>
|
<linktarget COLOR="#5a94d9" DESTINATION="ID_169121010" ENDARROW="Default" ENDINCLINATION="135;0;" ID="Arrow_ID_84801803" SOURCE="ID_1267317279" STARTARROW="None" STARTINCLINATION="76;6;"/>
|
||||||
|
|
@ -2145,11 +2150,90 @@
|
||||||
</richcontent>
|
</richcontent>
|
||||||
<icon BUILTIN="messagebox_warning"/>
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1784137038242" ID="ID_1199476075" MODIFIED="1784137051164" TEXT="dann doch ein klassisches OO-Callback-Interface"/>
|
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1784137038242" ID="ID_1199476075" MODIFIED="1784143571509" TEXT="dann doch ein klassisches OO-Callback-Interface">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784143662545" ID="ID_1198363494" MODIFIED="1784143666308" TEXT="Event-Handler">
|
||||||
|
<node COLOR="#338800" CREATED="1784143667543" ID="ID_1705410666" MODIFIED="1784152302590" TEXT="Setup der Event-Verarbeitung">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node COLOR="#338800" CREATED="1784143709139" ID="ID_1508199132" MODIFIED="1784151704956" TEXT="File öffnen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node CREATED="1784145655032" ID="ID_815825627" MODIFIED="1784145664817" TEXT="macht man das mit C++?"/>
|
||||||
|
<node CREATED="1784145665437" ID="ID_1276445757" MODIFIED="1784145828191" TEXT="besser direkt mit den POSIX-Funktionen">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Mehrere Argumente dafür: man könnte die low-level-Flags setzen (wie <code>O_CLOEXEX, O_NOFOLLOW, </code>oder gar <code>O_DIRECT</code>). Das Öffnen ist <i>atomic,</i>  d.h. das File kann nicht mehr gelöscht/verschoben werden beform man das Filehandle hat (was bei einem getrennten STAT und Path-Check durchaus möglich ist)
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784147238004" ID="ID_973311307" LINK="https://man7.org/linux/man-pages/man2/open.2.html" MODIFIED="1784147251992" TEXT="man: open()"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1784143714978" ID="ID_127436641" MODIFIED="1784151706946" TEXT="URings anlegen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1784143731216" ID="ID_101354381" MODIFIED="1784151710995" TEXT="Timer aktivieren">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node CREATED="1784151717872" ID="ID_1035839641" MODIFIED="1784151726466" TEXT="das ist eine spezielle Submission in den URing"/>
|
||||||
|
<node BACKGROUND_COLOR="#e6dfa8" COLOR="#690f14" CREATED="1784151807158" ID="ID_161068537" MODIFIED="1784152246318" TEXT="⟹ muß URing um +1 Slot größer dimensionieren">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Begründung
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
da wir stets <i>in bulk</i> die Submissions hinzufügen <i>und erst danach (synchronisiert)</i> den Output antriggern, können das maximal so viele Einträge sein, wie wir Buffer haben
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i>zusätzlich</i> wird ein Eintrag benötigt, um am Anfang auch den periodischen Timer in Gang zu setzen
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
eben dieser <i>eine zusätzliche Eintrag</i> genügt auch, um jeweils noch <i>ein</i> Timer-Event zu empfangen
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
weitere Completions können nicht kommen, da wir nicht mehr Submissions abgeschickt haben
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
weitere Timer-Events könnten kommen, falls wir zum Entnehmen und Übergeben mehr als einen Timer-tick brauchen (unwahrscheinlich, aber nicht auszuschließen). In einem solchen Fall würden schlimmstenfalls hinten weitere Timer-Events „runterfallen“ (wobei aktuelle Kernel ein internes Backlog haben). Sollten wir dergestalt Timer-Events verpassen, sind sie aber auch schon überholt, und das nächste reguläre Event wird uns wieder weiterschieben
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784151734786" ID="ID_546021072" MODIFIED="1784151801321" TEXT="verwende hier meine Hilfsfunktion für Chrono ⟼ Kernel-Timespec">
|
||||||
|
<arrowlink COLOR="#5b8796" DESTINATION="ID_918051178" ENDARROW="Default" ENDINCLINATION="-181;1174;" ID="Arrow_ID_1798992367" STARTARROW="None" STARTINCLINATION="-274;12;"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1784143738263" ID="ID_1385880788" MODIFIED="1784152297376" TEXT="Handler-Loop">
|
||||||
|
<icon BUILTIN="pencil"/>
|
||||||
|
<node CREATED="1784143781367" ID="ID_1463866164" MODIFIED="1784143789996" TEXT="gelesene Daten entgegennehmen"/>
|
||||||
|
<node COLOR="#338800" CREATED="1784143790590" ID="ID_1916682510" MODIFIED="1784152292235" TEXT="neue Leseaufträge absetzen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node CREATED="1784152255150" ID="ID_1732543149" MODIFIED="1784152264977" TEXT="lagere das in eine Hilfsfunktion aus"/>
|
||||||
|
<node CREATED="1784152265502" ID="ID_861900858" MODIFIED="1784152274216" TEXT="diese orientiert sich nur an den freien Slots"/>
|
||||||
|
<node CREATED="1784152276235" ID="ID_812423922" MODIFIED="1784152289135" TEXT="⟹ Backpressure und anfangs alle Slots">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784143798563" ID="ID_532286724" MODIFIED="1784143809876" TEXT="Time-Tick : Frame weiterschalten"/>
|
||||||
|
</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>
|
||||||
|
|
@ -2171,6 +2255,51 @@
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
</node>
|
</node>
|
||||||
|
<node CREATED="1784142959996" ID="ID_1894186700" MODIFIED="1784142979142" TEXT="Ansatz: realisiere das durch »Backpressure«">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
<node CREATED="1784142980731" ID="ID_1146524396" MODIFIED="1784142995774">
|
||||||
|
<richcontent TYPE="NODE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
also <i>keine explizite</i> Steuerung
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784143310222" ID="ID_1598149960" MODIFIED="1784143340787" TEXT="vielmehr sorgt die feste zyklische Buffer-Struktur für die Limitierung"/>
|
||||||
|
<node CREATED="1784143015199" ID="ID_218469149" MODIFIED="1784143039421" TEXT="zwei Phasen schreiten jeweils so schnell voran wie derzeig möglich">
|
||||||
|
<node CREATED="1784143040300" ID="ID_227838217" MODIFIED="1784143254426" TEXT="Phase-1 : read-Submissions beauftragen">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
ist jeweils nur möglich wenn der dafür vorgesehene Buffer bereits frei geworden ist
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1784143055979" ID="ID_1727640820" MODIFIED="1784143309405" TEXT="Phase-2 : eingelesene Daten übergeben">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Ist nur möglich wenn diese Daten für den erwartungsgemäß nächsten Frame bereits da sind, und der unmittelbar vorausgegangene Frame schon komplett vom Video-Displayer übernommen wurde
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,11 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <linux/time_types.h> // for struct __kernel_timespec
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using uint = unsigned int;
|
using uint = unsigned int;
|
||||||
using FrameRate = uint;
|
using FrameRate = uint;
|
||||||
|
|
@ -42,4 +45,20 @@ class NonCopyable
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a kernel timespec from a given C++ chrono duration
|
||||||
|
*/
|
||||||
|
template<class REP, class SCALE>
|
||||||
|
constexpr struct __kernel_timespec
|
||||||
|
asKernelTimespec (std::chrono::duration<REP, SCALE> dur)
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
auto secs = duration_cast<seconds>(dur);
|
||||||
|
auto nsecs = duration_cast<nanoseconds>(dur - secs);
|
||||||
|
return __kernel_timespec{ static_cast<long long> (secs.count())
|
||||||
|
, static_cast<long long> (nsecs.count())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*COMMONS_H*/
|
#endif /*COMMONS_H*/
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,24 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <liburing.h>
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
using std::chrono::operator ""ms;
|
||||||
|
|
||||||
|
|
||||||
//-----------------hard-coded-config--
|
//-----------------hard-coded-config--
|
||||||
const size_t RING_SIZ = 5;
|
const size_t RING_SIZ = 5;
|
||||||
|
const string RAW_VIDEO_INPUT_FILE = "demovideo.raw";
|
||||||
const uint VIDEO_WIDTH = 320;
|
const uint VIDEO_WIDTH = 320;
|
||||||
const uint VIDEO_HEIGHT = 240;
|
const uint VIDEO_HEIGHT = 240;
|
||||||
|
const size_t START_FRAME = 0;
|
||||||
|
const size_t MAX_LOOP_FRAME = 30 * 25;
|
||||||
|
|
||||||
|
auto calcSrcFrame = [](size_t runningNr){ return START_FRAME + runningNr % MAX_LOOP_FRAME; };
|
||||||
|
|
||||||
//-----------------hard-coded-config--
|
//-----------------hard-coded-config--
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -81,6 +91,7 @@ class UringVideoPlayer
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void playVideo();
|
void playVideo();
|
||||||
|
void addNextReadSubmissions (io_uring&, int inputFD);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -94,10 +105,58 @@ class UringVideoPlayer
|
||||||
void
|
void
|
||||||
UringVideoPlayer::playVideo()
|
UringVideoPlayer::playVideo()
|
||||||
{
|
{
|
||||||
|
/* ===== initial setup ===== */
|
||||||
|
int inputFD = open (RAW_VIDEO_INPUT_FILE.c_str(), O_RDONLY);
|
||||||
|
if (inputFD < 0)
|
||||||
|
__FAIL ("open file \""+RAW_VIDEO_INPUT_FILE+"\"");
|
||||||
|
|
||||||
|
// Allocate several data buffers (used as ring)
|
||||||
buffer_ = make_unique<Buffer[]> (RING_SIZ);
|
buffer_ = make_unique<Buffer[]> (RING_SIZ);
|
||||||
buffState_ = make_unique<AtomicBuffState[]> (RING_SIZ);
|
buffState_ = make_unique<AtomicBuffState[]> (RING_SIZ);
|
||||||
// initialise URing
|
|
||||||
// ++ proactor-loop ++
|
// initialise uRing Kernel interface
|
||||||
|
io_uring uRing;
|
||||||
|
io_uring_queue_init (RING_SIZ+1, &uRing, /*flags*/ 0 ); // Note: one additional »slot« for the timer event(s)
|
||||||
|
|
||||||
|
// Setup periodic frame beat, firing infinitely
|
||||||
|
const auto TICK_TAG = UINT64_MAX; // special marker for timer events (different from possible frame numbers)
|
||||||
|
auto timespec = asKernelTimespec (40ms); // 40ms ≈ 25fps
|
||||||
|
io_uring_sqe* timerSubmission = io_uring_get_sqe (&uRing);
|
||||||
|
io_uring_prep_timeout (timerSubmission, ×pec, /*no count limit*/ 0, IORING_TIMEOUT_MULTISHOT);
|
||||||
|
io_uring_sqe_set_data64(timerSubmission, TICK_TAG);
|
||||||
|
|
||||||
|
addNextReadSubmissions (uRing, inputFD);
|
||||||
|
io_uring_submit (&uRing);
|
||||||
|
|
||||||
|
/* ===== proactor-loop ===== */
|
||||||
|
|
||||||
|
close (inputFD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the next read operations,
|
||||||
|
* using all free buffer slots ahead.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
UringVideoPlayer::addNextReadSubmissions (io_uring& uRing, int inputFD)
|
||||||
|
{
|
||||||
|
assert (0 < inputFD);
|
||||||
|
const size_t BUFFSIZ = sizeof(Buffer);
|
||||||
|
|
||||||
|
while (buffState_[nextRead_ % RING_SIZ] == FREE)
|
||||||
|
{
|
||||||
|
size_t srcOffset = calcSrcFrame (nextRead_);
|
||||||
|
io_uring_sqe* readSubmission = io_uring_get_sqe (&uRing);
|
||||||
|
io_uring_prep_read (readSubmission
|
||||||
|
,inputFD
|
||||||
|
,& buffer_[nextRead_ % RING_SIZ]
|
||||||
|
,BUFFSIZ
|
||||||
|
,BUFFSIZ * srcOffset
|
||||||
|
);
|
||||||
|
io_uring_sqe_set_data64 (readSubmission, nextRead_);
|
||||||
|
++nextRead_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue