[controller][mic] Implement Enable/DisableStreaming()
When a mute button event happens, the controller would
enable and disable all the streams depending on the state
of the mute button.
The demo was calling the HAL APIs for Enabling/Disabling
streaming which was not necessary so removed those calls.
Fixed: 44011
Test: Added test
fx test camera_tests
Change-Id: I685b1a3301e0ec7226fa4567725e4a5d8f3e90c3
diff --git a/src/camera/drivers/controller/controller-protocol.cc b/src/camera/drivers/controller/controller-protocol.cc
index fb4147e..0108379 100644
--- a/src/camera/drivers/controller/controller-protocol.cc
+++ b/src/camera/drivers/controller/controller-protocol.cc
@@ -119,9 +119,9 @@
cleanup.cancel();
}
-void ControllerImpl::EnableStreaming() {}
+void ControllerImpl::EnableStreaming() { pipeline_manager_.StartStreaming(); }
-void ControllerImpl::DisableStreaming() {}
+void ControllerImpl::DisableStreaming() { pipeline_manager_.StopStreaming(); }
void ControllerImpl::GetDeviceInfo(GetDeviceInfoCallback callback) {
fuchsia::camera2::DeviceInfo camera_device_info;
diff --git a/src/camera/drivers/controller/pipeline_manager.cc b/src/camera/drivers/controller/pipeline_manager.cc
index ab1f239..41cb4ef 100644
--- a/src/camera/drivers/controller/pipeline_manager.cc
+++ b/src/camera/drivers/controller/pipeline_manager.cc
@@ -54,11 +54,14 @@
// TODO(braval): Handle already configured nodes
return result;
}
+ output_nodes_info_[info->stream_config->properties.stream_type()] = result.value();
break;
}
+ // clang-format off
default: {
return fit::error(ZX_ERR_NOT_SUPPORTED);
}
+ // clang-format on
}
return result;
}
@@ -291,6 +294,7 @@
fuchsia::camera2::CameraStreamType stream_to_disconnect) {
auto shutdown_callback = [this, input_stream_type, stream_to_disconnect]() {
ProcessNode* graph_head = nullptr;
+ output_nodes_info_.erase(stream_to_disconnect);
switch (input_stream_type) {
case fuchsia::camera2::CameraStreamType::FULL_RESOLUTION: {
@@ -315,6 +319,7 @@
}
default: {
ZX_ASSERT_MSG(false, "Invalid input stream type\n");
+ break;
}
}
};
@@ -354,10 +359,26 @@
}
default: {
ZX_ASSERT_MSG(false, "Invalid input stream type\n");
- return;
+ break;
}
}
DisconnectStream(graph_head, input_stream_type, stream_to_disconnect);
}
+void PipelineManager::StopStreaming() {
+ for (auto output_node_info : output_nodes_info_) {
+ if (output_node_info.second) {
+ output_node_info.second->client_stream()->Stop();
+ }
+ }
+}
+
+void PipelineManager::StartStreaming() {
+ for (auto output_node_info : output_nodes_info_) {
+ if (output_node_info.second) {
+ output_node_info.second->client_stream()->Start();
+ }
+ }
+}
+
} // namespace camera
diff --git a/src/camera/drivers/controller/pipeline_manager.h b/src/camera/drivers/controller/pipeline_manager.h
index 8e4ed4c..3cff37f 100644
--- a/src/camera/drivers/controller/pipeline_manager.h
+++ b/src/camera/drivers/controller/pipeline_manager.h
@@ -8,6 +8,7 @@
#include <fuchsia/camera2/cpp/fidl.h>
#include <fuchsia/camera2/hal/cpp/fidl.h>
+#include <map>
#include <vector>
#include "fbl/macros.h"
@@ -83,6 +84,9 @@
ProcessNode* full_resolution_stream() { return full_resolution_stream_.get(); }
ProcessNode* downscaled_resolution_stream() { return downscaled_resolution_stream_.get(); }
+ void StopStreaming();
+ void StartStreaming();
+
private:
fit::result<std::unique_ptr<InputNode>, zx_status_t> ConfigureStreamPipelineHelper(
StreamCreationData* info, fidl::InterfaceRequest<fuchsia::camera2::Stream>& stream);
@@ -98,6 +102,7 @@
std::unique_ptr<ProcessNode> full_resolution_stream_;
std::unique_ptr<ProcessNode> downscaled_resolution_stream_;
std::queue<async::TaskClosure> event_queue_ __TA_GUARDED(event_queue_lock_);
+ std::map<fuchsia::camera2::CameraStreamType, OutputNode*> output_nodes_info_;
};
} // namespace camera
diff --git a/src/camera/drivers/controller/processing_node.cc b/src/camera/drivers/controller/processing_node.cc
index ad9c606..1916d59 100644
--- a/src/camera/drivers/controller/processing_node.cc
+++ b/src/camera/drivers/controller/processing_node.cc
@@ -46,7 +46,7 @@
}
void ProcessNode::OnStartStreaming() {
- if (!enabled_) {
+ if (!shutdown_requested_ && !enabled_) {
enabled_ = true;
parent_node_->OnStartStreaming();
}
@@ -62,7 +62,7 @@
}
void ProcessNode::OnStopStreaming() {
- if (enabled_) {
+ if (!shutdown_requested_ && enabled_) {
if (AllChildNodesDisabled()) {
enabled_ = false;
parent_node_->OnStopStreaming();
diff --git a/src/camera/drivers/controller/test/protocol_test.cc b/src/camera/drivers/controller/test/protocol_test.cc
index 7166dca..3ebca51 100644
--- a/src/camera/drivers/controller/test/protocol_test.cc
+++ b/src/camera/drivers/controller/test/protocol_test.cc
@@ -627,6 +627,49 @@
EXPECT_TRUE(fake_gdc_.frame_released());
}
+ void TestEnabledDisableStreaming() {
+ fuchsia::camera2::StreamPtr stream_ds;
+ fuchsia::camera2::StreamPtr stream_fr;
+
+ auto stream_type_ds = kStreamTypeDS | kStreamTypeML;
+ auto stream_type_fr = kStreamTypeFR | kStreamTypeML;
+
+ auto result_fr = SetupStream(kMonitorConfig, stream_type_fr, stream_fr);
+ ASSERT_EQ(ZX_OK, result_fr.error());
+
+ auto result_ds = SetupStream(kMonitorConfig, stream_type_ds, stream_ds);
+ ASSERT_EQ(ZX_OK, result_ds.error());
+
+ // Start streaming.
+ stream_fr->Start();
+ stream_ds->Start();
+ RunLoopUntilIdle();
+
+ auto fr_head_node = pipeline_manager_->full_resolution_stream();
+ auto fr_ml_output_node = static_cast<OutputNode*>(fr_head_node->child_nodes().at(0).get());
+ auto gdc_node = static_cast<GdcNode*>(fr_head_node->child_nodes().at(1).get());
+ auto ds_ml_output_node = static_cast<OutputNode*>(gdc_node->child_nodes().at(0).get());
+
+ EXPECT_TRUE(fr_head_node->enabled());
+ EXPECT_TRUE(fr_ml_output_node->enabled());
+ EXPECT_TRUE(gdc_node->enabled());
+ EXPECT_TRUE(ds_ml_output_node->enabled());
+
+ pipeline_manager_->StopStreaming();
+
+ EXPECT_FALSE(fr_head_node->enabled());
+ EXPECT_FALSE(fr_ml_output_node->enabled());
+ EXPECT_FALSE(gdc_node->enabled());
+ EXPECT_FALSE(ds_ml_output_node->enabled());
+
+ pipeline_manager_->StartStreaming();
+
+ EXPECT_TRUE(fr_head_node->enabled());
+ EXPECT_TRUE(fr_ml_output_node->enabled());
+ EXPECT_TRUE(gdc_node->enabled());
+ EXPECT_TRUE(ds_ml_output_node->enabled());
+ }
+
FakeIsp fake_isp_;
FakeGdc fake_gdc_;
async::Loop loop_;
@@ -683,6 +726,8 @@
TEST_F(ControllerProtocolTest, TestReleaseAfterStopStreaming) { TestReleaseAfterStopStreaming(); }
+TEST_F(ControllerProtocolTest, TestEnabledDisableStreaming) { TestEnabledDisableStreaming(); }
+
TEST_F(ControllerProtocolTest, LoadGdcConfig) {
#ifdef INTERNAL_ACCESS
TestGdcConfigLoading();
diff --git a/src/camera/examples/camera_display/stream_provider/controller_stream_provider.cc b/src/camera/examples/camera_display/stream_provider/controller_stream_provider.cc
index 87c909e..789bc3f 100644
--- a/src/camera/examples/camera_display/stream_provider/controller_stream_provider.cc
+++ b/src/camera/examples/camera_display/stream_provider/controller_stream_provider.cc
@@ -23,12 +23,6 @@
static constexpr uint32_t kMonitoringStream = 2;
ControllerStreamProvider::~ControllerStreamProvider() {
- if (controller_ && streaming_) {
- zx_status_t status = controller_->DisableStreaming();
- if (status != ZX_OK) {
- FX_PLOGS(WARNING, status) << "Failed to stop streaming via the controller";
- }
- }
for (auto& buffer_collection : buffer_collections_) {
if (buffer_collection.second) {
zx_status_t status = buffer_collection.second->Close();
@@ -89,13 +83,6 @@
return nullptr;
}
- // Immediately enable streaming.
- status = provider->controller_->EnableStreaming();
- if (status != ZX_OK) {
- FX_LOGS(WARNING) << "Failed to start streaming via the controller";
- }
- provider->streaming_ = true;
-
return std::move(provider);
}
diff --git a/src/camera/examples/camera_display/stream_provider/controller_stream_provider.h b/src/camera/examples/camera_display/stream_provider/controller_stream_provider.h
index a11a5b7..011364d 100644
--- a/src/camera/examples/camera_display/stream_provider/controller_stream_provider.h
+++ b/src/camera/examples/camera_display/stream_provider/controller_stream_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SRC_CAMERA_EXAMPLES_DEMO_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_
-#define SRC_CAMERA_EXAMPLES_DEMO_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_
+#ifndef SRC_CAMERA_EXAMPLES_CAMERA_DISPLAY_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_
+#define SRC_CAMERA_EXAMPLES_CAMERA_DISPLAY_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_
#include <fuchsia/camera2/hal/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
@@ -24,11 +24,10 @@
virtual std::string GetName() override { return "fuchsia.camera2.Controller service"; }
private:
- bool streaming_ = false;
fuchsia::camera2::hal::ControllerSyncPtr controller_;
fuchsia::sysmem::AllocatorSyncPtr allocator_;
std::map<uint32_t, fuchsia::sysmem::BufferCollectionSyncPtr> buffer_collections_;
fidl::VectorPtr<fuchsia::camera2::hal::Config> configs_;
};
-#endif // SRC_CAMERA_EXAMPLES_DEMO_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_
+#endif // SRC_CAMERA_EXAMPLES_CAMERA_DISPLAY_STREAM_PROVIDER_CONTROLLER_STREAM_PROVIDER_H_