Fallback desktop video on decoder rejection and verify receive-only codecs
This commit is contained in:
1 parent
f47b7167a2
commit
634ef222a4
2 files changed
+35
-3
No files matched your search
@@ -146,6 +146,8 @@ void CallVideoEngine::transmit() {
|
||||
CallVideoEncoder encoder;
|
||||
call_video_format format{};
|
||||
uint64_t appliedRevision = 0, keySerial = 0, request = 0, frameId = 0;
|
||||
uint64_t userRevision = 0, rejectedGeneration = 0;
|
||||
unsigned excluded = 0;
|
||||
int64_t lastPts = -1, lastKey = -1;
|
||||
bool forceKey = true;
|
||||
while (m->running) {
|
||||
@@ -161,11 +163,28 @@ void CallVideoEngine::transmit() {
|
||||
raw = m->raw;
|
||||
#endif
|
||||
}
|
||||
if (revision != userRevision) { userRevision = revision; excluded = 0; }
|
||||
if (format.generation && state.decoded_generation == format.generation && !state.decoded_accepted
|
||||
&& rejectedGeneration != format.generation) {
|
||||
rejectedGeneration = format.generation; excluded |= 1u << format.codec;
|
||||
if (!codec) { appliedRevision = 0; lastKey = -1; m->report(tr("Receiver rejected video; selecting fallback")); }
|
||||
else {
|
||||
m->report(tr("Receiver cannot decode selected codec"));
|
||||
std::lock_guard<std::mutex> guard(m->lock); m->enabled = false; continue;
|
||||
}
|
||||
}
|
||||
if (format.generation && state.have_peer && !call_video_format_supported(&caps, &state.peer, &format)) appliedRevision = 0;
|
||||
if (!enabled || !state.have_peer || pts <= lastPts || (lastPts >= 0 && pts - lastPts < 33333)) { idle(); continue; }
|
||||
if (revision != appliedRevision) {
|
||||
if (lastKey >= 0 && pts - lastKey < 1000000) { idle(); continue; }
|
||||
call_video_format next{format.generation + 1, (uint16_t)width, (uint16_t)height, 30, 0, (uint8_t)codec, 0, 4000000, 0};
|
||||
if (call_video_choose(&caps, &state.peer, &next) <= 0 || !encoder.open(next, 1000000)) {
|
||||
bool opened = false;
|
||||
for (int candidate = 2; candidate >= 1; --candidate) {
|
||||
if ((codec && codec != candidate) || (excluded & (1u << candidate))) continue;
|
||||
next.codec = candidate; next.level = next.profile = 0;
|
||||
if (call_video_choose(&caps, &state.peer, &next) > 0 && encoder.open(next, 1000000)) { opened = true; break; }
|
||||
}
|
||||
if (!opened) {
|
||||
m->report(tr("Selected video mode is unavailable to the peer"));
|
||||
std::lock_guard<std::mutex> guard(m->lock); if (m->revision == revision) m->enabled = false;
|
||||
continue;
|
||||
@@ -209,6 +228,7 @@ void CallVideoEngine::receive() {
|
||||
std::deque<Picture> pictures;
|
||||
CallVideoDecoder decoder;
|
||||
uint64_t sourceEpoch = 0; int64_t lastShown = -1, report = 0; unsigned shown = 0;
|
||||
uint64_t reportedGeneration = 0, rejectedGeneration = 0;
|
||||
while (m->running) {
|
||||
int64_t now = nowUs(); call_clock_snapshot clock{};
|
||||
call_audio_get_clock(m->id, now, &clock);
|
||||
@@ -228,9 +248,16 @@ void CallVideoEngine::receive() {
|
||||
if (pictures.size() < 16) {
|
||||
call_video_frame packet{};
|
||||
if (call_video_port_pull(m->id, &packet) == 1) {
|
||||
if (packet.format.generation == rejectedGeneration) { u_free((void*)packet.data); continue; }
|
||||
QImage image;
|
||||
if (decoder.decode(packet, image)) pictures.push_back({packet.pts_us, image});
|
||||
else call_video_port_request_key(m->id);
|
||||
if (decoder.decode(packet, image)) {
|
||||
pictures.push_back({packet.pts_us, image});
|
||||
if (reportedGeneration != packet.format.generation) {
|
||||
reportedGeneration = packet.format.generation; call_video_port_decoded(m->id, reportedGeneration, 1);
|
||||
}
|
||||
} else {
|
||||
rejectedGeneration = packet.format.generation; call_video_port_decoded(m->id, rejectedGeneration, 0);
|
||||
}
|
||||
u_free((void*)packet.data); continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,11 @@ private slots:
|
||||
void switchesAtScheduledIdr_data() {
|
||||
QTest::addColumn<int>("codec"); QTest::newRow("H264") << 1; QTest::newRow("H265") << 2;
|
||||
}
|
||||
void independentDecoders() {
|
||||
auto caps = CallVideoDecoder::capabilities();
|
||||
QCOMPARE(caps.decode[0].profiles, uint8_t(3)); QCOMPARE(caps.decode[1].profiles, uint8_t(1));
|
||||
QCOMPARE(caps.encode[0].width, uint16_t(0)); QCOMPARE(caps.encode[1].width, uint16_t(0));
|
||||
}
|
||||
void switchesAtScheduledIdr() {
|
||||
QFETCH(int, codec);
|
||||
auto config = configuration(codec);
|
||||
|
||||
Reference in new issue
Block a user