update parseData for new network API

This commit is contained in:
Stephen Birarda 2015-07-13 14:26:10 -07:00
parent ca1ff9b0f5
commit ede39515d8
13 changed files with 76 additions and 118 deletions

View file

@ -24,7 +24,7 @@
class DomainServerNodeData : public NodeData {
public:
DomainServerNodeData();
int parseData(const QByteArray& packet) { return 0; }
int parseData(NLPacket& packet, QSharedPointer<Node> sendingNode) { return 0; }
const QJsonObject& getStatsJSONObject() const { return _statsJSONObject; }

View file

@ -33,7 +33,7 @@
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioOutput>
#ifdef __GNUC__
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdouble-promotion"
#endif
@ -142,10 +142,10 @@ AudioClient::AudioClient() :
configureGverbFilter(_gverb);
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerPacketListener(PacketType::AudioEnvironment, this, "handleAudioStreamStatsPacket");
packetReceiver.registerPacketListener(PacketType::AudioStreamStats, this, "handleAudioEnvironmentDataPacket");
packetReceiver.registerPacketListener(PacketType::AudioStreamStats, &_stats, "handleAudioStreamStatsPacket");
packetReceiver.registerPacketListener(PacketType::AudioEnvironment, this, "handleAudioEnvironmentDataPacket");
packetReceiver.registerPacketListener(PacketType::SilentAudioFrame, this, "handleAudioDataPacket");
packetReceiver.registerPacketListener(PacketType::MixedAudio, this, "handleAudioDataPacket");
packetReceiver.registerPacketListener(PacketType::SilentAudioFrame, this, "handleSilentAudioFrame");
packetReceiver.registerPacketListener(PacketType::NoisyMute, this, "handleNoisyMutePacket");
packetReceiver.registerPacketListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
}
@ -535,35 +535,24 @@ void AudioClient::stop() {
}
}
void AudioClient::handleAudioStreamStatsPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
_stats.parseAudioStreamStatsPacket(packet->getData());
updateLastHeardFromAudioMixer(packet);
}
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
const char* dataAt = packet->getPayload();
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
char bitset;
memcpy(&bitset, dataAt, sizeof(char));
dataAt += sizeof(char);
packet->readPrimitive(&bitset);
bool hasReverb = oneAtBit(bitset, HAS_REVERB_BIT);;
bool hasReverb = oneAtBit(bitset, HAS_REVERB_BIT);
if (hasReverb) {
float reverbTime, wetLevel;
memcpy(&reverbTime, dataAt, sizeof(float));
dataAt += sizeof(float);
memcpy(&wetLevel, dataAt, sizeof(float));
dataAt += sizeof(float);
packet->readPrimitive(&reverbTime);
packet->readPrimitive(&wetLevel);
_receivedAudioStream.setReverb(reverbTime, wetLevel);
} else {
_receivedAudioStream.clearReverb();
}
updateLastHeardFromAudioMixer(packet);
}
}
void AudioClient::handleAudioDataPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
void AudioClient::handleAudioDataPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveFirstAudioPacket);
@ -577,45 +566,29 @@ void AudioClient::handleAudioDataPacket(QSharedPointer<NLPacket> packet, HifiSoc
}
// Audio output must exist and be correctly set up if we're going to process received audio
_receivedAudioStream.parseData(packet->getData());
_receivedAudioStream.parseData(*packet, sendingNode);
}
updateLastHeardFromAudioMixer(packet);
}
void AudioClient::handleSilentAudioFrame(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
updateLastHeardFromAudioMixer(packet);
}
void AudioClient::handleNoisyMutePacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
void AudioClient::handleNoisyMutePacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
if (!_muted) {
toggleMute();
// TODO reimplement on interface side
//AudioScriptingInterface::getInstance().mutedByMixer();
}
}
void AudioClient::handleMuteEnvironmentPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr) {
void AudioClient::handleMuteEnvironmentPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
glm::vec3 position;
float radius;
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketType::MuteEnvironment);
memcpy(&position, packet->getPayload(), sizeof(glm::vec3));
memcpy(&radius, packet->getPayload() + sizeof(glm::vec3), sizeof(float));
packet->readPrimitive(&position);
packet->readPrimitive(&radius);
emit muteEnvironmentRequested(position, radius);
}
void AudioClient::updateLastHeardFromAudioMixer(QSharedPointer<NLPacket>& packet) {
// update having heard from the audio-mixer and record the bytes received
auto nodeList = DependencyManager::get<NodeList>();
SharedNodePointer audioMixer = nodeList->nodeWithUUID(packet->getSourceID());
if (audioMixer) {
audioMixer->setLastHeardMicrostamp(usecTimestampNow());
}
}
QString AudioClient::getDefaultDeviceName(QAudio::Mode mode) {
QAudioDeviceInfo deviceInfo = defaultAudioDeviceForMode(mode);
return deviceInfo.deviceName();

View file

@ -139,12 +139,10 @@ public slots:
void start();
void stop();
void handleAudioStreamStatsPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleAudioEnvironmentDataPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleAudioDataPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleSilentAudioFrame(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleNoisyMutePacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleMuteEnvironmentPacket(QSharedPointer<NLPacket> packet, HifiSockAddr senderSockAddr);
void handleAudioEnvironmentDataPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void handleAudioDataPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void handleNoisyMutePacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void handleMuteEnvironmentPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
void sendDownstreamAudioStatsPacket() { _stats.sendDownstreamAudioStatsPacket(); }
void handleAudioInput();
@ -214,7 +212,6 @@ private slots:
void audioStateChanged(QAudio::State state);
private:
void updateLastHeardFromAudioMixer(QSharedPointer<NLPacket>& packet);
void outputFormatChanged();
QByteArray firstInputFrame;

View file

@ -63,27 +63,24 @@ void AudioIOStats::sentPacket() {
_lastSentAudioPacket = now;
}
}
void AudioIOStats::parseAudioStreamStatsPacket(const QByteArray& packet) {
int numBytesPacketHeader = numBytesForPacketHeader(packet);
const char* dataAt = packet.constData() + numBytesPacketHeader;
void AudioIOStats::processStreamStatsPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
// parse the appendFlag, clear injected audio stream stats if 0
quint8 appendFlag = *(reinterpret_cast<const quint16*>(dataAt));
dataAt += sizeof(quint8);
quint8 appendFlag;
packet->readPrimitive(&appendFlag);
if (!appendFlag) {
_mixerInjectedStreamStatsMap.clear();
}
// parse the number of stream stats structs to follow
quint16 numStreamStats = *(reinterpret_cast<const quint16*>(dataAt));
dataAt += sizeof(quint16);
quint16 numStreamStats;
packet->readPrimitive(&numStreamStats);
// parse the stream stats
AudioStreamStats streamStats;
for (quint16 i = 0; i < numStreamStats; i++) {
memcpy(&streamStats, dataAt, sizeof(AudioStreamStats));
dataAt += sizeof(AudioStreamStats);
packet->readPrimitive(&streamStats);
if (streamStats._streamType == PositionalAudioStream::Microphone) {
_mixerAvatarStreamStats = streamStats;

View file

@ -17,6 +17,8 @@
#include <QObject>
#include <AudioStreamStats.h>
#include <Node.h>
#include <NLPacket.h>
class MixedProcessedAudioStream;
@ -41,7 +43,7 @@ public:
const MovingMinMaxAvg<quint64>& getPacketSentTimeGaps() const { return _packetSentTimeGaps; }
void sendDownstreamAudioStatsPacket();
void parseAudioStreamStatsPacket(const QByteArray& packet);
void processStreamStatsPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode);
private:
MixedProcessedAudioStream* _receivedAudioStream;
@ -57,4 +59,4 @@ private:
MovingMinMaxAvg<quint64> _packetSentTimeGaps;
};
#endif // hifi_AudioIOStats_h
#endif // hifi_AudioIOStats_h

View file

@ -11,6 +11,9 @@
#include <glm/glm.hpp>
#include <NLPacket.h>
#include <Node.h>
#include "InboundAudioStream.h"
#include "PacketHeaders.h"
@ -96,28 +99,23 @@ void InboundAudioStream::perSecondCallbackForUpdatingStats() {
_timeGapStatsForStatsPacket.currentIntervalComplete();
}
int InboundAudioStream::parseData(const QByteArray& packet) {
PacketType::Value packetType = packetTypeForPacket(packet);
QUuid senderUUID = uuidFromPacketHeader(packet);
// parse header
int numBytesHeader = numBytesForPacketHeader(packet);
const char* dataAt = packet.constData() + numBytesHeader;
int readBytes = numBytesHeader;
int InboundAudioStream::parseData(NLPacket& packet, SharedNodePointer sendingNode) {
// parse sequence number and track it
quint16 sequence = *(reinterpret_cast<const quint16*>(dataAt));
dataAt += sizeof(quint16);
readBytes += sizeof(quint16);
SequenceNumberStats::ArrivalInfo arrivalInfo = _incomingSequenceNumberStats.sequenceNumberReceived(sequence, senderUUID);
quint16 sequence;
packet.readPrimitive(&sequence);
SequenceNumberStats::ArrivalInfo arrivalInfo = _incomingSequenceNumberStats.sequenceNumberReceived(sequence,
sendingNode->getUUID());
packetReceivedUpdateTimingStats();
int networkSamples;
// parse the info after the seq number and before the audio data (the stream properties)
readBytes += parseStreamProperties(packetType, packet.mid(readBytes), networkSamples);
int propertyBytes = parseStreamProperties(packet.getType(),
QByteArray::fromRawData(packet.getPayload(), packet.pos()),
networkSamples);
packet.seek(packet.pos() + propertyBytes);
// handle this packet based on its arrival status.
switch (arrivalInfo._status) {
@ -132,10 +130,12 @@ int InboundAudioStream::parseData(const QByteArray& packet) {
}
case SequenceNumberStats::OnTime: {
// Packet is on time; parse its data to the ringbuffer
if (packetType == PacketType::SilentAudioFrame) {
if (packet.getType() == PacketType::SilentAudioFrame) {
writeDroppableSilentSamples(networkSamples);
} else {
readBytes += parseAudioData(packetType, packet.mid(readBytes), networkSamples);
int audioBytes = parseAudioData(packet.getType(), QByteArray::fromRawData(packet.getPayload(), packet.pos()),
networkSamples);
packet.seek(packet.pos() + audioBytes);
}
break;
}
@ -165,7 +165,7 @@ int InboundAudioStream::parseData(const QByteArray& packet) {
framesAvailableChanged();
return readBytes;
return packet.pos();
}
int InboundAudioStream::parseStreamProperties(PacketType::Value type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
@ -314,7 +314,7 @@ void InboundAudioStream::setToStarved() {
starvesInWindow++;
} while (starvesIterator != end);
// this starve put us over the starve threshold. update _desiredJitterBufferFrames to
// this starve put us over the starve threshold. update _desiredJitterBufferFrames to
// value determined by window A.
if (starvesInWindow >= _starveThreshold) {
int calculatedJitterBufferFrames;
@ -398,7 +398,7 @@ void InboundAudioStream::packetReceivedUpdateTimingStats() {
_timeGapStatsForDesiredReduction.update(gap);
if (_timeGapStatsForDesiredCalcOnTooManyStarves.getNewStatsAvailableFlag()) {
_calculatedJitterBufferFramesUsingMaxGap = ceilf((float)_timeGapStatsForDesiredCalcOnTooManyStarves.getWindowMax()
_calculatedJitterBufferFramesUsingMaxGap = ceilf((float)_timeGapStatsForDesiredCalcOnTooManyStarves.getWindowMax()
/ (float) AudioConstants::NETWORK_FRAME_USECS);
_timeGapStatsForDesiredCalcOnTooManyStarves.clearNewStatsAvailableFlag();
}

View file

@ -80,7 +80,7 @@ public:
{}
// max number of frames over desired in the ringbuffer.
int _maxFramesOverDesired;
int _maxFramesOverDesired;
// if false, _desiredJitterBufferFrames will always be _staticDesiredJitterBufferFrames. Otherwise,
// either fred or philip's method will be used to calculate _desiredJitterBufferFrames based on packet timegaps.
@ -107,7 +107,7 @@ public:
virtual void resetStats();
void clearBuffer();
virtual int parseData(const QByteArray& packet);
virtual int parseData(NLPacket& packet, QSharedPointer<Node> sendingNode);
int popFrames(int maxFrames, bool allOrNothing, bool starveIfNoFramesPopped = true);
int popSamples(int maxSamples, bool allOrNothing, bool starveIfNoSamplesPopped = true);
@ -131,7 +131,7 @@ public:
virtual AudioStreamStats getAudioStreamStats() const;
/// returns the desired number of jitter buffer frames under the dyanmic jitter buffers scheme
int getCalculatedJitterBufferFrames() const { return _useStDevForJitterCalc ?
int getCalculatedJitterBufferFrames() const { return _useStDevForJitterCalc ?
_calculatedJitterBufferFramesUsingStDev : _calculatedJitterBufferFramesUsingMaxGap; };
/// returns the desired number of jitter buffer frames using Philip's method
@ -217,7 +217,7 @@ protected:
bool _dynamicJitterBuffers; // if false, _desiredJitterBufferFrames is locked at 1 (old behavior)
int _staticDesiredJitterBufferFrames;
// if jitter buffer is dynamic, this determines what method of calculating _desiredJitterBufferFrames
// if jitter buffer is dynamic, this determines what method of calculating _desiredJitterBufferFrames
// if true, Philip's timegap std dev calculation is used. Otherwise, Freddy's max timegap calculation is used
bool _useStDevForJitterCalc;

View file

@ -86,7 +86,7 @@ public:
const char* getTypeName() const;
// implement parseData to return 0 so we can be a subclass of NodeData
int parseData(const QByteArray& packet) { return 0; }
int parseData(NLPacket& packet, SharedNodePointer sendingNode) { return 0; }
friend QDebug operator<<(QDebug debug, const Assignment& assignment);
friend QDataStream& operator<<(QDataStream &out, const Assignment& assignment);

View file

@ -231,35 +231,25 @@ PacketSequenceNumber LimitedNodeList::getNextSequenceNumberForPacket(const QUuid
return _packetSequenceNumbers[nodeUUID][packetType]++;
}
int LimitedNodeList::updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, QSharedPointer<NLPacket> packet) {
QMutexLocker locker(&matchingNode->getMutex());
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<NLPacket> packet, SharedNodePointer sendingNode) {
QMutexLocker locker(&sendingNode->getMutex());
// if this was a sequence numbered packet we should store the last seq number for
// a packet of this type for this node
if (SEQUENCE_NUMBERED_PACKETS.contains(packet->getType())) {
matchingNode->setLastSequenceNumberForPacketType(packet->readSequenceNumber(), packet->getType());
sendingNode->setLastSequenceNumberForPacketType(packet->readSequenceNumber(), packet->getType());
}
NodeData* linkedData = matchingNode->getLinkedData();
NodeData* linkedData = sendingNode->getLinkedData();
if (!linkedData && linkedDataCreateCallback) {
linkedDataCreateCallback(matchingNode.data());
linkedDataCreateCallback(sendingNode.data());
}
if (linkedData) {
QMutexLocker linkedDataLocker(&linkedData->getMutex());
return linkedData->parseData(QByteArray::fromRawData(packet->getData(), packet->getSizeWithHeader()));
return linkedData->parseData(*packet, sendingNode);
}
return 0;
}
int LimitedNodeList::findNodeAndUpdateWithDataFromPacket(QSharedPointer<NLPacket> packet) {
SharedNodePointer matchingNode = nodeWithUUID(packet->getSourceID());
if (matchingNode) {
return updateNodeWithDataFromPacket(matchingNode, packet);
}
// we weren't able to match the sender address to the address we have for this node, unlock and don't parse
return 0;
}

View file

@ -155,8 +155,7 @@ public:
void processKillNode(const QByteArray& datagram);
int updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, QSharedPointer<NLPacket> packet);
int findNodeAndUpdateWithDataFromPacket(const QSharedPointer<NLPacket> packet);
int updateNodeWithDataFromPacket(QSharedPointer<NLPacket> packet, SharedNodePointer matchingNode);
unsigned broadcastToNodes(std::unique_ptr<NLPacket> packet, const NodeSet& destinationNodeTypes) { assert(false); return 0; }
SharedNodePointer soloNodeOfType(char nodeType);

View file

@ -14,6 +14,9 @@
#include <QtCore/QMutex>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include "NLPacket.h"
class Node;
@ -22,7 +25,7 @@ class NodeData : public QObject {
public:
NodeData();
virtual ~NodeData() = 0;
virtual int parseData(const QByteArray& packet) = 0;
virtual int parseData(NLPacket& packet, QSharedPointer<Node> sendingNode) = 0;
QMutex& getMutex() { return _mutex; }

View file

@ -64,13 +64,10 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
}
// called on the other nodes - assigns it to my views of the others
int OctreeQuery::parseData(const QByteArray& packet) {
// increment to push past the packet header
int numBytesPacketHeader = numBytesForPacketHeader(packet);
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(packet.data());
const unsigned char* sourceBuffer = startPosition + numBytesPacketHeader;
int OctreeQuery::parseData(NLPacket& packet, QSharedPointer<Node> sendingNode) {
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(packet.getPayload());
const unsigned char* sourceBuffer = startPosition;
// camera details
memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));

View file

@ -48,7 +48,7 @@ public:
virtual ~OctreeQuery() {}
int getBroadcastData(unsigned char* destinationBuffer);
int parseData(const QByteArray& packet);
int parseData(NLPacket& packet, QSharedPointer<Node> sendingNode);
// getters for camera details
const glm::vec3& getCameraPosition() const { return _cameraPosition; }