mirror of https://github.com/odrling/Aegisub
Implement support for multiple tracks in the FFMS2 audio and video providers. Files with more than one audio or video track will now let the user pick which one he/she wishes to load. Closes #905.
Originally committed to SVN as r3145.
This commit is contained in:
parent
5cb4d1cae3
commit
c33ed91b12
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,6 +41,8 @@
|
|||
// Headers
|
||||
#include "include/aegisub/aegisub.h"
|
||||
#include "audio_provider_ffmpegsource.h"
|
||||
#include "options.h"
|
||||
#include <map>
|
||||
#ifdef WIN32
|
||||
#include <objbase.h>
|
||||
#endif
|
||||
|
@ -61,7 +63,7 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(Aegisub::String filename) {
|
|||
FFMS_Init(0);
|
||||
|
||||
MsgSize = sizeof(FFMSErrMsg);
|
||||
MsgString = _T("FFmpegSource audio provider: ");
|
||||
ErrorMsg = _T("FFmpegSource audio provider: ");
|
||||
|
||||
AudioSource = NULL;
|
||||
|
||||
|
@ -82,60 +84,78 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
|
|||
|
||||
wxString FileNameWX = wxFileName(wxString(filename.c_str(), wxConvFile)).GetShortPath();
|
||||
|
||||
// generate a default name for the cache file
|
||||
FFIndexer *Indexer = FFMS_CreateIndexer(FileNameWX.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
|
||||
if (Indexer == NULL) {
|
||||
// error messages that can possibly contain a filename use this method instead of
|
||||
// wxString::Format because they may contain utf8 characters
|
||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
||||
if (TrackList.size() <= 0)
|
||||
throw _T("FFmpegSource audio provider: no audio 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;
|
||||
if (TrackList.size() > 1) {
|
||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
||||
// if it's still -1 here, user pressed cancel
|
||||
if (TrackNumber == -1)
|
||||
throw _T("FFmpegSource audio provider: audio loading cancelled by user");
|
||||
}
|
||||
|
||||
// generate a name for the cache file
|
||||
wxString CacheName = GetCacheFilename(filename.c_str());
|
||||
|
||||
// try to read index
|
||||
FFIndex *Index = NULL;
|
||||
bool ReIndex = false;
|
||||
Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
|
||||
if (Index == NULL) {
|
||||
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) {
|
||||
bool IndexIsValid = false;
|
||||
if (Index != NULL) {
|
||||
if (FFMS_IndexBelongsToFile(Index, FileNameWX.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
throw _T("FFmpegSource audio provider: no tracks found in index file");
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumTracks; i++) {
|
||||
FFTrack *TrackData = FFMS_GetTrackFromIndex(Index, i);
|
||||
// more sanity checking
|
||||
if (TrackData == NULL) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = 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(TrackData) <= 0 && (FFMS_GetTrackType(TrackData) == FFMS_TYPE_AUDIO)) {
|
||||
// found an unindexed audio track, we'll need to reindex
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ReIndex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
IndexIsValid = true;
|
||||
}
|
||||
|
||||
// index didn't exist or was invalid, we'll have to (re)create it
|
||||
if (ReIndex) {
|
||||
// index valid but track number still not set?
|
||||
if (IndexIsValid) {
|
||||
// track number not set? just grab the first track
|
||||
if (TrackNumber < 0)
|
||||
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, FFMSErrMsg, MsgSize);
|
||||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any audio tracks: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
// index is valid and track number is now set,
|
||||
// but do we have indexing info for the desired audio track?
|
||||
FFTrack *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
||||
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
||||
IndexIsValid = false;
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
}
|
||||
}
|
||||
// no valid index exists and the file only has one audio track, index all tracks
|
||||
else if (TrackNumber < 0)
|
||||
TrackNumber = FFMSTrackMaskAll;
|
||||
// else: do nothing (keep track mask as it is)
|
||||
|
||||
// moment of truth
|
||||
if (!IndexIsValid) {
|
||||
int TrackMask = Options.AsBool(_T("FFmpegSource always index all tracks")) ? FFMSTrackMaskAll : 1 << TrackNumber;
|
||||
try {
|
||||
Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, false);
|
||||
Index = DoIndexing(Indexer, CacheName, TrackMask, false);
|
||||
} catch (wxString temp) {
|
||||
MsgString << temp;
|
||||
throw MsgString;
|
||||
ErrorMsg.Append(temp);
|
||||
throw ErrorMsg;
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
|
@ -144,23 +164,12 @@ void FFmpegSourceAudioProvider::LoadAudio(Aegisub::String filename) {
|
|||
// update access time of index file so it won't get cleaned away
|
||||
wxFileName(CacheName).Touch();
|
||||
|
||||
// FIXME: provide a way to choose which audio track to load?
|
||||
int TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, FFMSErrMsg, MsgSize);
|
||||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
wxString temp(FFMSErrMsg, wxConvUTF8);
|
||||
MsgString << _T("Couldn't find any audio tracks: ") << temp;
|
||||
throw MsgString;
|
||||
}
|
||||
|
||||
AudioSource = FFMS_CreateAudioSource(FileNameWX.mb_str(wxConvUTF8), TrackNumber, Index, FFMSErrMsg, MsgSize);
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
if (!AudioSource) {
|
||||
wxString temp(FFMSErrMsg, wxConvUTF8);
|
||||
MsgString << _T("Failed to open audio track: ") << temp;
|
||||
throw MsgString;
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to open audio track: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
const FFAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
||||
|
@ -171,7 +180,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
|
||||
// FIXME: use the actual sample format too?
|
||||
// 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;
|
||||
|
@ -207,9 +216,8 @@ void FFmpegSourceAudioProvider::Close() {
|
|||
// Get audio
|
||||
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, FFMSErrMsg, MsgSize)) {
|
||||
wxString temp(FFMSErrMsg, wxConvUTF8);
|
||||
MsgString << _T("Failed to get audio samples: ") << temp;
|
||||
throw MsgString;
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to get audio samples: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -49,7 +49,7 @@ private:
|
|||
|
||||
char FFMSErrMsg[1024];
|
||||
unsigned MsgSize;
|
||||
wxString MsgString;
|
||||
wxString ErrorMsg;
|
||||
|
||||
bool COMInited;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -50,7 +50,7 @@
|
|||
#include <map>
|
||||
|
||||
|
||||
// lookit dis here static shit
|
||||
// lookit dis here static storage
|
||||
wxMutex FFmpegSourceProvider::CleaningInProgress;
|
||||
|
||||
|
||||
|
@ -62,8 +62,8 @@ int FFMS_CC FFmpegSourceProvider::UpdateIndexingProgress(int64_t Current, int64_
|
|||
if (Progress->IndexingCanceled)
|
||||
return 1;
|
||||
|
||||
// noone cares about a little bit of a rounding error here anyway
|
||||
Progress->ProgressDialog->SetProgress((1000*Current)/Total, 1000);
|
||||
// no one cares about a little bit of a rounding error here anyway
|
||||
Progress->ProgressDialog->SetProgress(((int64_t)1000*Current)/Total, 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ int FFMS_CC FFmpegSourceProvider::UpdateIndexingProgress(int64_t Current, int64_
|
|||
|
||||
///////////
|
||||
// Do indexing
|
||||
FFIndex *FFmpegSourceProvider::DoIndexing(FFIndex *Index, wxString FileNameWX, wxString CacheName, int Trackmask, bool IgnoreDecodeErrors) {
|
||||
FFIndex *FFmpegSourceProvider::DoIndexing(FFIndexer *Indexer, const wxString &CacheName, int Trackmask, bool IgnoreDecodeErrors) {
|
||||
char FFMSErrMsg[1024];
|
||||
unsigned MsgSize = sizeof(FFMSErrMsg);
|
||||
wxString MsgString;
|
||||
|
@ -79,16 +79,17 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndex *Index, wxString FileNameWX, w
|
|||
// set up progress dialog callback
|
||||
IndexingProgressDialog Progress;
|
||||
Progress.IndexingCanceled = false;
|
||||
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled, _("Reading timecodes and frame/sample data"), 0, 1);
|
||||
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled,
|
||||
_("Reading timecodes and frame/sample data"), 0, 1);
|
||||
Progress.ProgressDialog->Show();
|
||||
Progress.ProgressDialog->SetProgress(0,1);
|
||||
|
||||
// index all audio tracks
|
||||
Index = FFMS_MakeIndex(FileNameWX.mb_str(wxConvUTF8), Trackmask, FFMSTrackMaskNone, NULL, NULL, IgnoreDecodeErrors, FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize);
|
||||
if (!Index) {
|
||||
FFIndex *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMSTrackMaskNone, NULL, NULL, IgnoreDecodeErrors,
|
||||
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize);
|
||||
if (Index == NULL) {
|
||||
Progress.ProgressDialog->Destroy();
|
||||
wxString temp(FFMSErrMsg, wxConvUTF8);
|
||||
MsgString << _T("Failed to index: ") << temp;
|
||||
MsgString.Append(_T("Failed to index: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
||||
throw MsgString;
|
||||
}
|
||||
Progress.ProgressDialog->Destroy();
|
||||
|
@ -105,6 +106,47 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndex *Index, wxString FileNameWX, w
|
|||
return Index;
|
||||
}
|
||||
|
||||
///////////
|
||||
// Find all tracks of the given typo and return their track numbers and respective codec names
|
||||
std::map<int,wxString> FFmpegSourceProvider::GetTracksOfType(FFIndexer *Indexer, FFMS_TrackType Type) {
|
||||
std::map<int,wxString> TrackList;
|
||||
int NumTracks = FFMS_GetNumTracksI(Indexer);
|
||||
|
||||
for (int i=0; i<NumTracks; i++) {
|
||||
if (FFMS_GetTrackTypeI(Indexer, i) == Type) {
|
||||
wxString CodecName(FFMS_GetCodecNameI(Indexer, i), wxConvUTF8);
|
||||
TrackList.insert(std::pair<int,wxString>(i, CodecName));
|
||||
}
|
||||
}
|
||||
|
||||
return TrackList;
|
||||
}
|
||||
|
||||
///////////
|
||||
// Ask user for which track he wants to load
|
||||
int FFmpegSourceProvider::AskForTrackSelection(const std::map<int,wxString> &TrackList, FFMS_TrackType Type) {
|
||||
std::vector<int> TrackNumbers;
|
||||
wxArrayString Choices;
|
||||
wxString TypeName = _T("");
|
||||
if (Type == FFMS_TYPE_VIDEO)
|
||||
TypeName = _("video");
|
||||
else if (Type == FFMS_TYPE_AUDIO)
|
||||
TypeName = _("audio");
|
||||
|
||||
for (std::map<int,wxString>::const_iterator i = TrackList.begin(); i != TrackList.end(); i++) {
|
||||
Choices.Add(wxString::Format(_("Track %02d: %s"), i->first, i->second.c_str()));
|
||||
TrackNumbers.push_back(i->first);
|
||||
}
|
||||
|
||||
int Choice = wxGetSingleChoiceIndex(wxString::Format(_("Multiple %s tracks detected, please choose the one you wish to load:"), TypeName.c_str()),
|
||||
wxString::Format(_("Choose %s track"), TypeName.c_str()), Choices);
|
||||
|
||||
if (Choice < 0)
|
||||
return Choice;
|
||||
else
|
||||
return TrackNumbers[Choice];
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// Creates a name for the ffmpegsource2 index and prepares the folder if it doesn't exist
|
||||
// method by amz
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -60,7 +60,10 @@ public:
|
|||
bool CleanCache();
|
||||
|
||||
static int FFMS_CC UpdateIndexingProgress(int64_t Current, int64_t Total, void *Private);
|
||||
FFIndex *DoIndexing(FFIndex *Index, wxString Filename, wxString Cachename, int Trackmask, bool IgnoreDecodeErrors);
|
||||
|
||||
FFIndex *DoIndexing(FFIndexer *Indexer, const wxString& Cachename, int Trackmask, bool IgnoreDecodeErrors);
|
||||
std::map<int,wxString> GetTracksOfType(FFIndexer *Indexer, FFMS_TrackType Type);
|
||||
int AskForTrackSelection(const std::map<int,wxString>& TrackList, FFMS_TrackType Type);
|
||||
wxString GetCacheFilename(const wxString& filename);
|
||||
|
||||
virtual FFmpegSourceProvider::~FFmpegSourceProvider() {}
|
||||
|
|
|
@ -176,6 +176,7 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) {
|
|||
SetBool(_T("Video Use Pixel Shaders"),false,1700);
|
||||
SetInt(_T("FFmpegSource max cache size"),42);
|
||||
SetInt(_T("FFmpegSource max cache files"),20);
|
||||
SetInt(_T("FFmpegSource always index all tracks"), true);
|
||||
|
||||
// Audio Options
|
||||
SetModificationType(MOD_AUTOMATIC);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -40,6 +40,8 @@
|
|||
///////////
|
||||
// Headers
|
||||
#include <wx/utils.h>
|
||||
#include <wx/choicdlg.h>
|
||||
#include <map>
|
||||
#include "include/aegisub/aegisub.h"
|
||||
#include "video_provider_ffmpegsource.h"
|
||||
#include "video_context.h"
|
||||
|
@ -72,7 +74,7 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d
|
|||
LastDstFormat = FFMS_GetPixFmt("none");
|
||||
KeyFramesLoaded = false;
|
||||
FrameNumber = -1;
|
||||
MessageSize = sizeof(FFMSErrorMessage);
|
||||
MsgSize = sizeof(FFMSErrMsg);
|
||||
ErrorMsg = _T("FFmpegSource video provider: ");
|
||||
|
||||
// and here we go
|
||||
|
@ -102,40 +104,75 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
|||
|
||||
wxString FileNameWX = wxFileName(wxString(filename.c_str(), wxConvFile)).GetShortPath();
|
||||
|
||||
FFIndexer *Indexer = FFMS_CreateIndexer(FileNameWX.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
|
||||
if (Indexer == NULL) {
|
||||
// error messages that can possibly contain a filename use this method instead of
|
||||
// wxString::Format because they may contain utf8 characters
|
||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_VIDEO);
|
||||
if (TrackList.size() <= 0)
|
||||
throw _T("FFmpegSource video provider: 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;
|
||||
if (TrackList.size() > 1) {
|
||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
||||
// if it's still -1 here, user pressed cancel
|
||||
if (TrackNumber == -1)
|
||||
throw _T("FFmpegSource video provider: video loading cancelled by user");
|
||||
}
|
||||
|
||||
// generate a name for the cache file
|
||||
wxString CacheName = GetCacheFilename(filename.c_str());
|
||||
|
||||
// try to read index
|
||||
FFIndex *Index = NULL;
|
||||
Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrorMessage, MessageSize);
|
||||
bool ReIndex = false;
|
||||
if (Index == NULL) {
|
||||
ReIndex = true;
|
||||
}
|
||||
else if (FFMS_IndexBelongsToFile(Index, FileNameWX.mb_str(wxConvUTF8), FFMSErrorMessage, MessageSize)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ReIndex = true;
|
||||
Index = FFMS_ReadIndex(CacheName.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize);
|
||||
bool IndexIsValid = false;
|
||||
if (Index != NULL) {
|
||||
if (FFMS_IndexBelongsToFile(Index, FileNameWX.mb_str(wxConvUTF8), FFMSErrMsg, MsgSize)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
}
|
||||
else
|
||||
IndexIsValid = true;
|
||||
}
|
||||
|
||||
// index didn't exist or was invalid, we'll have to (re)create it
|
||||
if (ReIndex) {
|
||||
// time to examine the index and check if the track we want is indexed
|
||||
// technically this isn't really needed since all video tracks should always be indexed,
|
||||
// but a bit of sanity checking never hurt anyone
|
||||
if (IndexIsValid && TrackNumber >= 0) {
|
||||
FFTrack *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
||||
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
||||
IndexIsValid = false;
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// moment of truth
|
||||
if (!IndexIsValid) {
|
||||
int TrackMask = Options.AsBool(_T("FFmpegSource always index all tracks")) ? FFMSTrackMaskAll : FFMSTrackMaskNone;
|
||||
try {
|
||||
try {
|
||||
// ignore audio decoding errors here, we don't care right now
|
||||
Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskAll, true);
|
||||
Index = DoIndexing(Indexer, CacheName, TrackMask, true);
|
||||
} catch (...) {
|
||||
// Try without audio
|
||||
Index = DoIndexing(Index, FileNameWX, CacheName, FFMSTrackMaskNone, true);
|
||||
// something borked, try if it works without audio
|
||||
Index = DoIndexing(Indexer, CacheName, FFMSTrackMaskNone, true);
|
||||
}
|
||||
} catch (wxString temp) {
|
||||
ErrorMsg << temp;
|
||||
ErrorMsg.Append(temp);
|
||||
throw ErrorMsg;
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// update access time of index file so it won't get cleaned away
|
||||
wxFileName(CacheName).Touch();
|
||||
|
||||
|
@ -144,6 +181,18 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
|||
//do something?
|
||||
}
|
||||
|
||||
// track number still not set?
|
||||
if (TrackNumber < 0) {
|
||||
// just grab the first track
|
||||
TrackNumber = FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_VIDEO, FFMSErrMsg, MsgSize);
|
||||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
}
|
||||
|
||||
// set thread count
|
||||
int Threads = Options.AsInt(_T("FFmpegSource decoding threads"));
|
||||
if (Threads < 1)
|
||||
|
@ -157,22 +206,11 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
|||
else
|
||||
SeekMode = FFMS_SEEK_NORMAL;
|
||||
|
||||
// FIXME: provide a way to choose which audio track to load?
|
||||
int TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_VIDEO, FFMSErrorMessage, MessageSize);
|
||||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
wxString temp(FFMSErrorMessage, wxConvUTF8);
|
||||
ErrorMsg << _T("Couldn't find any video tracks: ") << temp;
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
VideoSource = FFMS_CreateVideoSource(FileNameWX.mb_str(wxConvUTF8), TrackNumber, Index, "", Threads, SeekMode, FFMSErrorMessage, MessageSize);
|
||||
VideoSource = FFMS_CreateVideoSource(FileNameWX.mb_str(wxConvUTF8), TrackNumber, Index, "", Threads, SeekMode, FFMSErrMsg, MsgSize);
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
if (VideoSource == NULL) {
|
||||
wxString temp(FFMSErrorMessage, wxConvUTF8);
|
||||
ErrorMsg << _T("Failed to open video track: ") << temp;
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to open video track: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
|
@ -193,8 +231,7 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
|||
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
||||
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
|
||||
if (CurFrameData == NULL) {
|
||||
wxString temp(FFMSErrorMessage, wxConvUTF8);
|
||||
ErrorMsg << _T("Couldn't get framedata for frame ") << CurFrameNum << _T(": ") << temp;
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't get info about frame %d"), CurFrameNum));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
|
@ -278,19 +315,17 @@ 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_SetOutputFormatV(VideoSource, 1 << DstFormat, w, h, FFMS_RESIZER_BICUBIC, FFMSErrorMessage, MessageSize)) {
|
||||
wxString temp(FFMSErrorMessage, wxConvUTF8);
|
||||
ErrorMsg << _T("Failed to set output format: ") << temp;
|
||||
if (FFMS_SetOutputFormatV(VideoSource, 1 << DstFormat, w, h, FFMS_RESIZER_BICUBIC, FFMSErrMsg, MsgSize)) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
LastDstFormat = DstFormat;
|
||||
}
|
||||
|
||||
// decode frame
|
||||
const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize);
|
||||
const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrMsg, MsgSize);
|
||||
if (SrcFrame == NULL) {
|
||||
wxString temp(FFMSErrorMessage, wxConvUTF8);
|
||||
ErrorMsg << _T("Failed to retrieve frame: ") << temp;
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to retrieve frame: %s"), FFMSErrMsg));
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2008, Karl Blomster
|
||||
// Copyright (c) 2008-2009, Karl Blomster
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -60,8 +60,8 @@ private:
|
|||
int LastDstFormat;
|
||||
AegiVideoFrame CurFrame;
|
||||
|
||||
char FFMSErrorMessage[1024];
|
||||
unsigned MessageSize;
|
||||
char FFMSErrMsg[1024];
|
||||
unsigned MsgSize;
|
||||
wxString ErrorMsg;
|
||||
|
||||
bool COMInited;
|
||||
|
|
Loading…
Reference in New Issue