forked from mia/Aegisub
Update the FFMS2 audio and video providers to use the new API features.
Originally committed to SVN as r3116.
This commit is contained in:
parent
5dc912bf4d
commit
a45282bfbb
4 changed files with 61 additions and 46 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue