X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=video_widget.cpp;h=b50ea1c404a0494b8297180e8fc0f7c671c4bad6;hb=b6eaf3bbd5005eda6d9853897b2b5667c5fd63a7;hp=b783b00651e2652608ba72b1a649c9160ee7ddaf;hpb=d4c0ea6e97e0b0edd354ef8233f75938ea5dc08a;p=pkanalytics diff --git a/video_widget.cpp b/video_widget.cpp index b783b00..b50ea1c 100644 --- a/video_widget.cpp +++ b/video_widget.cpp @@ -30,6 +30,8 @@ extern "C" { #include #include +#include "post_to_main_thread.h" + #include #include #include @@ -139,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; } @@ -192,7 +194,10 @@ 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()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } update(); store_pts(frame->pts); break; @@ -223,7 +228,10 @@ 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()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } update(); store_pts(frame->pts); } @@ -373,7 +381,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; @@ -497,7 +509,11 @@ void VideoWidget::wheelEvent(QWheelEvent *event) void VideoWidget::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { + 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(); @@ -740,15 +756,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); @@ -908,7 +923,10 @@ 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()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } last_frame = steady_clock::now(); update(); break; @@ -922,7 +940,10 @@ 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()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } last_frame = steady_clock::now(); update(); break; @@ -943,7 +964,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)