Skip to content

Commit 87e648a

Browse files
committed
disp/omt: Initial
1 parent 0683686 commit 87e648a

File tree

2 files changed

+230
-1
lines changed

2 files changed

+230
-1
lines changed

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3467,7 +3467,7 @@ fi
34673467
if test "${omt_req?}" != no && test "${FOUND_LIBOMT_H?}" && test "${FOUND_LIBOMT_LIB?}" = yes
34683468
then
34693469
omt=yes
3470-
add_module rxtx_omt "src/omt_common.o src/video_rxtx/omt.o" "-lomt"
3470+
add_module rxtx_omt "src/omt_common.o src/video_rxtx/omt.o src/video_display/omt.o" "-lomt"
34713471
fi
34723472

34733473
ENSURE_FEATURE_PRESENT([${omt_req?}], [${omt?}], [libomt not found])

src/video_display/omt.cpp

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/**
2+
* @file video_display/omt.cpp
3+
* @author Martin Piatka <piatka@cesnet.cz>
4+
*/
5+
/*
6+
* Copyright (c) 2026 CESNET, zájmové sdružení právnických osob
7+
* All rights reserved.
8+
*
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, is permitted provided that the following conditions
11+
* are met:
12+
*
13+
* 1. Redistributions of source code must retain the above copyright
14+
* notice, this list of conditions and the following disclaimer.
15+
*
16+
* 2. Redistributions in binary form must reproduce the above copyright
17+
* notice, this list of conditions and the following disclaimer in the
18+
* documentation and/or other materials provided with the distribution.
19+
*
20+
* 3. Neither the name of CESNET nor the names of its contributors may be
21+
* used to endorse or promote products derived from this software without
22+
* specific prior written permission.
23+
*
24+
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25+
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26+
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27+
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28+
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34+
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36+
*/
37+
38+
#define MOD_NAME "[omt] "
39+
#include <condition_variable>
40+
#include <memory>
41+
#include <mutex>
42+
#include <queue>
43+
#include <thread>
44+
#include <vector>
45+
46+
#include "debug.h"
47+
#include "lib_common.h"
48+
#include "omt_common.hpp"
49+
#include "video_display.h"
50+
#include "video_frame.h"
51+
#include "utils/misc.h"
52+
#include "utils/thread.h"
53+
54+
namespace{
55+
using frame_uniq = std::unique_ptr<video_frame, deleter_from_fcn<vf_free>>;
56+
57+
struct state_vdisp_omt{
58+
omt_send_uniq omt_send;
59+
60+
OMTMediaFrame omt_frame{};
61+
62+
video_desc desc{};
63+
64+
std::mutex mutex;
65+
std::condition_variable free_frame_cv;
66+
std::vector<frame_uniq> free_frames;
67+
68+
std::condition_variable video_frame_cv;
69+
std::queue<frame_uniq> frame_queue;
70+
71+
std::thread worker;
72+
std::string sender_name = "UltraGrid";
73+
OMTQuality quality = OMTQuality_Medium;
74+
};
75+
76+
void omt_disp_worker(state_vdisp_omt *s){
77+
set_thread_name("OMT display worker");
78+
79+
while(true){
80+
std::unique_lock lock(s->mutex);
81+
s->video_frame_cv.wait(lock, [s]{ return !s->frame_queue.empty(); });
82+
auto frame = std::move(s->frame_queue.front());
83+
s->frame_queue.pop();
84+
lock.unlock();
85+
86+
if(!frame){
87+
break;
88+
}
89+
90+
omt_frame_init_from_desc(s->omt_frame, video_desc_from_frame(frame.get()));
91+
omt_frame_set_data(s->omt_frame, *frame);
92+
93+
omt_send(s->omt_send.get(), &s->omt_frame);
94+
95+
lock.lock();
96+
s->free_frames.push_back(std::move(frame));
97+
lock.unlock();
98+
}
99+
}
100+
101+
void init_send(state_vdisp_omt *s){
102+
s->omt_send.reset(omt_send_create(s->sender_name.c_str(), s->quality));
103+
set_omt_sender_info(s->omt_send.get());
104+
s->omt_frame.Type = OMTFrameType_Video;
105+
s->omt_frame.Timestamp = -1;
106+
}
107+
108+
void *display_omt_init(module *parent, const char *fmt, unsigned int flags){
109+
auto s = std::make_unique<state_vdisp_omt>();
110+
111+
constexpr size_t max_frames = 3;
112+
s->free_frames.resize(max_frames);
113+
114+
init_send(s.get());
115+
116+
s->worker = std::thread(omt_disp_worker, s.get());
117+
118+
return s.release();
119+
}
120+
121+
void display_omt_done(void *state){
122+
auto s = static_cast<state_vdisp_omt *>(state);
123+
124+
if(s->worker.joinable()){
125+
s->worker.join();
126+
}
127+
128+
delete s;
129+
}
130+
131+
video_frame *display_omt_getf(void *state){
132+
auto s = static_cast<state_vdisp_omt *>(state);
133+
134+
std::unique_lock lock(s->mutex);
135+
s->free_frame_cv.wait(lock, [s]{ return !s->free_frames.empty(); });
136+
137+
auto frame = std::move(s->free_frames.back());
138+
s->free_frames.pop_back();
139+
140+
if(!frame || !video_desc_eq(s->desc, video_desc_from_frame(frame.get()))){
141+
frame.reset(vf_alloc_desc_data(s->desc));
142+
}
143+
144+
return frame.release();
145+
}
146+
147+
bool display_omt_putf(void *state, video_frame *frame, long long timeout_ns){
148+
auto s = static_cast<state_vdisp_omt *>(state);
149+
auto f = frame_uniq(frame);
150+
151+
std::unique_lock lock(s->mutex);
152+
s->frame_queue.push(std::move(f));
153+
lock.unlock();
154+
s->video_frame_cv.notify_one();
155+
156+
return true;
157+
}
158+
159+
bool display_omt_reconfigure(void *state, video_desc desc){
160+
auto s = static_cast<state_vdisp_omt *>(state);
161+
if(desc.color_spec != UYVY)
162+
return false;
163+
164+
s->desc = desc;
165+
return true;
166+
}
167+
168+
bool display_omt_get_property(void */*state*/, int property, void *val, size_t *len){
169+
codec_t codecs[] = {UYVY};
170+
interlacing_t supported_il_modes[] = {PROGRESSIVE};
171+
int rgb_shift[] = {0, 8, 16};
172+
173+
switch (property) {
174+
case DISPLAY_PROPERTY_CODECS:
175+
if(sizeof(codecs) <= *len) {
176+
memcpy(val, codecs, sizeof(codecs));
177+
} else {
178+
return false;
179+
}
180+
181+
*len = sizeof(codecs);
182+
break;
183+
case DISPLAY_PROPERTY_RGB_SHIFT:
184+
if(sizeof(rgb_shift) > *len) {
185+
return false;
186+
}
187+
memcpy(val, rgb_shift, sizeof(rgb_shift));
188+
*len = sizeof(rgb_shift);
189+
break;
190+
case DISPLAY_PROPERTY_BUF_PITCH:
191+
*static_cast<int *>(val) = PITCH_DEFAULT;
192+
*len = sizeof(int);
193+
break;
194+
case DISPLAY_PROPERTY_SUPPORTED_IL_MODES:
195+
if(sizeof(supported_il_modes) <= *len) {
196+
memcpy(val, supported_il_modes, sizeof(supported_il_modes));
197+
} else {
198+
return false;
199+
}
200+
*len = sizeof(supported_il_modes);
201+
break;
202+
default:
203+
return false;
204+
}
205+
return true;
206+
}
207+
208+
void display_omt_probe(device_info **available_cards, int *count, void(**/*deleter*/)(void *)){
209+
//TODO
210+
*available_cards = nullptr;
211+
*count = 0;
212+
}
213+
}
214+
215+
static constexpr video_display_info display_omt_info = {
216+
display_omt_probe,
217+
display_omt_init,
218+
nullptr, // _run
219+
display_omt_done,
220+
display_omt_getf,
221+
display_omt_putf,
222+
display_omt_reconfigure,
223+
display_omt_get_property,
224+
nullptr, // _put_audio_frame
225+
nullptr, // _reconfigure_audio
226+
MOD_NAME,
227+
};
228+
229+
REGISTER_MODULE(omt, &display_omt_info, LIBRARY_CLASS_VIDEO_DISPLAY, VIDEO_DISPLAY_ABI_VERSION);

0 commit comments

Comments
 (0)