zhuizhu há 8 meses atrás
pai
commit
4f8727c44c

+ 0 - 4
AvPlayer2/audio_play_thread.h

@@ -56,10 +56,6 @@ public:
     void setOnUpdatePlayTime(std::function<void()> cb) { m_onUpdatePlayTime = std::move(cb); }
     void setOnDataVisualReady(std::function<void(const AudioData&)> cb) { m_onDataVisualReady = std::move(cb); }
 
-    // signals:
-    //     void update_play_time();
-    //     void data_visual_ready(const AudioData& data);
-
 protected:
     void run() override;
 

+ 6 - 11
AvPlayer2/clickable_slider.cpp

@@ -11,7 +11,8 @@
 #include <QStyleOptionSlider>
 #include "qnamespace.h"
 
-ClickableSlider::ClickableSlider(QWidget* parent) : QSlider(parent)
+ClickableSlider::ClickableSlider(QWidget* parent)
+    : QSlider(parent)
 {
     setOrientation(Qt::Horizontal);
 }
@@ -22,12 +23,10 @@ void ClickableSlider::mousePressEvent(QMouseEvent* event)
     initStyleOption(&opt);
     auto sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
 
-    if (event->button() == Qt::LeftButton && !sr.contains(event->pos()))
-    {
+    if (event->button() == Qt::LeftButton && !sr.contains(event->pos())) {
         int newVal = 0;
         double normalizedPosition = 0;
-        if (orientation() == Qt::Vertical)
-        {
+        if (orientation() == Qt::Vertical) {
             auto halfHandleHeight = (0.5 * sr.height()) + 0.5;
             int adaptedPosY = height() - event->pos().y();
             if (adaptedPosY < halfHandleHeight)
@@ -36,9 +35,7 @@ void ClickableSlider::mousePressEvent(QMouseEvent* event)
                 adaptedPosY = height() - halfHandleHeight;
             auto newHeight = (height() - halfHandleHeight) - halfHandleHeight;
             normalizedPosition = (adaptedPosY - halfHandleHeight) / newHeight;
-        }
-        else
-        {
+        } else {
             auto halfHandleWidth = (0.5 * sr.width()) + 0.5;
             int adaptedPosX = event->pos().x();
             if (adaptedPosX < halfHandleWidth)
@@ -58,9 +55,7 @@ void ClickableSlider::mousePressEvent(QMouseEvent* event)
         event->accept();
 
         emit onClick(this->value());
-    }
-    else
-    {
+    } else {
         QSlider::mousePressEvent(event);
     }
 }

+ 2 - 22
AvPlayer2/mainwindowa.cpp

@@ -300,7 +300,7 @@ MainWindowA::MainWindowA(QWidget* parent)
             &PlayerController::updatePlayTime,
             this,
             &MainWindowA::update_play_time);
-    connect(m_playerController, &PlayerController::playSeek, this, &MainWindowA::play_seek);
+    //connect(m_playerController, &PlayerController::playSeek, this, &MainWindowA::play_seek);
 
     hide_play_control(false);
 
@@ -1004,7 +1004,6 @@ void MainWindowA::update_paly_control_status()
 void MainWindowA::update_play_time()
 {
     if (auto pPlayControl = get_play_control()) {
-        qDebug() << "update_play_time";
         // pPlayControl->setVisible(true);
         // pPlayControl->resize(800, 200);
         // pPlayControl->show();
@@ -1027,28 +1026,9 @@ void MainWindowA::video_seek_inc(double incr) // incr seconds
     qDebug("!seek_by_bytes pos=%lf", pos);
 
     pos += incr;
-    video_seek(pos, incr);
+    m_playerController->videoSeek(pos, incr);
 }
 
-void MainWindowA::video_seek(double pos, double incr)
-{
-    auto pState = m_playerController->state();
-    if (!pState)
-        return;
-
-#if USE_AVFILTER_AUDIO
-    // pos /= pState->audio_speed;
-#endif
-
-    if (pState->ic->start_time != AV_NOPTS_VALUE
-        && pos < pState->ic->start_time / (double) AV_TIME_BASE) {
-        // qDebug("!seek_by_bytes pos=%lf, start_time=%lf, %lf", pos,
-        // pState->ic->start_time, pState->ic->start_time / (double)AV_TIME_BASE);
-        pos = pState->ic->start_time / (double) AV_TIME_BASE;
-    }
-
-    stream_seek(pState, (int64_t) (pos * AV_TIME_BASE), (int64_t) (incr * AV_TIME_BASE), 0);
-}
 
 void MainWindowA::play_seek()
 {

+ 0 - 1
AvPlayer2/mainwindowa.h

@@ -160,7 +160,6 @@ private:
     void show_audio_effect(bool bShow = true);
     void play_control_key(Qt::Key key);
     void video_seek_inc(double incr);
-    void video_seek(double pos = 0, double incr = 0);
     void update_menus();
     void enable_menus(bool enable = true);
     void enable_v_menus(bool enable = true);

+ 3 - 2
AvPlayer2/packets_sync.cpp

@@ -676,14 +676,15 @@ void check_external_clock_speed(VideoState* is)
 }
 
 /* seek in the stream */
-void stream_seek(VideoState* is, int64_t pos, int64_t rel, int seek_by_bytes)
+void stream_seek(VideoState* is, int64_t pos, int64_t rel, int by_bytes)
 {
     if (!is->seek_req) {
         is->seek_pos = pos;
         is->seek_rel = rel;
         is->seek_flags &= ~AVSEEK_FLAG_BYTE;
-        if (seek_by_bytes)
+        if (by_bytes)
             is->seek_flags |= AVSEEK_FLAG_BYTE;
+        is->seek_flags |= AVSEEK_FLAG_BACKWARD;
         is->seek_req = 1;
         // SDL_CondSignal(is->continue_read_thread);
         is->continue_read_thread->wakeAll();

+ 14 - 1
AvPlayer2/play_control_window.cpp

@@ -107,7 +107,20 @@ PlayControlWnd::PlayControlWnd(PlayerController* playerController, QWidget* pare
     connect(btn_next, &QPushButton::pressed, playerController, &PlayerController::playSeekNext);
     connect(progress_slider, &QSlider::sliderReleased, playerController, &PlayerController::playStartSeek);
     connect(progress_slider, &QSlider::sliderPressed, playerController, &PlayerController::pausePlay);
-    connect(progress_slider, &ClickableSlider::onClick, playerController, &PlayerController::playSeek);
+    connect(progress_slider, &ClickableSlider::onClick, playerController, [this, playerController]() {
+        int maxValue = get_progress_slider_max();
+        double total_time = get_total_time();
+        int value = get_progress_slider_value();
+
+        double seek_time = 0;
+        if (maxValue > 0)
+            seek_time = value * total_time * 1.0 / maxValue;
+
+        qDebug() << "val:" << value << ",maxVal:" << maxValue << ",total time" << total_time
+                 << ",seek time:" << seek_time;
+        // playerController->videoSeek(seek_time);
+        playerController->videoSeekEx(value, maxValue);
+    });
     connect(slider_speed, &QSlider::valueChanged, this, &PlayControlWnd::speed_changed);
     connect(slider_speed, &QSlider::valueChanged, playerController, [this, playerController]() {
         auto speed = get_speed();

+ 71 - 12
AvPlayer2/playercontroller.cpp

@@ -265,18 +265,17 @@ void PlayerController::playMute(bool mute)
 
 void PlayerController::playStartSeek()
 {
-    emit playSeek();
     pausePlay();
 }
 
 void PlayerController::playSeekPre()
 {
-    videoSeekInc(-2);
+    videoSeekInc(-0.5); // 将步长从2秒减小到0.5秒,提高精度
 }
 
 void PlayerController::playSeekNext()
 {
-    videoSeekInc(2);
+    videoSeekInc(0.5); // 将步长从2秒减小到0.5秒,提高精度
 }
 
 void PlayerController::setVolume(int volume, int maxValue)
@@ -311,14 +310,14 @@ bool PlayerController::isPlaying() const
     if (m_state != PlayerState::Playing) {
         return false;
     }
-    
+
     // 如果状态是Playing但所有线程都已停止,则实际上不是在播放状态
     if (areAllThreadsStopped()) {
         qCDebug(playerControllerLog) << "[isPlaying] State is Playing but all threads stopped";
 
         return false;
     }
-    
+
     return true;
 }
 
@@ -368,7 +367,7 @@ void PlayerController::playStarted(bool success)
 void PlayerController::playFailed(const QString& file)
 {
     qCWarning(playerControllerLog) << "Playback failed for file:" << toNativePath(file);
-    
+
     // 确保状态一致性
     if (m_state != PlayerState::Idle) {
         // 检查线程状态并重置
@@ -377,7 +376,7 @@ void PlayerController::playFailed(const QString& file)
             stopAndResetThreads();
         }
     }
-    
+
     emit showMessage(QString("Playback failed: %1").arg(toNativePath(file)), "Warning", "");
 }
 
@@ -457,20 +456,79 @@ void PlayerController::videoSeek(double position, double increment)
         && position < state->ic->start_time / static_cast<double>(AV_TIME_BASE)) {
         position = state->ic->start_time / static_cast<double>(AV_TIME_BASE);
     }
-
+    // 添加量化操作,精确到0.01秒
+    position = round(position * 100) / 100.0;
+    qDebug() << "position:" << position
+             << "position * AV_TIME_BASE:" << static_cast<int64_t>(position * AV_TIME_BASE)
+             << "increment * AV_TIME_BASE:" << static_cast<int64_t>(increment * AV_TIME_BASE);
     stream_seek(state,
                 static_cast<int64_t>(position * AV_TIME_BASE),
                 static_cast<int64_t>(increment * AV_TIME_BASE),
                 0);
 }
 
+void PlayerController::videoSeekEx(double value, double maxValue)
+{
+    if (!m_videoState)
+        return;
+
+    auto state = m_videoState->get_state();
+    if (!state)
+        return;
+    auto cur_stream = state;
+    auto x = value;
+    double frac;
+
+    if (m_videoState->seekByBytes() || cur_stream->ic->duration <= 0) {
+        uint64_t size = avio_size(cur_stream->ic->pb);
+        stream_seek(cur_stream, size * x / maxValue, 0, 1);
+    } else {
+        int64_t ts;
+        int ns, hh, mm, ss;
+        int tns, thh, tmm, tss;
+        tns = cur_stream->ic->duration / 1000000LL;
+        thh = tns / 3600;
+        tmm = (tns % 3600) / 60;
+        tss = (tns % 60);
+        frac = x / maxValue;
+        ns = frac * tns;
+        hh = ns / 3600;
+        mm = (ns % 3600) / 60;
+        ss = (ns % 60);
+        av_log(NULL,
+               AV_LOG_INFO,
+               "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n",
+               frac * 100,
+               hh,
+               mm,
+               ss,
+               thh,
+               tmm,
+               tss);
+        qDebug("Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)",
+               frac * 100,
+               hh,
+               mm,
+               ss,
+               thh,
+               tmm,
+               tss);
+        ts = frac * cur_stream->ic->duration;
+        if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
+            ts += cur_stream->ic->start_time;
+        stream_seek(cur_stream, ts, 0, 0);
+    }
+    return;
+}
+
 // 线程管理辅助方法
 void PlayerController::stopAndResetThreads()
 {
     auto stopAndReset = [](auto& threadPtr, const QString& threadName) {
         if (threadPtr) {
             qCDebug(playerControllerLog)
-                << "[stopAndReset] [" << threadName << "] try stop/join thread, isRunning=" << threadPtr->isRunning();
+                << "[stopAndReset] [" << threadName
+                << "] try stop/join thread, isRunning=" << threadPtr->isRunning();
             threadPtr->stop();
 
             // 添加超时等待机制
@@ -483,7 +541,8 @@ void PlayerController::stopAndResetThreads()
                     = std::chrono::duration_cast<std::chrono::milliseconds>(now - startTime).count();
                 if (elapsed > MAX_WAIT_MS) {
                     qCWarning(playerControllerLog)
-                        << "[stopAndReset] [" << threadName << "] Thread stop timeout after" << elapsed << "ms";
+                        << "[stopAndReset] [" << threadName << "] Thread stop timeout after"
+                        << elapsed << "ms";
                     break;
                 }
                 std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -768,11 +827,11 @@ bool PlayerController::createAudioPlayThread()
     m_audioPlayThread->setOnFinished([this]() { audioPlayStopped(); });
     m_audioPlayThread->setOnUpdatePlayTime([this]() {
         // TODO: 实现 PlayerController::onUpdatePlayTime() 处理播放时间更新
-        // emit updatePlayTime();
+        //emit updatePlayTime();
     });
     m_audioPlayThread->setOnDataVisualReady([this](const AudioData& data) {
         // 异步 ?
-        // emit audioData(data);
+        emit audioData(data);
     });
 
     // 音频设备初始化在独立线程中完成

+ 1 - 2
AvPlayer2/playercontroller.h

@@ -184,7 +184,7 @@ public slots:
     void setThreads();
     void startSendData(bool send = true);
     void videoSeek(double pos = 0, double incr = 0);
-
+    void videoSeekEx(double value = 0, double maxValue = 0);
 signals:
     //--------------------------------------------------------------------------
     // 线程控制信号
@@ -218,7 +218,6 @@ signals:
     void updatePlayControlVolume();
     void updatePlayControlStatus();
     void updatePlayTime();
-    void playSeek();
     void showMessage(const QString& message, const QString& windowTitle, const QString& styleSheet);
     void requestFullscreen(bool fullscreen);
     void requestHideStatusBar(bool hide);

+ 1 - 0
AvPlayer2/video_decode_thread.cpp

@@ -62,6 +62,7 @@ void VideoDecodeThread::run()
             << "[VideoDecodeThread] get_video_frame ret:" << ret << ", loop:" << loop_count++
             << ", m_exit:" << (m_exit ? m_exit->load() : -1)
             << ", abort_request:" << is->abort_request;
+
         if (ret < 0) {
             qCWarning(playerControllerVideoDecodeThread)
                 << "[VideoDecodeThread] get_video_frame failed, exit.";

+ 4 - 4
AvPlayer2/video_state.cpp

@@ -162,10 +162,10 @@ int VideoStateData::open_media(VideoState* is)
         // FIXME hack, ffplay maybe should not use avio_feof() to test for the end
         ic->pb->eof_reached = 0;
     }
-    // if (seek_by_bytes < 0)
-    //     seek_by_bytes = !(ic->iformat->flags & AVFMT_NO_BYTE_SEEK) &&
-    //                     !!(ic->iformat->flags & AVFMT_TS_DISCONT) &&
-    //                     strcmp("ogg", ic->iformat->name);
+    if (seek_by_bytes < 0)
+        seek_by_bytes = !(ic->iformat->flags & AVFMT_NO_BYTE_SEEK)
+                        && !!(ic->iformat->flags & AVFMT_TS_DISCONT)
+                        && strcmp("ogg", ic->iformat->name);
 
     // is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0;
 

+ 4 - 0
AvPlayer2/video_state.h

@@ -28,6 +28,8 @@ public:
     void print_state() const;
     void threads_setting(VideoState* is, const Threads& threads);
 
+    int seekByBytes() { return seek_by_bytes; }
+
 private:
     VideoState* stream_open(const char* filename, const AVInputFormat* iformat = NULL);
     void stream_close(VideoState* is);
@@ -59,6 +61,8 @@ private:
     AVBufferRef* m_hw_device_ctx{nullptr};
     //enum AVPixelFormat m_hw_pix_fmt;
     bool m_bLoopPlay{false};
+
+    int seek_by_bytes = -1;
 };
 
 #endif // AVPLAYER2_VIDEO_STATE_H

+ 1 - 1
main.cpp

@@ -52,7 +52,7 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const Q
 namespace avrecorder::video { void InitWinRTCapture(); }
 int main(int argc, char* argv[])
 {
-    // QLoggingCategory::setFilterRules(QStringLiteral("player.controller.debug=true\n"));
+    QLoggingCategory::setFilterRules(QStringLiteral("player.controller.*.debug=false\n"));
     // QLoggingCategory::setFilterRules("*.debug=false\n"
     //                                  "*.info=false\n"
     //                                  "*.warning=false\n"