X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=video_widget.cpp;h=7bafa64e4b0a00f444eecbb40b2ef09d776cf98f;hb=5ccdfdea87f84fcc4d6c981a88dacd1127ab7106;hp=b25b938161851e6ee9f05b55c0277bd1084a59ea;hpb=8321974fc7eb20f91ca4437bdd4ef94576e36098;p=pkanalytics diff --git a/video_widget.cpp b/video_widget.cpp index b25b938..7bafa64 100644 --- a/video_widget.cpp +++ b/video_widget.cpp @@ -30,8 +30,11 @@ extern "C" { #include #include +#include "post_to_main_thread.h" + #include #include +#include using namespace std; using namespace std::chrono; @@ -138,7 +141,7 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo 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; } @@ -191,7 +194,11 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo queue.pop_front(); queued_frames = std::move(queue); } - current_frame.reset(new Frame(make_video_frame(frame.get()))); + Frame *new_frame = new Frame(make_video_frame(frame.get())); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new_frame); + } update(); store_pts(frame->pts); break; @@ -222,7 +229,11 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo if (frame == nullptr || error) { return true; } - current_frame.reset(new Frame(make_video_frame(frame.get()))); + Frame *new_frame = new Frame(make_video_frame(frame.get())); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new_frame); + } update(); store_pts(frame->pts); } @@ -372,7 +383,11 @@ int num_levels(GLuint width, GLuint height) void VideoWidget::paintGL() { - std::shared_ptr frame = current_frame; + std::shared_ptr frame; + { + lock_guard lock(current_frame_mu); + frame = current_frame; + } if (frame == nullptr) { glClear(GL_COLOR_BUFFER_BIT); return; @@ -468,7 +483,7 @@ void VideoWidget::wheelEvent(QWheelEvent *event) } 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, @@ -491,6 +506,47 @@ void VideoWidget::wheelEvent(QWheelEvent *event) 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, @@ -702,15 +758,14 @@ AVFrameWithDeleter VideoWidget::decode_frame(AVFormatContext *format_ctx, AVCode AVFrameWithDeleter video_avframe = av_frame_alloc_unique(); bool eof = false; do { - AVPacket pkt; + AVPacket *pkt = av_packet_alloc(); unique_ptr 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); @@ -870,7 +925,11 @@ bool VideoWidget::play_video(const string &pathname) 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()))); + Frame *new_frame = new Frame(make_video_frame(frame.get())); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new_frame); + } last_frame = steady_clock::now(); update(); break; @@ -884,7 +943,11 @@ bool VideoWidget::play_video(const string &pathname) 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()))); + Frame *new_frame = new Frame(make_video_frame(frame.get())); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new_frame); + } last_frame = steady_clock::now(); update(); break; @@ -905,7 +968,9 @@ void VideoWidget::store_pts(int64_t pts) { 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)