added seq stats for Agent,

fixed  AudioInjector to do << (quint16)0 instead of
skipRawData(sizeof(quint16) to correctly allocate space for seq number;
added debug prints;
This commit is contained in:
wangyix 2014-06-27 11:23:50 -07:00
parent c5474f95bd
commit ff438a2434
10 changed files with 53 additions and 33 deletions

View file

@ -147,7 +147,13 @@ void Agent::readPendingDatagrams() {
}
} else if (datagramPacketType == PacketTypeMixedAudio) {
// TODO: track sequence numbers for mixed audio???
// parse sequence number for this packet
int numBytesPacketHeader = numBytesForPacketHeader(receivedPacket);
const char* sequenceAt = receivedPacket.constData() + numBytesPacketHeader;
quint16 sequence = *(reinterpret_cast<const quint16*>(sequenceAt));
_incomingMixedAudioSequenceNumberStats.sequenceNumberReceived(sequence);
printf("mixed audio received %d\n", sequence);
// parse the data and grab the average loudness
_receivedAudioBuffer.parseData(receivedPacket);

View file

@ -71,6 +71,8 @@ private:
ModelTreeHeadlessViewer _modelViewer;
MixedAudioRingBuffer _receivedAudioBuffer;
SequenceNumberStats _incomingMixedAudioSequenceNumberStats;
AvatarHashMap _avatarHashMap;
};

View file

@ -457,6 +457,7 @@ void AudioMixer::sendStatsPacket() {
// if we're too large, send the packet
if (sizeOfStats > TOO_BIG_FOR_MTU) {
printf("sending stats to domain server: size: %d\n", sizeOfStats);
nodeList->sendStatsToDomainServer(statsObject2);
sizeOfStats = 0;
statsObject2 = QJsonObject(); // clear it
@ -465,6 +466,7 @@ void AudioMixer::sendStatsPacket() {
}
if (somethingToSend) {
printf("sending stats to domain server: size: %d\n", sizeOfStats);
nodeList->sendStatsToDomainServer(statsObject2);
}
}
@ -621,7 +623,8 @@ void AudioMixer::run() {
dataAt += NETWORK_BUFFER_LENGTH_BYTES_STEREO;
// send mixed audio packet
nodeList->writeDatagram(clientMixBuffer, dataAt - clientMixBuffer, node);
//nodeList->writeDatagram(clientMixBuffer, dataAt - clientMixBuffer, node);
printf("mixed audio sent %d\n", sequence);
nodeData->incrementOutgoingSequenceNumber();
// send an audio stream stats packet if it's time

View file

@ -21,8 +21,8 @@
AudioMixerClientData::AudioMixerClientData() :
_ringBuffers(),
_outgoingSequenceNumber(0),
_incomingAvatarSequenceNumberStats()
_outgoingMixedAudioSequenceNumber(0),
_incomingAvatarAudioSequenceNumberStats()
{
}
@ -57,13 +57,14 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
|| packetType == PacketTypeMicrophoneAudioNoEcho
|| packetType == PacketTypeSilentAudioFrame) {
_incomingAvatarSequenceNumberStats.sequenceNumberReceived(sequence);
_incomingAvatarAudioSequenceNumberStats.sequenceNumberReceived(sequence);
printf("avatar audio received %d\n", sequence);
// grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist)
AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer();
// read the first byte after the header to see if this is a stereo or mono buffer
quint8 channelFlag = packet.at(numBytesForPacketHeader(packet));
quint8 channelFlag = packet.at(numBytesForPacketHeader(packet) + sizeof(quint16));
bool isStereo = channelFlag == 1;
if (avatarRingBuffer && avatarRingBuffer->isStereo() != isStereo) {
@ -86,9 +87,10 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
// this is injected audio
// grab the stream identifier for this injected audio
QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(numBytesForPacketHeader(packet), NUM_BYTES_RFC4122_UUID));
QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(numBytesForPacketHeader(packet) + sizeof(quint16), NUM_BYTES_RFC4122_UUID));
_incomingInjectedSequenceNumberStatsMap[streamIdentifier].sequenceNumberReceived(sequence);
_incomingInjectedAudioSequenceNumberStatsMap[streamIdentifier].sequenceNumberReceived(sequence);
printf("injected stream %s received seq %d\n", streamIdentifier.toString().toLatin1().data(), sequence);
InjectedAudioRingBuffer* matchingInjectedRingBuffer = NULL;
@ -96,6 +98,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
if (_ringBuffers[i]->getType() == PositionalAudioRingBuffer::Injector
&& ((InjectedAudioRingBuffer*) _ringBuffers[i])->getStreamIdentifier() == streamIdentifier) {
matchingInjectedRingBuffer = (InjectedAudioRingBuffer*) _ringBuffers[i];
printf("\t matching ring buffer found.\n");
}
}
@ -104,6 +107,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier,
AudioMixer::getUseDynamicJitterBuffers());
_ringBuffers.push_back(matchingInjectedRingBuffer);
printf("\t no matching ring buffer, creating new one. _ringBuffer size now %d\n", _ringBuffers.size());
}
matchingInjectedRingBuffer->parseData(packet);
@ -147,7 +151,7 @@ void AudioMixerClientData::pushBuffersAfterFrameSend() {
// this is an empty audio buffer that has starved, safe to delete
// also delete its sequence number stats
QUuid streamIdentifier = ((InjectedAudioRingBuffer*)audioBuffer)->getStreamIdentifier();
_incomingInjectedSequenceNumberStatsMap.remove(streamIdentifier);
_incomingInjectedAudioSequenceNumberStatsMap.remove(streamIdentifier);
delete audioBuffer;
i = _ringBuffers.erase(i);
continue;
@ -212,7 +216,7 @@ QString AudioMixerClientData::getJitterBufferStatsString() const {
} else {
result = "mic unknown";
}
printf("\tget jitter buffer stats string. _ringBuffer.size = %d\n", _ringBuffers.size());
for (int i = 0; i < _ringBuffers.size(); i++) {
if (_ringBuffers[i]->getType() == PositionalAudioRingBuffer::Injector) {
int desiredJitterBuffer = _ringBuffers[i]->getDesiredJitterBufferFrames();

View file

@ -38,17 +38,17 @@ public:
QString getJitterBufferStatsString() const;
void incrementOutgoingSequenceNumber() { _outgoingSequenceNumber++; }
void incrementOutgoingSequenceNumber() { _outgoingMixedAudioSequenceNumber++; }
quint16 getOutgoingSequenceNumber() const { return _outgoingSequenceNumber; }
quint16 getOutgoingSequenceNumber() const { return _outgoingMixedAudioSequenceNumber; }
//const SequenceNumberStats& getIncomingSequenceNumberStats() const { return _incomingSequenceNumberStats; }
private:
QList<PositionalAudioRingBuffer*> _ringBuffers;
quint16 _outgoingSequenceNumber;
SequenceNumberStats _incomingAvatarSequenceNumberStats;
QHash<QUuid, SequenceNumberStats> _incomingInjectedSequenceNumberStatsMap;
quint16 _outgoingMixedAudioSequenceNumber;
SequenceNumberStats _incomingAvatarAudioSequenceNumberStats;
QHash<QUuid, SequenceNumberStats> _incomingInjectedAudioSequenceNumberStatsMap;
};
#endif // hifi_AudioMixerClientData_h

View file

@ -104,7 +104,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_scopeOutputLeft(0),
_scopeOutputRight(0),
_audioMixerJitterBufferStats(),
_outgoingSequenceNumber(0)
_outgoingAvatarAudioSequenceNumber(0)
{
// clear the array of locally injected samples
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
@ -120,7 +120,7 @@ void Audio::init(QGLWidget *parent) {
void Audio::reset() {
_ringBuffer.reset();
_outgoingSequenceNumber = 0;
_outgoingAvatarAudioSequenceNumber = 0;
}
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
@ -657,7 +657,7 @@ void Audio::handleAudioInput() {
char* currentPacketPtr = audioDataPacket + populatePacketHeader(audioDataPacket, packetType);
// pack sequence number
memcpy(currentPacketPtr, &_outgoingSequenceNumber, sizeof(quint16));
memcpy(currentPacketPtr, &_outgoingAvatarAudioSequenceNumber, sizeof(quint16));
currentPacketPtr += sizeof(quint16);
// set the mono/stereo byte
@ -672,13 +672,14 @@ void Audio::handleAudioInput() {
currentPacketPtr += sizeof(headOrientation);
nodeList->writeDatagram(audioDataPacket, numAudioBytes + leadingBytes, audioMixer);
_outgoingSequenceNumber++;
printf("avatar audio sent %d\n", _outgoingAvatarAudioSequenceNumber);
_outgoingAvatarAudioSequenceNumber++;
Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
.updateValue(numAudioBytes + leadingBytes);
} else {
// reset seq numbers if there's no connection with an audiomixer
_outgoingSequenceNumber = 0;
_outgoingAvatarAudioSequenceNumber = 0;
}
delete[] inputAudioSamples;
}
@ -832,7 +833,8 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
int numBytesPacketHeader = numBytesForPacketHeader(audioByteArray);
const char* sequenceAt = audioByteArray.constData() + numBytesPacketHeader;
quint16 sequence = *((quint16*)sequenceAt);
_incomingSequenceNumberStats.sequenceNumberReceived(sequence);
_incomingMixedAudioSequenceNumberStats.sequenceNumberReceived(sequence);
printf("mixed audio received %d\n", sequence);
// parse audio data
_ringBuffer.parseData(audioByteArray);

View file

@ -239,8 +239,8 @@ private:
AudioMixerJitterBuffersStats _audioMixerJitterBufferStats;
quint16 _outgoingSequenceNumber;
SequenceNumberStats _incomingSequenceNumberStats;
quint16 _outgoingAvatarAudioSequenceNumber;
SequenceNumberStats _incomingMixedAudioSequenceNumberStats;
};

View file

@ -61,12 +61,13 @@ void AudioInjector::injectAudio() {
QByteArray injectAudioPacket = byteArrayWithPopulatedHeader(PacketTypeInjectAudio);
QDataStream packetStream(&injectAudioPacket, QIODevice::Append);
// skip sequence number for now
// pack some placeholder sequence number for now
int numPreSequenceNumberBytes = injectAudioPacket.size();
packetStream.skipRawData(sizeof(quint16));
packetStream << (quint16)0;
// pack stream identifier (a generated UUID)
packetStream << QUuid::createUuid();
QUuid streamID;
packetStream << (streamID = QUuid::createUuid());
// pack the flag for loopback
uchar loopbackFlag = (uchar) (!_options.getLoopbackAudioInterface());
@ -86,6 +87,7 @@ void AudioInjector::injectAudio() {
quint8 volume = MAX_INJECTOR_VOLUME * _options.getVolume();
packetStream << volume;
QElapsedTimer timer;
timer.start();
int nextFrame = 0;
@ -96,7 +98,7 @@ void AudioInjector::injectAudio() {
bool shouldLoop = _options.getLoop();
// loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks
quint16 outgoingSequenceNumber = 0;
quint16 outgoingInjectedAudioSequenceNumber = 0;
while (currentSendPosition < soundByteArray.size() && !_shouldStop) {
int bytesToCopy = std::min(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL,
@ -106,7 +108,7 @@ void AudioInjector::injectAudio() {
injectAudioPacket.resize(numPreAudioDataBytes + bytesToCopy);
// pack the sequence number
memcpy(injectAudioPacket.data() + numPreSequenceNumberBytes, &outgoingSequenceNumber, sizeof(quint16));
memcpy(injectAudioPacket.data() + numPreSequenceNumberBytes, &outgoingInjectedAudioSequenceNumber, sizeof(quint16));
// copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet
memcpy(injectAudioPacket.data() + numPreAudioDataBytes, soundByteArray.data() + currentSendPosition, bytesToCopy);
@ -116,7 +118,8 @@ void AudioInjector::injectAudio() {
// send off this audio packet
nodeList->writeDatagram(injectAudioPacket, audioMixer);
outgoingSequenceNumber++;
printf("injector stream %s sent seq %d\n", streamID.toString().toLatin1().data(), outgoingInjectedAudioSequenceNumber);
outgoingInjectedAudioSequenceNumber++;
currentSendPosition += bytesToCopy;

View file

@ -501,9 +501,9 @@ void ScriptEngine::run() {
// only send to nodes of type AudioMixer
if (node->getType() == NodeType::AudioMixer) {
// pack sequence number
quint16 sequence = _outgoingSequenceNumbers[node->getUUID()]++;
quint16 sequence = _outgoingInjectedAudioSequenceNumbers[node->getUUID()]++;
memcpy(sequenceAt, &sequence, sizeof(quint16));
printf("script engine audio sent %d\n", sequence);
// send audio packet
nodeList->writeDatagram(audioPacket, audioPacketSize, node);
}
@ -683,5 +683,5 @@ void ScriptEngine::include(const QString& includeFile) {
}
void ScriptEngine::nodeKilled(SharedNodePointer node) {
_outgoingSequenceNumbers.remove(node->getUUID());
_outgoingInjectedAudioSequenceNumbers.remove(node->getUUID());
}

View file

@ -148,7 +148,7 @@ private:
ScriptUUID _uuidLibrary;
AnimationCache _animationCache;
QHash<QUuid, quint16> _outgoingSequenceNumbers;
QHash<QUuid, quint16> _outgoingInjectedAudioSequenceNumbers;
};
#endif // hifi_ScriptEngine_h