Cancel desktop decoder probing when a call stops
This commit is contained in:
1 parent
c211e17af9
commit
7b341d9f4f
4 files changed
+22
-9
No files matched your search
@@ -230,19 +230,29 @@ int CallVideoDecoder::receive(call_video_frame& f, QImage& image) {
|
||||
#endif
|
||||
}
|
||||
|
||||
call_video_caps CallVideoDecoder::capabilities() {
|
||||
call_video_caps CallVideoDecoder::capabilities(const std::atomic<bool>* running) {
|
||||
static call_video_caps caps{};
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
static std::mutex lock;
|
||||
static bool initialized = false;
|
||||
auto cancelled = [running] {
|
||||
if (!running || running->load()) return false;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CALL, "video decoder capability probe cancelled by stop"); return true;
|
||||
};
|
||||
std::unique_lock<std::mutex> guard(lock, std::defer_lock);
|
||||
while (!guard.try_lock()) { if (cancelled()) return {}; QThread::usleep(1000); }
|
||||
if (initialized) return caps;
|
||||
call_video_caps probed{};
|
||||
for (unsigned codec = 1; codec <= 2; ++codec) {
|
||||
unsigned profiles = 0, maximumTier = 0;
|
||||
for (unsigned profile = 1; profile <= (codec == 1 ? 2u : 1u); ++profile) {
|
||||
for (unsigned tier = 0; tier < 2; ++tier) {
|
||||
const unsigned width = tier ? 1920 : 1280, height = tier ? 1080 : 720;
|
||||
for (Backend backend : {Backend::HardwareOnly, Backend::SoftwareOnly}) {
|
||||
if (cancelled()) return {};
|
||||
bool bothOrientations = true;
|
||||
unsigned backendPipeline = 0;
|
||||
for (int portrait = 0; portrait <= 1 && bothOrientations; ++portrait) {
|
||||
if (cancelled()) return {};
|
||||
const unsigned w = portrait ? height : width, h = portrait ? width : height;
|
||||
uint8_t bytes[8192]; int size = call_video_probe_key(codec, profile, w, h, bytes, sizeof(bytes));
|
||||
if (size < 0) { bothOrientations = false; break; }
|
||||
@@ -254,6 +264,7 @@ call_video_caps CallVideoDecoder::capabilities() {
|
||||
unsigned sent = 0, received = 0; bool valid = true, outputBeforeEos = false;
|
||||
const int64_t start = call_video_playout_now_us();
|
||||
while (valid && received < 8 && call_video_playout_now_us() - start < 1500000) {
|
||||
if (cancelled()) return {};
|
||||
if (sent < 8 && call_video_playout_now_us() - start >= sent * 33333ll) {
|
||||
input.frame_id = sent + 1; input.pts_us = 1000000 + sent * 33333ll;
|
||||
int result = decoder.submit(input); if (result < 0) valid = false; else if (result) ++sent;
|
||||
@@ -293,9 +304,9 @@ call_video_caps CallVideoDecoder::capabilities() {
|
||||
const uint16_t width = maximumTier ? 1920 : 1280, height = maximumTier ? 1080 : 720;
|
||||
call_video_limit limit{width, height, 30, uint32_t(width) * height * 30, 4000000, (uint8_t)profiles,
|
||||
(uint8_t)(codec == 1 ? (maximumTier ? 40 : 31) : (maximumTier ? 120 : 93))};
|
||||
if (!call_video_limit_orientations(&limit, codec)) caps.decode[codec - 1] = limit;
|
||||
if (!call_video_limit_orientations(&limit, codec)) probed.decode[codec - 1] = limit;
|
||||
}
|
||||
}
|
||||
});
|
||||
caps = probed; initialized = true;
|
||||
return caps;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "../../../src/call/call_video.h"
|
||||
#include <QImage>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
// Один RX worker. Независимые submit/receive сохраняют PTS при задержанном выходе.
|
||||
// Automatic использует проверенный capabilities() GPU, затем четыре CPU slice-потока.
|
||||
@@ -21,7 +22,8 @@ public:
|
||||
QString error() const;
|
||||
void useSoftware(); // После реального отказа устройства: следующий KEY открывает CPU, без повторной GPU пробы.
|
||||
void close();
|
||||
static call_video_caps capabilities();
|
||||
// running отменяет длительную пробу при stop; незавершённый результат не кэшируется.
|
||||
static call_video_caps capabilities(const std::atomic<bool>* running = nullptr);
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> m;
|
||||
|
||||
@@ -253,7 +253,7 @@ void CallVideoEngine::setVideo(bool enabled, const QByteArray& cameraId, int wid
|
||||
}
|
||||
|
||||
void CallVideoEngine::transmit() {
|
||||
call_video_caps caps = CallVideoDecoder::capabilities();
|
||||
call_video_caps caps = CallVideoDecoder::capabilities(&m->running);
|
||||
// Не связываем приём с наличием собственного encoder.
|
||||
for (unsigned codec = 1; codec <= 2 && m->running; ++codec) {
|
||||
for (const QSize size : {QSize(1920, 1080), QSize(1280, 720)}) {
|
||||
|
||||
@@ -35,7 +35,7 @@ int main() {
|
||||
assert(capture.captureLatency.low == 96000 && capture.captureLatency.high == 100000);
|
||||
assert(capture.captureLatency.count == 3 && capture.captureLatency.average() == 97333);
|
||||
assert(capture.captureBlock.low == 10000 && capture.captureBlock.high == 10000);
|
||||
report(devices, now(CLOCK_MONOTONIC), 1.0);
|
||||
report(devices, wallNow(), 1.0);
|
||||
timing.first_us = 1034000; timing.missing = 0; timing.measured = 0;
|
||||
audio_diag_capture_clock(nullptr, &timing);
|
||||
assert(take(e)); consume(e, devices);
|
||||
@@ -54,7 +54,7 @@ int main() {
|
||||
assert(capture.playbackLatency.low == -1000 && capture.playbackLatency.high == 30000);
|
||||
assert(capture.playbackBlock.high == 25000 && capture.playbackMaxConverter == 1000);
|
||||
assert(capture.playbackLatency.average() == 14500 && capture.playbackBlock.low == 20000);
|
||||
report(devices, now(CLOCK_MONOTONIC), 1.0);
|
||||
report(devices, wallNow(), 1.0);
|
||||
assert(capture.playbackBlocks == 0 && capture.playbackLatency.count == 0 && capture.playbackBlock.high == 0);
|
||||
std::vector<std::thread> workers;
|
||||
for (int p = 0; p < producers; ++p) workers.emplace_back([p, &done]() {
|
||||
|
||||
Reference in new issue
Block a user