Update the FFMS2 audio and video providers to use the new API features.

Originally committed to SVN as r3116.
This commit is contained in:
Karl Blomster 2009-07-13 22:30:48 +00:00
parent 5dc912bf4d
commit a45282bfbb
4 changed files with 61 additions and 46 deletions

View file

@ -58,7 +58,7 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(Aegisub::String filename) {
else if (res != RPC_E_CHANGED_MODE) else if (res != RPC_E_CHANGED_MODE)
throw _T("FFmpegSource video provider: COM initialization failure"); throw _T("FFmpegSource video provider: COM initialization failure");
#endif #endif
FFMS_Init(); FFMS_Init(0);
MsgSize = sizeof(FFMSErrMsg); MsgSize = sizeof(FFMSErrMsg);
MsgString = _T("FFmpegSource audio provider: "); MsgString = _T("FFmpegSource audio provider: ");
@ -85,21 +85,22 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
// generate a default name for the cache file // generate a default name for the cache file
wxString CacheName = GetCacheFilename(filename.c_str()); wxString CacheName = GetCacheFilename(filename.c_str());
FFIndex *Index; FFIndex *Index = NULL;
Index = FFMS_ReadIndex(CacheName.char_str(), FFMSErrMsg, MsgSize); bool ReIndex = false;
Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
if (Index == NULL) { if (Index == NULL) {
// index didn't exist or was invalid, we'll have to (re)create it ReIndex = true;
try {
Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
} catch (wxString temp) {
MsgString << temp;
throw MsgString;
} catch (...) {
throw;
} }
} else { // index exists, but is it the index we think it is?
// index exists, but does it have indexing info for the audio track(s)? 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); int NumTracks = FFMS_GetNumTracks(Index);
// sanity check
if (NumTracks <= 0) { if (NumTracks <= 0) {
FFMS_DestroyIndex(Index); FFMS_DestroyIndex(Index);
Index = NULL; Index = NULL;
@ -107,8 +108,9 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
} }
for (int i = 0; i < NumTracks; i++) { for (int i = 0; i < NumTracks; i++) {
FFTrack *FrameData = FFMS_GetTrackFromIndex(Index, i); FFTrack *TrackData = FFMS_GetTrackFromIndex(Index, i);
if (FrameData == NULL) { // more sanity checking
if (TrackData == NULL) {
FFMS_DestroyIndex(Index); FFMS_DestroyIndex(Index);
Index = NULL; Index = NULL;
wxString temp(FFMSErrMsg, wxConvUTF8); wxString temp(FFMSErrMsg, wxConvUTF8);
@ -117,11 +119,19 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
} }
// does the track have any indexed frames? // 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 // found an unindexed audio track, we'll need to reindex
try {
FFMS_DestroyIndex(Index); FFMS_DestroyIndex(Index);
Index = NULL; 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); Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
} catch (wxString temp) { } catch (wxString temp) {
MsgString << temp; MsgString << temp;
@ -129,11 +139,6 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
} catch (...) { } catch (...) {
throw; throw;
} }
// don't reindex more than once
break;
}
}
} }
// update access time of index file so it won't get cleaned away // update access time of index file so it won't get cleaned away
@ -149,7 +154,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
throw MsgString; 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); FFMS_DestroyIndex(Index);
Index = NULL; Index = NULL;
if (!AudioSource) { if (!AudioSource) {
@ -158,10 +163,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
throw MsgString; throw MsgString;
} }
const TAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource); const FFAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
if (AudioInfo.Float)
throw _T("FFmpegSource audio provider: I don't know what to do with floating point audio");
channels = AudioInfo.Channels; channels = AudioInfo.Channels;
sample_rate = AudioInfo.SampleRate; sample_rate = AudioInfo.SampleRate;
@ -169,6 +171,7 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0) if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
throw _T("FFmpegSource audio provider: sanity check failed, consult your local psychiatrist"); 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... // why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere...
switch (AudioInfo.BitsPerSample) { switch (AudioInfo.BitsPerSample) {
case 8: bytes_per_sample = 1; break; case 8: bytes_per_sample = 1; break;

View file

@ -84,7 +84,7 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndex *Index, wxString FileNameWX, w
Progress.ProgressDialog->SetProgress(0,1); Progress.ProgressDialog->SetProgress(0,1);
// index all audio tracks // 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) { if (!Index) {
Progress.ProgressDialog->Destroy(); Progress.ProgressDialog->Destroy();
wxString temp(FFMSErrMsg, wxConvUTF8); wxString temp(FFMSErrMsg, wxConvUTF8);
@ -239,7 +239,7 @@ wxThread::ExitCode FFmpegSourceCacheCleaner::Entry() {
if (numfiles <= maxfiles && cursize <= maxsize) { if (numfiles <= maxfiles && cursize <= maxsize) {
wxLogDebug(_T("FFmpegSourceCacheCleaner: cache does not need cleaning (maxsize=%d, cursize=%d; maxfiles=%d, numfiles=%d), exiting"), 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; return (wxThread::ExitCode)0;
} }

View file

@ -63,7 +63,8 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d
throw _T("FFmpegSource video provider: COM initialization failure"); throw _T("FFmpegSource video provider: COM initialization failure");
#endif #endif
// initialize ffmpegsource // initialize ffmpegsource
FFMS_Init(); // FIXME: CPU detection?
FFMS_Init(0);
// clean up variables // clean up variables
VideoSource = NULL; VideoSource = NULL;
@ -105,9 +106,20 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
wxString CacheName = GetCacheFilename(filename.c_str()); wxString CacheName = GetCacheFilename(filename.c_str());
// try to read index // 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) { if (Index == NULL) {
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 // index didn't exist or was invalid, we'll have to (re)create it
if (ReIndex) {
try { try {
try { try {
// ignore audio decoding errors here, we don't care right now // 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; 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); FFMS_DestroyIndex(Index);
Index = NULL; Index = NULL;
if (VideoSource == NULL) { if (VideoSource == NULL) {
@ -171,7 +183,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource); FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource);
if (FrameData == NULL) if (FrameData == NULL)
throw _T("FFmpegSource video provider: failed to get frame data"); 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) if (TimeBase == NULL)
throw _T("FFmpegSource video provider: failed to get track time base"); 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); KeyFramesList.Add(CurFrameNum);
// calculate timestamp and add to timecodes vector // 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); TimecodesVector.push_back(Timestamp);
} }
KeyFramesLoaded = true; 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 // requested format was changed since last time we were called, (re)set output format
if (LastDstFormat != DstFormat) { 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); wxString temp(FFMSErrorMessage, wxConvUTF8);
ErrorMsg << _T("Failed to set output format: ") << temp; ErrorMsg << _T("Failed to set output format: ") << temp;
throw ErrorMsg; throw ErrorMsg;
@ -275,7 +287,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
} }
// decode frame // decode frame
const TAVFrameLite *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize); const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize);
if (SrcFrame == NULL) { if (SrcFrame == NULL) {
wxString temp(FFMSErrorMessage, wxConvUTF8); wxString temp(FFMSErrorMessage, wxConvUTF8);
ErrorMsg << _T("Failed to retrieve frame: ") << temp; ErrorMsg << _T("Failed to retrieve frame: ") << temp;

View file

@ -48,7 +48,7 @@
class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider { class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
private: private:
FFVideo *VideoSource; FFVideo *VideoSource;
const TVideoProperties *VideoInfo; const FFVideoProperties *VideoInfo;
int FrameNumber; int FrameNumber;
wxArrayInt KeyFramesList; wxArrayInt KeyFramesList;