UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
previewWidget.cpp
Go to the documentation of this file.
1#ifdef _WIN32
2#include <windows.h> // for GetTempPathA, MAX_PATH
3#else
4#include <limits.h> // for PATH_MAX
5#endif
6#include <stdio.h>
7#include <QMessageBox>
8#include <QOpenGLFunctions_3_3_Core>
9#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
10#include <QOpenGLVersionFunctionsFactory>
11#endif
12#include "previewWidget.hpp"
13#include "debug.hpp"
14
15static const GLfloat rectangle[] = {
16 1.0f, 1.0f, 1.0f, 0.0f,
17 -1.0f, 1.0f, 0.0f, 0.0f,
18 -1.0f, -1.0f, 0.0f, 1.0f,
19
20 1.0f, 1.0f, 1.0f, 0.0f,
21 -1.0f, -1.0f, 0.0f, 1.0f,
22 1.0f, -1.0f, 1.0f, 1.0f
23};
24
25static const char *vert_src = R"END(
26#version 330 core
27layout(location = 0) in vec2 vert_pos;
28layout(location = 1) in vec2 vert_uv;
29
30out vec2 UV;
31
32uniform vec2 scale_vec;
33
34void main(){
35 gl_Position = vec4(vert_pos * scale_vec, 0.0f, 1.0f);
36 UV = vert_uv;
37}
38)END";
39
40static const char *frag_src = R"END(
41#version 330 core
42in vec2 UV;
43out vec4 color;
44uniform sampler2D tex;
45void main(){
46 color = vec4(texture(tex, UV).rgb, 1.0f);
47}
48)END";
49
50static void compileShader(GLuint shaderId, QOpenGLFunctions_3_3_Core *f){
51 f->glCompileShader(shaderId);
52
53 GLint ret = GL_FALSE;
54 int len;
55
56 f->glGetShaderiv(shaderId, GL_COMPILE_STATUS, &ret);
57 f->glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &len);
58 if (len > 0){
59 std::vector<char> errorMsg(len+1);
60 f->glGetShaderInfoLog(shaderId, len, NULL, &errorMsg[0]);
61 printf("%s\n", errorMsg.data());
62 }
63}
64
65
66static unsigned char pixels[] = {
67 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255,
68 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255,
69 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255,
70 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255
71};
72
73static QOpenGLFunctions_3_3_Core *getOpenGLFuncs(){
74#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
75 return QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
76#else
77 return QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_3_3_Core>(QOpenGLContext::currentContext());
78#endif
79}
80
82 QOpenGLWidget(parent),
83 ipc_frame(ipc_frame_new())
84{
85 connect(&timer, SIGNAL(timeout()), this, SLOT(update()));
86}
87
89 makeCurrent();
90
91 auto f = getOpenGLFuncs();
92 f->glDeleteBuffers(1, &vertexBuffer);
93 f->glDeleteProgram(program);
94 f->glDeleteTextures(1, &frame_texture);
95 f->glDeleteTextures(1, &testbars_texture);
96 vao.destroy();
97 doneCurrent();
98}
99
101 auto f = getOpenGLFuncs();
102
103 if(!f) {
104 QMessageBox warningBox(this);
105 warningBox.setText("OpenGL 3.3 is required!");
106 warningBox.exec();
107 exit(1);
108 }
109
110 vao.create();
111 vao.bind();
112
113 f->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
114
115 f->glDisable(GL_DEPTH_TEST);
116 f->glDisable(GL_SCISSOR_TEST);
117 f->glDisable(GL_STENCIL_TEST);
118
119 GLuint vertexShader = f->glCreateShader(GL_VERTEX_SHADER);
120 GLuint fragShader = f->glCreateShader(GL_FRAGMENT_SHADER);
121
122 f->glShaderSource(vertexShader, 1, &vert_src, NULL);
123 compileShader(vertexShader, f);
124 f->glShaderSource(fragShader, 1, &frag_src, NULL);
125 compileShader(fragShader, f);
126
127 program = f->glCreateProgram();
128 f->glAttachShader(program, vertexShader);
129 f->glAttachShader(program, fragShader);
130 f->glLinkProgram(program);
131 f->glUseProgram(program);
132
133 f->glDetachShader(program, vertexShader);
134 f->glDetachShader(program, fragShader);
135 f->glDeleteShader(vertexShader);
136 f->glDeleteShader(fragShader);
137
138 f->glGenTextures(1, &testbars_texture);
139 f->glBindTexture(GL_TEXTURE_2D, testbars_texture);
140 f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
141 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
142 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
143
144 f->glGenTextures(1, &frame_texture);
145 f->glBindTexture(GL_TEXTURE_2D, frame_texture);
146 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
147 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
148 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //UltraGrid formats dont have padding between rows
149
150 f->glBindTexture(GL_TEXTURE_2D, 0);
151
152 f->glGenBuffers(1, &vertexBuffer);
153 f->glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
154 f->glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle), rectangle, GL_STATIC_DRAW);
155
156 f->glEnableVertexAttribArray(0);
157 f->glVertexAttribPointer(
158 0,
159 2,
160 GL_FLOAT,
161 GL_FALSE,
162 4 * sizeof(float),
163 (void*)0
164 );
165 f->glEnableVertexAttribArray(1);
166 f->glVertexAttribPointer(
167 1,
168 2,
169 GL_FLOAT,
170 GL_FALSE,
171 4 * sizeof(float),
172 (void*)(2 * sizeof(float))
173 );
174
175 f->glBindBuffer(GL_ARRAY_BUFFER, 0);
176
177 vao.release();
178
179 scaleVec[0] = 0.75f;
180 scaleVec[1] = 0.5;
181
182 vidW = 1280;
183 vidH = 720;
184}
185
187 double videoAspect = (double) vidW / vidH;
188 double widgetAspect = (double) width / height;
189
190 if(videoAspect > widgetAspect){
191 float scale = widgetAspect / videoAspect;
192 scaleVec[0] = 1;
193 scaleVec[1] = scale;
194 } else {
195 float scale = videoAspect / widgetAspect;
196 scaleVec[0] = scale;
197 scaleVec[1] = 1;
198 }
199}
200
201void PreviewWidget::resizeGL(int w, int h){
202 width = w;
203 height = h;
204
206}
207
208void PreviewWidget::setVidSize(int w, int h){
209 if(vidW == w && vidH == h)
210 return;
211
212 vidW = w;
213 vidH = h;
215}
216
218 auto f = getOpenGLFuncs();
219
222 return true;
223 }
224
225
228 return false;
229
230 assert(ipc_frame->header.color_spec == IPC_FRAME_COLOR_RGB);
232 f->glBindTexture(GL_TEXTURE_2D, frame_texture);
233 f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
234 ipc_frame->header.width, ipc_frame->header.height,
235 0, GL_RGB, GL_UNSIGNED_BYTE, ipc_frame->data);
236 setVidSize(ipc_frame->header.width, ipc_frame->header.height);
237 }
238
239 return true;
240}
241
243 auto f = getOpenGLFuncs();
244
245 vao.bind();
246 f->glClear(GL_COLOR_BUFFER_BIT);
247
248 f->glUseProgram(program);
249
250 f->glBindTexture(GL_TEXTURE_2D, selected_texture);
251 GLuint loc;
252 loc = f->glGetUniformLocation(program, "scale_vec");
253 f->glUniform2fv(loc, 1, scaleVec);
254
255 f->glDrawArrays(GL_TRIANGLES, 0, 6);
256
257 vao.release();
258}
259
261 loadFrame();
262 render();
263}
264
265static const char *get_temp_dir(void)
266{
267#ifdef _WIN32
268 static __thread char temp_dir[MAX_PATH + 1];
269 if (GetTempPathA(sizeof temp_dir, temp_dir) == 0) {
270 return NULL;
271 }
272#else
273 static __thread char temp_dir[PATH_MAX];
274 if (char *req_tmp_dir = getenv("TMPDIR")) {
275 temp_dir[sizeof temp_dir - 1] = '\0';
276 strncpy(temp_dir, req_tmp_dir, sizeof temp_dir - 1);
277 } else {
278 strcpy(temp_dir, P_tmpdir);
279 }
280 strncat(temp_dir, "/", sizeof temp_dir - strlen(temp_dir) - 1);
281#endif
282
283 return temp_dir;
284}
285
286void PreviewWidget::setKey(std::string_view key){
287 std::string path = get_temp_dir();
288 path += key;
289 ipc_frame_reader.reset(ipc_frame_reader_new(path.c_str()));
290}
291
293 timer.start(1000/24);
294}
295
297 timer.stop();
298}
int void size_t * len
QOpenGLVertexArrayObject vao
PreviewWidget(QWidget *parent)
GLfloat scaleVec[2]
Ipc_frame_uniq ipc_frame
void setVidSize(int w, int h)
void resizeGL(int w, int h)
void setKey(std::string_view key)
GLuint testbars_texture
Ipc_frame_reader_uniq ipc_frame_reader
GLuint selected_texture
Ipc_frame * ipc_frame_new()
Definition ipc_frame.cpp:48
@ IPC_FRAME_COLOR_RGB
Definition ipc_frame.h:13
bool ipc_frame_reader_has_frame(struct Ipc_frame_reader *reader)
Ipc_frame_reader * ipc_frame_reader_new(const char *path)
bool ipc_frame_reader_is_connected(struct Ipc_frame_reader *reader)
bool ipc_frame_reader_read(Ipc_frame_reader *reader, Ipc_frame *dst)
static const GLfloat rectangle[]
static QOpenGLFunctions_3_3_Core * getOpenGLFuncs()
static const char * vert_src
static void compileShader(GLuint shaderId, QOpenGLFunctions_3_3_Core *f)
static unsigned char pixels[]
static const char * get_temp_dir(void)
static const char * frag_src
const char * parent
Definition settings.cpp:198
const char * key
Definition cineform.cpp:125