From 8ecedcbc2d9679feafd054e68f5cc26a4e5ba849 Mon Sep 17 00:00:00 2001 From: Karl Blomster Date: Tue, 23 Sep 2008 23:30:27 +0000 Subject: [PATCH] Update ffms providers to use new and improved FFMS API functionality. Also moved the indexing function to ffmpegsource_common.cpp. Originally committed to SVN as r2387. --- aegisub/audio_provider_ffmpegsource.cpp | 58 ++++++++++++++++--------- aegisub/ffmpegsource_common.cpp | 35 +++++++++++++++ aegisub/ffmpegsource_common.h | 3 +- aegisub/video_provider_ffmpegsource.cpp | 29 +++---------- 4 files changed, 82 insertions(+), 43 deletions(-) diff --git a/aegisub/audio_provider_ffmpegsource.cpp b/aegisub/audio_provider_ffmpegsource.cpp index 74e094d80..70951c269 100644 --- a/aegisub/audio_provider_ffmpegsource.cpp +++ b/aegisub/audio_provider_ffmpegsource.cpp @@ -76,29 +76,45 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) { Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrMsg, MsgSize); if (Index == NULL) { // index didn't exist or was invalid, we'll have to (re)create it - IndexingProgressDialog Progress; - Progress.IndexingCanceled = false; - Progress.ProgressDialog = new DialogProgress(NULL, _("Indexing"), &Progress.IndexingCanceled, _("Indexing audio file"), 0, 1); - Progress.ProgressDialog->Show(); - Progress.ProgressDialog->SetProgress(0,1); - - // index all audio tracks - Index = FFMS_MakeIndex(FileNameWX.char_str(), FFMSTrackMaskAll, CacheName.char_str(), FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize); - if (Index == NULL) { - Progress.ProgressDialog->Destroy(); - wxString temp(FFMSErrMsg, wxConvUTF8); - MsgString << _T("failed to index: ") << temp; + try { + Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll); + } catch (wxString temp) { + MsgString << temp; throw MsgString; + } catch (...) { + throw; } - Progress.ProgressDialog->Destroy(); + } else { + // index exists, but does it have indexing info for the audio track(s)? + int NumTracks = FFMS_GetNumTracks(Index, FFMSErrMsg, MsgSize); + if (NumTracks <= 0) + throw _T("FFmpegSource audio provider: no tracks found in index file"); - // write index to disk for later use - if (FFMS_WriteIndex(CacheName.char_str(), Index, FFMSErrMsg, MsgSize)) { - wxString temp(FFMSErrMsg, wxConvUTF8); - MsgString << _T("failed to write index: ") << temp; - throw MsgString; + for (int i = 0; i < NumTracks; i++) { + FrameInfoVector *FrameData = FFMS_GetTITrackIndex(Index, i, FFMSErrMsg, MsgSize); + if (FrameData == NULL) { + wxString temp(FFMSErrMsg, wxConvUTF8); + MsgString << _T("couldn't get track data: ") << temp; + throw MsgString; + } + + // does the track have any indexed frames? + if (FFMS_GetNumFrames(FrameData, FFMSErrMsg, MsgSize) <= 0 && (FFMS_GetTrackType(FrameData, FFMSErrMsg, MsgSize) == FFMS_TYPE_AUDIO)) { + // found an unindexed audio track, we'll need to reindex + try { + Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll); + } catch (wxString temp) { + MsgString << temp; + throw MsgString; + } catch (...) { + throw; + } + + // don't reindex more than once + break; + } } - } + } // FIXME: provide a way to choose which audio track to load? AudioSource = FFMS_CreateAudioSource(FileNameWX.char_str(), FFMSFirstSuitableTrack, Index, FFMSErrMsg, MsgSize); @@ -111,11 +127,13 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) { const AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource); if (AudioInfo.Float) - throw _T("FFmpegSource audio provider: don't know what to do with floating point audio"); + throw _T("FFmpegSource audio provider: I don't know what to do with floating point audio"); channels = AudioInfo.Channels; sample_rate = AudioInfo.SampleRate; num_samples = AudioInfo.NumSamples; + if (channels <= 0 || sample_rate <= 0 || num_samples <= 0) + throw _T("FFmpegSource audio provider: sanity check failed, consult your local psychiatrist"); // why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere... switch (AudioInfo.BitsPerSample) { diff --git a/aegisub/ffmpegsource_common.cpp b/aegisub/ffmpegsource_common.cpp index ea82610bc..dc7aa7fce 100644 --- a/aegisub/ffmpegsource_common.cpp +++ b/aegisub/ffmpegsource_common.cpp @@ -53,4 +53,39 @@ int __stdcall FFmpegSourceProvider::UpdateIndexingProgress(int State, int64_t Cu return 0; } + +/////////// +// Do indexing +FrameIndex *FFmpegSourceProvider::DoIndexing(FrameIndex *Index, wxString FileNameWX, wxString CacheName, int Trackmask) { + char FFMSErrMsg[1024]; + unsigned MsgSize = sizeof(FFMSErrMsg); + wxString MsgString; + + // set up progress dialog callback + IndexingProgressDialog Progress; + Progress.IndexingCanceled = false; + Progress.ProgressDialog = new DialogProgress(NULL, _("Indexing"), &Progress.IndexingCanceled, _("Indexing timecodes and frame/sample data"), 0, 1); + Progress.ProgressDialog->Show(); + Progress.ProgressDialog->SetProgress(0,1); + + // index all audio tracks + Index = FFMS_MakeIndex(FileNameWX.char_str(), Trackmask, FFMSTrackMaskNone, NULL, FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize); + if (!Index) { + Progress.ProgressDialog->Destroy(); + wxString temp(FFMSErrMsg, wxConvUTF8); + MsgString << _T("failed to index: ") << temp; + throw MsgString; + } + Progress.ProgressDialog->Destroy(); + + // write index to disk for later use + if (FFMS_WriteIndex(CacheName.char_str(), Index, FFMSErrMsg, MsgSize)) { + wxString temp(FFMSErrMsg, wxConvUTF8); + MsgString << _T("failed to write index: ") << temp; + throw MsgString; + } + + return Index; +} + #endif WITH_FFMPEGSOURCE \ No newline at end of file diff --git a/aegisub/ffmpegsource_common.h b/aegisub/ffmpegsource_common.h index b168f0d63..d5695f4d4 100644 --- a/aegisub/ffmpegsource_common.h +++ b/aegisub/ffmpegsource_common.h @@ -54,7 +54,8 @@ public: DialogProgress *ProgressDialog; }; - static int __stdcall FFmpegSourceProvider::UpdateIndexingProgress(int State, int64_t Current, int64_t Total, void *Private); + static int __stdcall UpdateIndexingProgress(int State, int64_t Current, int64_t Total, void *Private); + FrameIndex *DoIndexing(FrameIndex *Index, wxString Filename, wxString Cachename, int Trackmask); }; #endif /* WITH_FFMPEGSOURCE */ \ No newline at end of file diff --git a/aegisub/video_provider_ffmpegsource.cpp b/aegisub/video_provider_ffmpegsource.cpp index 69fd2bb59..42cf64408 100644 --- a/aegisub/video_provider_ffmpegsource.cpp +++ b/aegisub/video_provider_ffmpegsource.cpp @@ -88,29 +88,14 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps) // try to read index Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrorMessage, MessageSize); if (Index == NULL) { - // reading failed, create index - // prepare stuff for callback - IndexingProgressDialog Progress; - Progress.IndexingCanceled = false; - Progress.ProgressDialog = new DialogProgress(NULL, _("Indexing"), &Progress.IndexingCanceled, _("Reading keyframes and timecodes from video"), 0, 1); - Progress.ProgressDialog->Show(); - Progress.ProgressDialog->SetProgress(0,1); - - // set trackmask to -1 (all) here but don't output any audio file, this allows the audio provider to reuse the index later - Index = FFMS_MakeIndex(FileNameWX.char_str(), FFMSTrackMaskAll, CacheName.char_str(), FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrorMessage, MessageSize); - if (Index == NULL) { - Progress.ProgressDialog->Destroy(); - wxString temp(FFMSErrorMessage, wxConvUTF8); - ErrorMsg << _T("failed to index: ") << temp; - throw ErrorMsg; - } - Progress.ProgressDialog->Destroy(); - - // write it to disk - if (FFMS_WriteIndex(CacheName.char_str(), Index, FFMSErrorMessage, MessageSize)) { - wxString temp(FFMSErrorMessage, wxConvUTF8); - ErrorMsg << _T("failed to write index: ") << temp; + // index didn't exist or was invalid, we'll have to (re)create it + try { + Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll); + } catch (wxString temp) { + ErrorMsg << temp; throw ErrorMsg; + } catch (...) { + throw; } }