#include <QOpenGLFunctions>
#include <QWheelEvent>
#include <QMouseEvent>
+#include <QMouseEvent>
+#include <QHBoxLayout>
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
queue.pop_front();
queued_frames = std::move(queue);
}
- shared_ptr<Frame> new_frame = make_video_frame(frame.get());
- {
- lock_guard lock(current_frame_mu);
- current_frame = std::move(new_frame);
- }
+ video_window->set_current_frame(make_video_frame(frame.get()));
update();
store_pts(frame->pts);
break;
if (frame == nullptr || error) {
return true;
}
- shared_ptr<Frame> new_frame = make_video_frame(frame.get());
- {
- lock_guard lock(current_frame_mu);
- current_frame = std::move(new_frame);
- }
+ video_window->set_current_frame(make_video_frame(frame.get()));
update();
store_pts(frame->pts);
}
}
VideoWidget::VideoWidget(QWidget *parent)
- : QOpenGLWidget(parent) {}
+ : QWidget(parent),
+ video_window(new VideoWindow(this)) {
+ setLayout(new QHBoxLayout);
+ layout()->setContentsMargins(QMargins());
+ layout()->addWidget(QWidget::createWindowContainer(video_window));
+
+ // ...
+ connect(video_window, &VideoWindow::mouse_wheel, this, &VideoWidget::wheelEvent);
+ connect(video_window, &VideoWindow::mouse_pressed, this, &VideoWidget::mousePressEvent);
+ connect(video_window, &VideoWindow::mouse_released, this, &VideoWidget::mouseReleaseEvent);
+ connect(video_window, &VideoWindow::mouse_moved, this, &VideoWidget::mouseMoveEvent);
+}
+
+VideoWidget::~VideoWidget()
+{
+ stop();
+
+ // Qt will delete video_window for us after we're gone,
+ // so make sure its destructor does not try to mess with
+ // our freelist. The actual freelist frames will leak.
+ video_window->set_current_frame(nullptr);
+}
GLuint compile_shader(const string &shader_src, GLenum type)
{
return obj;
}
-void VideoWidget::initializeGL()
+void VideoWindow::initializeGL()
{
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glSamplerParameteri(bilinear_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
-void VideoWidget::resizeGL(int w, int h)
+void VideoWindow::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
display_aspect = double(w) / h;
return levels;
}
-void VideoWidget::paintGL()
+void VideoWindow::paintGL()
{
- std::shared_ptr<Frame> frame;
+ std::shared_ptr<VideoWidget::Frame> frame;
{
lock_guard lock(current_frame_mu);
frame = current_frame;
glEnd();
}
+void VideoWindow::set_current_frame(shared_ptr<VideoWidget::Frame> new_frame)
+{
+ {
+ lock_guard lock(current_frame_mu);
+ current_frame = std::move(new_frame);
+ }
+ update();
+}
+
void matmul3x3(const double a[9], const double b[9], double res[9])
{
for (int i = 0; i < 3; ++i) {
matmul3x3(tmp2, translation_matrix, zoom_matrix);
fixup_zoom_matrix();
+ video_window->set_zoom_matrix(zoom_matrix);
update();
}
zoom_matrix[6] += dx;
zoom_matrix[7] -= dy;
fixup_zoom_matrix();
+ video_window->set_zoom_matrix(zoom_matrix);
last_drag_x = e->position().x();
last_drag_y = e->position().y();
bool finished_wakeup;
finished_wakeup = producer_thread_should_quit.sleep_until(next_frame_start);
if (finished_wakeup) {
- shared_ptr<Frame> new_frame = make_video_frame(frame.get());
- {
- lock_guard lock(current_frame_mu);
- current_frame = std::move(new_frame);
- }
+ video_window->set_current_frame(make_video_frame(frame.get()));
last_frame = steady_clock::now();
update();
break;
if (paused) {
// Just paused, so present the frame immediately and then go into deep sleep.
- shared_ptr<Frame> new_frame = make_video_frame(frame.get());
- {
- lock_guard lock(current_frame_mu);
- current_frame = std::move(new_frame);
- }
+ video_window->set_current_frame(make_video_frame(frame.get()));
last_frame = steady_clock::now();
update();
break;
size_t len = frame->width * frame->height + 2 * frame->chroma_width * frame->chroma_height;
+ while (!video_window->isValid()) {
+ usleep(100000);
+ }
+
// Augh :-)
mutex mu;
condition_variable done_cv;
bool done = false;
post_to_main_thread([this, &frame, len, &done, &mu, &done_cv]{
- makeCurrent();
+ video_window->makeCurrent();
glCreateBuffers(1, &frame->pbo);
glNamedBufferStorage(frame->pbo, len, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
frame->data = (uint8_t *)glMapNamedBufferRange(frame->pbo, 0, len, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT);
- doneCurrent();
+ video_window->doneCurrent();
lock_guard lock(mu);
done = true;
if (self->frame_freelist.size() >= 16) {
GLuint pbo = frame->pbo;
post_to_main_thread([self, pbo]{
- self->makeCurrent();
+ self->video_window->makeCurrent();
glUnmapNamedBuffer(pbo);
glDeleteBuffers(1, &pbo);
- self->doneCurrent();
+ self->video_window->doneCurrent();
});
delete self->frame_freelist.front();
self->frame_freelist.pop_front();
AV_CEIL_RSHIFT(int(frame->height), desc->log2_chroma_h));
// We always assume left chroma placement for now.
- cbcr_offset[0] = compute_chroma_offset(0.0f, 1 << desc->log2_chroma_w, video_frame->chroma_width);
- cbcr_offset[1] = compute_chroma_offset(0.5f, 1 << desc->log2_chroma_h, video_frame->chroma_height);
+ video_window->set_cbcr_offset(
+ compute_chroma_offset(0.0f, 1 << desc->log2_chroma_w, video_frame->chroma_width),
+ compute_chroma_offset(0.5f, 1 << desc->log2_chroma_h, video_frame->chroma_height)
+ );
pic_data[0] = video_frame->data;
linesizes[0] = frame->width;