Use FFMS_DoIndexing2 when using a recent version of ffms2
And clean up the audio track selection logic a bit.
This commit is contained in:
parent
95f3f30d53
commit
1aa9215e7f
4 changed files with 56 additions and 65 deletions
|
@ -91,18 +91,20 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, std::string> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
std::map<int, std::string> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
||||||
if (TrackList.empty())
|
|
||||||
throw agi::AudioDataNotFound("no audio tracks found");
|
|
||||||
|
|
||||||
// initialize the track number to an invalid value so we can detect later on
|
// initialize the track number to an invalid value so we can detect later on
|
||||||
// whether the user actually had to choose a track or not
|
// whether the user actually had to choose a track or not
|
||||||
int TrackNumber = -1;
|
int TrackNumber = -1;
|
||||||
if (TrackList.size() > 1) {
|
if (TrackList.size() > 1) {
|
||||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
auto Selection = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
||||||
// if it's still -1 here, user pressed cancel
|
if (Selection == TrackSelection::None)
|
||||||
if (TrackNumber == -1)
|
|
||||||
throw agi::UserCancelException("audio loading canceled by user");
|
throw agi::UserCancelException("audio loading canceled by user");
|
||||||
|
TrackNumber = static_cast<int>(Selection);
|
||||||
}
|
}
|
||||||
|
else if (TrackList.size() == 1)
|
||||||
|
TrackNumber = TrackList.begin()->first;
|
||||||
|
else
|
||||||
|
throw agi::AudioDataNotFound("no audio tracks found");
|
||||||
|
|
||||||
// generate a name for the cache file
|
// generate a name for the cache file
|
||||||
agi::fs::path CacheName = GetCacheFilename(filename);
|
agi::fs::path CacheName = GetCacheFilename(filename);
|
||||||
|
@ -114,24 +116,13 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
if (Index && FFMS_IndexBelongsToFile(Index, filename.string().c_str(), &ErrInfo))
|
if (Index && FFMS_IndexBelongsToFile(Index, filename.string().c_str(), &ErrInfo))
|
||||||
Index = nullptr;
|
Index = nullptr;
|
||||||
|
|
||||||
// index valid but track number still not set?
|
|
||||||
if (Index) {
|
if (Index) {
|
||||||
// track number not set? just grab the first track
|
// we already have an index, but the desired track may not have been
|
||||||
if (TrackNumber < 0)
|
// indexed, and if it wasn't we need to reindex
|
||||||
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
|
|
||||||
if (TrackNumber < 0)
|
|
||||||
throw agi::AudioDataNotFound(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer);
|
|
||||||
|
|
||||||
// index is valid and track number is now set,
|
|
||||||
// but do we have indexing info for the desired audio track?
|
|
||||||
FFMS_Track *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
FFMS_Track *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
||||||
if (FFMS_GetNumFrames(TempTrackData) <= 0)
|
if (FFMS_GetNumFrames(TempTrackData) <= 0)
|
||||||
Index = nullptr;
|
Index = nullptr;
|
||||||
}
|
}
|
||||||
// no valid index exists and the file only has one audio track, index it
|
|
||||||
else if (TrackNumber < 0)
|
|
||||||
TrackNumber = FFMS_TRACKMASK_ALL;
|
|
||||||
// else: do nothing (keep track mask as it is)
|
|
||||||
|
|
||||||
// reindex if the error handling mode has changed
|
// reindex if the error handling mode has changed
|
||||||
FFMS_IndexErrorHandling ErrorHandling = GetErrorHandlingMode();
|
FFMS_IndexErrorHandling ErrorHandling = GetErrorHandlingMode();
|
||||||
|
@ -142,17 +133,10 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
|
|
||||||
// moment of truth
|
// moment of truth
|
||||||
if (!Index) {
|
if (!Index) {
|
||||||
int TrackMask;
|
TrackSelection TrackMask = static_cast<TrackSelection>(TrackNumber);
|
||||||
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() || TrackNumber == FFMS_TRACKMASK_ALL)
|
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool())
|
||||||
TrackMask = FFMS_TRACKMASK_ALL;
|
TrackMask = TrackSelection::All;
|
||||||
else
|
|
||||||
TrackMask = (1 << TrackNumber);
|
|
||||||
|
|
||||||
Index = DoIndexing(Indexer, CacheName, TrackMask, ErrorHandling);
|
Index = DoIndexing(Indexer, CacheName, TrackMask, ErrorHandling);
|
||||||
|
|
||||||
// if tracknumber still isn't set we need to set it now
|
|
||||||
if (TrackNumber == FFMS_TRACKMASK_ALL)
|
|
||||||
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
FFMS_CancelIndexing(Indexer);
|
FFMS_CancelIndexing(Indexer);
|
||||||
|
|
|
@ -60,7 +60,10 @@ FFmpegSourceProvider::FFmpegSourceProvider(agi::BackgroundRunner *br)
|
||||||
/// @param Indexer A pointer to the indexer object representing the file to be indexed
|
/// @param Indexer A pointer to the indexer object representing the file to be indexed
|
||||||
/// @param CacheName The filename of the output index file
|
/// @param CacheName The filename of the output index file
|
||||||
/// @param Trackmask A binary mask of the track numbers to index
|
/// @param Trackmask A binary mask of the track numbers to index
|
||||||
FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, agi::fs::path const& CacheName, int Trackmask, FFMS_IndexErrorHandling IndexEH) {
|
FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer,
|
||||||
|
agi::fs::path const& CacheName,
|
||||||
|
TrackSelection Track,
|
||||||
|
FFMS_IndexErrorHandling IndexEH) {
|
||||||
char FFMSErrMsg[1024];
|
char FFMSErrMsg[1024];
|
||||||
FFMS_ErrorInfo ErrInfo;
|
FFMS_ErrorInfo ErrInfo;
|
||||||
ErrInfo.Buffer = FFMSErrMsg;
|
ErrInfo.Buffer = FFMSErrMsg;
|
||||||
|
@ -78,8 +81,22 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, agi::fs::pat
|
||||||
ps->SetProgress(Current, Total);
|
ps->SetProgress(Current, Total);
|
||||||
return ps->IsCancelled();
|
return ps->IsCancelled();
|
||||||
};
|
};
|
||||||
Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE,
|
#if FFMS_VERSION >= ((2 << 24) | (21 << 16) | (0 << 8) | 0)
|
||||||
|
if (Track == TrackSelection::All)
|
||||||
|
FFMS_TrackTypeIndexSettings(Indexer, FFMS_TYPE_AUDIO, 1, 0);
|
||||||
|
else if (Track != TrackSelection::None)
|
||||||
|
FFMS_TrackIndexSettings(Indexer, static_cast<int>(Track), 1, 0);
|
||||||
|
FFMS_SetProgressCallback(Indexer, callback, ps);
|
||||||
|
Index = FFMS_DoIndexing2(Indexer, IndexEH, &ErrInfo);
|
||||||
|
#else
|
||||||
|
int Trackmask = 0;
|
||||||
|
if (Track == TrackSelection::All)
|
||||||
|
Trackmask = std::numeric_limits<int>::max();
|
||||||
|
else if (Track != TrackSelection::None)
|
||||||
|
Trackmask = 1 << static_cast<int>(Track);
|
||||||
|
Index = FFMS_DoIndexing(Indexer, Trackmask, 0,
|
||||||
nullptr, nullptr, IndexEH, callback, ps, &ErrInfo);
|
nullptr, nullptr, IndexEH, callback, ps, &ErrInfo);
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Index == nullptr)
|
if (Index == nullptr)
|
||||||
|
@ -99,21 +116,24 @@ std::map<int, std::string> FFmpegSourceProvider::GetTracksOfType(FFMS_Indexer *I
|
||||||
std::map<int,std::string> TrackList;
|
std::map<int,std::string> TrackList;
|
||||||
int NumTracks = FFMS_GetNumTracksI(Indexer);
|
int NumTracks = FFMS_GetNumTracksI(Indexer);
|
||||||
|
|
||||||
|
// older versions of ffms2 can't index audio tracks past 31
|
||||||
|
#if FFMS_VERSION < ((2 << 24) | (21 << 16) | (0 << 8) | 0)
|
||||||
|
if (Type == FFMS_TYPE_AUDIO)
|
||||||
|
NumTracks = std::min(NumTracks, std::numeric_limits<int>::digits);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i=0; i<NumTracks; i++) {
|
for (int i=0; i<NumTracks; i++) {
|
||||||
if (FFMS_GetTrackTypeI(Indexer, i) == Type) {
|
if (FFMS_GetTrackTypeI(Indexer, i) == Type) {
|
||||||
const char *CodecName = FFMS_GetCodecNameI(Indexer, i);
|
if (auto CodecName = FFMS_GetCodecNameI(Indexer, i))
|
||||||
if (CodecName)
|
TrackList[i] = CodecName;
|
||||||
TrackList.insert(std::pair<int,std::string>(i, CodecName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TrackList;
|
return TrackList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Ask user for which track he wants to load
|
FFmpegSourceProvider::TrackSelection
|
||||||
/// @param TrackList A std::map with the track numbers as keys and codec names as values
|
FFmpegSourceProvider::AskForTrackSelection(const std::map<int, std::string> &TrackList,
|
||||||
/// @param Type The track type to ask about
|
FFMS_TrackType Type) {
|
||||||
/// @return Returns the track number chosen (an integer >= 0) on success, or a negative integer if the user cancelled.
|
|
||||||
int FFmpegSourceProvider::AskForTrackSelection(const std::map<int, std::string> &TrackList, FFMS_TrackType Type) {
|
|
||||||
std::vector<int> TrackNumbers;
|
std::vector<int> TrackNumbers;
|
||||||
wxArrayString Choices;
|
wxArrayString Choices;
|
||||||
|
|
||||||
|
@ -128,8 +148,8 @@ int FFmpegSourceProvider::AskForTrackSelection(const std::map<int, std::string>
|
||||||
Choices);
|
Choices);
|
||||||
|
|
||||||
if (Choice < 0)
|
if (Choice < 0)
|
||||||
return Choice;
|
return TrackSelection::None;
|
||||||
return TrackNumbers[Choice];
|
return static_cast<TrackSelection>(TrackNumbers[Choice]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Set ffms2 log level according to setting in config.dat
|
/// @brief Set ffms2 log level according to setting in config.dat
|
||||||
|
|
|
@ -42,11 +42,6 @@
|
||||||
|
|
||||||
namespace agi { class BackgroundRunner; }
|
namespace agi { class BackgroundRunner; }
|
||||||
|
|
||||||
/// Index all tracks
|
|
||||||
#define FFMS_TRACKMASK_ALL -1
|
|
||||||
/// Index no tracks
|
|
||||||
#define FFMS_TRACKMASK_NONE 0
|
|
||||||
|
|
||||||
/// @class FFmpegSourceProvider
|
/// @class FFmpegSourceProvider
|
||||||
/// @brief Base class for FFMS2 source providers; contains common functions etc
|
/// @brief Base class for FFMS2 source providers; contains common functions etc
|
||||||
class FFmpegSourceProvider {
|
class FFmpegSourceProvider {
|
||||||
|
@ -56,24 +51,18 @@ class FFmpegSourceProvider {
|
||||||
public:
|
public:
|
||||||
FFmpegSourceProvider(agi::BackgroundRunner *br);
|
FFmpegSourceProvider(agi::BackgroundRunner *br);
|
||||||
|
|
||||||
/// Logging level constants from avutil/log.h
|
enum class TrackSelection : int {
|
||||||
enum FFMS_LogLevel {
|
None = -1,
|
||||||
/// nothing printed
|
All = -2
|
||||||
FFMS_LOG_QUIET = -8,
|
|
||||||
FFMS_LOG_PANIC = 0,
|
|
||||||
FFMS_LOG_FATAL = 8,
|
|
||||||
FFMS_LOG_ERROR = 16,
|
|
||||||
FFMS_LOG_WARNING = 24,
|
|
||||||
FFMS_LOG_INFO = 32,
|
|
||||||
FFMS_LOG_VERBOSE = 40,
|
|
||||||
FFMS_LOG_DEBUG = 48,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void CleanCache();
|
void CleanCache();
|
||||||
|
|
||||||
FFMS_Index *DoIndexing(FFMS_Indexer *Indexer, agi::fs::path const& Cachename, int Trackmask, FFMS_IndexErrorHandling IndexEH);
|
FFMS_Index *DoIndexing(FFMS_Indexer *Indexer, agi::fs::path const& Cachename,
|
||||||
|
TrackSelection Track,
|
||||||
|
FFMS_IndexErrorHandling IndexEH);
|
||||||
std::map<int, std::string> GetTracksOfType(FFMS_Indexer *Indexer, FFMS_TrackType Type);
|
std::map<int, std::string> GetTracksOfType(FFMS_Indexer *Indexer, FFMS_TrackType Type);
|
||||||
int AskForTrackSelection(const std::map<int, std::string>& TrackList, FFMS_TrackType Type);
|
TrackSelection AskForTrackSelection(const std::map<int, std::string>& TrackList, FFMS_TrackType Type);
|
||||||
agi::fs::path GetCacheFilename(agi::fs::path const& filename);
|
agi::fs::path GetCacheFilename(agi::fs::path const& filename);
|
||||||
void SetLogLevel();
|
void SetLogLevel();
|
||||||
FFMS_IndexErrorHandling GetErrorHandlingMode();
|
FFMS_IndexErrorHandling GetErrorHandlingMode();
|
||||||
|
|
|
@ -149,14 +149,12 @@ void FFmpegSourceVideoProvider::LoadVideo(agi::fs::path const& filename, std::st
|
||||||
if (TrackList.size() <= 0)
|
if (TrackList.size() <= 0)
|
||||||
throw VideoNotSupported("no video tracks found");
|
throw VideoNotSupported("no video tracks found");
|
||||||
|
|
||||||
// initialize the track number to an invalid value so we can detect later on
|
|
||||||
// whether the user actually had to choose a track or not
|
|
||||||
int TrackNumber = -1;
|
int TrackNumber = -1;
|
||||||
if (TrackList.size() > 1) {
|
if (TrackList.size() > 1) {
|
||||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
auto Selection = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
||||||
// if it's still -1 here, user pressed cancel
|
if (Selection == TrackSelection::None)
|
||||||
if (TrackNumber == -1)
|
|
||||||
throw agi::UserCancelException("video loading cancelled by user");
|
throw agi::UserCancelException("video loading cancelled by user");
|
||||||
|
TrackNumber = static_cast<int>(Selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a name for the cache file
|
// generate a name for the cache file
|
||||||
|
@ -180,9 +178,9 @@ void FFmpegSourceVideoProvider::LoadVideo(agi::fs::path const& filename, std::st
|
||||||
|
|
||||||
// moment of truth
|
// moment of truth
|
||||||
if (!Index) {
|
if (!Index) {
|
||||||
int TrackMask = FFMS_TRACKMASK_NONE;
|
auto TrackMask = TrackSelection::None;
|
||||||
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() || OPT_GET("Video/Open Audio")->GetBool())
|
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() || OPT_GET("Video/Open Audio")->GetBool())
|
||||||
TrackMask = FFMS_TRACKMASK_ALL;
|
TrackMask = TrackSelection::All;
|
||||||
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
|
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in a new issue