From 83960dcce374bbc57f16194160bc55a90fa8cc17 Mon Sep 17 00:00:00 2001
From: Karl Blomster <kalle.blomster@gmail.com>
Date: Mon, 13 Jul 2009 22:30:48 +0000
Subject: [PATCH] Update the FFMS2 audio and video providers to use the new API
 features.

Originally committed to SVN as r3116.
---
 aegisub/src/audio_provider_ffmpegsource.cpp | 71 +++++++++++----------
 aegisub/src/ffmpegsource_common.cpp         |  4 +-
 aegisub/src/video_provider_ffmpegsource.cpp | 30 ++++++---
 aegisub/src/video_provider_ffmpegsource.h   |  2 +-
 4 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/aegisub/src/audio_provider_ffmpegsource.cpp b/aegisub/src/audio_provider_ffmpegsource.cpp
index 6a121477e..50433db62 100644
--- a/aegisub/src/audio_provider_ffmpegsource.cpp
+++ b/aegisub/src/audio_provider_ffmpegsource.cpp
@@ -58,7 +58,7 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(Aegisub::String filename) {
 	else if (res != RPC_E_CHANGED_MODE)
 		throw _T("FFmpegSource video provider: COM initialization failure");
 #endif
-	FFMS_Init();
+	FFMS_Init(0);
 
 	MsgSize = sizeof(FFMSErrMsg);
 	MsgString = _T("FFmpegSource audio provider: ");
@@ -85,21 +85,22 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 	// generate a default name for the cache file
 	wxString CacheName = GetCacheFilename(filename.c_str());
 
-	FFIndex *Index;
-	Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrMsg, MsgSize);
+	FFIndex *Index = NULL;
+	bool ReIndex = false;
+	Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
 	if (Index == NULL) {
-		// index didn't exist or was invalid, we'll have to (re)create it
-		try {
-			Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
-		} catch (wxString temp) {
-			MsgString << temp;
-			throw MsgString;
-		} catch (...) {
-			throw;
-		}
-	} else {
-		// index exists, but does it have indexing info for the audio track(s)?
+		ReIndex = true;
+	}
+	// index exists, but is it the index we think it is?
+	else if (FFMS_IndexBelongsToFile(Index, FileNameWX.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize)) {
+		FFMS_DestroyIndex(Index);
+		Index = NULL;
+		ReIndex = true;
+	}
+	// it is, but does it have indexing info for the audio track(s)?
+	else {
 		int NumTracks = FFMS_GetNumTracks(Index);
+		// sanity check
 		if (NumTracks <= 0) {
 			FFMS_DestroyIndex(Index);
 			Index = NULL;
@@ -107,8 +108,9 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 		}
 
 		for (int i = 0; i < NumTracks; i++) {
-			FFTrack *FrameData = FFMS_GetTrackFromIndex(Index, i);
-			if (FrameData == NULL) {
+			FFTrack *TrackData = FFMS_GetTrackFromIndex(Index, i);
+			// more sanity checking
+			if (TrackData == NULL) {
 				FFMS_DestroyIndex(Index);
 				Index = NULL;
 				wxString temp(FFMSErrMsg, wxConvUTF8);
@@ -117,24 +119,27 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 			}
 
 			// does the track have any indexed frames?
-			if (FFMS_GetNumFrames(FrameData) <= 0 && (FFMS_GetTrackType(FrameData) == FFMS_TYPE_AUDIO)) {
+			if (FFMS_GetNumFrames(TrackData) <= 0 && (FFMS_GetTrackType(TrackData) == FFMS_TYPE_AUDIO)) {
 				// found an unindexed audio track, we'll need to reindex
-				try {
-					FFMS_DestroyIndex(Index);
-					Index = NULL;
-					Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
-				} catch (wxString temp) {
-					MsgString << temp;
-					throw MsgString;
-				} catch (...) {
-					throw;
-				}
-
-				// don't reindex more than once
+				FFMS_DestroyIndex(Index);
+				Index = NULL;
+				ReIndex = true;
 				break;
 			}
 		}
 	}
+	
+	// index didn't exist or was invalid, we'll have to (re)create it
+	if (ReIndex) {
+		try {
+			Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
+		} catch (wxString temp) {
+			MsgString << temp;
+			throw MsgString;
+		} catch (...) {
+			throw;
+		}
+	}
 
 	// update access time of index file so it won't get cleaned away
 	wxFileName(CacheName).Touch();
@@ -149,7 +154,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 		throw MsgString;
 	}
 
-	AudioSource = FFMS_CreateAudioSource(FileNameWX.mb_str(wxConvLocal), TrackNumber, Index, FFMSErrMsg, MsgSize);
+	AudioSource = FFMS_CreateAudioSource(FileNameWX.mb_str(wxConvUTF8), TrackNumber, Index, FFMSErrMsg, MsgSize);
 	FFMS_DestroyIndex(Index);
 	Index = NULL;
 	if (!AudioSource) {
@@ -158,10 +163,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 			throw MsgString;
 	}
 		
-	const TAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
-
-	if (AudioInfo.Float)
-		throw _T("FFmpegSource audio provider: I don't know what to do with floating point audio");
+	const FFAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
 
 	channels	= AudioInfo.Channels;
 	sample_rate	= AudioInfo.SampleRate;
@@ -169,6 +171,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
 	if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
 		throw _T("FFmpegSource audio provider: sanity check failed, consult your local psychiatrist");
 
+	// FIXME: use 
 	// why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere...
 	switch (AudioInfo.BitsPerSample) {
 		case 8:		bytes_per_sample = 1; break;
diff --git a/aegisub/src/ffmpegsource_common.cpp b/aegisub/src/ffmpegsource_common.cpp
index 3f52e4555..f2be3f12b 100644
--- a/aegisub/src/ffmpegsource_common.cpp
+++ b/aegisub/src/ffmpegsource_common.cpp
@@ -84,7 +84,7 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndex *Index, wxString FileNameWX, w
 	Progress.ProgressDialog->SetProgress(0,1);
 
 	// index all audio tracks
-	Index = FFMS_MakeIndex(FileNameWX.mb_str(wxConvLocal), Trackmask, FFMSTrackMaskNone, NULL, NULL, IgnoreDecodeErrors, FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize);
+	Index = FFMS_MakeIndex(FileNameWX.mb_str(wxConvUTF8), Trackmask, FFMSTrackMaskNone, NULL, NULL, IgnoreDecodeErrors, FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize);
 	if (!Index) {
 		Progress.ProgressDialog->Destroy();
 		wxString temp(FFMSErrMsg, wxConvUTF8);
@@ -239,7 +239,7 @@ wxThread::ExitCode FFmpegSourceCacheCleaner::Entry() {
 
 	if (numfiles <= maxfiles && cursize <= maxsize) {
 		wxLogDebug(_T("FFmpegSourceCacheCleaner: cache does not need cleaning (maxsize=%d, cursize=%d; maxfiles=%d, numfiles=%d), exiting"),
-			maxsize, cursize, maxfiles, numfiles);
+			(int)maxsize, (int)cursize, maxfiles, numfiles);
 		return (wxThread::ExitCode)0;
 	}
 
diff --git a/aegisub/src/video_provider_ffmpegsource.cpp b/aegisub/src/video_provider_ffmpegsource.cpp
index 02e10eab9..247eb4681 100644
--- a/aegisub/src/video_provider_ffmpegsource.cpp
+++ b/aegisub/src/video_provider_ffmpegsource.cpp
@@ -63,7 +63,8 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d
 		throw _T("FFmpegSource video provider: COM initialization failure");
 #endif
 	// initialize ffmpegsource
-	FFMS_Init();
+	// FIXME: CPU detection?
+	FFMS_Init(0);
 
 	// clean up variables
 	VideoSource = NULL;
@@ -99,15 +100,26 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
 	// make sure we don't have anything messy lying around
 	Close();
 
-	wxString FileNameWX = wxFileName(wxString(filename.c_str(), wxConvFile)).GetShortPath();
+	wxString FileNameWX = wxFileName(wxString(filename.c_str(), wxConvFile)).GetShortPath(); 
 
 	// generate a name for the cache file
 	wxString CacheName = GetCacheFilename(filename.c_str());
 
 	// try to read index
-	FFIndex *Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrorMessage, MessageSize);
+	FFIndex *Index = NULL;
+	Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrorMessage, MessageSize);
+	bool ReIndex = false;
 	if (Index == NULL) {
-		// index didn't exist or was invalid, we'll have to (re)create it
+		ReIndex = true;
+	}
+	else if (FFMS_IndexBelongsToFile(Index, FileNameWX.mb_str(wxConvUTF8), FFMSErrorMessage, MessageSize)) {
+		FFMS_DestroyIndex(Index);
+		Index = NULL;
+		ReIndex = true;
+	}
+
+	// index didn't exist or was invalid, we'll have to (re)create it
+	if (ReIndex) {
 		try {
 			try {
 				// ignore audio decoding errors here, we don't care right now
@@ -155,7 +167,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
 		throw ErrorMsg;
 	}
 
-	VideoSource = FFMS_CreateVideoSource(FileNameWX.mb_str(wxConvLocal), TrackNumber, Index, "", Threads, SeekMode, FFMSErrorMessage, MessageSize);
+	VideoSource = FFMS_CreateVideoSource(FileNameWX.mb_str(wxConvUTF8), TrackNumber, Index, "", Threads, SeekMode, FFMSErrorMessage, MessageSize);
 	FFMS_DestroyIndex(Index);
 	Index = NULL;
 	if (VideoSource == NULL) {
@@ -171,7 +183,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
 	FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource);
 	if (FrameData == NULL)
 		throw _T("FFmpegSource video provider: failed to get frame data");
-	const TTrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
+	const FFTrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
 	if (TimeBase == NULL)
 		throw _T("FFmpegSource video provider: failed to get track time base");
 
@@ -191,7 +203,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
 			KeyFramesList.Add(CurFrameNum);
 
 		// calculate timestamp and add to timecodes vector
-		int64_t Timestamp = (int64_t)((CurFrameData->DTS * TimeBase->Num) / (double)TimeBase->Den);
+		int Timestamp = (int)((CurFrameData->DTS * TimeBase->Num) / TimeBase->Den);
 		TimecodesVector.push_back(Timestamp);
 	}
 	KeyFramesLoaded = true;
@@ -266,7 +278,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
 
 	// requested format was changed since last time we were called, (re)set output format
 	if (LastDstFormat != DstFormat) {
-		if (FFMS_SetOutputFormat(VideoSource, 1 << DstFormat, w, h, FFMSErrorMessage, MessageSize)) {
+		if (FFMS_SetOutputFormatV(VideoSource, 1 << DstFormat, w, h, FFMS_RESIZER_BICUBIC, FFMSErrorMessage, MessageSize)) {
 			wxString temp(FFMSErrorMessage, wxConvUTF8);
 			ErrorMsg << _T("Failed to set output format: ") << temp;
 			throw ErrorMsg;
@@ -275,7 +287,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
 	}
 
 	// decode frame
-	const TAVFrameLite *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize);
+	const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize);
 	if (SrcFrame == NULL) {
 		wxString temp(FFMSErrorMessage, wxConvUTF8);
 		ErrorMsg << _T("Failed to retrieve frame: ") << temp;
diff --git a/aegisub/src/video_provider_ffmpegsource.h b/aegisub/src/video_provider_ffmpegsource.h
index a51d42754..a568e2877 100644
--- a/aegisub/src/video_provider_ffmpegsource.h
+++ b/aegisub/src/video_provider_ffmpegsource.h
@@ -48,7 +48,7 @@
 class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
 private:
 	FFVideo *VideoSource;
-	const TVideoProperties *VideoInfo;
+	const FFVideoProperties *VideoInfo;
 
 	int FrameNumber;
 	wxArrayInt KeyFramesList;
-- 
GitLab