blob: 91906af21c72a1ea08e647e06c1555513e27621f [file] [log] [blame]
/*
*
* Copyright (c) 2025 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "default-media-controller.h"
#include "camera-device.h"
#include "pushav-prerollbuffer.h"
#include <algorithm>
#include <lib/support/logging/CHIPLogging.h>
void DefaultMediaController::SetCameraDevice(Camera::CameraDevice * device)
{
mCameraDevice = device;
if (mCameraDevice)
{
size_t bufferSize = mCameraDevice->GetPreRollBufferSize();
mPreRollBuffer.SetMaxTotalBytes(bufferSize * 1000);
ChipLogProgress(Camera, "PreRollBuffer size set to %zu bytes from CameraDevice.", bufferSize);
}
else
{
// Handle case where device is null, perhaps revert to a default or log an error
ChipLogError(Camera, "CameraDevice is null in DefaultMediaController::SetCameraDevice. PreRollBuffer size not set.");
mPreRollBuffer.SetMaxTotalBytes(509600); // Fallback to a small default
}
}
void DefaultMediaController::RegisterTransport(Transport * transport, const std::vector<uint16_t> & videoStreams,
const std::vector<uint16_t> & audioStreams)
{
ChipLogProgress(Camera, "Registering transport: videoStreams count=%u, audioStreams count=%u",
static_cast<unsigned>(videoStreams.size()), static_cast<unsigned>(audioStreams.size()));
std::lock_guard<std::mutex> lock(mConnectionsMutex);
mConnections.push_back({ transport, videoStreams, audioStreams });
auto * bufferSink = new BufferSink();
bufferSink->transport = transport;
// 0: Deliver with the minimum I-frame duration
// 1: Deliver with a delay of up to 1 ms (default)
// Other values: Deliver with the specified delay
bufferSink->requestedPreBufferLengthMs = 1;
if (mCameraDevice)
{
bufferSink->minKeyframeIntervalMs = mCameraDevice->GetMinKeyframeIntervalMs();
ChipLogProgress(Camera, "MinKeyframeIntervalMs set to %lld ms from CameraDevice.",
static_cast<long long>(bufferSink->minKeyframeIntervalMs));
}
else
{
bufferSink->minKeyframeIntervalMs = 1000; // Fallback default if CameraDevice not set
ChipLogError(Camera, "CameraDevice not set in DefaultMediaController. Using default MinKeyframeIntervalMs.");
}
std::unordered_set<std::string> streamKeys;
for (uint16_t audioStream : audioStreams)
{
streamKeys.insert("a" + std::to_string(audioStream));
ChipLogProgress(Camera, " Registered audioStream=%u", audioStream);
}
for (uint16_t videoStream : videoStreams)
{
streamKeys.insert("v" + std::to_string(videoStream));
ChipLogProgress(Camera, " Registered videoStream=%u", videoStream);
}
mPreRollBuffer.RegisterTransportToBuffer(bufferSink, streamKeys);
mSinkMap[transport] = bufferSink;
ChipLogProgress(Camera, "Transport registered successfully. Total connections: %u", (unsigned) mConnections.size());
}
void DefaultMediaController::UnregisterTransport(Transport * transport)
{
std::lock_guard<std::mutex> lock(mConnectionsMutex);
mConnections.erase(std::remove_if(mConnections.begin(), mConnections.end(),
[transport](const Connection & c) { return c.transport == transport; }),
mConnections.end());
auto it = mSinkMap.find(transport);
if (it != mSinkMap.end())
{
mPreRollBuffer.DeregisterTransportFromBuffer(it->second);
delete it->second;
mSinkMap.erase(it);
ChipLogProgress(Camera, "Sink deregistered for transport.");
}
}
void DefaultMediaController::DistributeVideo(const uint8_t * data, size_t size, uint16_t videoStreamID, int64_t timestamp)
{
std::string streamKey = "v" + std::to_string(videoStreamID);
mPreRollBuffer.PushFrameToBuffer(streamKey, data, size, timestamp);
}
void DefaultMediaController::DistributeAudio(const uint8_t * data, size_t size, uint16_t audioStreamID, int64_t timestamp)
{
std::string streamKey = "a" + std::to_string(audioStreamID);
mPreRollBuffer.PushFrameToBuffer(streamKey, data, size, timestamp);
}
void DefaultMediaController::SetPreRollLength(Transport * transport, uint16_t preRollBufferLength)
{
auto it = mSinkMap.find(transport);
if (it != mSinkMap.end() && it->second != nullptr)
{
it->second->requestedPreBufferLengthMs = preRollBufferLength;
ChipLogProgress(Camera, "Delay updated for transport to %u ms", preRollBufferLength);
}
else
{
ChipLogError(Camera, "SetDelay: Transport not registered");
}
}
Transport * DefaultMediaController::GetTransportForVideoStream(uint16_t videoStreamID)
{
std::lock_guard<std::mutex> lock(mConnectionsMutex);
for (const auto & conn : mConnections)
{
for (uint16_t id : conn.videoStreams)
{
if (id == videoStreamID)
{
return conn.transport;
}
}
}
return nullptr;
}
Transport * DefaultMediaController::GetTransportForAudioStream(uint16_t audioStreamID)
{
std::lock_guard<std::mutex> lock(mConnectionsMutex);
for (const auto & conn : mConnections)
{
for (uint16_t id : conn.audioStreams)
{
if (id == audioStreamID)
{
return conn.transport;
}
}
}
return nullptr;
}