make codec negotiation stateless for replicated agents

This commit is contained in:
Stephen Birarda 2017-06-12 12:14:59 -07:00
parent 2929573cb0
commit fe668b1bb1
8 changed files with 38 additions and 17 deletions

View file

@ -97,8 +97,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
PacketType::ReplicatedMicrophoneAudioNoEcho, PacketType::ReplicatedMicrophoneAudioNoEcho,
PacketType::ReplicatedMicrophoneAudioWithEcho, PacketType::ReplicatedMicrophoneAudioWithEcho,
PacketType::ReplicatedInjectAudio, PacketType::ReplicatedInjectAudio,
PacketType::ReplicatedSilentAudioFrame, PacketType::ReplicatedSilentAudioFrame
PacketType::ReplicatedNegotiateAudioFormat
}, },
this, "queueReplicatedAudioPacket" this, "queueReplicatedAudioPacket"
); );
@ -121,10 +120,10 @@ void AudioMixer::queueReplicatedAudioPacket(QSharedPointer<ReceivedMessage> mess
QUuid nodeID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); QUuid nodeID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
auto node = nodeList->addOrUpdateNode(nodeID, NodeType::Agent, auto node = nodeList->addOrUpdateNode(nodeID, NodeType::ReplicatedAgent,
message->getSenderSockAddr(), message->getSenderSockAddr()); message->getSenderSockAddr(), message->getSenderSockAddr(),
DEFAULT_AGENT_PERMISSIONS, true);
node->setIsUpstream(true); node->setIsUpstream(true);
node->setIsMirror(true);
node->setLastHeardMicrostamp(usecTimestampNow()); node->setLastHeardMicrostamp(usecTimestampNow());
getOrCreateClientData(node.data())->queuePacket(message, node); getOrCreateClientData(node.data())->queuePacket(message, node);

View file

@ -73,6 +73,11 @@ void AudioMixerClientData::processPackets() {
case PacketType::ReplicatedMicrophoneAudioWithEcho: case PacketType::ReplicatedMicrophoneAudioWithEcho:
case PacketType::ReplicatedInjectAudio: case PacketType::ReplicatedInjectAudio:
case PacketType::ReplicatedSilentAudioFrame: { case PacketType::ReplicatedSilentAudioFrame: {
if (node->getType() == NodeType::ReplicatedAgent && !_codec) {
setupCodecForReplicatedAgent(packet);
}
QMutexLocker lock(&getMutex()); QMutexLocker lock(&getMutex());
parseData(*packet); parseData(*packet);
@ -81,9 +86,7 @@ void AudioMixerClientData::processPackets() {
break; break;
} }
case PacketType::NegotiateAudioFormat: case PacketType::NegotiateAudioFormat:
case PacketType::ReplicatedNegotiateAudioFormat:
negotiateAudioFormat(*packet, node); negotiateAudioFormat(*packet, node);
replicatePacket(*packet);
break; break;
case PacketType::RequestsDomainListData: case PacketType::RequestsDomainListData:
parseRequestsDomainListData(*packet); parseRequestsDomainListData(*packet);
@ -119,15 +122,20 @@ void AudioMixerClientData::replicatePacket(ReceivedMessage& message) {
mirroredType = PacketType::ReplicatedInjectAudio; mirroredType = PacketType::ReplicatedInjectAudio;
} else if (message.getType() == PacketType::SilentAudioFrame) { } else if (message.getType() == PacketType::SilentAudioFrame) {
mirroredType = PacketType::ReplicatedSilentAudioFrame; mirroredType = PacketType::ReplicatedSilentAudioFrame;
} else if (message.getType() == PacketType::NegotiateAudioFormat) {
mirroredType = PacketType::ReplicatedNegotiateAudioFormat;
} else { } else {
return; return;
} }
// construct an NLPacket to send to the replicant that has the contents of the received packet // construct an NLPacket to send to the replicant that has the contents of the received packet
auto packet = NLPacket::create(mirroredType, message.getSize() + NUM_BYTES_RFC4122_UUID); auto packet = NLPacket::create(mirroredType, message.getSize() + NUM_BYTES_RFC4122_UUID);
// since this packet will be non-sourced, we add the replicated node's ID here
packet->write(message.getSourceID().toRfc4122()); packet->write(message.getSourceID().toRfc4122());
// we won't negotiate an audio format with the replicant, because we aren't a listener
// so pack the codec string here so that it can statelessly setup a decoder for this string when it needs
packet->writeString(_selectedCodecName);
packet->write(message.getMessage()); packet->write(message.getMessage());
// enumerate the replicant audio mixers and send them the replicated version of this packet // enumerate the replicant audio mixers and send them the replicated version of this packet
@ -311,7 +319,12 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|| packetType == PacketType::ReplicatedMicrophoneAudioNoEcho || packetType == PacketType::ReplicatedMicrophoneAudioNoEcho
|| packetType == PacketType::ReplicatedSilentAudioFrame || packetType == PacketType::ReplicatedSilentAudioFrame
|| packetType == PacketType::ReplicatedInjectAudio) { || packetType == PacketType::ReplicatedInjectAudio) {
// skip past source ID for the replicated packet
message.seek(NUM_BYTES_RFC4122_UUID); message.seek(NUM_BYTES_RFC4122_UUID);
// skip past the codec string
message.readString();
} }
// check the overflow count before we parse data // check the overflow count before we parse data
@ -660,3 +673,15 @@ bool AudioMixerClientData::shouldIgnore(const SharedNodePointer self, const Shar
return shouldIgnore; return shouldIgnore;
} }
void AudioMixerClientData::setupCodecForReplicatedAgent(QSharedPointer<ReceivedMessage> message) {
// first pull the codec string from the packet
// read the string for the codec
auto codecString = message->readString();
qDebug() << "Manually setting codec for replicated agent" << codecString;
const std::pair<QString, CodecPluginPointer> codec = AudioMixer::negotiateCodec({ codecString });
setupCodec(codec.second, codec.first);
}

View file

@ -108,6 +108,8 @@ public:
bool getRequestsDomainListData() { return _requestsDomainListData; } bool getRequestsDomainListData() { return _requestsDomainListData; }
void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; } void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }
void setupCodecForReplicatedAgent(QSharedPointer<ReceivedMessage> message);
signals: signals:
void injectorStreamFinished(const QUuid& streamIdentifier); void injectorStreamFinished(const QUuid& streamIdentifier);

View file

@ -44,6 +44,7 @@ void NodeType::init() {
TypeNameHash.insert(NodeType::EntityScriptServer, "Entity Script Server"); TypeNameHash.insert(NodeType::EntityScriptServer, "Entity Script Server");
TypeNameHash.insert(NodeType::ReplicantAudioMixer, "Replicant Audio Mixer"); TypeNameHash.insert(NodeType::ReplicantAudioMixer, "Replicant Audio Mixer");
TypeNameHash.insert(NodeType::ReplicantAvatarMixer, "Replicant Avatar Mixer"); TypeNameHash.insert(NodeType::ReplicantAvatarMixer, "Replicant Avatar Mixer");
TypeNameHash.insert(NodeType::ReplicatedAgent, "Replicated Agent");
TypeNameHash.insert(NodeType::Unassigned, "Unassigned"); TypeNameHash.insert(NodeType::Unassigned, "Unassigned");
} }

View file

@ -86,9 +86,6 @@ public:
bool isIgnoreRadiusEnabled() const { return _ignoreRadiusEnabled; } bool isIgnoreRadiusEnabled() const { return _ignoreRadiusEnabled; }
bool isMirror() const { return _isMirror; }
void setIsMirror(bool isMirror) { _isMirror = isMirror; }
private: private:
// privatize copy and assignment operator to disallow Node copying // privatize copy and assignment operator to disallow Node copying
Node(const Node &otherNode); Node(const Node &otherNode);
@ -109,8 +106,6 @@ private:
mutable QReadWriteLock _ignoredNodeIDSetLock; mutable QReadWriteLock _ignoredNodeIDSetLock;
std::atomic_bool _ignoreRadiusEnabled; std::atomic_bool _ignoreRadiusEnabled;
bool _isMirror { false };
}; };
Q_DECLARE_METATYPE(Node*) Q_DECLARE_METATYPE(Node*)

View file

@ -27,6 +27,7 @@ namespace NodeType {
const NodeType_t EntityScriptServer = 'S'; const NodeType_t EntityScriptServer = 'S';
const NodeType_t ReplicantAudioMixer = 'a'; const NodeType_t ReplicantAudioMixer = 'a';
const NodeType_t ReplicantAvatarMixer = 'w'; const NodeType_t ReplicantAvatarMixer = 'w';
const NodeType_t ReplicatedAgent = 'z';
const NodeType_t Unassigned = 1; const NodeType_t Unassigned = 1;
void init(); void init();

View file

@ -41,8 +41,7 @@ const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
<< PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode << PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode
<< PacketType::DomainServerRemovedNode << PacketType::UsernameFromIDReply << PacketType::OctreeFileReplacement << PacketType::DomainServerRemovedNode << PacketType::UsernameFromIDReply << PacketType::OctreeFileReplacement
<< PacketType::ReplicatedMicrophoneAudioNoEcho << PacketType::ReplicatedMicrophoneAudioWithEcho << PacketType::ReplicatedMicrophoneAudioNoEcho << PacketType::ReplicatedMicrophoneAudioWithEcho
<< PacketType::ReplicatedInjectAudio << PacketType::ReplicatedSilentAudioFrame << PacketType::ReplicatedInjectAudio << PacketType::ReplicatedSilentAudioFrame;
<< PacketType::ReplicatedNegotiateAudioFormat;
PacketVersion versionForPacketType(PacketType packetType) { PacketVersion versionForPacketType(PacketType packetType) {
switch (packetType) { switch (packetType) {

View file

@ -115,7 +115,6 @@ public:
AdjustAvatarSorting, AdjustAvatarSorting,
OctreeFileReplacement, OctreeFileReplacement,
CollisionEventChanges, CollisionEventChanges,
ReplicatedNegotiateAudioFormat,
ReplicatedMicrophoneAudioNoEcho, ReplicatedMicrophoneAudioNoEcho,
ReplicatedMicrophoneAudioWithEcho, ReplicatedMicrophoneAudioWithEcho,
ReplicatedInjectAudio, ReplicatedInjectAudio,