Updating ffms2 to r221 (2.12), step 3/3: Aegisub interface
Originally committed to SVN as r3576.
This commit is contained in:
parent
6e39199cb4
commit
9d80eb066f
6 changed files with 116 additions and 169 deletions
|
@ -68,7 +68,10 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
||||||
#endif
|
#endif
|
||||||
FFMS_Init(0);
|
FFMS_Init(0);
|
||||||
|
|
||||||
MsgSize = sizeof(FFMSErrMsg);
|
ErrInfo.Buffer = FFMSErrMsg;
|
||||||
|
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||||
|
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||||
|
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||||
ErrorMsg = _T("FFmpegSource audio provider: ");
|
ErrorMsg = _T("FFmpegSource audio provider: ");
|
||||||
|
|
||||||
AudioSource = NULL;
|
AudioSource = NULL;
|
||||||
|
@ -94,11 +97,11 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
|
|
||||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||||
|
|
||||||
FFIndexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), FFMSErrMsg, MsgSize);
|
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||||
if (Indexer == NULL) {
|
if (Indexer == NULL) {
|
||||||
// error messages that can possibly contain a filename use this method instead of
|
// error messages that can possibly contain a filename use this method instead of
|
||||||
// wxString::Format because they may contain utf8 characters
|
// wxString::Format because they may contain utf8 characters
|
||||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,11 +123,11 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
wxString CacheName = GetCacheFilename(filename);
|
wxString CacheName = GetCacheFilename(filename);
|
||||||
|
|
||||||
// try to read index
|
// try to read index
|
||||||
FFIndex *Index = NULL;
|
FFMS_Index *Index = NULL;
|
||||||
Index = FFMS_ReadIndex(CacheName.utf8_str(), FFMSErrMsg, MsgSize);
|
Index = FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo);
|
||||||
bool IndexIsValid = false;
|
bool IndexIsValid = false;
|
||||||
if (Index != NULL) {
|
if (Index != NULL) {
|
||||||
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), FFMSErrMsg, MsgSize)) {
|
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo)) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
}
|
}
|
||||||
|
@ -136,17 +139,17 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
if (IndexIsValid) {
|
if (IndexIsValid) {
|
||||||
// track number not set? just grab the first track
|
// track number not set? just grab the first track
|
||||||
if (TrackNumber < 0)
|
if (TrackNumber < 0)
|
||||||
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, FFMSErrMsg, MsgSize);
|
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
|
||||||
if (TrackNumber < 0) {
|
if (TrackNumber < 0) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any audio tracks: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Couldn't find any audio tracks: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// index is valid and track number is now set,
|
// index is valid and track number is now set,
|
||||||
// but do we have indexing info for the desired audio track?
|
// but do we have indexing info for the desired audio track?
|
||||||
FFTrack *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
FFMS_Track *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
||||||
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
||||||
IndexIsValid = false;
|
IndexIsValid = false;
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
|
@ -176,15 +179,15 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
// warn user?
|
// warn user?
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioSource = FFMS_CreateAudioSource(FileNameShort.utf8_str(), TrackNumber, Index, FFMSErrMsg, MsgSize);
|
AudioSource = FFMS_CreateAudioSource(FileNameShort.utf8_str(), TrackNumber, Index, &ErrInfo);
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
if (!AudioSource) {
|
if (!AudioSource) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to open audio track: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Failed to open audio track: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FFAudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
||||||
|
|
||||||
channels = AudioInfo.Channels;
|
channels = AudioInfo.Channels;
|
||||||
sample_rate = AudioInfo.SampleRate;
|
sample_rate = AudioInfo.SampleRate;
|
||||||
|
@ -233,8 +236,8 @@ void FFmpegSourceAudioProvider::Close() {
|
||||||
/// @param Count
|
/// @param Count
|
||||||
///
|
///
|
||||||
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||||
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, FFMSErrMsg, MsgSize)) {
|
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, &ErrInfo)) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to get audio samples: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Failed to get audio samples: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,30 +41,16 @@
|
||||||
#include "ffmpegsource_common.h"
|
#include "ffmpegsource_common.h"
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class FFmpegSourceAudioProvider
|
/// @class FFmpegSourceAudioProvider
|
||||||
/// @brief DOCME
|
/// @brief Implents audio loading with the FFMS library.
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
|
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
|
||||||
private:
|
private:
|
||||||
|
FFMS_AudioSource *AudioSource; /// audio source object
|
||||||
|
bool COMInited; /// COM initialization state
|
||||||
|
|
||||||
/// DOCME
|
char FFMSErrMsg[1024]; /// FFMS error message
|
||||||
FFAudio *AudioSource;
|
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||||
|
wxString ErrorMsg; /// wx-ified error message
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
char FFMSErrMsg[1024];
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned MsgSize;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxString ErrorMsg;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
bool COMInited;
|
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
void LoadAudio(wxString filename);
|
void LoadAudio(wxString filename);
|
||||||
|
@ -73,29 +59,23 @@ public:
|
||||||
FFmpegSourceAudioProvider(wxString filename);
|
FFmpegSourceAudioProvider(wxString filename);
|
||||||
virtual ~FFmpegSourceAudioProvider();
|
virtual ~FFmpegSourceAudioProvider();
|
||||||
|
|
||||||
|
/// @brief Checks sample endianness
|
||||||
/// @brief // FFMS always delivers samples in machine endian
|
/// @return Returns true.
|
||||||
/// @return
|
/// FFMS always delivers native endian samples.
|
||||||
///
|
|
||||||
bool AreSamplesNativeEndian() { return true; }
|
bool AreSamplesNativeEndian() { return true; }
|
||||||
|
|
||||||
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class FFmpegSourceAudioProviderFactory
|
/// @class FFmpegSourceAudioProviderFactory
|
||||||
/// @brief DOCME
|
/// @brief Creates a FFmpegSource audio provider.
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class FFmpegSourceAudioProviderFactory : public AudioProviderFactory {
|
class FFmpegSourceAudioProviderFactory : public AudioProviderFactory {
|
||||||
public:
|
public:
|
||||||
|
/// @brief Creates a FFmpegSource audio provider.
|
||||||
/// @brief DOCME
|
/// @param video The audio filename to open.
|
||||||
/// @param file
|
/// @return Returns the audio provider.
|
||||||
///
|
|
||||||
AudioProvider *CreateProvider(wxString file) { return new FFmpegSourceAudioProvider(file); }
|
AudioProvider *CreateProvider(wxString file) { return new FFmpegSourceAudioProvider(file); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,13 @@ int FFMS_CC FFmpegSourceProvider::UpdateIndexingProgress(int64_t Current, int64_
|
||||||
/// @param IgnoreDecodeErrors True if audio decoding errors will be tolerated, false otherwise
|
/// @param IgnoreDecodeErrors True if audio decoding errors will be tolerated, false otherwise
|
||||||
/// @return Returns the index object on success, NULL otherwise
|
/// @return Returns the index object on success, NULL otherwise
|
||||||
///
|
///
|
||||||
FFIndex *FFmpegSourceProvider::DoIndexing(FFIndexer *Indexer, const wxString &CacheName, int Trackmask, bool IgnoreDecodeErrors) {
|
FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxString &CacheName, int Trackmask, bool IgnoreDecodeErrors) {
|
||||||
char FFMSErrMsg[1024];
|
char FFMSErrMsg[1024];
|
||||||
unsigned MsgSize = sizeof(FFMSErrMsg);
|
FFMS_ErrorInfo ErrInfo;
|
||||||
|
ErrInfo.Buffer = FFMSErrMsg;
|
||||||
|
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||||
|
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||||
|
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||||
wxString MsgString;
|
wxString MsgString;
|
||||||
|
|
||||||
// set up progress dialog callback
|
// set up progress dialog callback
|
||||||
|
@ -97,19 +101,21 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndexer *Indexer, const wxString &Ca
|
||||||
Progress.ProgressDialog->Show();
|
Progress.ProgressDialog->Show();
|
||||||
Progress.ProgressDialog->SetProgress(0,1);
|
Progress.ProgressDialog->SetProgress(0,1);
|
||||||
|
|
||||||
|
int ErrHandling = IgnoreDecodeErrors ? FFMS_IEH_IGNORE : FFMS_IEH_STOP_TRACK;
|
||||||
|
|
||||||
// index all audio tracks
|
// index all audio tracks
|
||||||
FFIndex *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE, NULL, NULL, IgnoreDecodeErrors,
|
FFMS_Index *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE, NULL, NULL, ErrHandling,
|
||||||
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, FFMSErrMsg, MsgSize);
|
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, &ErrInfo);
|
||||||
if (Index == NULL) {
|
if (Index == NULL) {
|
||||||
Progress.ProgressDialog->Destroy();
|
Progress.ProgressDialog->Destroy();
|
||||||
MsgString.Append(_T("Failed to index: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
MsgString.Append(_T("Failed to index: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||||
throw MsgString;
|
throw MsgString;
|
||||||
}
|
}
|
||||||
Progress.ProgressDialog->Destroy();
|
Progress.ProgressDialog->Destroy();
|
||||||
|
|
||||||
// write index to disk for later use
|
// write index to disk for later use
|
||||||
// ignore write errors for now
|
// ignore write errors for now
|
||||||
FFMS_WriteIndex(CacheName.utf8_str(), Index, FFMSErrMsg, MsgSize);
|
FFMS_WriteIndex(CacheName.utf8_str(), Index, &ErrInfo);
|
||||||
/*if (FFMS_WriteIndex(CacheName.char_str(), Index, FFMSErrMsg, MsgSize)) {
|
/*if (FFMS_WriteIndex(CacheName.char_str(), Index, FFMSErrMsg, MsgSize)) {
|
||||||
wxString temp(FFMSErrMsg, wxConvUTF8);
|
wxString temp(FFMSErrMsg, wxConvUTF8);
|
||||||
MsgString << _T("Failed to write index: ") << temp;
|
MsgString << _T("Failed to write index: ") << temp;
|
||||||
|
@ -125,7 +131,7 @@ FFIndex *FFmpegSourceProvider::DoIndexing(FFIndexer *Indexer, const wxString &Ca
|
||||||
/// @param Indexer The indexer object representing the source file
|
/// @param Indexer The indexer object representing the source file
|
||||||
/// @param Type The track type to look for
|
/// @param Type The track type to look for
|
||||||
/// @return Returns a std::map with the track numbers as keys and the codec names as values.
|
/// @return Returns a std::map with the track numbers as keys and the codec names as values.
|
||||||
std::map<int,wxString> FFmpegSourceProvider::GetTracksOfType(FFIndexer *Indexer, FFMS_TrackType Type) {
|
std::map<int,wxString> FFmpegSourceProvider::GetTracksOfType(FFMS_Indexer *Indexer, FFMS_TrackType Type) {
|
||||||
std::map<int,wxString> TrackList;
|
std::map<int,wxString> TrackList;
|
||||||
int NumTracks = FFMS_GetNumTracksI(Indexer);
|
int NumTracks = FFMS_GetNumTracksI(Indexer);
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,8 @@ public:
|
||||||
|
|
||||||
static int FFMS_CC UpdateIndexingProgress(int64_t Current, int64_t Total, void *Private);
|
static int FFMS_CC UpdateIndexingProgress(int64_t Current, int64_t Total, void *Private);
|
||||||
|
|
||||||
FFIndex *DoIndexing(FFIndexer *Indexer, const wxString& Cachename, int Trackmask, bool IgnoreDecodeErrors);
|
FFMS_Index *DoIndexing(FFMS_Indexer *Indexer, const wxString& Cachename, int Trackmask, bool IgnoreDecodeErrors);
|
||||||
std::map<int,wxString> GetTracksOfType(FFIndexer *Indexer, FFMS_TrackType Type);
|
std::map<int,wxString> GetTracksOfType(FFMS_Indexer *Indexer, FFMS_TrackType Type);
|
||||||
int AskForTrackSelection(const std::map<int,wxString>& TrackList, FFMS_TrackType Type);
|
int AskForTrackSelection(const std::map<int,wxString>& TrackList, FFMS_TrackType Type);
|
||||||
wxString GetCacheFilename(const wxString& filename);
|
wxString GetCacheFilename(const wxString& filename);
|
||||||
void SetLogLevel();
|
void SetLogLevel();
|
||||||
|
|
|
@ -61,8 +61,7 @@
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param filename
|
/// @param filename The filename to open
|
||||||
///
|
|
||||||
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
||||||
COMInited = false;
|
COMInited = false;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -81,7 +80,10 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
||||||
VideoSource = NULL;
|
VideoSource = NULL;
|
||||||
KeyFramesLoaded = false;
|
KeyFramesLoaded = false;
|
||||||
FrameNumber = -1;
|
FrameNumber = -1;
|
||||||
MsgSize = sizeof(FFMSErrMsg);
|
ErrInfo.Buffer = FFMSErrMsg;
|
||||||
|
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||||
|
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||||
|
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||||
ErrorMsg = _T("FFmpegSource video provider: ");
|
ErrorMsg = _T("FFmpegSource video provider: ");
|
||||||
|
|
||||||
SetLogLevel();
|
SetLogLevel();
|
||||||
|
@ -97,7 +99,6 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
|
||||||
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
||||||
Close();
|
Close();
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -107,20 +108,19 @@ FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open video
|
/// @brief Opens video
|
||||||
/// @param filename
|
/// @param filename The filename to open
|
||||||
///
|
|
||||||
void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
// make sure we don't have anything messy lying around
|
// make sure we don't have anything messy lying around
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||||
|
|
||||||
FFIndexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), FFMSErrMsg, MsgSize);
|
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||||
if (Indexer == NULL) {
|
if (Indexer == NULL) {
|
||||||
// error messages that can possibly contain a filename use this method instead of
|
// error messages that can possibly contain a filename use this method instead of
|
||||||
// wxString::Format because they may contain utf8 characters
|
// wxString::Format because they may contain utf8 characters
|
||||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(FFMSErrMsg, wxConvUTF8));
|
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +142,11 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
wxString CacheName = GetCacheFilename(filename);
|
wxString CacheName = GetCacheFilename(filename);
|
||||||
|
|
||||||
// try to read index
|
// try to read index
|
||||||
FFIndex *Index = NULL;
|
FFMS_Index *Index = NULL;
|
||||||
Index = FFMS_ReadIndex(CacheName.utf8_str(), FFMSErrMsg, MsgSize);
|
Index = FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo);
|
||||||
bool IndexIsValid = false;
|
bool IndexIsValid = false;
|
||||||
if (Index != NULL) {
|
if (Index != NULL) {
|
||||||
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), FFMSErrMsg, MsgSize)) {
|
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo)) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
// technically this isn't really needed since all video tracks should always be indexed,
|
// technically this isn't really needed since all video tracks should always be indexed,
|
||||||
// but a bit of sanity checking never hurt anyone
|
// but a bit of sanity checking never hurt anyone
|
||||||
if (IndexIsValid && TrackNumber >= 0) {
|
if (IndexIsValid && TrackNumber >= 0) {
|
||||||
FFTrack *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
FFMS_Track *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
|
||||||
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
|
||||||
IndexIsValid = false;
|
IndexIsValid = false;
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
|
@ -181,10 +181,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
if (!wxFileName(CacheName).Touch()) {
|
wxFileName(CacheName).Touch();
|
||||||
// warn user?
|
|
||||||
// FIND OUT WHY IT'S POPPING UP ERROR MESSAGES HERE
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have now read the index and may proceed with cleaning the index cache
|
// we have now read the index and may proceed with cleaning the index cache
|
||||||
if (!CleanCache()) {
|
if (!CleanCache()) {
|
||||||
|
@ -194,11 +191,11 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
// track number still not set?
|
// track number still not set?
|
||||||
if (TrackNumber < 0) {
|
if (TrackNumber < 0) {
|
||||||
// just grab the first track
|
// just grab the first track
|
||||||
TrackNumber = FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_VIDEO, FFMSErrMsg, MsgSize);
|
TrackNumber = FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_VIDEO, &ErrInfo);
|
||||||
if (TrackNumber < 0) {
|
if (TrackNumber < 0) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,31 +213,39 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
else
|
else
|
||||||
SeekMode = FFMS_SEEK_NORMAL;
|
SeekMode = FFMS_SEEK_NORMAL;
|
||||||
|
|
||||||
VideoSource = FFMS_CreateVideoSource(FileNameShort.utf8_str(), TrackNumber, Index, "", Threads, SeekMode, FFMSErrMsg, MsgSize);
|
VideoSource = FFMS_CreateVideoSource(FileNameShort.utf8_str(), TrackNumber, Index, Threads, SeekMode, &ErrInfo);
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
if (VideoSource == NULL) {
|
if (VideoSource == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to open video track: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Failed to open video track: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load video properties
|
// load video properties
|
||||||
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
||||||
|
|
||||||
if (FFMS_SetOutputFormatV(VideoSource, 1 << FFMS_GetPixFmt("bgra"), VideoInfo->Width, VideoInfo->Height, FFMS_RESIZER_BICUBIC, FFMSErrMsg, MsgSize)) {
|
const FFMS_Frame *TempFrame = FFMS_GetFrame(VideoSource, 0, &ErrInfo);
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), FFMSErrMsg));
|
if (TempFrame == NULL) {
|
||||||
|
ErrorMsg.Append(wxString::Format(_T("Failed to decode first frame: %s"), ErrInfo.Buffer));
|
||||||
|
throw ErrorMsg;
|
||||||
|
}
|
||||||
|
Width = TempFrame->EncodedWidth;
|
||||||
|
Height = TempFrame->EncodedHeight;
|
||||||
|
|
||||||
|
if (FFMS_SetOutputFormatV(VideoSource, 1 << FFMS_GetPixFmt("bgra"), Width, Height, FFMS_RESIZER_BICUBIC, &ErrInfo)) {
|
||||||
|
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get frame info data
|
// get frame info data
|
||||||
FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
FFMS_Track *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 FFTrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
|
const FFMS_TrackTimeBase *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");
|
||||||
|
|
||||||
const FFFrameInfo *CurFrameData;
|
const FFMS_FrameInfo *CurFrameData;
|
||||||
|
|
||||||
// build list of keyframes and timecodes
|
// build list of keyframes and timecodes
|
||||||
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
||||||
|
@ -306,25 +311,21 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
|
||||||
n = GetFrameCount()-1;
|
n = GetFrameCount()-1;
|
||||||
// set position
|
// set position
|
||||||
FrameNumber = n;
|
FrameNumber = n;
|
||||||
|
|
||||||
// these are for convenience
|
|
||||||
// int w = VideoInfo->Width;
|
|
||||||
// int h = VideoInfo->Height;
|
|
||||||
|
|
||||||
// this is what we'll return eventually
|
// this is what we'll return eventually
|
||||||
AegiVideoFrame &DstFrame = CurFrame;
|
AegiVideoFrame &DstFrame = CurFrame;
|
||||||
|
|
||||||
// decode frame
|
// decode frame
|
||||||
const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrMsg, MsgSize);
|
const FFMS_Frame *SrcFrame = FFMS_GetFrame(VideoSource, n, &ErrInfo);
|
||||||
if (SrcFrame == NULL) {
|
if (SrcFrame == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to retrieve frame: %s"), FFMSErrMsg));
|
ErrorMsg.Append(wxString::Format(_T("Failed to retrieve frame: %s"), ErrInfo.Buffer));
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set some properties
|
// set some properties
|
||||||
DstFrame.format = FORMAT_RGB32;
|
DstFrame.format = FORMAT_RGB32;
|
||||||
DstFrame.w = VideoInfo->Width;
|
DstFrame.w = Width;
|
||||||
DstFrame.h = VideoInfo->Height;
|
DstFrame.h = Height;
|
||||||
DstFrame.flipped = false;
|
DstFrame.flipped = false;
|
||||||
DstFrame.invertChannels = true;
|
DstFrame.invertChannels = true;
|
||||||
|
|
||||||
|
@ -345,7 +346,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
int FFmpegSourceVideoProvider::GetWidth() {
|
int FFmpegSourceVideoProvider::GetWidth() {
|
||||||
return VideoInfo->Width;
|
return Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -353,7 +354,7 @@ int FFmpegSourceVideoProvider::GetWidth() {
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
int FFmpegSourceVideoProvider::GetHeight() {
|
int FFmpegSourceVideoProvider::GetHeight() {
|
||||||
return VideoInfo->Height;
|
return Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,59 +46,31 @@
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class FFmpegSourceVideoProvider
|
/// @class FFmpegSourceVideoProvider
|
||||||
/// @brief DOCME
|
/// @brief Implements video loading through the FFMS library.
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
|
class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
|
||||||
private:
|
private:
|
||||||
|
FFMS_VideoSource *VideoSource; /// video source object
|
||||||
|
const FFMS_VideoProperties *VideoInfo; /// video properties
|
||||||
|
|
||||||
/// DOCME
|
int Width; /// width in pixels
|
||||||
FFVideo *VideoSource;
|
int Height; /// height in pixels
|
||||||
|
int FrameNumber; /// current framenumber
|
||||||
/// DOCME
|
wxArrayInt KeyFramesList; /// list of keyframes
|
||||||
const FFVideoProperties *VideoInfo;
|
bool KeyFramesLoaded; /// keyframe loading state
|
||||||
|
std::vector<int> TimecodesVector; /// list of timestamps
|
||||||
|
FrameRate Timecodes; /// vfr object
|
||||||
/// DOCME
|
bool COMInited; /// COM initialization state
|
||||||
int FrameNumber;
|
|
||||||
|
AegiVideoFrame CurFrame; /// current video frame
|
||||||
/// DOCME
|
|
||||||
wxArrayInt KeyFramesList;
|
char FFMSErrMsg[1024]; /// FFMS error message
|
||||||
|
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||||
/// DOCME
|
wxString ErrorMsg; /// wx-ified error message
|
||||||
bool KeyFramesLoaded;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
std::vector<int> TimecodesVector;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
FrameRate Timecodes;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
AegiVideoFrame CurFrame;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
char FFMSErrMsg[1024];
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned MsgSize;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxString ErrorMsg;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
bool COMInited;
|
|
||||||
|
|
||||||
void LoadVideo(wxString filename);
|
void LoadVideo(wxString filename);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FFmpegSourceVideoProvider(wxString filename);
|
FFmpegSourceVideoProvider(wxString filename);
|
||||||
~FFmpegSourceVideoProvider();
|
~FFmpegSourceVideoProvider();
|
||||||
|
@ -111,50 +83,35 @@ public:
|
||||||
int GetHeight();
|
int GetHeight();
|
||||||
double GetFPS();
|
double GetFPS();
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Reports keyframe status
|
||||||
/// @return
|
/// @return Returns true if keyframes are loaded, false otherwise.
|
||||||
///
|
|
||||||
bool AreKeyFramesLoaded() { return KeyFramesLoaded; };
|
bool AreKeyFramesLoaded() { return KeyFramesLoaded; };
|
||||||
|
/// @brief Gets a list of keyframes
|
||||||
/// @brief DOCME
|
/// @return Returns a wxArrayInt of keyframes.
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
wxArrayInt GetKeyFrames() { return KeyFramesList; };
|
wxArrayInt GetKeyFrames() { return KeyFramesList; };
|
||||||
|
/// @brief Checks if source is VFR
|
||||||
/// @brief DOCME
|
/// @return Returns true.
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool IsVFR() { return true; };
|
bool IsVFR() { return true; };
|
||||||
|
/// @brief Gets a VFR framerate object
|
||||||
/// @brief DOCME
|
/// @return Returns the framerate object.
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
FrameRate GetTrueFrameRate() { return Timecodes; };
|
FrameRate GetTrueFrameRate() { return Timecodes; };
|
||||||
|
/// @brief Gets the name of the provider
|
||||||
/// @brief DOCME
|
/// @return Returns "FFmpegSource".
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
wxString GetDecoderName() { return L"FFmpegSource"; }
|
wxString GetDecoderName() { return L"FFmpegSource"; }
|
||||||
|
/// @brief Gets the number of frames to cache.
|
||||||
/// @brief DOCME
|
/// @return Returns 8.
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
int GetDesiredCacheSize() { return 8; }
|
int GetDesiredCacheSize() { return 8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class FFmpegSourceVideoProviderFactory
|
/// @class FFmpegSourceVideoProviderFactory
|
||||||
/// @brief DOCME
|
/// @brief Creates a FFmpegSource video provider.
|
||||||
///
|
|
||||||
/// DOCME
|
|
||||||
class FFmpegSourceVideoProviderFactory : public VideoProviderFactory {
|
class FFmpegSourceVideoProviderFactory : public VideoProviderFactory {
|
||||||
public:
|
public:
|
||||||
|
/// @brief Creates a FFmpegSource video provider.
|
||||||
/// @brief DOCME
|
/// @param video The video filename to open.
|
||||||
/// @param video
|
/// @return Returns the video provider.
|
||||||
///
|
|
||||||
VideoProvider *CreateProvider(wxString video) { return new FFmpegSourceVideoProvider(video); }
|
VideoProvider *CreateProvider(wxString video) { return new FFmpegSourceVideoProvider(video); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue