2026-07-11 19:03:31 +02:00
|
|
|
|
/*
|
|
|
|
|
|
demo-uring.cpp - async file IO with io_uring
|
|
|
|
|
|
|
|
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2026, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU GPL version 2+ See the LICENSE file for details.
|
|
|
|
|
|
|
|
|
|
|
|
* ************************************************************************/
|
|
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
|
|
|
|
|
#include "commons.hpp"
|
|
|
|
|
|
#include "egl-display.hpp"
|
|
|
|
|
|
#include "gtk-uring-app.hpp"
|
|
|
|
|
|
|
2026-07-11 19:03:31 +02:00
|
|
|
|
#include <iostream>
|
2026-07-14 19:27:27 +02:00
|
|
|
|
#include <memory>
|
|
|
|
|
|
#include <thread>
|
2026-07-15 20:40:59 +02:00
|
|
|
|
#include <atomic>
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
|
|
|
|
|
using std::unique_ptr;
|
2026-07-15 20:40:59 +02:00
|
|
|
|
using std::make_unique;
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
|
|
|
|
|
//-----------------hard-coded-config--
|
2026-07-15 18:56:37 +02:00
|
|
|
|
const size_t RING_SIZ = 5;
|
|
|
|
|
|
|
|
|
|
|
|
const uint VIDEO_WIDTH = 320;
|
|
|
|
|
|
const uint VIDEO_HEIGHT = 240;
|
2026-07-14 19:27:27 +02:00
|
|
|
|
//-----------------hard-coded-config--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UringVideoPlayer
|
2026-07-15 20:40:59 +02:00
|
|
|
|
: NonCopyable
|
2026-07-14 19:27:27 +02:00
|
|
|
|
{
|
2026-07-15 18:56:37 +02:00
|
|
|
|
using VideoDisplay = EglDisplay<uint8_t, VIDEO_WIDTH,VIDEO_HEIGHT>;
|
|
|
|
|
|
using Buffer = VideoDisplay::Buffer;
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
enum BuffState { FREE, READ, SHOW };
|
|
|
|
|
|
using AtomicBuffState = std::atomic<BuffState>;
|
|
|
|
|
|
|
|
|
|
|
|
using BufferAlloc = unique_ptr<Buffer[]>;
|
|
|
|
|
|
using BuffStateAlloc = unique_ptr<AtomicBuffState[]>;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Connector to the VideoDisplay for dispatching video data.
|
|
|
|
|
|
* @note inherits from Glib::Dispatcher -> signal frame readiness
|
|
|
|
|
|
* @remark the callback functions allow the VideoDisplay to interact
|
|
|
|
|
|
* with the buffer data and state in a threadsafe manner
|
|
|
|
|
|
*/
|
|
|
|
|
|
class BufferDispatcher
|
|
|
|
|
|
: public VideoDisplay::PixelFeed
|
|
|
|
|
|
{
|
|
|
|
|
|
Buffer* retrieveFrame() override;
|
|
|
|
|
|
void completedFrame() override;
|
|
|
|
|
|
|
|
|
|
|
|
UringVideoPlayer& player_;
|
|
|
|
|
|
public:
|
|
|
|
|
|
BufferDispatcher (UringVideoPlayer& player)
|
|
|
|
|
|
: player_{player}
|
|
|
|
|
|
{ }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
size_t nextRead_{0};
|
|
|
|
|
|
size_t nextShow_{0};
|
|
|
|
|
|
BufferAlloc buffer_{};
|
|
|
|
|
|
BuffStateAlloc buffState_{};
|
|
|
|
|
|
std::atomic_bool playing_{false};
|
|
|
|
|
|
BufferDispatcher dispatchFrame_;
|
2026-07-15 18:56:37 +02:00
|
|
|
|
VideoDisplay videoDisplayer_;
|
2026-07-14 19:27:27 +02:00
|
|
|
|
std::thread proactorThread_;
|
2026-07-14 20:16:18 +02:00
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
public:
|
|
|
|
|
|
UringVideoPlayer (Gtk::Window& appWindow)
|
2026-07-15 20:40:59 +02:00
|
|
|
|
: dispatchFrame_{*this}
|
|
|
|
|
|
, videoDisplayer_{appWindow, dispatchFrame_}
|
2026-07-14 19:27:27 +02:00
|
|
|
|
, proactorThread_{[this]{ playVideo(); }}
|
|
|
|
|
|
{ }
|
2026-07-14 20:16:18 +02:00
|
|
|
|
|
|
|
|
|
|
void terminate();
|
2026-07-15 18:56:37 +02:00
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
private:
|
2026-07-15 20:40:59 +02:00
|
|
|
|
void playVideo();
|
2026-07-14 19:27:27 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Logic of the »Proactor Thread«:
|
|
|
|
|
|
* - maintain the working buffers
|
|
|
|
|
|
* - open the raw video file to retrieve data
|
|
|
|
|
|
* - establish an IO_URING connection for reading
|
|
|
|
|
|
* - periodic processing to fill and hand-off buffers
|
|
|
|
|
|
*/
|
|
|
|
|
|
void
|
|
|
|
|
|
UringVideoPlayer::playVideo()
|
2026-07-14 19:27:27 +02:00
|
|
|
|
{
|
2026-07-15 20:40:59 +02:00
|
|
|
|
buffer_ = make_unique<Buffer[]> (RING_SIZ);
|
|
|
|
|
|
buffState_ = make_unique<AtomicBuffState[]> (RING_SIZ);
|
|
|
|
|
|
// initialise URing
|
|
|
|
|
|
// ++ proactor-loop ++
|
|
|
|
|
|
}
|
2026-07-14 20:16:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
UringVideoPlayer::Buffer*
|
|
|
|
|
|
UringVideoPlayer::BufferDispatcher::retrieveFrame()
|
|
|
|
|
|
{
|
|
|
|
|
|
///////OOO threadsafe hand-over of current frame data
|
2026-07-14 19:27:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
void
|
|
|
|
|
|
UringVideoPlayer::BufferDispatcher::completedFrame()
|
|
|
|
|
|
{
|
|
|
|
|
|
///////OOO mark end of buffer access
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-14 19:27:27 +02:00
|
|
|
|
|
|
|
|
|
|
void
|
2026-07-14 20:16:18 +02:00
|
|
|
|
UringVideoPlayer::terminate()
|
2026-07-14 19:27:27 +02:00
|
|
|
|
{
|
2026-07-15 20:40:59 +02:00
|
|
|
|
playing_.store (false, std::memory_order_release);
|
|
|
|
|
|
proactorThread_.join();
|
2026-07-14 20:16:18 +02:00
|
|
|
|
videoDisplayer_.cleanUp();
|
2026-07-14 19:27:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-11 19:03:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
2026-07-15 20:40:59 +02:00
|
|
|
|
unique_ptr<UringVideoPlayer>
|
|
|
|
|
|
launchPlayer (Gtk::Window& appWindow)
|
|
|
|
|
|
{
|
|
|
|
|
|
appWindow.resize (VIDEO_WIDTH, VIDEO_HEIGHT);
|
|
|
|
|
|
return std::make_unique<UringVideoPlayer> (appWindow);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-07-11 19:03:31 +02:00
|
|
|
|
int
|
|
|
|
|
|
main (int, const char*[])
|
|
|
|
|
|
{
|
2026-07-14 19:27:27 +02:00
|
|
|
|
return GtkUringApp<UringVideoPlayer>{"io-uring-demo"}
|
|
|
|
|
|
.onClick (launchPlayer)
|
2026-07-14 20:16:18 +02:00
|
|
|
|
.onClose ([](auto& player){ player.terminate();})
|
2026-07-14 19:27:27 +02:00
|
|
|
|
.run();
|
2026-07-11 19:03:31 +02:00
|
|
|
|
}
|