diff --git a/openvidu-testapp/src/app/components/video-track/video-track.component.css b/openvidu-testapp/src/app/components/video-track/video-track.component.css
index 81a5faadc..b16e3f017 100644
--- a/openvidu-testapp/src/app/components/video-track/video-track.component.css
+++ b/openvidu-testapp/src/app/components/video-track/video-track.component.css
@@ -56,18 +56,31 @@ video {
/* Keep the form-field visually compact (16×16 clipped box).
The CDK overlay uses the Popover API (top layer) so it is
immune to overflow:hidden and renders at its natural size. */
-#max-video-quality {
+#max-video-quality,
+#restart-video-resolution {
width: 16px;
height: 16px;
overflow: hidden;
font-size: 10px;
font-weight: bold;
+ --mat-form-field-container-vertical-padding: 0px;
}
-::ng-deep #max-video-quality .mdc-notched-outline * {
+/* The MDC outlined text field reserves 16px of horizontal padding
+ for the value, which alone exceeds this 16px-wide box and pushes
+ the value/arrow trigger (and therefore the dropdown svg) out of
+ the visible area. Removing it keeps the trigger inside the clip. */
+::ng-deep #max-video-quality .mat-mdc-text-field-wrapper,
+::ng-deep #restart-video-resolution .mat-mdc-text-field-wrapper {
+ padding: 0;
+}
+
+::ng-deep #max-video-quality .mdc-notched-outline *,
+::ng-deep #restart-video-resolution .mdc-notched-outline * {
border-color: transparent !important;
}
-::ng-deep #max-video-quality .mat-mdc-form-field-subscript-wrapper {
+::ng-deep #max-video-quality .mat-mdc-form-field-subscript-wrapper,
+::ng-deep #restart-video-resolution .mat-mdc-form-field-subscript-wrapper {
display: none !important;
}
diff --git a/openvidu-testapp/src/app/components/video-track/video-track.component.html b/openvidu-testapp/src/app/components/video-track/video-track.component.html
index 5cd416bea..401aced44 100644
--- a/openvidu-testapp/src/app/components/video-track/video-track.component.html
+++ b/openvidu-testapp/src/app/components/video-track/video-track.component.html
@@ -7,20 +7,26 @@
{{muteVideoIcon}}
- }
- @if (localParticipant) {
+
- }
- @if (localParticipant) {
+
+
+
+
+ @for (r of ['1920x1080', '1280x720', '640x360', '320x180']; track r) {
+ {{r}}
+ }
+
+
}
@if (!localParticipant) {
- }
- @if (!localParticipant) {
+
- }
- @if (!localParticipant) {
+
@for (q of ['LOW', 'MEDIUM', 'HIGH']; track q) {
diff --git a/openvidu-testapp/src/app/components/video-track/video-track.component.ts b/openvidu-testapp/src/app/components/video-track/video-track.component.ts
index 27b9b3ca6..a5448aefc 100644
--- a/openvidu-testapp/src/app/components/video-track/video-track.component.ts
+++ b/openvidu-testapp/src/app/components/video-track/video-track.component.ts
@@ -2,6 +2,7 @@ import { Component, inject, ChangeDetectionStrategy } from '@angular/core';
import { NgClass } from '@angular/common';
import {
LocalTrack,
+ LocalVideoTrack,
VideoTrack,
RemoteTrackPublication,
VideoQuality,
@@ -32,6 +33,8 @@ import { MatSelectModule } from '@angular/material/select';
export class VideoTrackComponent extends TrackComponent {
muteVideoIcon: string = 'videocam';
maxVideoQuality: string;
+ // Resolution to re-capture the local video track at (see onRestartResolutionChange)
+ restartResolution: string;
videoZoom = false;
@@ -96,6 +99,16 @@ export class VideoTrackComponent extends TrackComponent {
);
}
+ // Re-captures the local video track at the selected resolution. Useful to make
+ // the encoder change its layer structure on the fly: an SVC encoder drops its
+ // upper spatial layers when the capture is too small to host them
+ async onRestartResolutionChange() {
+ const [width, height] = this.restartResolution.split('x').map(Number);
+ await (this._track as LocalVideoTrack).restartTrack({
+ resolution: { width, height, frameRate: 30 },
+ });
+ }
+
openInfoDialog() {
const updateFunction = async (): Promise => {
const videoLayers: any[] = [];