diff --git a/aegisub/audio_provider_ffmpegsource.cpp b/aegisub/audio_provider_ffmpegsource.cpp
index 3e57bc7a23111eb1df77f8f1bb66eaa7e71de48f..5ff946db6c0ea5d78d70c2eb491dfbbdc9b161b1 100644
--- a/aegisub/audio_provider_ffmpegsource.cpp
+++ b/aegisub/audio_provider_ffmpegsource.cpp
@@ -69,8 +69,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 	wxString FileNameWX(filename.c_str(), wxConvFile);
 
 	// generate a default name for the cache file
-	wxString CacheName(filename.c_str(), wxConvFile);
-	CacheName.append(_T(".ffindex"));
+	wxString CacheName = GetCacheFilename(filename);
 
 	FrameIndex *Index;
 	Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrMsg, MsgSize);
diff --git a/aegisub/dialog_progress.cpp b/aegisub/dialog_progress.cpp
index 2b836e62493c5d6744acfab44a3c39e6c081766a..00ddcdeef4269e7603071e03157f5c8d60ce39a6 100644
--- a/aegisub/dialog_progress.cpp
+++ b/aegisub/dialog_progress.cpp
@@ -41,6 +41,9 @@
 #include "dialog_progress.h"
 
 
+DEFINE_EVENT_TYPE(wxEVT_PROGRESS_UPDATE)
+
+
 ///////////////
 // Constructor
 DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *cancel,wxString message,int cur,int max)
@@ -49,9 +52,10 @@ DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *ca
 	// Variables
 	canceled = cancel;
 	if (cancel) *canceled = false;
+	virtualMax = max;
 
 	// Gauge
-	gauge = new wxGauge(this, -1, max, wxDefaultPosition, wxSize(300,20), wxGA_HORIZONTAL);
+	gauge = new wxGauge(this, -1, 100, wxDefaultPosition, wxSize(300,20), wxGA_HORIZONTAL);
 	wxButton *cancelButton = NULL;
 	if (cancel) cancelButton = new wxButton(this,wxID_CANCEL);
 	text = new wxStaticText(this, -1, message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE | wxST_NO_AUTORESIZE);
@@ -64,23 +68,46 @@ DialogProgress::DialogProgress(wxWindow *parent,wxString title,volatile bool *ca
 	MainSizer->SetSizeHints(this);
 	SetSizer(MainSizer);
 	CenterOnParent();
+	Connect(0,wxEVT_PROGRESS_UPDATE,wxCommandEventHandler(DialogProgress::OnUpdateProgress));
 }
 
 
 ////////////////
 // Set progress
 void DialogProgress::SetProgress(int cur,int max) {
-	// Lock
-	bool isMain = wxIsMainThread();
-	if (!isMain) wxMutexGuiEnter();
+	// Return if there's nothing to do
+	int value = cur*100/virtualMax;
+	if (gauge->GetValue() == value && virtualMax == max) return;
+	virtualMax = max;
+
+	// Check if it's the main thread, if so, just process it now
+	if (wxIsMainThread()) {
+		gauge->SetValue(value);
+		wxYield();
+		return;
+	}
+
+	// Otherwise, go on
+	{
+		wxMutexLocker locker(mutex);
+		if (count >= 2) return;
+		else count++;
+	}
+
+	wxCommandEvent* evt = new wxCommandEvent(wxEVT_PROGRESS_UPDATE,0);
+	evt->SetInt(value);
+	AddPendingEvent(*evt);
+}
 
-	// Update
-	gauge->SetRange(max);
-	gauge->SetValue(cur);
-	wxSafeYield(this);
 
-	// Unlock
-	if (!isMain) wxMutexGuiLeave();
+///////////////////
+// Update progress
+void DialogProgress::OnUpdateProgress(wxCommandEvent &event)
+{
+	int value = event.GetInt();
+	if (gauge->GetValue() != value) gauge->SetValue(value);
+	wxMutexLocker locker(mutex);
+	count--;
 }
 
 
@@ -117,7 +144,6 @@ void DialogProgress::OnCancel(wxCommandEvent &event) {
 	if (!isMain) wxMutexGuiLeave();
 }
 
-
 //////////////////////
 // Thread constructor
 DialogProgressThread::DialogProgressThread(wxWindow *parent,wxString title,volatile bool *canceled,wxString message,int cur,int max)
diff --git a/aegisub/dialog_progress.h b/aegisub/dialog_progress.h
index 4d7cc9c141c0d21d631edaf1fc6bc0cb59e1fcce..de0eac56051aa7d4478bde57eb89a07e122d82f6 100644
--- a/aegisub/dialog_progress.h
+++ b/aegisub/dialog_progress.h
@@ -50,9 +50,14 @@
 // Progress dialog class
 class DialogProgress : public wxDialog {
 private:
+	volatile int count;
+	int virtualMax;
+	wxMutex mutex;
+
 	wxGauge *gauge;
 	wxStaticText *text;
 	void OnCancel(wxCommandEvent &event);
+	void OnUpdateProgress(wxCommandEvent &event);
 
 public:
 	volatile bool *canceled;
diff --git a/aegisub/ffmpegsource_common.cpp b/aegisub/ffmpegsource_common.cpp
index 16554fe821b401ae10adc8a230274961610e6eac..60beb7afaf639ad694e0a8b785937e54e75b90b6 100644
--- a/aegisub/ffmpegsource_common.cpp
+++ b/aegisub/ffmpegsource_common.cpp
@@ -38,6 +38,10 @@
 ///////////
 // Headers
 #include "ffmpegsource_common.h"
+#include "md5.h"
+#include "standard_paths.h"
+#include "main.h"
+#include "frame_main.h"
 
 ///////////////
 // Update indexing progress
@@ -64,7 +68,7 @@ FrameIndex *FFmpegSourceProvider::DoIndexing(FrameIndex *Index, wxString FileNam
 	// set up progress dialog callback
 	IndexingProgressDialog Progress;
 	Progress.IndexingCanceled = false;
-	Progress.ProgressDialog = new DialogProgress(NULL, _("Indexing"), &Progress.IndexingCanceled, _("Reading timecodes and frame/sample data"), 0, 1);
+	Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled, _("Reading timecodes and frame/sample data"), 0, 1);
 	Progress.ProgressDialog->Show();
 	Progress.ProgressDialog->SetProgress(0,1);
 
@@ -90,4 +94,42 @@ FrameIndex *FFmpegSourceProvider::DoIndexing(FrameIndex *Index, wxString FileNam
 	return Index;
 }
 
+/////////////////////
+// Creates a name for the ffmpegsource2 index and prepares the folder if it doesn't exist
+// method by amz
+wxString FFmpegSourceProvider::GetCacheFilename(const wxString& filename)
+{
+	// Get the size of the file to be hashed
+	wxFileOffset len = 0;
+	{
+		wxFile file(filename,wxFile::read);
+		if (file.IsOpened()) len = file.Length();
+	}
+
+	// Generate string to be hashed
+	wxString toHash = filename + wxString::Format(_T(":%i"),len);
+
+	// Get the MD5 digest of the string
+	md5_state_t state;
+	md5_byte_t digest[16];
+	md5_init(&state);
+	md5_append(&state,(md5_byte_t*)toHash.c_str(),toHash.Length()*sizeof(wxChar));
+	md5_finish(&state,digest);
+
+	// Generate the filename
+	unsigned int *md5 = (unsigned int*) digest;
+	wxString result = wxString::Format(_T("?user/ffms2cache/%08X%08X%08X%08X.ffindex"),md5[0],md5[1],md5[2],md5[3]);
+	result = StandardPaths::DecodePath(result);
+
+	// Ensure that folder exists
+	wxFileName fn(result);
+	wxString dir = fn.GetPath();
+	if (!wxFileName::DirExists(dir)) {
+		wxFileName::Mkdir(dir);
+	}
+
+	wxFileName dirfn(dir);
+	return dirfn.GetShortPath() + _T("/") + fn.GetFullName();
+}
+
 #endif WITH_FFMPEGSOURCE
\ No newline at end of file
diff --git a/aegisub/ffmpegsource_common.h b/aegisub/ffmpegsource_common.h
index 1ad0757e085f267f66be34f18d3dbc5f9562b200..72d950a47bf2dbf96c21925ef73ca817acb99d04 100644
--- a/aegisub/ffmpegsource_common.h
+++ b/aegisub/ffmpegsource_common.h
@@ -55,6 +55,7 @@ public:
 
 	static int FFMS_CC UpdateIndexingProgress(int State, int64_t Current, int64_t Total, void *Private);
 	FrameIndex *DoIndexing(FrameIndex *Index, wxString Filename, wxString Cachename, int Trackmask, bool IgnoreDecodeErrors);
+	wxString GetCacheFilename(const wxString& filename);
 };
 
 #endif /* WITH_FFMPEGSOURCE */
\ No newline at end of file
diff --git a/aegisub/video_provider_ffmpegsource.cpp b/aegisub/video_provider_ffmpegsource.cpp
index b64ff0202d3a7f7926e3874be938e8ded3350729..d09ae3a7bbbc657a337d787d64b3337c279b73e3 100644
--- a/aegisub/video_provider_ffmpegsource.cpp
+++ b/aegisub/video_provider_ffmpegsource.cpp
@@ -63,7 +63,7 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d
 		LoadVideo(filename, fps);
 	} catch (...) {
 		Close();
-		throw;
+		//throw;
 	}
 }
 
@@ -82,8 +82,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
 	wxString FileNameWX(filename.c_str(), wxConvFile);
 
 	// generate a name for the cache file
-	wxString CacheName(filename.c_str(), wxConvFile);
-	CacheName.append(_T(".ffindex"));
+	wxString CacheName = GetCacheFilename(filename);
 
 	// try to read index
 	Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrorMessage, MessageSize);