Skip to content

Commit 3548c02

Browse files
pidarpedCopilotsamadDotDev
authored
Fix VideoStreamModify and SnapshotStreamModify to invoke callback for subscription reporting. (#41806)
* Fix VideoStreamModify and SnapshotStreamModify to invoke callback for subscription reporting. * Add test steps to scripts TC_AVSM_2_3.py and TC_AVSM_2_8.py to subscribe to attributes and verify on report generation. * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> * Fix python linter errors. * Fix wasModified logic check for optional OSD and WMark. * Apply suggestions from code review Co-authored-by: Abdul Samad <[email protected]> --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Abdul Samad <[email protected]>
1 parent 80f0f2b commit 3548c02

File tree

4 files changed

+89
-9
lines changed

4 files changed

+89
-9
lines changed

src/app/clusters/camera-av-stream-management-server/camera-av-stream-management-server.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,15 +1001,22 @@ void CameraAVStreamMgmtServer::ModifyVideoStream(const uint16_t streamID, const
10011001
{
10021002
if (stream.videoStreamID == streamID)
10031003
{
1004+
bool wasModified = false;
10041005
if (waterMarkEnabled.HasValue())
10051006
{
1007+
wasModified = !stream.watermarkEnabled.HasValue() || stream.watermarkEnabled.Value() != waterMarkEnabled.Value();
10061008
stream.watermarkEnabled = waterMarkEnabled;
10071009
}
10081010
if (osdEnabled.HasValue())
10091011
{
1012+
wasModified = wasModified || !stream.OSDEnabled.HasValue() || stream.OSDEnabled.Value() != osdEnabled.Value();
10101013
stream.OSDEnabled = osdEnabled;
10111014
}
1012-
ChipLogError(Camera, "Modified video stream with ID: %d", streamID);
1015+
if (wasModified)
1016+
{
1017+
PersistAndNotify<Attributes::AllocatedVideoStreams::Id>();
1018+
ChipLogProgress(Camera, "Modified video stream with ID: %d", streamID);
1019+
}
10131020
return;
10141021
}
10151022
}
@@ -1022,15 +1029,22 @@ void CameraAVStreamMgmtServer::ModifySnapshotStream(const uint16_t streamID, con
10221029
{
10231030
if (stream.snapshotStreamID == streamID)
10241031
{
1032+
bool wasModified = false;
10251033
if (waterMarkEnabled.HasValue())
10261034
{
1035+
wasModified = !stream.watermarkEnabled.HasValue() || stream.watermarkEnabled.Value() != waterMarkEnabled.Value();
10271036
stream.watermarkEnabled = waterMarkEnabled;
10281037
}
10291038
if (osdEnabled.HasValue())
10301039
{
1040+
wasModified = wasModified || !stream.OSDEnabled.HasValue() || stream.OSDEnabled.Value() != osdEnabled.Value();
10311041
stream.OSDEnabled = osdEnabled;
10321042
}
1033-
ChipLogError(Camera, "Modified snapshot stream with ID: %d", streamID);
1043+
if (wasModified)
1044+
{
1045+
PersistAndNotify<Attributes::AllocatedSnapshotStreams::Id>();
1046+
ChipLogProgress(Camera, "Modified snapshot stream with ID: %d", streamID);
1047+
}
10341048
return;
10351049
}
10361050
}

src/python_testing/TC_AVSMTestBase.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,31 @@
2222
import matter.clusters as Clusters
2323
from matter.clusters import Globals
2424
from matter.interaction_model import InteractionModelError, Status
25+
from matter.testing.matter_testing import AttributeMatcher, AttributeValue
2526

2627
logger = logging.getLogger(__name__)
2728

2829

30+
def wmark_osd_matcher(attribute_id: int, wmark: bool | None, osd: bool | None, wmark_check: bool, osd_check: bool) -> "AttributeMatcher":
31+
def predicate(report: AttributeValue) -> bool:
32+
if report.attribute != attribute_id:
33+
return False
34+
35+
if len(report.value) == 0:
36+
return False
37+
38+
stream = report.value[0]
39+
wmark_match = (not wmark_check) or (stream.watermarkEnabled == wmark)
40+
osd_match = (not osd_check) or (stream.OSDEnabled == osd)
41+
42+
return wmark_match and osd_match
43+
44+
return AttributeMatcher.from_callable(
45+
description=f"check watermarkEnabled is {wmark} and OSDEnabled is {osd}",
46+
matcher=predicate
47+
)
48+
49+
2950
class AVSMTestBase:
3051
async def precondition_one_allocated_snapshot_stream(self):
3152
endpoint = self.get_endpoint(default=1)

src/python_testing/TC_AVSM_2_3.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@
3838
import logging
3939

4040
from mobly import asserts
41-
from TC_AVSMTestBase import AVSMTestBase
41+
from TC_AVSMTestBase import AVSMTestBase, wmark_osd_matcher
4242

4343
import matter.clusters as Clusters
4444
from matter.interaction_model import InteractionModelError, Status
45+
from matter.testing.event_attribute_reporting import AttributeSubscriptionHandler
4546
from matter.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches
4647

4748
logger = logging.getLogger(__name__)
@@ -80,12 +81,20 @@ def steps_TC_AVSM_2_3(self) -> list[TestStep]:
8081
),
8182
TestStep(
8283
5,
84+
"Establish a subscription to the AllocatedSnapshotStreams attribute"
85+
),
86+
TestStep(
87+
6,
8388
"TH sends the SnapshotStreamModify command with SnapshotStreamID set to aStreamID. If WMARK is supported, set WaterMarkEnabled to !aWmark`and if OSD is supported, set OSDEnabled to `!aOSD in the command.",
8489
"If HardwareEncoder is True, DUT responds with a SUCCESS status code.",
85-
"If HardwareEncoder is False, DUT responds with an INVALID_INSTATE status code."
90+
"If HardwareEncoder is False, DUT responds with an INVALID_INSTATE status code.",
8691
),
8792
TestStep(
88-
6,
93+
7,
94+
"If HardwareEncoder is True, wait until a subscription report with AllocatedSnapshotStreams attribute is received",
95+
),
96+
TestStep(
97+
8,
8998
"TH reads AllocatedSnapshotStreams attribute from CameraAVStreamManagement Cluster on DUT",
9099
"If HardwareEncoder is True, verify the following: If WMARK is supported, verify WaterMarkEnabled == !aWmark. If OSD is supported, verify OSDEnabled == !aOSD.",
91100
),
@@ -157,6 +166,13 @@ async def test_TC_AVSM_2_3(self):
157166
pass
158167

159168
self.step(5)
169+
# Establish subscription to AllocatedSnapshotStreams
170+
sub_handler = AttributeSubscriptionHandler(cluster, attr.AllocatedSnapshotStreams)
171+
await sub_handler.start(self.default_controller, self.dut_node_id, endpoint=endpoint, min_interval_sec=0, max_interval_sec=30, keepSubscriptions=False)
172+
173+
sub_handler.reset()
174+
175+
self.step(6)
160176
try:
161177
cmd = commands.SnapshotStreamModify(
162178
snapshotStreamID=aStreamID,
@@ -171,7 +187,14 @@ async def test_TC_AVSM_2_3(self):
171187
asserts.assert_equal(e.status, Status.InvalidInState, "Wrong error code returned")
172188
pass
173189

174-
self.step(6)
190+
self.step(7)
191+
if aHardwareEncoder:
192+
expected_wmark = None if aWmark is None else not aWmark
193+
expected_osd = None if aOSD is None else not aOSD
194+
sub_handler.await_all_expected_report_matches(expected_matchers=[wmark_osd_matcher(
195+
attr.AllocatedSnapshotStreams, expected_wmark, expected_osd, wmarkSupport, osdSupport)], timeout_sec=20)
196+
197+
self.step(8)
175198
aAllocatedSnapshotStreams = await self.read_single_attribute_check_success(
176199
endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedSnapshotStreams
177200
)

src/python_testing/TC_AVSM_2_8.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@
3838
import logging
3939

4040
from mobly import asserts
41-
from TC_AVSMTestBase import AVSMTestBase
41+
from TC_AVSMTestBase import AVSMTestBase, wmark_osd_matcher
4242

4343
import matter.clusters as Clusters
4444
from matter.interaction_model import InteractionModelError, Status
45+
from matter.testing.event_attribute_reporting import AttributeSubscriptionHandler
4546
from matter.testing.matter_testing import MatterBaseTest, TestStep, default_matter_test_main, has_feature, run_if_endpoint_matches
4647

4748
logger = logging.getLogger(__name__)
@@ -79,11 +80,19 @@ def steps_TC_AVSM_2_8(self) -> list[TestStep]:
7980
),
8081
TestStep(
8182
5,
83+
"Establish a subscription to the AllocatedVideoStreams attribute"
84+
),
85+
TestStep(
86+
6,
8287
"TH sends the VideoStreamModify command with VideoStreamID set to aStreamID. If WMARK is supported, set WaterMarkEnabled to !aWmark and if OSD is supported, set OSDEnabled to !aOSD in the command.",
8388
"DUT responds with a SUCCESS status code.",
8489
),
8590
TestStep(
86-
6,
91+
7,
92+
"Wait until a subscription report with AllocatedVideoStreams attribute is received",
93+
),
94+
TestStep(
95+
8,
8796
"TH reads AllocatedVideoStreams attribute from CameraAVStreamManagement Cluster on DUT",
8897
"Verify the following: If WMARK is supported, verify WaterMarkEnabled == !aWmark. If OSD is supported, verify OSDEnabled == !aOSD.",
8998
),
@@ -151,6 +160,13 @@ async def test_TC_AVSM_2_8(self):
151160
pass
152161

153162
self.step(5)
163+
# Establish subscription to AllocatedVideoStreams
164+
sub_handler = AttributeSubscriptionHandler(cluster, attr.AllocatedVideoStreams)
165+
await sub_handler.start(self.default_controller, self.dut_node_id, endpoint=endpoint, min_interval_sec=0, max_interval_sec=30, keepSubscriptions=False)
166+
167+
sub_handler.reset()
168+
169+
self.step(6)
154170
try:
155171
videoStreamModifyCmd = commands.VideoStreamModify(
156172
videoStreamID=aStreamID,
@@ -162,7 +178,13 @@ async def test_TC_AVSM_2_8(self):
162178
asserts.assert_equal(e.status, Status.Success, "Unexpected error returned")
163179
pass
164180

165-
self.step(6)
181+
self.step(7)
182+
expected_wmark = None if aWmark is None else not aWmark
183+
expected_osd = None if aOSD is None else not aOSD
184+
sub_handler.await_all_expected_report_matches(expected_matchers=[wmark_osd_matcher(
185+
attr.AllocatedVideoStreams, expected_wmark, expected_osd, wmarkSupport, osdSupport)], timeout_sec=20)
186+
187+
self.step(8)
166188
aAllocatedVideoStreams = await self.read_single_attribute_check_success(
167189
endpoint=endpoint, cluster=cluster, attribute=attr.AllocatedVideoStreams
168190
)

0 commit comments

Comments
 (0)