diff --git a/autobuild.xml b/autobuild.xml
index 4468a1cf724bf560c9c5e21b3a3ee9cf003ddcfd..9583220c88520023a18c00d1fc2fb10047e325e5 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -476,11 +476,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>026311237049cebc083b35ccf92e9d301adea46cb707833e283b6ee4f83e4ca662c2b5e9a00b14673aaa4f2ce4051cf38877c0c27c8361d3604225dbc1db4c49</string>
+              <string>3a2e26f01656a6634023d83f2a53a36a373c61b6af1d00517543050a09826113a2f99121ece20c2c0b581aab9020aeb7cdfe972fa331ea94f3862556a70eae19</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.14.0_119.3.1_gf768881_chromium-119.0.6045.124.2234/dullahan-1.14.0_119.3.1_gf768881_chromium-119.0.6045.124-darwin64-2234.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54.2178/dullahan-1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54-darwin64-2178.tar.zst</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -490,11 +490,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>47b7cf28add3b59f7fe6aa9e7eb52ce65af6f656e47190cdf33703c65c84cc8ea494e38ab9b844aa764b87c9fb61cb344e430e0c7b8f1e171f0f284c32672397</string>
+              <string>ab9d290a61fb038e6c0ba9ce4efa5f431238e1ab9d4de2c28da1ad0114926af9b716db90cb216816ec8a1de3680d358913851e316d8df6b5eea5302989d9f3bc</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.14.0_119.3.1_gf768881_chromium-119.0.6045.124.2234/dullahan-1.14.0_119.3.1_gf768881_chromium-119.0.6045.124-linux64-2234.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54.2178/dullahan-1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54-linux64-2178.tar.zst</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -504,11 +504,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b9167b9a0fdd95aedd300a6f010986e16a9f43c46092be7a9b2d5e930df8c300d34b17e80d9108315ac4348ea02014624bbf123da9b7851785c0c393051c6940</string>
+              <string>e88cd99c9d71b2dd1297007bcfdac224d5401cdfadd7aeb069195392274559f7f63ee312061d3441ba7505a4e649ccea67f9d8f3f3c56c9cce638b35c29b6eb5</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.14.0_119.3.1_gf768881_chromium-119.0.6045.124.2234/dullahan-1.14.0_119.3.1_gf768881_chromium-119.0.6045.124-windows64-2234.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/103/packages/generic/dullahan/1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54.2178/dullahan-1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54-windows64-2178.tar.zst</string>
             </map>
             <key>name</key>
             <string>windows64</string>
@@ -521,7 +521,7 @@
         <key>copyright</key>
         <string>Copyright (c) 2017, Linden Research, Inc.</string>
         <key>version</key>
-        <string>1.14.0_119.3.1_gf768881_chromium-119.0.6045.124</string>
+        <string>1.12.4_118.4.1_g3dd6078_chromium-118.0.5993.54</string>
         <key>name</key>
         <string>dullahan</string>
         <key>description</key>
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index e20725579853b7245d81517a8ea8c01b62270b72..812e065aa57387e91aa82a84f5a0eab298c9f916 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -142,7 +142,7 @@ class LLAvatarAppearance : public LLCharacter
 	LLVector3			mHeadOffset; // current head position
 	LLAvatarJoint		*mRoot;
 
-	typedef boost::unordered_flat_map<std::string, LLJoint*> joint_map_t;
+	typedef boost::unordered_flat_map<std::string, LLJoint*, al::string_hash, std::equal_to<>> joint_map_t;
 	joint_map_t			mJointMap;
 
     typedef std::map<std::string, LLVector3> joint_state_map_t;
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 906f19203cfc6caa824586a2ffa604dc549431e5..5282900f9fc024d6cb6fba509b1570311983da6c 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -533,6 +533,9 @@ void LLVorbisDecodeState::flushBadFile()
 	{
 		LL_WARNS("AudioEngine") << "Flushing bad vorbis file from cache for " << mUUID << LL_ENDL;
 		mInFilep->remove();
+
+		delete mInFilep;
+		mInFilep = NULL;
 	}
 }
 
@@ -623,6 +626,9 @@ void LLAudioDecodeMgr::Impl::startMoreDecodes()
 
                 if (!decode_state)
                 {
+                    if (gAudiop)
+                        gAudiop->markSoundCorrupt(decode_id);
+
                     // Audio decode has errored
                     return decode_state;
                 }
@@ -789,6 +795,8 @@ void LLAudioDecodeMgr::processQueue()
 
 BOOL LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
 {
+	if (gAudiop && gAudiop->isCorruptSound(uuid))
+		return FALSE;
 	if (gAudiop && gAudiop->hasDecodedFile(uuid))
 	{
 		// Already have a decoded version, don't need to decode it.
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 0fa3de28008d002055f74575949b566fdca6c793..7d647d54e415b08e3528bd417ec8819783f7890f 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -642,6 +642,9 @@ bool LLAudioEngine::preloadSound(const LLUUID &uuid)
 {
 	LL_DEBUGS("AudioEngine")<<"( "<<uuid<<" )"<<LL_ENDL;
 
+	if (isCorruptSound(uuid))
+		return false;
+
 	getAudioData(uuid);	// We don't care about the return value, this is just to make sure
 									// that we have an entry, which will mean that the audio engine knows about this
 
@@ -1925,3 +1928,23 @@ bool LLAudioData::load()
 	mBufferp->mAudioDatap = this;
 	return true;
 }
+
+const U32 MAX_SOUND_RETRIES = 25;
+
+void LLAudioEngine::markSoundCorrupt(const LLUUID& sound_id)
+{
+	auto itr = mCorruptData.find(sound_id);
+	if (mCorruptData.end() == itr)
+		mCorruptData[sound_id] = 1;
+	else if (itr->second != MAX_SOUND_RETRIES)
+		itr->second += 1;
+}
+
+bool LLAudioEngine::isCorruptSound(const LLUUID& sound_id) const
+{
+	auto itr = mCorruptData.find(sound_id);
+	if (mCorruptData.end() == itr)
+		return false;
+
+	return itr->second == MAX_SOUND_RETRIES;
+}
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index d1c3dab9b3f1afc34f4b40281a8de26b9a634777..1171b63f150146e2a1c5dfc33846fd674e8d7087 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -43,6 +43,7 @@
 
 #include "lllistener.h"
 #include "boost/unordered/unordered_flat_map.hpp"
+#include "boost/unordered_map.hpp"
 
 const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
 const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;
@@ -51,7 +52,7 @@ const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;
 const F32 DEFAULT_MIN_DISTANCE = 2.0f;
 
 #define LL_MAX_AUDIO_CHANNELS 30
-#define LL_MAX_AUDIO_BUFFERS 40 // Some extra for preloading, maybe?
+#define LL_MAX_AUDIO_BUFFERS 60 // Some extra for preloading, maybe?
 
 class LLAudioSource;
 class LLAudioData;
@@ -258,6 +259,13 @@ class LLAudioEngine
 private:
 	void setDefaults();
 	LLStreamingAudioInterface *mStreamingAudioImpl;
+
+	boost::unordered_map<LLUUID,U32> mCorruptData;
+
+public:
+	void markSoundCorrupt(LLUUID const&);
+	bool isCorruptSound(LLUUID const&) const;
+
 };
 
 
diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp
index 4798ae05c0d96adfc7f30aad585a872f6330ad4f..075282051b04e4e2eb915d2d31dbd67bb38bb1a4 100644
--- a/indra/llaudio/llaudioengine_fmodstudio.cpp
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -44,7 +44,7 @@
 
 #include "sound_ids.h"
 
-const U32 EXTRA_SOUND_CHANNELS = 100;
+const U32 EXTRA_SOUND_CHANNELS = 10;
 
 FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels);
 
diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
index 45ef7910f702b5a3357037b67b365fbc39058634..817ddc509ba1a2c0a35705990d7ce7466cc2fcd2 100644
--- a/indra/llaudio/llstreamingaudio_fmodstudio.cpp
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp
@@ -36,33 +36,33 @@
 
 inline bool Check_FMOD_Stream_Error(FMOD_RESULT result, const char *string)
 {
-	if (result == FMOD_OK)
-		return false;
-	LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
-	return true;
+    if (result == FMOD_OK)
+        return false;
+    LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
+    return true;
 }
 
 class LLAudioStreamManagerFMODSTUDIO
 {
 public:
-	LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
-	FMOD::Channel* startStream();
-	bool stopStream(); // Returns true if the stream was successfully stopped.
+    LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url);
+    FMOD::Channel* startStream();
+    bool stopStream(); // Returns true if the stream was successfully stopped.
 
-	const std::string& getURL() 	{ return mInternetStreamURL; }
+    const std::string& getURL() 	{ return mInternetStreamURL; }
 
-	FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = nullptr, bool* starving = nullptr, bool* diskbusy = nullptr);
+    FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = nullptr, bool* starving = nullptr, bool* diskbusy = nullptr);
 protected:
-	FMOD::System* mSystem;
-	FMOD::ChannelGroup* mChannelGroup;
-	FMOD::Channel* mStreamChannel;
-	FMOD::Sound* mInternetStream;
-	bool mReady;
+    FMOD::System* mSystem;
+    FMOD::ChannelGroup* mChannelGroup;
+    FMOD::Channel* mStreamChannel;
+    FMOD::Sound* mInternetStream;
+    bool mReady;
 
-	std::string mInternetStreamURL;
+    std::string mInternetStreamURL;
 };
 
-LLMutex gWaveDataMutex;	//Just to be extra strict.
+LLMutex gWaveDataMutex;    //Just to be extra strict.
 const U32 WAVE_BUFFER_SIZE = 1024;
 U32 gWaveBufferMinSize = 0;
 F32 gWaveDataBuffer[WAVE_BUFFER_SIZE] = { 0.f };
@@ -70,392 +70,415 @@ U32 gWaveDataBufferSize = 0;
 
 FMOD_RESULT F_CALLBACK waveDataCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
 {
-	if (!length || !inchannels)
-		return FMOD_OK;
-	memcpy(outbuffer, inbuffer, length * inchannels * sizeof(float));
-
-	static std::vector<F32> local_buf;
-	if (local_buf.size() < length)
-		local_buf.resize(length, 0.f);
-
-	for (U32 i = 0; i < length; ++i)
-	{
-		F32 total = 0.f;
-		for (S32 j = 0; j < inchannels; ++j)
-		{
-			total += inbuffer[i*inchannels + j];
-		}
-		local_buf[i] = total / inchannels;
-	}
-
-	{
-		LLMutexLock lock(&gWaveDataMutex);
-
-		for (U32 i = length; i > 0; --i)
-		{
-			if (++gWaveDataBufferSize > WAVE_BUFFER_SIZE)
-			{
-				if (gWaveBufferMinSize)
-					memcpy(gWaveDataBuffer + WAVE_BUFFER_SIZE - gWaveBufferMinSize, gWaveDataBuffer, gWaveBufferMinSize * sizeof(float));
-				gWaveDataBufferSize = 1 + gWaveBufferMinSize;
-			}
-			gWaveDataBuffer[WAVE_BUFFER_SIZE - gWaveDataBufferSize] = local_buf[i - 1];
-		}
-	}
-	
-	return FMOD_OK;
+    if (!length || !inchannels)
+        return FMOD_OK;
+    memcpy(outbuffer, inbuffer, length * inchannels * sizeof(float));
+
+    static std::vector<F32> local_buf;
+    if (local_buf.size() < length)
+        local_buf.resize(length, 0.f);
+
+    for (U32 i = 0; i < length; ++i)
+    {
+        F32 total = 0.f;
+        for (S32 j = 0; j < inchannels; ++j)
+        {
+            total += inbuffer[i*inchannels + j];
+        }
+        local_buf[i] = total / inchannels;
+    }
+
+    {
+        LLMutexLock lock(&gWaveDataMutex);
+
+        for (U32 i = length; i > 0; --i)
+        {
+            if (++gWaveDataBufferSize > WAVE_BUFFER_SIZE)
+            {
+                if (gWaveBufferMinSize)
+                    memcpy(gWaveDataBuffer + WAVE_BUFFER_SIZE - gWaveBufferMinSize, gWaveDataBuffer, gWaveBufferMinSize * sizeof(float));
+                gWaveDataBufferSize = 1 + gWaveBufferMinSize;
+            }
+            gWaveDataBuffer[WAVE_BUFFER_SIZE - gWaveDataBufferSize] = local_buf[i - 1];
+        }
+    }
+    
+    return FMOD_OK;
 }
 
 //---------------------------------------------------------------------------
 // Internet Streaming
 //---------------------------------------------------------------------------
 LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) :
-	mSystem(system),
-	mCurrentInternetStreamp(nullptr),
-	mStreamDSP(nullptr),
-	mStreamGroup(nullptr),
-	mFMODInternetStreamChannelp(nullptr),
-	mGain(1.0f),
-	mMetaData(nullptr),
-	mNewMetadata(true)
+    mSystem(system),
+    mCurrentInternetStreamp(nullptr),
+    mStreamDSP(nullptr),
+    mStreamGroup(nullptr),
+    mFMODInternetStreamChannelp(nullptr),
+    mGain(1.0f),
+    mWasAlreadyPlaying(false),
+    mMetaData(nullptr),
+    mNewMetadata(true)
 {
-	FMOD_RESULT result;
+    // Number of milliseconds of audio to buffer for the audio card.
+    // Must be larger than the usual Second Life frame stutter time.
+    const U32 buffer_seconds = 10;		//sec
+    const U32 estimated_bitrate = 128;	//kbit/sec
+    Check_FMOD_Stream_Error(mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
 
-	// Number of milliseconds of audio to buffer for the audio card.
-	// Must be larger than the usual Second Life frame stutter time.
-	const U32 buffer_seconds = 10;		//sec
-	const U32 estimated_bitrate = 128;	//kbit/sec
-	result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
-	Check_FMOD_Stream_Error(result, "FMOD::System::setStreamBufferSize");
+    Check_FMOD_Stream_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
 
-	Check_FMOD_Stream_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup");
+    FMOD_DSP_DESCRIPTION dspdesc = { };
+    dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
+    strncpy(dspdesc.name, "Waveform", sizeof(dspdesc.name));
+    dspdesc.numoutputbuffers = 1;
+    dspdesc.read = &waveDataCallback; //Assign callback.
 
-	FMOD_DSP_DESCRIPTION dspdesc = { };
-	dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
-	strncpy(dspdesc.name, "Waveform", sizeof(dspdesc.name));
-	dspdesc.numoutputbuffers = 1;
-	dspdesc.read = &waveDataCallback; //Assign callback.
-
-	Check_FMOD_Stream_Error(system->createDSP(&dspdesc, &mStreamDSP), "FMOD::System::createDSP");
+    Check_FMOD_Stream_Error(system->createDSP(&dspdesc, &mStreamDSP), "FMOD::System::createDSP");
 }
 
 LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO()
 {
-	stop();
-	for (U32 i = 0; i < 100; ++i)
-	{
-		if (releaseDeadStreams())
-			break;
-		ms_sleep(10);
-	}
-
-	cleanupWaveData();
+    stop();
+    for (U32 i = 0; i < 100; ++i)
+    {
+        if (releaseDeadStreams())
+            break;
+        ms_sleep(10);
+    }
+
+    cleanupWaveData();
 }
 
 void LLStreamingAudio_FMODSTUDIO::start(const std::string& url)
 {
-	//if (!mInited)
-	//{
-	//	LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
-	//	return;
-	//}
-
-	// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
-	stop();
-
-	if (!url.empty())
-	{
-		if(mDeadStreams.empty())
-		{
-			LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
-			mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
-			mURL = url;
-			mMetaData = new LLSD;
-		}
-		else
-		{
-			LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
-			mPendingURL = url;
-		}
-	}
-	else
-	{
-		LL_INFOS() << "Set internet stream to null" << LL_ENDL;
-		mURL.clear();
-	}
+    //if (!mInited)
+    //{
+    //	LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL;
+    //	return;
+    //}
+
+    // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
+    stop();
+
+    if (!url.empty())
+    {
+        if (mDeadStreams.empty())
+        {
+            LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
+            mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url);
+            mURL = url;
+            mMetaData = new LLSD;
+        }
+        else
+        {
+            LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
+            mPendingURL = url;
+        }
+    }
+    else
+    {
+        LL_INFOS() << "Set internet stream to null" << LL_ENDL;
+        mURL.clear();
+    }
 }
 
 enum utf_endian_type_t
 {
-	UTF16LE,
-	UTF16BE,
-	UTF16
+    UTF16LE,
+    UTF16BE,
+    UTF16
 };
 
 std::string utf16input_to_utf8(unsigned char* input, U32 len, utf_endian_type_t type)
 {
-	if (type == UTF16)
-	{
-		type = UTF16BE;	//Default
-		if (len > 2)
-		{
-			//Parse and strip BOM.
-			if ((input[0] == 0xFE && input[1] == 0xFF) || 
-				(input[0] == 0xFF && input[1] == 0xFE))
-			{
-				input += 2;
-				len -= 2;
-				type = input[0] == 0xFE ? UTF16BE : UTF16LE;
-			}
-		}
-	}
-	llutf16string out_16((llutf16string::value_type*)input, len / 2);
-	if (len % 2)
-	{
-		out_16.push_back((input)[len - 1] << 8);
-	}
-	if (type == UTF16BE)
-	{
-		for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i)
-		{
-			llutf16string::value_type v = *i;
-			*i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
-		}
-	}
-	return utf16str_to_utf8str(out_16);
+    if (type == UTF16)
+    {
+        type = UTF16BE;    //Default
+        if (len > 2)
+        {
+            //Parse and strip BOM.
+            if ((input[0] == 0xFE && input[1] == 0xFF) || 
+                (input[0] == 0xFF && input[1] == 0xFE))
+            {
+                input += 2;
+                len -= 2;
+                type = input[0] == 0xFE ? UTF16BE : UTF16LE;
+            }
+        }
+    }
+    llutf16string out_16((llutf16string::value_type*)input, len / 2);
+    if (len % 2)
+    {
+        out_16.push_back((input)[len - 1] << 8);
+    }
+    if (type == UTF16BE)
+    {
+        for (llutf16string::iterator i = out_16.begin(); i < out_16.end(); ++i)
+        {
+            llutf16string::value_type v = *i;
+            *i = ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8);
+        }
+    }
+    return utf16str_to_utf8str(out_16);
 }
 
 void LLStreamingAudio_FMODSTUDIO::update()
 {
-	if (!releaseDeadStreams())
-	{
-		llassert_always(mCurrentInternetStreamp == NULL);
-		return;
-	}
-
-	if(!mPendingURL.empty())
-	{
-		llassert_always(mCurrentInternetStreamp == NULL);
-		LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
-		mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL);
-		mURL = mPendingURL;
-		mMetaData = new LLSD;
-		mPendingURL.clear();
-	}
-
-	// Don't do anything if there are no streams playing
-	if (!mCurrentInternetStreamp)
-	{
-		return;
-	}
-
-	unsigned int progress;
-	bool starving;
-	bool diskbusy;
-	FMOD_OPENSTATE open_state;
-	FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
-
-	if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
-	{
-		stop();
-		return;
-	}
-	else if (open_state == FMOD_OPENSTATE_READY)
-	{
-		// Stream is live
-
-		// start the stream if it's ready
-		if (!mFMODInternetStreamChannelp &&
-			(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
-		{
-			// Reset volume to previously set volume
-			setGain(getGain());
-			if (mStreamDSP)
-			{
-				Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->addDSP(FMOD_CHANNELCONTROL_DSP_TAIL, mStreamDSP), "FMOD::Channel::addDSP");
-			}
-			Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
-		}
-	}
-
-
-	if(mFMODInternetStreamChannelp)
-	{
-		if(!mMetaData)
-			mMetaData = new LLSD;
-
-		FMOD::Sound *sound = nullptr;
-
-		if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
-		{
-			FMOD_TAG tag;
-			S32 tagcount, dirtytagcount;
-			if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
-			{
-				mMetaData->clear();
-				mNewMetadata = true;
-
-				for(S32 i = 0; i < tagcount; ++i)
-				{
-					if(sound->getTag(nullptr, i, &tag)!=FMOD_OK)
-						continue;
-
-					std::string name = tag.name;
-					switch(tag.type)	//Crappy tag translate table.
-					{
-					case(FMOD_TAGTYPE_ID3V2):
-						if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE";
-						else if(name == "TPE1") name = "ARTIST";
-						break;
-					case(FMOD_TAGTYPE_ASF):
-						if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE";
-						else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST";
-						break;
-					case(FMOD_TAGTYPE_FMOD):
-						if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change"))
-						{
-							LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
-							Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency");
-						}
-						continue;
-					default:
-						if (!LLStringUtil::compareInsensitive(name, "TITLE") ||
-							!LLStringUtil::compareInsensitive(name, "ARTIST"))
-							LLStringUtil::toUpper(name);
-						break;
-					}
-
-					switch(tag.datatype)
-					{
-						case(FMOD_TAGDATATYPE_INT):
-							(*mMetaData)[name]=*(LLSD::Integer*)(tag.data);
-							LL_INFOS() << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
-							break;
-						case(FMOD_TAGDATATYPE_FLOAT):
-							(*mMetaData)[name]=*(LLSD::Real*)(tag.data);
-							LL_INFOS() << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
-							break;
-						case(FMOD_TAGDATATYPE_STRING):
-						{
-							std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
-							if (out.length() && out[out.size() - 1] == 0)
-								out.erase(out.size() - 1);
-							(*mMetaData)[name]=out;
-							LL_INFOS() << tag.name << "(RAW): " << out << LL_ENDL;
-						}
-							break;
-						case(FMOD_TAGDATATYPE_STRING_UTF8) :
-						{
-							U8 offs = 0;
-							if (tag.datalen > 3 && ((unsigned char*)tag.data)[0] == 0xEF && ((unsigned char*)tag.data)[1] == 0xBB && ((unsigned char*)tag.data)[2] == 0xBF)
-								offs = 3;
-							std::string out((char*)tag.data + offs, tag.datalen - offs);
-							if (out.length() && out[out.size() - 1] == 0)
-								out.erase(out.size() - 1);
-							(*mMetaData)[name] = out;
-							LL_INFOS() << tag.name << "(UTF8): " << out << LL_ENDL;
-						}
-							break;
-						case(FMOD_TAGDATATYPE_STRING_UTF16):
-						{
-							std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16);
-							if (out.length() && out[out.size() - 1] == 0)
-								out.erase(out.size() - 1);
-							(*mMetaData)[name] = out;
-							LL_INFOS() << tag.name << "(UTF16): " << out << LL_ENDL;
-						}
-							break;
-						case(FMOD_TAGDATATYPE_STRING_UTF16BE):
-						{
-							std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16BE);
-							if (out.length() && out[out.size() - 1] == 0)
-								out.erase(out.size() - 1);
-							(*mMetaData)[name] = out;
-							LL_INFOS() << tag.name << "(UTF16BE): " << out << LL_ENDL;
-						}
-						default:
-							break;
-					}
-				}
-			}
-			static bool was_starved = false;
-			if(starving)
-			{
-				bool paused = false;
-				if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
-				{
-					LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
-					LL_INFOS() << "  (diskbusy="<<diskbusy<<")" << LL_ENDL;
-					LL_INFOS() << "  (progress="<<progress<<")" << LL_ENDL;
-					Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
-				}
-				was_starved = true;
-			}
-			else if(progress > 80 && was_starved)
-			{
-				was_starved = false;
-				Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
-			}
-		}
-	}
+    if (!releaseDeadStreams())
+    {
+        llassert_always(mCurrentInternetStreamp == NULL);
+        return;
+    }
+
+    if (!mPendingURL.empty())
+    {
+        llassert_always(mCurrentInternetStreamp == NULL);
+        LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
+        mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL);
+        mURL = mPendingURL;
+        mMetaData = new LLSD;
+        mPendingURL.clear();
+    }
+
+    // Don't do anything if there are no streams playing
+    if (!mCurrentInternetStreamp)
+    {
+        return;
+    }
+
+    unsigned int progress;
+    bool starving;
+    bool diskbusy;
+    FMOD_OPENSTATE open_state;
+
+    if (Check_FMOD_Stream_Error(mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy), "FMOD::Sound::getOpenState")  || open_state == FMOD_OPENSTATE_ERROR)
+    {
+        LL_WARNS() << "Internet stream openstate error: open_state = " << open_state << " - progress = " << progress << " - starving = " << starving << " - diskbusy = " << diskbusy << LL_ENDL;
+        bool was_playing = mWasAlreadyPlaying;
+        stop();
+        // Try to restart previously playing stream on socket error
+        if (open_state == FMOD_OPENSTATE_ERROR && was_playing)
+        {
+            LL_WARNS() << "Stream was playing before - trying to restart" << LL_ENDL;
+            start(mURL);
+        }
+        return;
+    }
+    else if (open_state == FMOD_OPENSTATE_READY)
+    {
+        // Stream is live
+
+        // start the stream if it's ready
+        if (!mFMODInternetStreamChannelp &&
+            (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
+        {
+            // Reset volume to previously set volume
+            setGain(getGain());
+            if (mStreamDSP)
+            {
+                Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->addDSP(FMOD_CHANNELCONTROL_DSP_TAIL, mStreamDSP), "FMOD::Channel::addDSP");
+            }
+            Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
+            mWasAlreadyPlaying = true;
+        }
+    }
+    else if (open_state == FMOD_OPENSTATE_PLAYING)
+    {
+        if (!mWasAlreadyPlaying)
+        {
+            mWasAlreadyPlaying = true;
+        }
+    }
+
+
+    if (mFMODInternetStreamChannelp)
+    {
+        if(!mMetaData)
+            mMetaData = new LLSD;
+
+        FMOD::Sound *sound = nullptr;
+
+        if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
+        {
+            FMOD_TAG tag;
+            S32 tagcount, dirtytagcount;
+            if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
+            {
+                mMetaData->clear();
+                mNewMetadata = true;
+
+                for(S32 i = 0; i < tagcount; ++i)
+                {
+                    if(sound->getTag(nullptr, i, &tag)!=FMOD_OK)
+                        continue;
+
+                    std::string name = tag.name;
+                    switch (tag.type)
+                    {
+                        case FMOD_TAGTYPE_ID3V2:
+                        {
+	                        if (!LLStringUtil::compareInsensitive(name, "TIT2")) name = "TITLE";
+	                        else if(!LLStringUtil::compareInsensitive(name, "TPE1")) name = "ARTIST";
+                            break;
+                        }
+                        case FMOD_TAGTYPE_ASF:
+                        {
+	                        if (!LLStringUtil::compareInsensitive(name, "Title")) name = "TITLE";
+	                        else if (!LLStringUtil::compareInsensitive(name, "WM/AlbumArtist")) name = "ARTIST";
+                            break;
+                        }
+                        case FMOD_TAGTYPE_VORBISCOMMENT:
+                        {
+	                            if (!LLStringUtil::compareInsensitive(name, "title")) name = "TITLE";
+	                            else if (!LLStringUtil::compareInsensitive(name, "artist")) name = "ARTIST";
+                            break;
+                        }
+                        case FMOD_TAGTYPE_FMOD:
+                        {
+	                        if (!LLStringUtil::compareInsensitive(name, "Sample Rate Change"))
+                            {
+                                LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL;
+	                            Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)), "FMOD::Channel::setFrequency");
+                            }
+                            continue;
+                        }
+                        default:
+	                        if (!LLStringUtil::compareInsensitive(name, "TITLE") ||
+	                            !LLStringUtil::compareInsensitive(name, "ARTIST"))
+	                            LLStringUtil::toUpper(name);
+                            break;
+                    }
+                    switch (tag.datatype)
+                    {
+                        case(FMOD_TAGDATATYPE_INT):
+                            (*mMetaData)[name]=*(LLSD::Integer*)(tag.data);
+                            LL_INFOS() << tag.name << ": " << *(int*)(tag.data) << LL_ENDL;
+                            break;
+                        case(FMOD_TAGDATATYPE_FLOAT):
+                            (*mMetaData)[name]=*(LLSD::Real*)(tag.data);
+                            LL_INFOS() << tag.name << ": " << *(float*)(tag.data) << LL_ENDL;
+                            break;
+                        case(FMOD_TAGDATATYPE_STRING):
+                        {
+                            std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
+                            if (out.length() && out[out.size() - 1] == 0)
+                                out.erase(out.size() - 1);
+                            (*mMetaData)[name]=out;
+                            LL_INFOS() << tag.name << "(RAW): " << out << LL_ENDL;
+                            break;
+                        }
+                        case(FMOD_TAGDATATYPE_STRING_UTF8) :
+                        {
+                            U8 offs = 0;
+                            if (tag.datalen > 3 && ((unsigned char*)tag.data)[0] == 0xEF && ((unsigned char*)tag.data)[1] == 0xBB && ((unsigned char*)tag.data)[2] == 0xBF)
+                                offs = 3;
+                            std::string out((char*)tag.data + offs, tag.datalen - offs);
+                            if (out.length() && out[out.size() - 1] == 0)
+                                out.erase(out.size() - 1);
+                            (*mMetaData)[name] = out;
+                            LL_INFOS() << tag.name << "(UTF8): " << out << LL_ENDL;
+                            break;
+                        }
+                        case(FMOD_TAGDATATYPE_STRING_UTF16):
+                        {
+                            std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16);
+                            if (out.length() && out[out.size() - 1] == 0)
+                                out.erase(out.size() - 1);
+                            (*mMetaData)[name] = out;
+                            LL_INFOS() << tag.name << "(UTF16): " << out << LL_ENDL;
+                            break;
+                        }
+                        case(FMOD_TAGDATATYPE_STRING_UTF16BE):
+                        {
+                            std::string out = utf16input_to_utf8((unsigned char*)tag.data, tag.datalen, UTF16BE);
+                            if (out.length() && out[out.size() - 1] == 0)
+                                out.erase(out.size() - 1);
+                            (*mMetaData)[name] = out;
+                            LL_INFOS() << tag.name << "(UTF16BE): " << out << LL_ENDL;
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            if (starving)
+            {
+                bool paused = false;
+                if (!Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->getPaused(&paused), "FMOD:Channel::getPaused") && !paused)
+                {
+                    LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
+                    LL_INFOS() << "  (diskbusy=" << diskbusy << ")" << LL_ENDL;
+                    LL_INFOS() << "  (progress=" << progress << ")" << LL_ENDL;
+                    Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
+                }
+            }
+            else if(progress > 80)
+            {
+                Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
+            }
+        }
+    }
 }
 
 void LLStreamingAudio_FMODSTUDIO::stop()
 {
-	mPendingURL.clear();
-
-	if(mMetaData)
-	{
-		delete mMetaData;
-		mMetaData = nullptr;
-	}
-	
-	if (mFMODInternetStreamChannelp)
-	{
-		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
-		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
-		if (mStreamDSP)
-		{
-			Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->removeDSP(mStreamDSP), "FMOD::Channel::removeDSP");
-		}
-		mFMODInternetStreamChannelp = nullptr;
-	}
-
-	if (mCurrentInternetStreamp)
-	{
+    mPendingURL.clear();
+    mWasAlreadyPlaying = false;
+
+    if(mMetaData)
+    {
+        delete mMetaData;
+        mMetaData = nullptr;
+    }
+    
+    if (mFMODInternetStreamChannelp)
+    {
+        Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
+        Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
+        if (mStreamDSP)
+        {
+            Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->removeDSP(mStreamDSP), "FMOD::Channel::removeDSP");
+        }
+        mFMODInternetStreamChannelp = nullptr;
+    }
+
+    if (mCurrentInternetStreamp)
+    {
         LL_INFOS("FMOD") << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
-		if (mCurrentInternetStreamp->stopStream())
-		{
-			delete mCurrentInternetStreamp;
-		}
-		else
-		{
+        if (mCurrentInternetStreamp->stopStream())
+        {
+            delete mCurrentInternetStreamp;
+        }
+        else
+        {
             LL_WARNS("FMOD") << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL;
-			mDeadStreams.push_back(mCurrentInternetStreamp);
-		}
-		mCurrentInternetStreamp = nullptr;
-	}
+            mDeadStreams.push_back(mCurrentInternetStreamp);
+        }
+        mCurrentInternetStreamp = nullptr;
+    }
 }
 
 void LLStreamingAudio_FMODSTUDIO::pause(S32 pauseopt)
 {
-	if (pauseopt < 0)
-	{
-		pauseopt = mCurrentInternetStreamp ? 1 : 0;
-	}
-
-	if (pauseopt)
-	{
-		if (mCurrentInternetStreamp)
-		{
-            LL_INFOS("FMOD") << "Pausing internet stream" << LL_ENDL;
-			stop();
-		}
-	}
-	else
-	{
-		start(getURL());
-	}
+    if (pauseopt < 0)
+    {
+        pauseopt = mCurrentInternetStreamp ? 1 : 0;
+    }
+
+    if (pauseopt)
+    {
+        if (mCurrentInternetStreamp)
+        {
+            stop();
+        }
+    }
+    else
+    {
+        start(getURL());
+    }
 }
 
 
@@ -463,212 +486,212 @@ void LLStreamingAudio_FMODSTUDIO::pause(S32 pauseopt)
 // doesn't necessarily mean audio is coming out of the speakers.
 int LLStreamingAudio_FMODSTUDIO::isPlaying()
 {
-	if (mCurrentInternetStreamp)
-	{
-		return 1; // Active and playing
-	}
-	else if (!mURL.empty() || !mPendingURL.empty())
-	{
-		return 2; // "Paused"
-	}
-	else
-	{
-		return 0;
-	}
+    if (mCurrentInternetStreamp)
+    {
+        return 1; // Active and playing
+    }
+    else if (!mURL.empty() || !mPendingURL.empty())
+    {
+        return 2; // "Paused"
+    }
+    else
+    {
+        return 0;
+    }
 }
 
 
 F32 LLStreamingAudio_FMODSTUDIO::getGain()
 {
-	return mGain;
+    return mGain;
 }
 
 
 std::string LLStreamingAudio_FMODSTUDIO::getURL()
 {
-	return mURL;
+    return mURL;
 }
 
 
 void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol)
 {
-	mGain = vol;
+    mGain = vol;
 
-	if (mFMODInternetStreamChannelp)
-	{
-		vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here?
+    if (mFMODInternetStreamChannelp)
+    {
+        vol = llclamp(vol * vol, 0.f, 1.f);	//should vol be squared here?
 
-		Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
-	}
+        Check_FMOD_Stream_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
+    }
 }
 
 bool LLStreamingAudio_FMODSTUDIO::hasNewMetaData()
 {
-	if (mCurrentInternetStreamp && mNewMetadata)
-	{
-		mNewMetadata = false;
-		return true;
-	}
-	else
-	{
-		return false;
-	}
+    if (mCurrentInternetStreamp && mNewMetadata)
+    {
+        mNewMetadata = false;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
 }
 
 /* virtual */
 bool LLStreamingAudio_FMODSTUDIO::getWaveData(float* arr, S32 count, S32 stride/*=1*/)
 {
-	if (count > (WAVE_BUFFER_SIZE / 2))
-		LL_ERRS("AudioImpl") << "Count=" << count << " exceeds WAVE_BUFFER_SIZE/2=" << WAVE_BUFFER_SIZE << LL_ENDL;
-
-	if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
-		return false;
-
-	bool muted = false;
-	FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted);
-	if(res != FMOD_OK || muted)
-		return false;
-	{
-		U32 buff_size;
-		{
-			LLMutexLock lock(&gWaveDataMutex);
-			gWaveBufferMinSize = count;
-			buff_size = gWaveDataBufferSize;
-			if (!buff_size)
-				return false;
-			memcpy(arr, gWaveDataBuffer + WAVE_BUFFER_SIZE - buff_size, llmin(U32(count), buff_size) * sizeof(float));
-		}
-		if (buff_size < U32(count))
-			memset(arr + buff_size, 0, (count - buff_size) * sizeof(float));
-	}
-	return true;
+    if (count > (WAVE_BUFFER_SIZE / 2))
+        LL_ERRS("AudioImpl") << "Count=" << count << " exceeds WAVE_BUFFER_SIZE/2=" << WAVE_BUFFER_SIZE << LL_ENDL;
+
+    if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
+        return false;
+
+    bool muted = false;
+    FMOD_RESULT res = mFMODInternetStreamChannelp->getMute(&muted);
+    if(res != FMOD_OK || muted)
+        return false;
+    {
+        U32 buff_size;
+        {
+            LLMutexLock lock(&gWaveDataMutex);
+            gWaveBufferMinSize = count;
+            buff_size = gWaveDataBufferSize;
+            if (!buff_size)
+                return false;
+            memcpy(arr, gWaveDataBuffer + WAVE_BUFFER_SIZE - buff_size, llmin(U32(count), buff_size) * sizeof(float));
+        }
+        if (buff_size < U32(count))
+            memset(arr + buff_size, 0, (count - buff_size) * sizeof(float));
+    }
+    return true;
 }
 
 ///////////////////////////////////////////////////////
 // manager of possibly-multiple internet audio streams
 
 LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) :
-	mSystem(system),
-	mChannelGroup(group),
-	mStreamChannel(nullptr),
-	mInternetStream(nullptr),
-	mReady(false),
-	mInternetStreamURL(url)
+    mSystem(system),
+    mChannelGroup(group),
+    mStreamChannel(nullptr),
+    mInternetStream(nullptr),
+    mReady(false),
+    mInternetStreamURL(url)
 {
-	FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, nullptr, &mInternetStream);
+    FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, nullptr, &mInternetStream);
 
-	if (result!= FMOD_OK)
-	{
+    if (result != FMOD_OK)
+    {
         LL_WARNS("FMOD") << "Couldn't open fmod stream, error "
-			<< FMOD_ErrorString(result)
-			<< LL_ENDL;
-		mReady = false;
-		return;
-	}
+            << FMOD_ErrorString(result)
+            << LL_ENDL;
+        mReady = false;
+        return;
+    }
 
-	mReady = true;
+    mReady = true;
 }
 
 FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream()
 {
-	// We need a live and opened stream before we try and play it.
-	FMOD_OPENSTATE open_state;
-	if (!mInternetStream  || (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY))
-	{
+    // We need a live and opened stream before we try and play it.
+    FMOD_OPENSTATE open_state;
+    if (!mInternetStream || Check_FMOD_Stream_Error(getOpenState(open_state), "FMOD::Sound::getOpenState") || open_state != FMOD_OPENSTATE_READY)
+    {
         LL_WARNS("FMOD") << "No internet stream to start playing!" << LL_ENDL;
-		return nullptr;
-	}
+        return nullptr;
+    }
 
-	if(mStreamChannel)
-		return mStreamChannel;	//Already have a channel for this stream.
+    if (mStreamChannel)
+        return mStreamChannel;	//Already have a channel for this stream.
 
-	Check_FMOD_Stream_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
-	return mStreamChannel;
+    Check_FMOD_Stream_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound");
+    return mStreamChannel;
 }
 
 bool LLAudioStreamManagerFMODSTUDIO::stopStream()
 {
-	if (mInternetStream)
-	{
-		bool close = true;
-		FMOD_OPENSTATE open_state;
-		if (getOpenState(open_state) == FMOD_OK)
-		{
-			switch (open_state)
-			{
-			case FMOD_OPENSTATE_CONNECTING:
-				close = false;
-				break;
-			default:
-				close = true;
-			}
-		}
-
-		if (close && mInternetStream->release() == FMOD_OK)
-		{
-			mStreamChannel = nullptr;
-			mInternetStream = nullptr;
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-	else
-	{
-		return true;
-	}
+    if (mInternetStream)
+    {
+        bool close = true;
+        FMOD_OPENSTATE open_state;
+        if (getOpenState(open_state) == FMOD_OK)
+        {
+            switch (open_state)
+            {
+            case FMOD_OPENSTATE_CONNECTING:
+                close = false;
+                break;
+            default:
+                close = true;
+            }
+        }
+
+        if (close && mInternetStream->release() == FMOD_OK)
+        {
+            mStreamChannel = nullptr;
+            mInternetStream = nullptr;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    else
+    {
+        return true;
+    }
 }
 
 FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
 {
-	if (!mInternetStream)
-		return FMOD_ERR_INVALID_HANDLE;
-	FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
-	Check_FMOD_Stream_Error(result, "FMOD::Sound::getOpenState");
-	return result;
+    if (!mInternetStream)
+        return FMOD_ERR_INVALID_HANDLE;
+    FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
+    Check_FMOD_Stream_Error(result, "FMOD::Sound::getOpenState");
+    return result;
 }
 
 void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
 {
-	Check_FMOD_Stream_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
-	FMOD_ADVANCEDSETTINGS settings = { };
-	settings.cbSize=sizeof(settings);
-	settings.defaultDecodeBufferSize = decodebuffertime;//ms
-	Check_FMOD_Stream_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
+    Check_FMOD_Stream_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
+    FMOD_ADVANCEDSETTINGS settings = { };
+    settings.cbSize = sizeof(settings);
+    settings.defaultDecodeBufferSize = decodebuffertime;//ms
+    Check_FMOD_Stream_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
 }
 
 bool LLStreamingAudio_FMODSTUDIO::releaseDeadStreams()
 {
-	// Kill dead internet streams, if possible
-	for (auto iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
-	{
-		LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
-		if (streamp->stopStream())
-		{
-			LL_INFOS() << "Closed dead stream" << LL_ENDL;
-			delete streamp;
-			mDeadStreams.erase(iter++);
-		}
-		else
-		{
-			++iter;
-		}
-	}
-
-	return mDeadStreams.empty();
+    // Kill dead internet streams, if possible
+    for (auto iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
+    {
+        LLAudioStreamManagerFMODSTUDIO *streamp = *iter;
+        if (streamp->stopStream())
+        {
+            LL_INFOS() << "Closed dead stream" << LL_ENDL;
+            delete streamp;
+            iter = mDeadStreams.erase(iter);
+        }
+        else
+        {
+            ++iter;
+        }
+    }
+
+    return mDeadStreams.empty();
 }
 
 void LLStreamingAudio_FMODSTUDIO::cleanupWaveData()
 {
-	if (mStreamGroup)
-	{
-		Check_FMOD_Stream_Error(mStreamGroup->release(), "FMOD::ChannelGroup::release");
-		mStreamGroup = nullptr;
-	}
-	
-	if(mStreamDSP)
-		Check_FMOD_Stream_Error(mStreamDSP->release(), "FMOD::DSP::release");
-	mStreamDSP = nullptr;
+    if (mStreamGroup)
+    {
+        Check_FMOD_Stream_Error(mStreamGroup->release(), "FMOD::ChannelGroup::release");
+        mStreamGroup = nullptr;
+    }
+    
+    if(mStreamDSP)
+        Check_FMOD_Stream_Error(mStreamDSP->release(), "FMOD::DSP::release");
+    mStreamDSP = nullptr;
 }
diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h
index ea1b5c81a8357b5bfaf7699283b47fbb5d11b724..ccfc16961f6de1c243b624da334819b65fea6fd6 100644
--- a/indra/llaudio/llstreamingaudio_fmodstudio.h
+++ b/indra/llaudio/llstreamingaudio_fmodstudio.h
@@ -82,6 +82,8 @@ class LLStreamingAudio_FMODSTUDIO final : public LLStreamingAudioInterface
 	std::string mPendingURL;
 	F32 mGain;
 
+    bool mWasAlreadyPlaying;
+
 	LLSD *mMetaData;
 	bool mNewMetadata;
 };
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 636083787d86c1d3e2bc368ff52ce554befa9d0a..1b2427c633406545fd03f500c5722333e973253f 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -499,7 +499,7 @@ namespace
 	}
 
 
-	typedef boost::unordered_flat_map<std::string, LLError::ELevel> LevelMap;
+	typedef boost::unordered_flat_map<std::string, LLError::ELevel, al::string_hash, std::equal_to<>> LevelMap;
 	typedef std::vector<LLError::RecorderPtr> Recorders;
 	typedef std::vector<LLError::CallSite*> CallSiteVector;
 
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index f219dce9fcd0e1134a04194825d076ef981e1466..25320fb683a95c58a1472a6db824e8bbfd1290ab 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -265,7 +265,7 @@ namespace LLInitParam
 	private:
 		struct Inaccessable{};
 	public:
-		typedef boost::unordered_flat_map<std::string, T> value_name_map_t;
+		typedef boost::unordered_flat_map<std::string, T, al::string_hash, std::equal_to<>> value_name_map_t;
 		typedef Inaccessable name_t;
 		typedef TypeValues<T> type_value_t;
 		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t;
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index e420e4a8107874d258f1278507a7ec77c4dbca5b..49a73d3b074d9eb6040832f1fb87a9cbe489cf05 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -95,7 +95,7 @@ class LLSettingsBase :
     };
     // Contains settings' names (map key), related shader id-key and default
     // value for revert in case we need to reset shader (no need to search each time)
-    typedef boost::unordered_flat_map<std::string, DefaultParam>  parammapping_t;
+    typedef boost::unordered_flat_map<std::string, DefaultParam, al::string_hash, std::equal_to<>>  parammapping_t;
 
     typedef PTR_NAMESPACE::shared_ptr<LLSettingsBase> ptr_t;
 
@@ -329,7 +329,7 @@ class LLSettingsBase :
     LLSettingsBase();
     LLSettingsBase(const LLSD setting);
 
-    typedef boost::unordered_flat_set<std::string>   stringset_t;
+    typedef boost::unordered_flat_set<std::string, al::string_hash, std::equal_to<>>   stringset_t;
     
     // combining settings objects. Customize for specific setting types
     virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix);
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 366ce79381411c0b3e1331a39345ed6c066b4142..1c142502abc2a54a2d82a70602b23beab57311fc 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -185,7 +185,7 @@ typedef std::set<LLUUID>					AskQueue;
 typedef std::list<PendingReply*>			ReplyQueue;
 typedef std::map<LLUUID,U32>				PendingQueue;
 typedef boost::unordered_flat_map<LLUUID, LLCacheNameEntry*> Cache;
-typedef boost::unordered_flat_map<std::string, LLUUID> 		ReverseCache;
+typedef boost::unordered_flat_map<std::string, LLUUID, al::string_hash, std::equal_to<>> 		ReverseCache;
 
 class LLCacheName::Impl
 {
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index bca5960eb17d90e53a167c382b7e90c4a54d7c62..e58b11af7b42f8bc5c1e2d1a964462fcc63dce3e 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -84,10 +84,8 @@ class LLTextureEntry final
 	LLTextureEntry();
 	LLTextureEntry(const LLUUID& tex_id);
 	LLTextureEntry(const LLTextureEntry &rhs);
-    LLTextureEntry(LLTextureEntry&& rhs) noexcept;
 
 	LLTextureEntry& operator=(const LLTextureEntry &rhs);
-    LLTextureEntry& operator=(LLTextureEntry&& rhs) noexcept;
     ~LLTextureEntry();
 
 	bool operator==(const LLTextureEntry &rhs) const;
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c45be78039d2798bb98311e8f287f5ab30952eec..32f900105439a49465b50dea4b226e4936cd0fac 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -17569,7 +17569,7 @@
     <key>Type</key>
     <string>U32</string>
     <key>Value</key>
-    <integer>4000</integer>
+    <integer>7000</integer>
   </map>
   <key>DisablePrecacheDelayAfterTeleporting</key>
   <map>
diff --git a/indra/newview/llfloatermessagelog.h b/indra/newview/llfloatermessagelog.h
index a1f6edcf96b3fbd6d54059787aca85f30e33b7c6..ece7665ded2ca5c45a55b7b16e5dfdf5dfc463da 100644
--- a/indra/newview/llfloatermessagelog.h
+++ b/indra/newview/llfloatermessagelog.h
@@ -37,7 +37,7 @@ class LLFloaterMessageLog;
 typedef boost::circular_buffer<LogPayload> LogPayloadList;
 typedef std::shared_ptr<LLEasyMessageLogEntry> FloaterMessageItem;
 typedef std::vector<FloaterMessageItem> FloaterMessageList;
-typedef boost::container::flat_map<U64, FloaterMessageItem> HTTPConvoMap;
+typedef boost::unordered_map<U64, FloaterMessageItem> HTTPConvoMap;
 
 class LLMessageLogFilter
 {
@@ -51,8 +51,8 @@ class LLMessageLogFilter
 	std::string asString() const { return mInputString; }
 
 	//these should probably be unordered_sets
-	boost::container::flat_set<std::string> mPositiveNames;
-	boost::container::flat_set<std::string> mNegativeNames;
+	boost::unordered_flat_set<std::string, al::string_hash, std::equal_to<>> mPositiveNames;
+	boost::unordered_flat_set<std::string, al::string_hash, std::equal_to<>> mNegativeNames;
 
 protected:
 	std::string mInputString;
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 1792af64f978a3d4e958e354d9c3ec91cfd43732..ca9f210f67734f61ddadd6aaafb6db6692f56567 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -250,8 +250,12 @@ BOOL LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_da
 	role_list_t::const_iterator rit = mRoles.find(role_id);
 	if (rit != mRoles.end())
 	{
-		role_data = (*rit).second->getRoleData();
-		return TRUE;
+		auto& role_datap = rit->second;
+		if (role_datap)
+		{
+			role_data = role_datap->getRoleData();
+			return TRUE;
+		}
 	}
 
 	// This role must not exist.
@@ -1451,11 +1455,11 @@ LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
 {
 	LLGroupMgrGroupData* group_datap = NULL;
 
-	group_map_t::iterator existing_group = LLGroupMgr::getInstance()->mGroups.find(id);
-	if (existing_group == LLGroupMgr::getInstance()->mGroups.end())
+	group_map_t::iterator existing_group = mGroups.find(id);
+	if (existing_group == mGroups.end())
 	{
 		group_datap = new LLGroupMgrGroupData(id);
-		LLGroupMgr::getInstance()->addGroup(group_datap);
+		addGroup(group_datap);
 	}
 	else
 	{
@@ -1472,8 +1476,8 @@ LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
 
 bool LLGroupMgr::hasPendingPropertyRequest(const LLUUID & id)
 {
-    properties_request_map_t::iterator existing_req = LLGroupMgr::getInstance()->mPropRequests.find(id);
-    if (existing_req != LLGroupMgr::getInstance()->mPropRequests.end())
+    properties_request_map_t::iterator existing_req = mPropRequests.find(id);
+    if (existing_req != mPropRequests.end())
     {
         if (gFrameTime - existing_req->second < MIN_GROUP_PROPERTY_REQUEST_FREQ)
         {
@@ -1481,7 +1485,7 @@ bool LLGroupMgr::hasPendingPropertyRequest(const LLUUID & id)
         }
         else
         {
-            LLGroupMgr::getInstance()->mPropRequests.erase(existing_req);
+            mPropRequests.erase(existing_req);
         }
     }
     return false;
@@ -1489,7 +1493,7 @@ bool LLGroupMgr::hasPendingPropertyRequest(const LLUUID & id)
 
 void LLGroupMgr::addPendingPropertyRequest(const LLUUID& id)
 {
-    LLGroupMgr::getInstance()->mPropRequests.insert_or_assign(id, gFrameTime);
+    mPropRequests.insert_or_assign(id, gFrameTime);
 }
 
 void LLGroupMgr::notifyObservers(LLGroupChange gc)
@@ -1579,12 +1583,12 @@ void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
 	// This will happen when we get the reply
 	//LLGroupMgrGroupData* group_datap = createGroupData(group_id);
 	
-    if (LLGroupMgr::getInstance()->hasPendingPropertyRequest(group_id))
+    if (hasPendingPropertyRequest(group_id))
     {
         LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupPropertiesRequest suppressed repeat for " << group_id << LL_ENDL;
         return;
     }
-    LLGroupMgr::getInstance()->addPendingPropertyRequest(group_id);
+    addPendingPropertyRequest(group_id);
 
 	LLMessageSystem* msg = gMessageSystem;
 	msg->newMessageFast(_PREHASH_GroupProfileRequest);
@@ -1926,7 +1930,7 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
 				for (LLGroupMemberData::role_list_t::iterator rit = member_data->roleBegin();
 					rit != member_data->roleEnd(); ++rit)
 				{
-					if ((*rit).first.notNull() && (*rit).second != 0)
+					if ((*rit).first.notNull() && (*rit).second != nullptr)
 					{
 						(*rit).second->removeMember(ejected_member_id);
 					}
@@ -2213,7 +2217,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 		// Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237
 		group_datap->mMemberDataComplete = true;
 		group_datap->mChanged = TRUE;
-		LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
+		notifyObservers(GC_MEMBER_DATA);
 		return;
 	}
 	
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index 2fac45ece7d29791cfad98d85f24a471e47a2744..4fc56a9b4dabd59d1078aae35d63e4c914b08050 100644
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -77,7 +77,7 @@ class LLGroupMemberData
 friend class LLGroupMgrGroupData;
 
 public:
-	typedef boost::unordered_flat_map<LLUUID, LLGroupRoleData*> role_list_t;
+	typedef boost::unordered_map<LLUUID,LLGroupRoleData*> role_list_t;
 	
 	LLGroupMemberData(const LLUUID& id, 
 						S32 contribution,
@@ -102,8 +102,6 @@ friend class LLGroupMgrGroupData;
 
 	BOOL isInRole(const LLUUID& role_id) { return (mRolesList.find(role_id) != mRolesList.end()); }
 
-	const role_list_t& getRoles() { return mRolesList; }
-
 	LLUUID	mID;
 	S32		mContribution;
 	U64		mAgentPowers;
@@ -117,6 +115,36 @@ struct LLRoleData
 {
 	LLRoleData() : mRolePowers(0), mChangeType(RC_UPDATE_NONE) { }
 
+	LLRoleData(const LLRoleData& rd) 
+	{
+		*this = rd;
+	}
+
+	LLRoleData(LLRoleData&& rd) 
+	{
+		*this = std::move(rd);
+	}
+
+	LLRoleData& operator=(const LLRoleData& rd)
+	{
+		mRoleName = rd.mRoleName;
+		mRoleTitle = rd.mRoleTitle;
+		mRoleDescription = rd.mRoleDescription;
+		mRolePowers = rd.mRolePowers;
+		mChangeType = rd.mChangeType;
+		return *this;
+	};
+
+	LLRoleData& operator=(LLRoleData&& rd) noexcept
+	{
+		mRoleName = std::move(rd.mRoleName);
+		mRoleTitle = std::move(rd.mRoleTitle);
+		mRoleDescription = std::move(rd.mRoleDescription);
+		mRolePowers = rd.mRolePowers;
+		mChangeType = rd.mChangeType;
+		return *this;
+	};
+
 	std::string mRoleName;
 	std::string mRoleTitle;
 	std::string mRoleDescription;
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 044affe4f5cb632e0967f0dc10f2ed1e0a33760c..c3721ddfa0c85f71a95b4fff59915943f04fbeb7 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -423,6 +423,10 @@ void LLPanelGroupRoles::setGroupID(const LLUUID& id)
 	if ( button )
 		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
 
+	button = getChild<LLButton>("export_list");
+	if (button)
+		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_VISIBLE_IN_DIR));
+
 	if(mSubTabContainer)
 		mSubTabContainer->selectTab(1);
 	group_roles_tab->mFirstOpen = TRUE;
@@ -1089,7 +1093,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
 		else
 		{
 			// This could happen if changes are not synced right on sub-panel change.
-			LL_WARNS() << "No group role data for " << iter->second << LL_ENDL;
+			LL_WARNS() << "No group role data for " << iter->first << LL_ENDL;
 		}
 	}
 	mAssignedRolesList->setEnabled(TRUE);
@@ -1815,6 +1819,15 @@ void LLPanelGroupMembersSubTab::updateMembers()
 		mMembersList->deleteAllItems();
 	}
 
+	for (avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.begin(); it != mAvatarNameCacheConnections.end(); ++it)
+	{
+		if (it->second.connected())
+		{
+			it->second.disconnect();
+		}
+	}
+	mAvatarNameCacheConnections.clear();
+
 	LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
 
 	LLTimer update_time;
@@ -2403,7 +2416,7 @@ void LLPanelGroupRolesSubTab::handleRoleSelect()
 	mSelectedRole = item->getUUID();
 	buildMembersList();
 
-	mCopyRoleButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE));
+	mCopyRoleButton->setEnabled((gdatap->mRoles.size() < (U32)MAX_ROLES) && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE));
 	can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
 													  GP_ROLE_DELETE);
 	mDeleteRoleButton->setEnabled(can_delete);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index e7fbbf16888d0edd790c3a7c6eda2884d83279c5..49a8c52cd7aa70d07581a118991d6115044103f8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -164,7 +164,7 @@ using namespace LLAvatarAppearanceDefines;
 
 typedef LLPointer<LLViewerObject> LLViewerObjectPtr;
 
-static boost::unordered_flat_map<std::string, LLStringExplicit> sDefaultItemLabels;
+static boost::unordered_flat_map<std::string, LLStringExplicit, al::string_hash, std::equal_to<>> sDefaultItemLabels;
 
 BOOL enable_land_build(void*);
 BOOL enable_object_build(void*);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e3339d215b9b308871eb8a5fdde8f1d131fbf31e..564c7efbb435179efc541e45b521f2e5eea84c0b 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4202,6 +4202,10 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
 	msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_SoundID, sound_id);
 	msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_OwnerID, owner_id);
 	msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ObjectID, object_id);
+
+	if (gAudiop->isCorruptSound(sound_id))
+		return;
+
 	msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ParentID, parent_id);
 	msg->getU64Fast(_PREHASH_SoundData, _PREHASH_Handle, region_handle);
 	msg->getVector3Fast(_PREHASH_SoundData, _PREHASH_Position, pos_local);
@@ -4273,6 +4277,9 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
 	msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id);
 	msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
 
+	if (gAudiop->isCorruptSound(sound_id))
+		return;
+
 	LLViewerObject *objectp = gObjectList.findObject(object_id);
 	if (!objectp) return;
 
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index da7c3fbe6b548ac06b91b87a74420c206be99248..7f575e993c3f6a6505ec106adfa4a91e7cdb2776 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -696,7 +696,7 @@ class LLViewerRegion final : public LLCapabilityProvider // implements this inte
     std::vector<LLPointer<LLReflectionMap> > mReflectionMaps;
 
 	mutable tex_matrix_t mWorldMapTiles;
-	boost::unordered_flat_set<std::string> mGodNames;
+	boost::unordered_flat_set<std::string, al::string_hash, std::equal_to<>> mGodNames;
 
 	LLEasyMessageSender mMessageSender;
 	using url_mapping_t = boost::unordered_multimap<std::string, std::string>;
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index a05d045d8ceda894b3bc6a0f2c231a12cb8e98d8..c03c45551e1001e721fc9a149abdac13ba0222b6 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -70,7 +70,7 @@
           max_chars="128"
           combo_editor.commit_on_focus_lost="false"
           combo_editor.prevalidate_callback="ascii"
-          tool_tip="The account name you chose when you registered, like bobsmith420 or Steller Sunshine"
+          tool_tip="The account name you chose when you registered, like bobsmith12 or Steller Sunshine"
           top_pad="0"
           name="username_combo"
           width="178">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 7a69c997c9ceaf4f02bcb97413d35a08d16c33cf..281c0141f2edc27596f9cbd76be7bb4a97f92f39 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -160,7 +160,7 @@ If you feel this is an error, please contact support.</string>
 	<string name="LoginFailedAlreadyLoggedIn">This agent is already logged in.</string>
 	<string name="LoginFailedAuthenticationFailed">Sorry! We couldn't log you in.
 Please check to make sure you entered the right
-    * Username (like yiffmaster69 or steller.sunshine)
+    * Username (like bobsmith12 or steller.sunshine)
     * Password
     * Second Factor Token (if enabled)
 Also, please make sure your Caps Lock key is off.</string>
diff --git a/indra/newview/skins/heretic/colors.xml b/indra/newview/skins/heretic/colors.xml
index ab7159606bf220d6e20de1b6176afd1933a394a5..b05ea6934456c7201a9da4ecc52925ec2d9e522e 100644
--- a/indra/newview/skins/heretic/colors.xml
+++ b/indra/newview/skins/heretic/colors.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <colors>
-
 	<color
 	 name="ScriptDialog"
 	 value="0.25 0.25 0.25 1" />
diff --git a/indra/newview/skins/heretic/xui/en/panel_login.xml b/indra/newview/skins/heretic/xui/en/panel_login.xml
index 26be5e536deab70a212613be31ae2d4278899946..b854c5de8cefaacda3c13436d9de3d31d24df2e0 100644
--- a/indra/newview/skins/heretic/xui/en/panel_login.xml
+++ b/indra/newview/skins/heretic/xui/en/panel_login.xml
@@ -71,7 +71,7 @@
           max_chars="128"
           combo_editor.commit_on_focus_lost="false"
           combo_editor.prevalidate_callback="ascii"
-          tool_tip="The account name you chose when you registered, like yiffmaster420 or Steller Sunshine"
+          tool_tip="The account name you chose when you registered, like bobsmith12 or Steller Sunshine"
           top_pad="0"
           name="username_combo"
           width="178">
diff --git a/indra/newview/skins/heretic/xui/en/widgets/floater.xml b/indra/newview/skins/heretic/xui/en/widgets/floater.xml
index a8c63dca7f54f7d78edc998301d1a005aee2e635..e53ee2521d1c384c4d036ad4eac818dc148ba470 100644
--- a/indra/newview/skins/heretic/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/heretic/xui/en/widgets/floater.xml
@@ -12,16 +12,16 @@
  background_opaque="false"
  header_height="20"
  close_image="Icon_Close_Foreground"
- snooze_image="Icon_Snooze_Foreground"
  restore_image="Icon_Restore_Foreground"
  minimize_image="Icon_Minimize_Foreground"
+ collapse_image="Icon_Collapse_Foreground"
  tear_off_image="tearoffbox.tga"
  dock_image="Icon_Dock_Foreground"
  help_image="Icon_Help_Foreground"
  close_pressed_image="Icon_Close_Press"
- snooze_pressed_image="Icon_Snooze_Press"
  restore_pressed_image="Icon_Restore_Press"
  minimize_pressed_image="Icon_Minimize_Press"
+ collapse_pressed_image="Icon_Collapse_Press"
  tear_off_pressed_image="tearoff_pressed.tga"
  dock_pressed_image="Icon_Dock_Press"
  help_pressed_image="Icon_Help_Press"
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index ba4e7f77ec4533b26d491696d55ab77ff4229549..122a2a3016b121125f4499fcc391d73a146c264e 100644
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -217,7 +217,7 @@ get_region(const LLSD & sd, U64 region_handle1)
 	U32 grid_x(0), grid_y(0);
 	grid_from_region_handle(region_handle1, &grid_x, &grid_y);
 
-	for (const LLSD& llsd_val : sd["regions"].array())
+	for (const LLSD& llsd_val : sd["regions"].asArray())
 	{
 		if (llsd_val.has("grid_x") &&
 			llsd_val.has("grid_y") &&