#include <vector>
#include <unordered_set>
+#include "post_to_main_thread.h"
+
#include <QOpenGLFunctions>
#include <QWheelEvent>
+#include <QMouseEvent>
using namespace std;
using namespace std::chrono;
relative_seek_ms += cmd.relative_seek_ms;
relative_seek_frames += cmd.relative_seek_frames;
} else if (cmd.command == QueuedCommand::SEEK_ABSOLUTE) {
- base_pts = cmd.seek_ms;
+ base_pts = av_rescale_q(cmd.seek_ms, AVRational{ 1, 1000 }, video_timebase);
relative_seek_ms = 0;
relative_seek_frames = 0;
}
queue.pop_front();
queued_frames = std::move(queue);
}
- current_frame.reset(new Frame(make_video_frame(frame.get())));
+ {
+ lock_guard lock(current_frame_mu);
+ current_frame.reset(new Frame(make_video_frame(frame.get())));
+ }
update();
store_pts(frame->pts);
break;
if (frame == nullptr || error) {
return true;
}
- current_frame.reset(new Frame(make_video_frame(frame.get())));
+ {
+ lock_guard lock(current_frame_mu);
+ current_frame.reset(new Frame(make_video_frame(frame.get())));
+ }
update();
store_pts(frame->pts);
}
void VideoWidget::paintGL()
{
- std::shared_ptr<Frame> frame = current_frame;
+ std::shared_ptr<Frame> frame;
+ {
+ lock_guard lock(current_frame_mu);
+ frame = current_frame;
+ }
if (frame == nullptr) {
glClear(GL_COLOR_BUFFER_BIT);
return;
}
double x = event->position().x() / width();
double y = 1.0 - event->position().y() / height();
- double zoom = delta > 0 ? pow(1.01, delta) : pow(1/1.01, -delta);
+ double zoom = delta > 0 ? pow(1.005, delta) : pow(1/1.005, -delta);
const double inv_translation_matrix[9] = {
1.0, 0.0, 0.0,
matmul3x3(tmp2, translation_matrix, zoom_matrix);
fixup_zoom_matrix();
+ update();
+}
+
+void VideoWidget::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::BackButton) {
+ emit mouse_back_clicked();
+ } else if (e->button() == Qt::ForwardButton) {
+ emit mouse_forward_clicked();
+ } else if (e->button() == Qt::LeftButton) {
+ dragging = true;
+ last_drag_x = e->position().x();
+ last_drag_y = e->position().y();
+ }
+}
+
+void VideoWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::LeftButton) {
+ dragging = false;
+ }
+}
+
+void VideoWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!dragging) {
+ return;
+ }
+ float dx = (e->position().x() - last_drag_x) / width();
+ float dy = (e->position().y() - last_drag_y) / height();
+
+ //zoom_matrix[6] += dx * zoom_matrix[0];
+ //zoom_matrix[7] += dy * zoom_matrix[4];
+ zoom_matrix[6] += dx;
+ zoom_matrix[7] -= dy;
+ fixup_zoom_matrix();
+
+ last_drag_x = e->position().x();
+ last_drag_y = e->position().y();
+
+ update();
}
// Normalize the matrix so that we never get skew or similar,
AVFrameWithDeleter video_avframe = av_frame_alloc_unique();
bool eof = false;
do {
- AVPacket pkt;
+ AVPacket *pkt = av_packet_alloc();
unique_ptr<AVPacket, decltype(av_packet_unref)*> pkt_cleanup(
- &pkt, av_packet_unref);
- av_init_packet(&pkt);
- pkt.data = nullptr;
- pkt.size = 0;
- if (av_read_frame(format_ctx, &pkt) == 0) {
- if (pkt.stream_index == video_stream_index) {
- if (avcodec_send_packet(video_codec_ctx, &pkt) < 0) {
+ pkt, av_packet_unref);
+ pkt->data = nullptr;
+ pkt->size = 0;
+ if (av_read_frame(format_ctx, pkt) == 0) {
+ if (pkt->stream_index == video_stream_index) {
+ if (avcodec_send_packet(video_codec_ctx, pkt) < 0) {
fprintf(stderr, "%s: Cannot send packet to video codec.\n", pathname.c_str());
*error = true;
return AVFrameWithDeleter(nullptr);
bool finished_wakeup;
finished_wakeup = producer_thread_should_quit.sleep_until(next_frame_start);
if (finished_wakeup) {
- current_frame.reset(new Frame(make_video_frame(frame.get())));
+ {
+ lock_guard lock(current_frame_mu);
+ current_frame.reset(new 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.
- current_frame.reset(new Frame(make_video_frame(frame.get())));
+ {
+ lock_guard lock(current_frame_mu);
+ current_frame.reset(new Frame(make_video_frame(frame.get())));
+ }
last_frame = steady_clock::now();
update();
break;
{
last_pts = pts;
last_position = lrint(pts * double(video_timebase.num) / double(video_timebase.den) * 1000);
- emit position_changed(last_position);
+ post_to_main_thread([this, last_position{last_position.load()}] {
+ emit position_changed(last_position);
+ });
}
// Taken from Movit (see the comment there for explanation)