Use scoped_holder in a handful of places

Originally committed to SVN as r6492.
This commit is contained in:
Thomas Goyne 2012-02-20 18:22:12 +00:00
parent b9ddf00ead
commit 17b0d83831
12 changed files with 125 additions and 250 deletions

View file

@ -119,25 +119,19 @@ struct COMObjectRetainer {
};
/// @brief RAII wrapper around Win32 HANDLE type
struct Win32KernelHandle {
/// HANDLE value being managed
HANDLE handle;
struct Win32KernelHandle : public agi::scoped_holder<HANDLE, BOOL (__stdcall *)(HANDLE)> {
/// @brief Create with a managed handle
/// @param handle Win32 handle to manage
Win32KernelHandle(HANDLE handle = 0)
: handle(handle)
: scoped_holder(handle, CloseHandle)
{
}
/// @brief Destructor, closes the managed handle
~Win32KernelHandle()
Win32KernelHandle& operator=(HANDLE new_handle)
{
if (handle) CloseHandle(handle);
scoped_holder::operator=(new_handle);
return *this;
}
/// @brief Returns the managed handle
operator HANDLE () const { return handle; }
};
/// @class DirectSoundPlayer2Thread
@ -667,7 +661,7 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int
start_frame = 0;
end_frame = 0;
thread_handle.handle = (HANDLE)_beginthreadex(0, 0, ThreadProc, this, 0, 0);
thread_handle = (HANDLE)_beginthreadex(0, 0, ThreadProc, this, 0, 0);
if (!thread_handle)
throw agi::AudioPlayerOpenError("Failed creating playback thread in DirectSoundPlayer2. This is bad.", 0);

View file

@ -53,52 +53,31 @@
#include "main.h"
/// @brief Constructor
/// @param filename
///
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename)
: AudioSource(NULL)
, COMInited(false)
/// @param filename The filename to open
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) try
: AudioSource(NULL, FFMS_DestroyAudioSource)
{
#ifdef WIN32
HRESULT res;
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(res))
COMInited = true;
else if (res != RPC_E_CHANGED_MODE)
throw agi::AudioProviderOpenError("COM initialization failure", 0);
#endif
// initialize ffmpegsource
// FIXME: CPU detection?
#if FFMS_VERSION >= ((2 << 24) | (14 << 16) | (0 << 8) | 0)
FFMS_Init(0, 1);
#else
FFMS_Init(0);
#endif
ErrInfo.Buffer = FFMSErrMsg;
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
SetLogLevel();
try {
LoadAudio(filename);
} catch (...) {
Close();
throw;
}
catch (wxString const& err) {
throw agi::AudioProviderOpenError(STD_STR(err), 0);
}
catch (const char *err) {
throw agi::AudioProviderOpenError(err, 0);
}
/// @brief Load audio file
/// @param filename
///
void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
wxString FileNameShort = wxFileName(filename).GetShortPath();
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
if (Indexer == NULL) {
if (!Indexer)
throw agi::FileNotFoundError(ErrInfo.Buffer);
}
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
if (TrackList.size() <= 0)
@ -118,57 +97,40 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
wxString CacheName = GetCacheFilename(filename);
// try to read index
FFMS_Index *Index = NULL;
Index = FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo);
bool IndexIsValid = false;
if (Index != NULL) {
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo)) {
FFMS_DestroyIndex(Index);
agi::scoped_holder<FFMS_Index*, void (FFMS_CC*)(FFMS_Index*)>
Index(FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo), FFMS_DestroyIndex);
if (Index && !FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo))
Index = NULL;
}
else
IndexIsValid = true;
}
// index valid but track number still not set?
if (IndexIsValid) {
if (Index) {
// track number not set? just grab the first track
if (TrackNumber < 0)
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
if (TrackNumber < 0) {
FFMS_DestroyIndex(Index);
Index = NULL;
if (TrackNumber < 0)
throw agi::AudioDataNotFoundError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer, 0);
}
// 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);
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
IndexIsValid = false;
FFMS_DestroyIndex(Index);
if (FFMS_GetNumFrames(TempTrackData) <= 0)
Index = NULL;
}
}
// 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)
// moment of truth
if (!IndexIsValid) {
if (!Index) {
int TrackMask;
if (OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() || TrackNumber == FFMS_TRACKMASK_ALL)
TrackMask = FFMS_TRACKMASK_ALL;
else
TrackMask = (1 << TrackNumber);
try {
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
}
catch (wxString const& err) {
throw agi::AudioProviderOpenError(STD_STR(err), 0);
}
// if tracknumber still isn't set we need to set it now
if (TrackNumber == FFMS_TRACKMASK_ALL)
@ -185,11 +147,8 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
#else
AudioSource = FFMS_CreateAudioSource(FileNameShort.utf8_str(), TrackNumber, Index, &ErrInfo);
#endif
FFMS_DestroyIndex(Index);
Index = NULL;
if (!AudioSource) {
throw agi::AudioProviderOpenError(std::string("Failed to open audio track: %s") + ErrInfo.Buffer, 0);
}
if (!AudioSource)
throw agi::AudioProviderOpenError(std::string("Failed to open audio track: ") + ErrInfo.Buffer, 0);
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
@ -211,27 +170,6 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
}
}
/// @brief Destructor
///
FFmpegSourceAudioProvider::~FFmpegSourceAudioProvider() {
Close();
}
/// @brief Clean up
///
void FFmpegSourceAudioProvider::Close() {
if (AudioSource) FFMS_DestroyAudioSource(AudioSource);
#ifdef WIN32
if (COMInited)
CoUninitialize();
#endif
}
/// @brief Get audio
/// @param Buf
/// @param Start
/// @param Count
///
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) const {
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, &ErrInfo)) {
throw AudioDecodeError(std::string("Failed to get audio samples: ") + ErrInfo.Buffer);

View file

@ -42,19 +42,16 @@
/// @class FFmpegSourceAudioProvider
/// @brief Implements audio loading with the FFMS library.
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
private:
FFMS_AudioSource *AudioSource; ///< audio source object
bool COMInited; ///< COM initialization state
/// audio source object
agi::scoped_holder<FFMS_AudioSource*, void (FFMS_CC *)(FFMS_AudioSource*)> AudioSource;
mutable char FFMSErrMsg[1024]; ///< FFMS error message
mutable FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages
void Close();
void LoadAudio(wxString filename);
public:
FFmpegSourceAudioProvider(wxString filename);
virtual ~FFmpegSourceAudioProvider();
/// @brief Checks sample endianness
/// @return Returns true.

View file

@ -64,8 +64,10 @@
/// @param filename
///
PCMAudioProvider::PCMAudioProvider(const wxString &filename)
{
#ifdef _WIN32
: file_handle(0, CloseHandle)
, file_mapping(0, CloseHandle)
{
file_handle = CreateFile(
filename.c_str(),
FILE_READ_DATA,
@ -75,15 +77,13 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS,
0);
if (file_handle == INVALID_HANDLE_VALUE) {
if (file_handle == INVALID_HANDLE_VALUE)
throw agi::FileNotFoundError(STD_STR(filename));
}
LARGE_INTEGER li_file_size = {0};
if (!GetFileSizeEx(file_handle, &li_file_size)) {
CloseHandle(file_handle);
if (!GetFileSizeEx(file_handle, &li_file_size))
throw agi::AudioProviderOpenError("Failed getting file size", 0);
}
file_size = li_file_size.QuadPart;
file_mapping = CreateFileMapping(
@ -93,20 +93,16 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
0, 0,
0);
if (file_mapping == 0) {
CloseHandle(file_handle);
if (file_mapping == 0)
throw agi::AudioProviderOpenError("Failed creating file mapping", 0);
}
current_mapping = 0;
#else
file_handle = open(filename.mb_str(*wxConvFileName), O_RDONLY);
if (file_handle == -1) {
: file_handle(open(filename.mb_str(*wxConvFileName), O_RDONLY), close)
{
if (file_handle == -1)
throw agi::FileNotFoundError(STD_STR(filename));
}
struct stat filestats;
memset(&filestats, 0, sizeof(filestats));
@ -125,18 +121,11 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
PCMAudioProvider::~PCMAudioProvider()
{
#ifdef _WIN32
if (current_mapping) {
if (current_mapping)
UnmapViewOfFile(current_mapping);
}
CloseHandle(file_mapping);
CloseHandle(file_handle);
#else
if (current_mapping) {
if (current_mapping)
munmap(current_mapping, mapping_length);
}
close(file_handle);
#endif
}

View file

@ -47,6 +47,8 @@
#include "include/aegisub/audio_provider.h"
#include <libaegisub/scoped_ptr.h>
/// DOCME
/// @class PCMAudioProvider
@ -54,14 +56,12 @@
///
/// DOCME
class PCMAudioProvider : public AudioProvider {
private:
#ifdef _WIN32
/// DOCME
agi::scoped_holder<HANDLE, BOOL (__stdcall *)(HANDLE)> file_handle;
/// DOCME
HANDLE file_handle;
/// DOCME
HANDLE file_mapping;
agi::scoped_holder<HANDLE, BOOL (__stdcall *)(HANDLE)> file_mapping;
/// DOCME
mutable void *current_mapping;
@ -72,7 +72,7 @@ private:
/// DOCME
mutable size_t mapping_length;
#else
int file_handle;
agi::scoped_holder<int, int(*)(int)> file_handle;
mutable void *current_mapping;
mutable off_t mapping_start;
mutable size_t mapping_length;

View file

@ -271,28 +271,22 @@ typedef BOOL (WINAPI * PGetUserPreferredUILanguages)(DWORD dwFlags, PULONG pulNu
// Try using Win 6+ functions if available
static wxString GetUILanguage()
{
wxString res;
HMODULE kernel32 = LoadLibraryW(L"kernel32.dll");
if (!kernel32) return res;
agi::scoped_holder<HMODULE, BOOL (__stdcall *)(HMODULE)> kernel32(LoadLibraryW(L"kernel32.dll"), FreeLibrary);
if (!kernel32) return "";
PGetUserPreferredUILanguages gupuil = (PGetUserPreferredUILanguages)GetProcAddress(kernel32, "GetUserPreferredUILanguages");
if (!gupuil) goto error;
if (!gupuil) return "";
ULONG numlang = 0, output_len = 0;
if (gupuil(MUI_LANGUAGE_NAME, &numlang, 0, &output_len) == TRUE && output_len)
{
std::vector<wchar_t> output(output_len);
if (gupuil(MUI_LANGUAGE_NAME, &numlang, &output[0], &output_len) && numlang >= 1)
{
// We got at least one language, just treat it as the only, and a null-terminated string
res = &output[0];
}
}
if (gupuil(MUI_LANGUAGE_NAME, &numlang, 0, &output_len) != TRUE || !output_len)
return "";
error:
FreeModule(kernel32);
return res;
std::vector<wchar_t> output(output_len);
if (!gupuil(MUI_LANGUAGE_NAME, &numlang, &output[0], &output_len) || numlang < 1)
return "";
// We got at least one language, just treat it as the only, and a null-terminated string
return &output[0];
}
static wxString GetSystemLanguage()
{

View file

@ -56,6 +56,33 @@
#include "md5.h"
#include "standard_paths.h"
#ifdef WIN32
static void deinit_com(bool) {
CoUninitialize();
}
#else
static void deinit_com(bool) { }
#endif
FFmpegSourceProvider::FFmpegSourceProvider()
: COMInited(false, deinit_com)
{
#ifdef WIN32
HRESULT res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(res))
COMInited = true;
else if (res != RPC_E_CHANGED_MODE)
throw "COM initialization failure";
#endif
// initialize ffmpegsource
// FIXME: CPU detection?
#if FFMS_VERSION >= ((2 << 24) | (14 << 16) | (0 << 8) | 0)
FFMS_Init(0, 1);
#else
FFMS_Init(0);
#endif
}
wxMutex FFmpegSourceProvider::CleaningInProgress;

View file

@ -45,6 +45,8 @@
#include <ffms.h>
#include <libaegisub/scoped_ptr.h>
/// Index all tracks
#define FFMS_TRACKMASK_ALL -1
/// Index no tracks
@ -54,7 +56,11 @@
/// @brief Base class for FFMS2 source providers; contains common functions etc
class FFmpegSourceProvider {
friend class FFmpegSourceCacheCleaner;
agi::scoped_holder<bool> COMInited; ///< COM initialization state
public:
FFmpegSourceProvider();
/// Logging level constants from avutil/log.h
enum FFMS_LogLevel {
/// nothing printed
@ -85,7 +91,6 @@ public:
/// @class FFmpegSourceCacheCleaner
/// @brief Implements index cache cleaning functionality for the FFMS2 providers
class FFmpegSourceCacheCleaner : public wxThread {
private:
FFmpegSourceProvider *parent;
public:
@ -96,4 +101,3 @@ public:
};
#endif /* WITH_FFMS2 */

View file

@ -124,7 +124,7 @@ FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(wxString
bold;
int slant = italic ? 110 : 0;
scoped<FcPattern*> pat(FcPatternCreate(), FcPatternDestroy);
agi::scoped_holder<FcPattern*> pat(FcPatternCreate(), FcPatternDestroy);
if (!pat) return ret;
int family_cnt = add_families(pat, family);
@ -138,11 +138,11 @@ FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(wxString
if (!FcConfigSubstitute(config, pat, FcMatchPattern)) return ret;
FcResult result;
scoped<FcFontSet*> fsorted(FcFontSort(config, pat, true, NULL, &result), FcFontSetDestroy);
scoped<FcFontSet*> ffullname(MatchFullname(family.c_str(), weight, slant), FcFontSetDestroy);
agi::scoped_holder<FcFontSet*> fsorted(FcFontSort(config, pat, true, NULL, &result), FcFontSetDestroy);
agi::scoped_holder<FcFontSet*> ffullname(MatchFullname(family.c_str(), weight, slant), FcFontSetDestroy);
if (!fsorted || !ffullname) return ret;
scoped<FcFontSet*> fset(FcFontSetCreate(), FcFontSetDestroy);
agi::scoped_holder<FcFontSet*> fset(FcFontSetCreate(), FcFontSetDestroy);
for (int cur_font = 0; cur_font < ffullname->nfont; ++cur_font) {
FcPattern *curp = ffullname->fonts[cur_font];
FcPatternReference(curp);
@ -169,7 +169,7 @@ FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(wxString
for (; family_cnt > 1; --family_cnt)
FcPatternRemove(pat, FC_FAMILY, family_cnt - 1);
scoped<FcPattern*> rpat(FcFontRenderPrepare(config, pat, fset->fonts[cur_font]), FcPatternDestroy);
agi::scoped_holder<FcPattern*> rpat(FcFontRenderPrepare(config, pat, fset->fonts[cur_font]), FcPatternDestroy);
if (!rpat) return ret;
FcChar8 *r_family;

View file

@ -25,23 +25,15 @@
#include "font_file_lister.h"
#include <libaegisub/scoped_ptr.h>
typedef struct _FcConfig FcConfig;
typedef struct _FcFontSet FcFontSet;
/// @class FontConfigFontFileLister
/// @brief fontconfig powered font lister
class FontConfigFontFileLister : public FontFileLister {
template<typename T> class scoped {
T data;
void (*destructor)(T);
public:
scoped(T data, void (*destructor)(T)) : data(data), destructor(destructor) { }
~scoped() { if (data) destructor(data); }
operator T() { return data; }
T operator->() { return data; }
};
scoped<FcConfig*> config;
agi::scoped_holder<FcConfig*> config;
/// @brief Case-insensitive match ASS/SSA font family against full name. (also known as "name for humans")
/// @param family font fullname

View file

@ -57,33 +57,15 @@
#include "video_context.h"
#include "video_provider_ffmpegsource.h"
/// @brief Constructor
/// @param filename The filename to open
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename)
: VideoSource(NULL)
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) try
: VideoSource(NULL, FFMS_DestroyVideoSource)
, VideoInfo(NULL)
, Width(-1)
, Height(-1)
, FrameNumber(-1)
, COMInited(false)
{
#ifdef WIN32
HRESULT res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(res))
COMInited = true;
else if (res != RPC_E_CHANGED_MODE)
throw VideoOpenError("COM initialization failure");
#endif
// initialize ffmpegsource
// FIXME: CPU detection?
#if FFMS_VERSION >= ((2 << 24) | (14 << 16) | (0 << 8) | 0)
FFMS_Init(0, 1);
#else
FFMS_Init(0);
#endif
ErrInfo.Buffer = FFMSErrMsg;
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
@ -92,25 +74,14 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename)
SetLogLevel();
// and here we go
try {
LoadVideo(filename);
}
catch (wxString const& err) {
Close();
throw VideoOpenError(STD_STR(err));
}
catch (...) {
Close();
throw;
catch (const char * err) {
throw VideoOpenError(err);
}
}
/// @brief Destructor
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
Close();
}
/// @brief Opens video
/// @param filename The filename to open
@ -118,9 +89,8 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
wxString FileNameShort = wxFileName(filename).GetShortPath();
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
if (Indexer == NULL) {
if (!Indexer)
throw agi::FileNotFoundError(ErrInfo.Buffer);
}
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_VIDEO);
if (TrackList.size() <= 0)
@ -140,41 +110,27 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
wxString CacheName = GetCacheFilename(filename);
// try to read index
FFMS_Index *Index = NULL;
Index = FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo);
bool IndexIsValid = false;
if (Index != NULL) {
if (FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo)) {
FFMS_DestroyIndex(Index);
agi::scoped_holder<FFMS_Index*, void (FFMS_CC*)(FFMS_Index*)>
Index(FFMS_ReadIndex(CacheName.utf8_str(), &ErrInfo), FFMS_DestroyIndex);
if (Index && !FFMS_IndexBelongsToFile(Index, FileNameShort.utf8_str(), &ErrInfo))
Index = NULL;
}
else
IndexIsValid = true;
}
// 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) {
if (Index && TrackNumber >= 0) {
FFMS_Track *TempTrackData = FFMS_GetTrackFromIndex(Index, TrackNumber);
if (FFMS_GetNumFrames(TempTrackData) <= 0) {
IndexIsValid = false;
FFMS_DestroyIndex(Index);
if (FFMS_GetNumFrames(TempTrackData) <= 0)
Index = NULL;
}
}
// moment of truth
if (!IndexIsValid) {
if (!Index) {
int TrackMask = OPT_GET("Provider/FFmpegSource/Index All Tracks")->GetBool() ? FFMS_TRACKMASK_ALL : FFMS_TRACKMASK_NONE;
try {
// ignore audio decoding errors here, we don't care right now
Index = DoIndexing(Indexer, CacheName, TrackMask, FFMS_IEH_IGNORE);
}
catch (wxString err) {
throw VideoOpenError(STD_STR(err));
}
}
// update access time of index file so it won't get cleaned away
wxFileName(CacheName).Touch();
@ -188,12 +144,9 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
if (TrackNumber < 0) {
// just grab the first track
TrackNumber = FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_VIDEO, &ErrInfo);
if (TrackNumber < 0) {
FFMS_DestroyIndex(Index);
Index = NULL;
if (TrackNumber < 0)
throw VideoNotSupported(std::string("Couldn't find any video tracks: ") + ErrInfo.Buffer);
}
}
// set thread count
int Threads = OPT_GET("Provider/Video/FFmpegSource/Decoding Threads")->GetInt();
@ -207,11 +160,8 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
SeekMode = FFMS_SEEK_NORMAL;
VideoSource = FFMS_CreateVideoSource(FileNameShort.utf8_str(), TrackNumber, Index, Threads, SeekMode, &ErrInfo);
FFMS_DestroyIndex(Index);
Index = NULL;
if (VideoSource == NULL) {
if (!VideoSource)
throw VideoOpenError(std::string("Failed to open video track: ") + ErrInfo.Buffer);
}
// load video properties
VideoInfo = FFMS_GetVideoProperties(VideoSource);
@ -274,14 +224,6 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
FrameNumber = 0;
}
void FFmpegSourceVideoProvider::Close() {
if (VideoSource) FFMS_DestroyVideoSource(VideoSource);
#ifdef WIN32
if (COMInited)
CoUninitialize();
#endif
}
const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int n) {
FrameNumber = mid(0, n, GetFrameCount() - 1);

View file

@ -46,7 +46,8 @@
/// @class FFmpegSourceVideoProvider
/// @brief Implements video loading through the FFMS library.
class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
FFMS_VideoSource *VideoSource; ///< video source object
/// video source object
agi::scoped_holder<FFMS_VideoSource*, void (FFMS_CC*)(FFMS_VideoSource*)> VideoSource;
const FFMS_VideoProperties *VideoInfo; ///< video properties
int Width; ///< width in pixels
@ -54,7 +55,6 @@ class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
int FrameNumber; ///< current framenumber
std::vector<int> KeyFramesList; ///< list of keyframes
agi::vfr::Framerate Timecodes; ///< vfr object
bool COMInited; ///< COM initialization state
wxString ColorSpace; ///< Colorspace name
AegiVideoFrame CurFrame; ///< current video frame
@ -63,11 +63,9 @@ class FFmpegSourceVideoProvider : public VideoProvider, FFmpegSourceProvider {
FFMS_ErrorInfo ErrInfo; ///< FFMS error codes/messages
void LoadVideo(wxString filename);
void Close();
public:
FFmpegSourceVideoProvider(wxString filename);
~FFmpegSourceVideoProvider();
const AegiVideoFrame GetFrame(int n);