|
@@ -358,6 +358,15 @@ ErrorCode PlayerCoreV2::pause() {
|
|
|
std::lock_guard<std::mutex> lock(m_pauseMutex);
|
|
std::lock_guard<std::mutex> lock(m_pauseMutex);
|
|
|
Logger::instance().info("Setting m_paused to true");
|
|
Logger::instance().info("Setting m_paused to true");
|
|
|
m_paused = true;
|
|
m_paused = true;
|
|
|
|
|
+
|
|
|
|
|
+ m_videoPacketQueue->wakeup(); // 唤醒等待的解码线程
|
|
|
|
|
+
|
|
|
|
|
+ m_audioPacketQueue->wakeup(); // 唤醒等待的解码线程
|
|
|
|
|
+
|
|
|
|
|
+ m_videoFrameQueue->wakeup(); // 唤醒等待的播放线程
|
|
|
|
|
+
|
|
|
|
|
+ m_audioFrameQueue->wakeup(); // 唤醒等待的播放线程
|
|
|
|
|
+
|
|
|
Logger::instance().info("m_paused set to: " + std::to_string(m_paused.load()));
|
|
Logger::instance().info("m_paused set to: " + std::to_string(m_paused.load()));
|
|
|
}
|
|
}
|
|
|
// 立即通知所有等待的线程检查暂停状态
|
|
// 立即通知所有等待的线程检查暂停状态
|
|
@@ -1259,15 +1268,15 @@ void PlayerCoreV2::readThreadFunc() {
|
|
|
while (!m_threadsShouldStop) {
|
|
while (!m_threadsShouldStop) {
|
|
|
// 检查暂停状态,类似ffplay.c中的paused检查
|
|
// 检查暂停状态,类似ffplay.c中的paused检查
|
|
|
bool pausedState = m_paused.load();
|
|
bool pausedState = m_paused.load();
|
|
|
- Logger::instance().debug("Video play thread loop - m_paused: " + std::to_string(pausedState));
|
|
|
|
|
|
|
+ Logger::instance().debug("Read thread loop - m_paused: " + std::to_string(pausedState));
|
|
|
if (pausedState) {
|
|
if (pausedState) {
|
|
|
- Logger::instance().info("Video play thread entering pause wait");
|
|
|
|
|
|
|
+ Logger::instance().info("Read thread entering pause wait");
|
|
|
std::unique_lock<std::mutex> lock(m_pauseMutex);
|
|
std::unique_lock<std::mutex> lock(m_pauseMutex);
|
|
|
m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
|
|
m_pauseCondition.wait(lock, [this] { return !m_paused || m_threadsShouldStop; });
|
|
|
if (m_threadsShouldStop) {
|
|
if (m_threadsShouldStop) {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
- Logger::instance().info("Video play thread exiting pause wait");
|
|
|
|
|
|
|
+ Logger::instance().info("Read thread exiting pause wait");
|
|
|
// 暂停状态结束后,继续下一次循环
|
|
// 暂停状态结束后,继续下一次循环
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
@@ -1337,6 +1346,12 @@ void PlayerCoreV2::readThreadFunc() {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 在读取数据包前检查暂停状态,避免在读取期间阻塞
|
|
|
|
|
+ if (m_paused.load()) {
|
|
|
|
|
+ Logger::instance().debug("Read thread detected pause before av_read_frame");
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 读取数据包
|
|
// 读取数据包
|
|
|
int ret = av_read_frame(m_formatContext, packet);
|
|
int ret = av_read_frame(m_formatContext, packet);
|
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -1395,7 +1410,6 @@ void PlayerCoreV2::readThreadFunc() {
|
|
|
AVPacket* packetCopy = av_packet_alloc();
|
|
AVPacket* packetCopy = av_packet_alloc();
|
|
|
if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
|
|
if (packetCopy && av_packet_ref(packetCopy, packet) == 0) {
|
|
|
m_audioPacketQueue->push(packetCopy);
|
|
m_audioPacketQueue->push(packetCopy);
|
|
|
-
|
|
|
|
|
// 记录队列大小,用于监控
|
|
// 记录队列大小,用于监控
|
|
|
if (m_audioPacketQueue->size() % 100 == 0) {
|
|
if (m_audioPacketQueue->size() % 100 == 0) {
|
|
|
Logger::instance().debug("Audio packet queue size: " + std::to_string(m_audioPacketQueue->size()));
|
|
Logger::instance().debug("Audio packet queue size: " + std::to_string(m_audioPacketQueue->size()));
|
|
@@ -1405,6 +1419,8 @@ void PlayerCoreV2::readThreadFunc() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ m_audioPacketQueue->wakeup();
|
|
|
|
|
+ m_videoPacketQueue->wakeup();
|
|
|
|
|
|
|
|
av_packet_unref(packet);
|
|
av_packet_unref(packet);
|
|
|
}
|
|
}
|
|
@@ -1446,6 +1462,11 @@ void PlayerCoreV2::videoDecodeThreadFunc() {
|
|
|
// 从视频包队列获取包
|
|
// 从视频包队列获取包
|
|
|
AVPacket* packet = nullptr;
|
|
AVPacket* packet = nullptr;
|
|
|
while (!m_threadsShouldStop && !packet) {
|
|
while (!m_threadsShouldStop && !packet) {
|
|
|
|
|
+ // 在 pop 操作前检查暂停状态,避免在 pop 期间阻塞
|
|
|
|
|
+ if (m_paused.load()) {
|
|
|
|
|
+ Logger::instance().debug("Video decode thread detected pause before pop");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
Logger::instance().info("Video decode thread read Packet");
|
|
Logger::instance().info("Video decode thread read Packet");
|
|
|
packet = m_videoPacketQueue->pop(10); // 减少超时时间以提高seek响应速度
|
|
packet = m_videoPacketQueue->pop(10); // 减少超时时间以提高seek响应速度
|
|
|
Logger::instance().infof("Video decode thread read Packet %d", packet);
|
|
Logger::instance().infof("Video decode thread read Packet %d", packet);
|
|
@@ -1566,6 +1587,11 @@ void PlayerCoreV2::audioDecodeThreadFunc() {
|
|
|
// 从音频包队列获取包
|
|
// 从音频包队列获取包
|
|
|
AVPacket* packet = nullptr;
|
|
AVPacket* packet = nullptr;
|
|
|
while (!m_threadsShouldStop && !packet) {
|
|
while (!m_threadsShouldStop && !packet) {
|
|
|
|
|
+ // 在 pop 操作前检查暂停状态,避免在 pop 期间阻塞
|
|
|
|
|
+ if (m_paused.load()) {
|
|
|
|
|
+ Logger::instance().debug("Audio decode thread detected pause before pop");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
packet = m_audioPacketQueue->pop(10); // 减少超时时间以提高seek响应速度
|
|
packet = m_audioPacketQueue->pop(10); // 减少超时时间以提高seek响应速度
|
|
|
if (packet) {
|
|
if (packet) {
|
|
|
// 检查是否是EOF标记
|
|
// 检查是否是EOF标记
|
|
@@ -1735,9 +1761,10 @@ void PlayerCoreV2::videoPlayThreadFunc() {
|
|
|
if (decision.action == FrameAction::DISPLAY) {
|
|
if (decision.action == FrameAction::DISPLAY) {
|
|
|
// 如果需要延迟显示,等待指定时间
|
|
// 如果需要延迟显示,等待指定时间
|
|
|
if (decision.delay > 0.0) {
|
|
if (decision.delay > 0.0) {
|
|
|
- std::this_thread::sleep_for(std::chrono::microseconds(static_cast<int64_t>(decision.delay * 1000000)));
|
|
|
|
|
|
|
+ std::this_thread::sleep_for(
|
|
|
|
|
+ std::chrono::microseconds(static_cast<int64_t>(decision.delay * 1000000)));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 通知显示帧
|
|
// 通知显示帧
|
|
|
if (m_eventCallback) {
|
|
if (m_eventCallback) {
|
|
|
m_eventCallback->onVideoFrameReady(framePtr.get());
|
|
m_eventCallback->onVideoFrameReady(framePtr.get());
|