Раздели PCM-сессии и исправь частоту и перемотку звука
This commit is contained in:
1 parent
40b974b29c
commit
217e5795bf
13 files changed
+226
-134
No files matched your search
@@ -295,11 +295,22 @@ void VideoPlayerEngine::open(const QString& path) {
|
||||
m_worker->moveToThread(m_thread);
|
||||
|
||||
connect(m_thread, &QThread::started, m_worker, &Worker::run);
|
||||
connect(m_worker, &Worker::opened, this, &VideoPlayerEngine::onWorkerOpened);
|
||||
connect(m_worker, &Worker::audioDecoded, this, &VideoPlayerEngine::onAudioDecoded);
|
||||
connect(m_worker, &Worker::frameDecoded, this, &VideoPlayerEngine::onFrameDecoded);
|
||||
connect(m_worker, &Worker::error, this, &VideoPlayerEngine::onWorkerError);
|
||||
connect(m_worker, &Worker::finished, this, &VideoPlayerEngine::onWorkerFinished);
|
||||
uint64_t generation = ++m_openGeneration;
|
||||
connect(m_worker, &Worker::opened, this, [this, generation](int w, int h, qint64 duration, bool audio) {
|
||||
if (generation == m_openGeneration) onWorkerOpened(w, h, duration, audio);
|
||||
});
|
||||
connect(m_worker, &Worker::audioDecoded, this, [this, generation](auto pcm, int rate, int channels, qint64 duration) {
|
||||
if (generation == m_openGeneration) onAudioDecoded(pcm, rate, channels, duration);
|
||||
});
|
||||
connect(m_worker, &Worker::frameDecoded, this, [this, generation](const QImage& frame, qint64 pts, int epoch) {
|
||||
if (generation == m_openGeneration) onFrameDecoded(frame, pts, epoch);
|
||||
});
|
||||
connect(m_worker, &Worker::error, this, [this, generation](const QString& error) {
|
||||
if (generation == m_openGeneration) onWorkerError(error);
|
||||
});
|
||||
connect(m_worker, &Worker::finished, this, [this, generation]() {
|
||||
if (generation == m_openGeneration) onWorkerFinished();
|
||||
});
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "VideoEngine: open %s", qPrintable(path));
|
||||
m_thread->start();
|
||||
@@ -308,7 +319,7 @@ void VideoPlayerEngine::open(const QString& path) {
|
||||
void VideoPlayerEngine::play() {
|
||||
if (m_state != Paused && m_state != Playing) return;
|
||||
m_paused.storeRelaxed(0);
|
||||
if (m_hasAudio) SoundManager::instance()->resumeCurrentPcm();
|
||||
if (m_hasAudio) SoundManager::instance()->resumePcm(m_audioPlayback);
|
||||
else { m_elapsedBaseMs = m_positionMs; m_elapsed.restart(); }
|
||||
setState(Playing);
|
||||
m_presentTimer.start();
|
||||
@@ -317,7 +328,7 @@ void VideoPlayerEngine::play() {
|
||||
void VideoPlayerEngine::pause() {
|
||||
if (m_state != Playing) return;
|
||||
m_paused.storeRelaxed(1);
|
||||
if (m_hasAudio) SoundManager::instance()->pauseCurrentPcm();
|
||||
if (m_hasAudio) SoundManager::instance()->pausePcm(m_audioPlayback);
|
||||
setState(Paused);
|
||||
m_presentTimer.stop();
|
||||
}
|
||||
@@ -336,8 +347,8 @@ void VideoPlayerEngine::seekMs(qint64 ms) {
|
||||
m_seekReq.storeRelaxed(1);
|
||||
clearPending();
|
||||
if (m_hasAudio) {
|
||||
int sr = SoundManager::instance()->currentPcmSampleRate();
|
||||
if (sr > 0) SoundManager::instance()->seekCurrentPcm((unsigned long long)(ms * sr / 1000));
|
||||
int sr = SoundManager::instance()->pcmSampleRate(m_audioPlayback);
|
||||
if (sr > 0) SoundManager::instance()->seekPcm(m_audioPlayback, (unsigned long long)(ms * sr / 1000));
|
||||
} else {
|
||||
m_elapsedBaseMs = ms;
|
||||
m_elapsed.restart();
|
||||
@@ -348,11 +359,12 @@ void VideoPlayerEngine::seekMs(qint64 ms) {
|
||||
}
|
||||
|
||||
void VideoPlayerEngine::stop() {
|
||||
++m_openGeneration;
|
||||
m_abort.storeRelaxed(1);
|
||||
m_presentTimer.stop();
|
||||
clearPending();
|
||||
m_renderFrame = QImage();
|
||||
if (m_hasAudio) SoundManager::instance()->stopCurrentPcm();
|
||||
if (m_hasAudio) SoundManager::instance()->stopPcm(m_audioPlayback);
|
||||
setState(Stopped);
|
||||
m_positionMs = 0;
|
||||
m_durationMs = 0;
|
||||
@@ -373,9 +385,9 @@ void VideoPlayerEngine::close() {
|
||||
|
||||
qint64 VideoPlayerEngine::clockMs() const {
|
||||
if (m_hasAudio && m_audioSampleRate > 0) {
|
||||
if (m_state == Finished && !SoundManager::instance()->isCurrentPcmPlaying())
|
||||
if (m_state == Finished && !SoundManager::instance()->isPcmPlaying(m_audioPlayback))
|
||||
return m_durationMs; /* аудио закончилось — часы в конец */
|
||||
unsigned long long cur = SoundManager::instance()->currentPcmCursor();
|
||||
unsigned long long cur = SoundManager::instance()->pcmCursor(m_audioPlayback);
|
||||
return (qint64)(cur * 1000 / (unsigned long long)m_audioSampleRate);
|
||||
}
|
||||
return m_elapsedBaseMs + m_elapsed.elapsed();
|
||||
@@ -410,15 +422,16 @@ void VideoPlayerEngine::onAudioDecoded(std::shared_ptr<std::vector<int16_t>> pcm
|
||||
int sampleRate, int channels, qint64 durationMs) {
|
||||
if (pcm && !pcm->empty() && channels > 0) {
|
||||
m_audioSampleRate = sampleRate;
|
||||
SoundManager::instance()->playRawPcm(pcm->data(), (int)(pcm->size() / (size_t)channels),
|
||||
sampleRate, channels);
|
||||
if (!SoundManager::instance()->isCurrentPcmPlaying()) {
|
||||
SoundManager::instance()->stopPcm(m_audioPlayback);
|
||||
m_audioPlayback = SoundManager::instance()->playRawPcm(pcm->data(), (int)(pcm->size() / (size_t)channels),
|
||||
sampleRate, channels, pcm);
|
||||
if (!SoundManager::instance()->isPcmPlaying(m_audioPlayback)) {
|
||||
/* аудио-устройство недоступно — переходим на системные часы */
|
||||
m_hasAudio = false;
|
||||
m_audioSampleRate = 0;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_VIDEO, "VideoEngine: audio not playing, fallback to system clock");
|
||||
} else {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "VideoEngine: audio started %dHz %dch", sampleRate, channels);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "VideoEngine: audio started %dHz %dch", sampleRate, channels, pcm);
|
||||
}
|
||||
} else {
|
||||
m_hasAudio = false;
|
||||
@@ -471,7 +484,7 @@ void VideoPlayerEngine::presentTick() {
|
||||
|
||||
if (m_state == Finished && m_pending.empty()) {
|
||||
m_presentTimer.stop();
|
||||
if (m_hasAudio) SoundManager::instance()->stopCurrentPcm();
|
||||
if (m_hasAudio) SoundManager::instance()->stopPcm(m_audioPlayback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user