1 #include "timecode_renderer.h"
11 #include <movit/effect_util.h>
12 #include <movit/resource_pool.h>
13 #include <movit/util.h>
17 #include "embedded_files.h"
18 #include "shared/read_file.h"
21 using namespace movit;
23 TimecodeRenderer::TimecodeRenderer(movit::ResourcePool *resource_pool, unsigned display_width, unsigned display_height)
24 : resource_pool(resource_pool), display_width(display_width), display_height(display_height), height(28)
26 string vert_shader = read_file("timecode.vert", _binary_timecode_vert_data, _binary_timecode_vert_size);
28 if (global_flags.bit_depth > 8) {
29 frag_shader = read_file("timecode_10bit.frag", _binary_timecode_10bit_frag_data, _binary_timecode_10bit_frag_size);
31 frag_shader = read_file("timecode.frag", _binary_timecode_frag_data, _binary_timecode_frag_size);
34 vector<string> frag_shader_outputs;
35 program_num = resource_pool->compile_glsl_program(vert_shader, frag_shader, frag_shader_outputs);
38 texture_sampler_uniform = glGetUniformLocation(program_num, "tex");
40 position_attribute_index = glGetAttribLocation(program_num, "position");
42 texcoord_attribute_index = glGetAttribLocation(program_num, "texcoord");
45 // Shared between the two.
51 vbo = generate_vbo(2, GL_FLOAT, sizeof(vertices), vertices);
54 tex = resource_pool->create_2d_texture(GL_R8, display_width, height);
56 image.reset(new QImage(display_width, height, QImage::Format_Grayscale8));
59 TimecodeRenderer::~TimecodeRenderer()
61 resource_pool->release_2d_texture(tex);
63 resource_pool->release_glsl_program(program_num);
65 glDeleteBuffers(1, &vbo);
69 string TimecodeRenderer::get_timecode_text(double pts, unsigned frame_num)
71 // Find the wall time, and round it to the nearest millisecond.
73 gettimeofday(&now, nullptr);
74 time_t unixtime = now.tv_sec;
75 unsigned msecs = (now.tv_usec + 500) / 1000;
82 gmtime_r(&unixtime, &utc_tm);
84 strftime(clock_text, sizeof(clock_text), "%Y-%m-%d %H:%M:%S", &utc_tm);
86 // Make the stream timecode, rounded to the nearest millisecond.
87 long stream_time = lrint(pts * 1e3);
88 assert(stream_time >= 0);
89 unsigned stream_time_ms = stream_time % 1000;
91 unsigned stream_time_sec = stream_time % 60;
93 unsigned stream_time_min = stream_time % 60;
94 unsigned stream_time_hour = stream_time / 60;
96 char timecode_text[512];
97 snprintf(timecode_text, sizeof(timecode_text), "Nageru - %s.%03u UTC - Stream time %02u:%02u:%02u.%03u (frame %u)",
98 clock_text, msecs, stream_time_hour, stream_time_min, stream_time_sec, stream_time_ms, frame_num);
102 void TimecodeRenderer::render_timecode(GLuint fbo, const string &text)
104 render_string_to_buffer(text);
105 render_buffer_to_fbo(fbo);
108 void TimecodeRenderer::render_string_to_buffer(const string &text)
111 QPainter painter(image.get());
113 painter.setPen(Qt::white);
114 QFont font = painter.font();
115 font.setPointSize(16);
116 painter.setFont(font);
118 painter.drawText(QRectF(0, 0, display_width, height), Qt::AlignCenter, QString::fromStdString(text));
121 void TimecodeRenderer::render_buffer_to_fbo(GLuint fbo)
123 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
127 glGenVertexArrays(1, &vao);
130 glBindVertexArray(vao);
133 glViewport(0, display_height - height, display_width, height);
136 glActiveTexture(GL_TEXTURE0);
138 glBindTexture(GL_TEXTURE_2D, tex);
140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
147 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, display_width, height, GL_RED, GL_UNSIGNED_BYTE, image->bits());
150 glUseProgram(program_num);
152 glUniform1i(texture_sampler_uniform, 0);
155 glBindBuffer(GL_ARRAY_BUFFER, vbo);
158 for (GLint attr_index : { position_attribute_index, texcoord_attribute_index }) {
159 if (attr_index == -1) continue;
160 glEnableVertexAttribArray(attr_index);
162 glVertexAttribPointer(attr_index, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
166 glDrawArrays(GL_TRIANGLES, 0, 3);
169 for (GLint attr_index : { position_attribute_index, texcoord_attribute_index }) {
170 if (attr_index == -1) continue;
171 glDisableVertexAttribArray(attr_index);
175 glActiveTexture(GL_TEXTURE0);
180 glDeleteVertexArrays(1, &vao);
183 glBindFramebuffer(GL_FRAMEBUFFER, 0);