diff --git a/src/include/display-facade.h b/src/include/display-facade.h index 37bc4c4a6..76f72620a 100644 --- a/src/include/display-facade.h +++ b/src/include/display-facade.h @@ -96,7 +96,7 @@ namespace lumiera { * through the CL Interface. * @see DisplayService::allocate */ inline void - operator() (LumieraDisplayFrame frame) + operator() (DummyFrame frame) { impl().put_ (&impl(),frame); } @@ -126,9 +126,9 @@ extern "C" { #include "common/interface.h" LUMIERA_INTERFACE_DECLARE (lumieraorg_Display, 0 - , LUMIERA_INTERFACE_SLOT (void, allocate,(LumieraDisplaySlot) ) - , LUMIERA_INTERFACE_SLOT (void, release,(LumieraDisplaySlot) ) - , LUMIERA_INTERFACE_SLOT (void, put,(LumieraDisplaySlot, LumieraDisplayFrame)) + , LUMIERA_INTERFACE_SLOT (void, allocate,(LumieraDisplaySlot) ) + , LUMIERA_INTERFACE_SLOT (void, release,(LumieraDisplaySlot) ) + , LUMIERA_INTERFACE_SLOT (void, put,(LumieraDisplaySlot, DummyFrame)) ); diff --git a/src/include/display-handles.h b/src/include/display-handles.h index eefc6f0fa..5e104f885 100644 --- a/src/include/display-handles.h +++ b/src/include/display-handles.h @@ -23,15 +23,15 @@ #ifndef LUMIERA_DISPLAY_HANDLES_H #define LUMIERA_DISPLAY_HANDLES_H +#include - -typedef unsigned char * LumieraDisplayFrame; +using DummyFrame = std::byte *; struct lumiera_displaySlot_struct { - void (*put_)(lumiera_displaySlot_struct*, LumieraDisplayFrame); + void (*put_)(lumiera_displaySlot_struct*, DummyFrame); }; typedef struct lumiera_displaySlot_struct lumiera_displaySlot; typedef lumiera_displaySlot* LumieraDisplaySlot; diff --git a/src/stage/display-service.cpp b/src/stage/display-service.cpp index 639c30e35..cb34c12d6 100644 --- a/src/stage/display-service.cpp +++ b/src/stage/display-service.cpp @@ -145,7 +145,7 @@ namespace stage { } ) , LUMIERA_INTERFACE_INLINE (put, - void, (LumieraDisplaySlot slotHandle, LumieraDisplayFrame frame), + void, (LumieraDisplaySlot slotHandle, DummyFrame frame), { //skipping full checks for performance reasons REQUIRE (_instance && !lumiera_error_peek()); diff --git a/src/stage/display-service.hpp b/src/stage/display-service.hpp index e4b1de786..359549ff5 100644 --- a/src/stage/display-service.hpp +++ b/src/stage/display-service.hpp @@ -79,7 +79,7 @@ namespace stage { Dispatcher dispatcher_; FrameSignal hasFrame_; - LumieraDisplayFrame currBuffer_; + DummyFrame currBuffer_; public: @@ -89,7 +89,7 @@ namespace stage { /* Implementation-level API to be used by DisplayService */ /** receive a frame to be displayed */ - inline void put (LumieraDisplayFrame); + inline void put (DummyFrame); private: @@ -161,7 +161,7 @@ namespace stage { void - DisplayerSlot::put(LumieraDisplayFrame newFrame) + DisplayerSlot::put(DummyFrame newFrame) { if (newFrame != currBuffer_) { diff --git a/src/steam/engine/worker/dummy-image-generator.cpp b/src/steam/engine/worker/dummy-image-generator.cpp index 3b1be4c1c..0257478a5 100644 --- a/src/steam/engine/worker/dummy-image-generator.cpp +++ b/src/steam/engine/worker/dummy-image-generator.cpp @@ -21,56 +21,55 @@ #include "steam/engine/worker/dummy-image-generator.hpp" +#include + namespace steam { namespace node { - + using std::byte; + using std::clamp; namespace { // implementation details - - typedef unsigned char byte; + using Trip = std::array; - inline int - clamp (const int &val, const int &maxval, const int &minval) + /** slightly simplified conversion from RGB components to Y'CbCr with Rec.601 (MPEG style) */ + inline Trip + rgb_to_yuv (Trip const& rgb) { - if(val > maxval) return maxval; - if(val < minval) return minval; - return val; - } - - inline void - rgb_to_yuv (int r, int g, int b, byte &y, byte &u, byte &v) - { - // This code isn't great, but it does the job - y = (byte)clamp((299 * r + 587 * g + 114 * b) / 1000, 235, 16); - v = (byte)clamp((500 * r - 419 * g - 81 * b) / 1000 + 127, 255, 0); - u = (byte)clamp((-169 * r - 331 * g + 500 * b) / 1000 + 127, 255, 0); + auto r = int(rgb[0]); + auto g = int(rgb[1]); + auto b = int(rgb[2]); + Trip yuv; + auto& [y,u,v] = yuv; + y = byte(clamp ( 0 + ( 299 * r + 587 * g + 114 * b) / 1000, 16,235)); // Luma clamped to MPEG scan range + u = byte(clamp (128 + (-169 * r - 331 * g + 500 * b) / 1000, 0, 255)); // Chroma components mapped according to Rec.601 + v = byte(clamp (128 + ( 500 * r - 419 * g - 81 * b) / 1000, 0, 255)); // (but with integer arithmetics and slightly rounded coefficients) + return yuv; } void - rgb_buffer_to_yuy2 (unsigned char *in, unsigned char *out) + rgb_buffer_to_yuy2 (byte* in, byte* out, uint cntPix) { - for (uint i = 0; i < 320*240*2; i+=4) - { - byte y0, u0, v0; - const byte r0 = *(in++); - const byte g0 = *(in++); - const byte b0 = *(in++); - rgb_to_yuv(r0, g0, b0, y0, u0, v0); + REQUIRE (cntPix %2 == 0); + for (uint i = 0; i < cntPix; i += 2) + {// convert and interleave 2 pixels in one step + uint ip = i * 3; // Input uses (RGB)-triples + uint op = i * 2; // Output packed in groups with 2 bytes + Trip& rgb0 = reinterpret_cast (in[ip]); + Trip& rgb1 = reinterpret_cast (in[ip+3]); + Trip yuv0 = rgb_to_yuv (rgb0); + Trip yuv1 = rgb_to_yuv (rgb1); - byte y1, u1, v1; - const byte r1 = *(in++); - const byte g1 = *(in++); - const byte b1 = *(in++); - rgb_to_yuv(r1, g1, b1, y1, u1, v1); + auto& [y0,u0,v0] = yuv0; + auto& [y1,_u,_v] = yuv1; // note: this format discards half of the chroma information - out[i] = y0; - out[i + 1] = u0; - out[i + 2] = y1; - out[i + 3] = v0; + out[op ] = y0; + out[op + 1] = u0; + out[op + 2] = y1; + out[op + 3] = v0; } } @@ -80,84 +79,81 @@ namespace node { DummyImageGenerator::DummyImageGenerator(uint fps) - : current_(0) - , frame_(0) - , fps_(fps) + : fps_{fps} + , beat_{false} + , frame_{0} { } - LumieraDisplayFrame - DummyImageGenerator::next() + void + DummyImageGenerator::generateFrame (DummyFrame buffer) { - ++frame_; if(frame_ > 2 * fps_) frame_ = 0; if(frame_ < 1 * fps_) - { + { // create random snow... - for(int i = 0; i < 320*240*3; i+=3) + for (uint i = 0; i < W*H*3; i+=3) { - byte value ( rand() ); - buf_[i] = value; - buf_[i+1] = value; - buf_[i+2] = value; + auto value = byte(rand()); + buffer[i] = value; + buffer[i+1] = value; + buffer[i+2] = value; } } else { // create a colour strip pattern - typedef unsigned char Row[320 * 3]; + typedef byte Row[W * 3]; - unsigned char * row = buf_; + byte* row = buffer; // create a colour strip pattern in the first row... - for(int x = 0; x < 320; ++x) + for (uint x = 0; x < W; ++x) { - byte &r = row[x*3]; - byte &g = row[x*3+1]; - byte &b = row[x*3+2]; + byte& r = row[x*3]; + byte& g = row[x*3+1]; + byte& b = row[x*3+2]; - if (x < 1*320/7) r = 0xC0, g = 0xC0, b = 0xC0; - else if(x < 2*320/7) r = 0xC0, g = 0xC0, b = 0x00; - else if(x < 3*320/7) r = 0x00, g = 0xC0, b = 0xC0; - else if(x < 4*320/7) r = 0x00, g = 0xC0, b = 0x00; - else if(x < 5*320/7) r = 0xC0, g = 0x00, b = 0xC0; - else if(x < 6*320/7) r = 0xC0, g = 0x00, b = 0x00; - else r = 0x00, g = 0x00, b = 0xC0; + const byte ON = byte(0xC0); + const byte OFF{0}; + + if (x < 1*W/7) r = ON, g = ON, b = ON; + else if(x < 2*W/7) r = ON, g = ON, b = OFF; + else if(x < 3*W/7) r = OFF, g = ON, b = ON; + else if(x < 4*W/7) r = OFF, g = ON, b = OFF; + else if(x < 5*W/7) r = ON, g = OFF, b = ON; + else if(x < 6*W/7) r = ON, g = OFF, b = OFF; + else r = OFF, g = OFF, b = ON; } // fill remaining rows of the frame with the same pattern - for(int y = 1; y < 240; ++y) - memcpy(buf_ + y*sizeof(Row), row, sizeof(Row)); + for (uint y = 1; y < H; ++y) + memcpy(buffer + y*sizeof(Row), row, sizeof(Row)); } + } + + DummyFrame + DummyImageGenerator::next() + { + beat_ = not beat_; + DummyFrame outBuff = current(); + // next output buffer to return - // select output buffer to return - LumieraDisplayFrame outBuff; + generateFrame (workBuf_.data()); - if (!current_) - { - outBuff = outFrame_A_; - current_= 1; - } - else - { - outBuff = outFrame_B_; - current_= 0; - } - - rgb_buffer_to_yuy2(buf_, outBuff); + rgb_buffer_to_yuy2(workBuf_.data(), outBuff, W*H); return outBuff; } - LumieraDisplayFrame + DummyFrame DummyImageGenerator::current() { - if (!current_) return outFrame_A_; - else return outFrame_B_; + return beat_? outFrame_A_.data() : outFrame_B_.data(); } diff --git a/src/steam/engine/worker/dummy-image-generator.hpp b/src/steam/engine/worker/dummy-image-generator.hpp index 15e387761..fb4651dbc 100644 --- a/src/steam/engine/worker/dummy-image-generator.hpp +++ b/src/steam/engine/worker/dummy-image-generator.hpp @@ -23,7 +23,7 @@ ** @todo obsolete since 2010, can be removed once we have a real player in the UI ** @see stage::controller::PlaybackController ** @see steam::play::DummyPlayerService - ** + ** */ @@ -34,42 +34,44 @@ #include "lib/error.hpp" #include "include/display-facade.h" +#include + namespace steam { namespace node { - - + + class DummyImageGenerator { - - unsigned char buf_[320 * 240 * 3]; ///< working buffer for next frame - - unsigned char outFrame_A_[320 * 240 * 4]; ///< output frame 1 - unsigned char outFrame_B_[320 * 240 * 4]; ///< output frame 2 - - uint current_; - uint frame_; uint fps_; - public: + static const uint W = 320; + static const uint H = 240; + DummyImageGenerator(uint fps); - ~DummyImageGenerator() { } - - /** generate the next frame and - * occupy the alternate buffer. - * @return the buffer containing the new frame - */ - LumieraDisplayFrame next(); + /** generate the next frame and occupy the alternate buffer. + * @return the buffer containing the new frame */ + DummyFrame next(); /** just re-return a pointer to the current frame * without generating any new image data */ - LumieraDisplayFrame current(); - + DummyFrame current(); + private: + static constexpr uint WORK_SIZ = W * H * 3; + static constexpr uint BUFF_SIZ = W * H * 4; + bool beat_; + uint frame_; + + std::array workBuf_; ///< workspace for RGB calculation + std::array outFrame_A_; ///< alternating output buffers + std::array outFrame_B_; + + void generateFrame (DummyFrame buffer); }; diff --git a/tests/library/random-concurrent-test.cpp b/tests/library/random-concurrent-test.cpp index 0337458bd..d2c531a1e 100644 --- a/tests/library/random-concurrent-test.cpp +++ b/tests/library/random-concurrent-test.cpp @@ -41,7 +41,7 @@ namespace test { namespace { const uint NUM_THREADS = 8; ///< for concurrent probes const uint NUM_SAMPLES = 80; ///< overall number measurement runs - const uint NUM_INVOKES = 1'000'000; ///< invocations of the target per measurment + const uint NUM_INVOKES = 1'000'000; ///< invocations of the target per measurement } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index d32879297..8e7e5e21d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -130060,6 +130060,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + @@ -130109,6 +130113,174 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + + + + + + + + + + +

+ Tip: suche nach "image data" +

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

+ sieht zwar nach nitpicking aus, aber da wir dann explizit per structured-Binding auf die Komponenten zugreifen, könnte der Code etwas klarer werden +

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

+ ...sonst ist es nicht möglich, das als virtuellen Zugriff für Input und Output zu verwenden +

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

+ ...denn sonst endet man doch wieder mit z.B. einem Debian-Paket, das build-depends on the world of media processing +

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

+ sie könnte zwar im System installiert und vorhanden sein, aber nicht richtig konfiguriert, vielleicht überhaupt nie nutzbar sein, oder aber derzeit grade nicht nutzbar (weil eine externe Verbindung oder Ressource fehlt) +

+ + +
+
+
+