forked from mia/Aegisub
Improved handling of VFR files with DirectShow and Avisynth providers.
Originally committed to SVN as r667.
This commit is contained in:
parent
1ea3e085d9
commit
5813033fa8
10 changed files with 236 additions and 57 deletions
|
@ -243,20 +243,21 @@ void MatroskaWrapper::SetToTimecodes(FrameRate &target) {
|
|||
// Check if it's CFR
|
||||
bool isCFR = true;
|
||||
double estimateCFR = timecodes.back() / timecodes.size()-1;
|
||||
double curTime = 0;
|
||||
for (int i=0;i<frames;i++) {
|
||||
int delta = int(curTime - timecodes[i]);
|
||||
if (abs(delta > 1)) {
|
||||
double t1,t2;
|
||||
for (int i=1;i<frames;i++) {
|
||||
t1 = timecodes[i];
|
||||
t2 = timecodes[i-1];
|
||||
int delta = int(t1 - t2 - estimateCFR);
|
||||
if (abs(delta > 2)) {
|
||||
isCFR = false;
|
||||
break;
|
||||
}
|
||||
curTime += estimateCFR;
|
||||
}
|
||||
|
||||
// Constant framerate
|
||||
if (isCFR) {
|
||||
if (abs(estimateCFR - 23.976) < 0.01) estimateCFR = 23.976;
|
||||
if (abs(estimateCFR - 29.97) < 0.01) estimateCFR = 29.97;
|
||||
if (abs(estimateCFR - 23.976) < 0.01) estimateCFR = 24000.0 / 1001.0;
|
||||
if (abs(estimateCFR - 29.97) < 0.01) estimateCFR = 30000.0 / 1001.0;
|
||||
target.SetCFR(estimateCFR);
|
||||
}
|
||||
|
||||
|
|
108
aegisub/vfr.cpp
108
aegisub/vfr.cpp
|
@ -390,6 +390,114 @@ int FrameRate::GetTimeAtFrame(int frame,bool start,bool exact) {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Get the current list of frames/times
|
||||
wxArrayInt FrameRate::GetFrameTimeList() {
|
||||
wxArrayInt final;
|
||||
for (unsigned int i=0;i<Frame.size();i++) final.Add(Frame[i]);
|
||||
return final;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Calculate the common FPS for evil stuff
|
||||
// e.g., in a mix of 24fps and 30fps, returns 120fps
|
||||
double FrameRate::GetCommonFPS() {
|
||||
// Variables
|
||||
int curDist;
|
||||
int lastDist = 0;
|
||||
int sectionStart = 0;
|
||||
double curFps;
|
||||
|
||||
// List of likely frame rates
|
||||
std::vector<double> frameRates;
|
||||
frameRates.push_back(15.0 / 1.001);
|
||||
frameRates.push_back(15);
|
||||
frameRates.push_back(24.0 / 1.001);
|
||||
frameRates.push_back(24);
|
||||
frameRates.push_back(30.0 / 1.001);
|
||||
frameRates.push_back(30);
|
||||
frameRates.push_back(120.0 / 1.001);
|
||||
frameRates.push_back(120);
|
||||
|
||||
// List of rates found
|
||||
std::vector<double> found;
|
||||
|
||||
// Find the relative fps of each area
|
||||
for (unsigned int i=1;i<Frame.size();i++) {
|
||||
// Find the current frame distance
|
||||
curDist = Frame[i]-Frame[i-1];
|
||||
|
||||
// See if it's close enough to the last
|
||||
if ((abs(curDist - lastDist) < 2 || i-1 == sectionStart) && i != Frame.size()-1) {
|
||||
lastDist = curDist;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate section fps
|
||||
curFps = (i - sectionStart - 1) * 1000.0 / double(Frame[i-1]-Frame[sectionStart]);
|
||||
sectionStart = i;
|
||||
lastDist = curDist;
|
||||
|
||||
// See if it's close enough to one of the likely rates
|
||||
for (unsigned int j=0;j<frameRates.size();j++) {
|
||||
if (curFps-0.01 <= frameRates[j] && curFps+0.01 >= frameRates[j]) {
|
||||
curFps = frameRates[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// See if it's on list
|
||||
bool onList = false;
|
||||
for (unsigned int j=0;j<found.size();j++) {
|
||||
if (found[j] == curFps) {
|
||||
onList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, add it
|
||||
if (!onList) found.push_back(curFps);
|
||||
}
|
||||
|
||||
// Find common between them
|
||||
double v1,v2,minInt,tempd;
|
||||
int tempi1,tempi2;
|
||||
while (found.size() > 1) {
|
||||
// Extract last two values
|
||||
v1 = found.back();
|
||||
found.pop_back();
|
||||
v2 = found.back();
|
||||
found.pop_back();
|
||||
|
||||
// Divide them
|
||||
v2 = v1/v2;
|
||||
|
||||
// Find what it takes to make it an integer
|
||||
for (minInt = 1;minInt<20;minInt++) {
|
||||
tempd = v2 * minInt;
|
||||
tempi1 = (int)(tempd-0.001);
|
||||
tempi2 = (int)(tempd+0.001);
|
||||
if (tempi1 != tempi2) break;
|
||||
}
|
||||
if (minInt != 20) v1 = v1*minInt;
|
||||
|
||||
// See if it's close enough to one of the likely rates
|
||||
for (unsigned int j=0;j<frameRates.size();j++) {
|
||||
if (v1-0.01 <= frameRates[j] && v1+0.01 >= frameRates[j]) {
|
||||
v1 = frameRates[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Re-insert obtained result
|
||||
found.push_back(v1);
|
||||
}
|
||||
|
||||
return found.back();
|
||||
}
|
||||
|
||||
|
||||
///////////
|
||||
// Globals
|
||||
FrameRate VFR_Output;
|
||||
|
|
|
@ -77,6 +77,7 @@ private:
|
|||
ASS_FrameRateType FrameRateType;
|
||||
bool loaded;
|
||||
wxString vfrFile;
|
||||
|
||||
public:
|
||||
FrameRate();
|
||||
~FrameRate();
|
||||
|
@ -94,6 +95,9 @@ public:
|
|||
bool IsLoaded() { return loaded; };
|
||||
ASS_FrameRateType GetFrameRateType() { return FrameRateType; };
|
||||
wxString GetFilename() { return vfrFile; };
|
||||
|
||||
wxArrayInt GetFrameTimeList();
|
||||
double GetCommonFPS();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -163,14 +163,9 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
|||
if (!filename.IsEmpty()) {
|
||||
try {
|
||||
grid->CommitChanges(true);
|
||||
bool isVfr = false;
|
||||
double overFps = 0;
|
||||
|
||||
// Choose a provider
|
||||
provider = VideoProvider::GetProvider(filename,GetTempWorkFile());
|
||||
provider->SetZoom(zoomValue);
|
||||
if (arType != 4) arValue = GetARFromType(arType); // 4 = custom
|
||||
provider->SetDAR(arValue);
|
||||
|
||||
// Why the hell was this disabled?
|
||||
// Read extra data from file
|
||||
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
||||
wxString ext = filename.Right(4).Lower();
|
||||
|
@ -186,7 +181,11 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
|||
// Ask to override timecodes
|
||||
int override = wxYES;
|
||||
if (VFR_Output.IsLoaded()) override = wxMessageBox(_("You already have timecodes loaded. Replace them with the timecodes from the Matroska file?"),_("Replace timecodes?"),wxYES_NO | wxICON_QUESTION);
|
||||
if (override == wxYES) MatroskaWrapper::wrapper.SetToTimecodes(VFR_Output);
|
||||
if (override == wxYES) {
|
||||
MatroskaWrapper::wrapper.SetToTimecodes(VFR_Output);
|
||||
isVfr = VFR_Output.GetFrameRateType() == VFR;
|
||||
if (isVfr) overFps = VFR_Output.GetCommonFPS();
|
||||
}
|
||||
|
||||
// Close mkv
|
||||
MatroskaWrapper::wrapper.Close();
|
||||
|
@ -198,6 +197,13 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// Choose a provider
|
||||
provider = VideoProvider::GetProvider(filename,GetTempWorkFile(),overFps);
|
||||
if (isVfr) provider->OverrideFrameTimeList(VFR_Output.GetFrameTimeList());
|
||||
provider->SetZoom(zoomValue);
|
||||
if (arType != 4) arValue = GetARFromType(arType); // 4 = custom
|
||||
provider->SetDAR(arValue);
|
||||
|
||||
// Update size
|
||||
UpdateSize();
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
////////////////
|
||||
// Get provider
|
||||
VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
||||
VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles,double fps) {
|
||||
// Check if avisynth is available
|
||||
bool avisynthAvailable = false;
|
||||
bool dshowAvailable = false;
|
||||
|
@ -106,7 +106,7 @@ VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
|||
// Use DirectShow provider
|
||||
if (!provider && (preffered == _T("dshow") || !avisynthAvailable)) {
|
||||
try {
|
||||
provider = new DirectShowVideoProvider(video,subtitles);
|
||||
provider = new DirectShowVideoProvider(video,subtitles,fps);
|
||||
}
|
||||
catch (...) {
|
||||
delete provider;
|
||||
|
@ -119,7 +119,7 @@ VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
|||
// Use Avisynth provider
|
||||
if (!provider) {
|
||||
try {
|
||||
provider = new AvisynthVideoProvider(video,subtitles);
|
||||
provider = new AvisynthVideoProvider(video,subtitles,fps);
|
||||
}
|
||||
catch (...) {
|
||||
delete provider;
|
||||
|
|
|
@ -65,5 +65,7 @@ public:
|
|||
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
||||
virtual int GetSourceHeight()=0; // Returns the original source height in pixels
|
||||
|
||||
static VideoProvider *GetProvider(wxString video,wxString subtitles);
|
||||
virtual void OverrideFrameTimeList(wxArrayInt list) {} // Override the list with the provided one, for VFR handling
|
||||
|
||||
static VideoProvider *GetProvider(wxString video,wxString subtitles,double fps=0.0);
|
||||
};
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "video_provider_avs.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "vfr.h"
|
||||
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -46,17 +47,19 @@
|
|||
|
||||
///////////////
|
||||
// Constructor
|
||||
AvisynthVideoProvider::AvisynthVideoProvider(wxString _filename, wxString _subfilename) {
|
||||
AvisynthVideoProvider::AvisynthVideoProvider(wxString _filename, wxString _subfilename, double _fps) {
|
||||
AVSTRACE(wxString::Format(_T("AvisynthVideoProvider: Creating new AvisynthVideoProvider: \"%s\", \"%s\""), _filename, _subfilename));
|
||||
bool mpeg2dec3_priority = true;
|
||||
RGB32Video = NULL;
|
||||
SubtitledVideo = NULL;
|
||||
ResizedVideo = NULL;
|
||||
data = NULL;
|
||||
fps = _fps;
|
||||
|
||||
depth = 0;
|
||||
|
||||
last_fnum = -1;
|
||||
num_frames = 0;
|
||||
|
||||
subfilename = _subfilename;
|
||||
zoom = 1.0;
|
||||
|
@ -219,7 +222,12 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
dss2 = false;
|
||||
if (env->FunctionExists("dss2")) {
|
||||
AVSTRACE(_T("visynthVideoProvider::OpenVideo: Invoking DSS2"));
|
||||
script = env->Invoke("DSS2", videoFilename);
|
||||
if (fps == 0.0) script = env->Invoke("DSS2", videoFilename);
|
||||
else {
|
||||
const char *argnames[2] = { 0, "fps" };
|
||||
AVSValue args[2] = { videoFilename, fps };
|
||||
script = env->Invoke("DSS2", AVSValue(args,2), argnames);
|
||||
}
|
||||
AVSTRACE(_T("visynthVideoProvider::OpenVideo: Successfully opened file with DSS2"));
|
||||
dss2 = true;
|
||||
}
|
||||
|
@ -333,7 +341,18 @@ PClip AvisynthVideoProvider::ApplyDARZoom(double _zoom, double _dar, PClip video
|
|||
|
||||
////////////////////////
|
||||
// Actually get a frame
|
||||
wxBitmap AvisynthVideoProvider::GetFrame(int n, bool force) {
|
||||
wxBitmap AvisynthVideoProvider::GetFrame(int _n, bool force) {
|
||||
// Transform n if overriden
|
||||
int n = _n;
|
||||
if (frameTime.Count()) {
|
||||
if (n < 0) n = 0;
|
||||
if (n >= (signed) frameTime.Count()) n = frameTime.Count()-1;
|
||||
int time = frameTime[n];
|
||||
double curFps = (double)vi.fps_numerator/(double)vi.fps_denominator;
|
||||
n = time * curFps / 1000.0;
|
||||
}
|
||||
|
||||
// Get frame
|
||||
AVSTRACE(_T("AvisynthVideoProvider::GetFrame"));
|
||||
if (n != last_fnum || force) {
|
||||
wxMutexLocker lock(AviSynthMutex);
|
||||
|
@ -464,4 +483,12 @@ void AvisynthVideoProvider::LoadVSFilter() {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////
|
||||
// Override frame times
|
||||
void AvisynthVideoProvider::OverrideFrameTimeList(wxArrayInt list) {
|
||||
frameTime = list;
|
||||
num_frames = frameTime.Count();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@ private:
|
|||
wxString subfilename;
|
||||
|
||||
int last_fnum;
|
||||
int num_frames;
|
||||
|
||||
int depth;
|
||||
|
||||
|
@ -73,6 +74,8 @@ private:
|
|||
|
||||
double dar;
|
||||
double zoom;
|
||||
double fps;
|
||||
wxArrayInt frameTime;
|
||||
|
||||
PClip RGB32Video;
|
||||
PClip SubtitledVideo;
|
||||
|
@ -86,7 +89,7 @@ private:
|
|||
void AttachOverlay(SubtitleProvider::Overlay *_overlay) {}
|
||||
|
||||
public:
|
||||
AvisynthVideoProvider(wxString _filename, wxString _subfilename);
|
||||
AvisynthVideoProvider(wxString _filename, wxString _subfilename, double fps=0.0);
|
||||
~AvisynthVideoProvider();
|
||||
|
||||
void RefreshSubtitles();
|
||||
|
@ -98,7 +101,7 @@ public:
|
|||
|
||||
// properties
|
||||
int GetPosition() { return last_fnum; };
|
||||
int GetFrameCount() { return vi.num_frames; };
|
||||
int GetFrameCount() { return num_frames? num_frames: vi.num_frames; };
|
||||
double GetFPS() { return (double)vi.fps_numerator/(double)vi.fps_denominator; };
|
||||
|
||||
int GetWidth() { return vi.width; };
|
||||
|
@ -107,6 +110,8 @@ public:
|
|||
|
||||
int GetSourceWidth() { return RGB32Video->GetVideoInfo().width; };
|
||||
int GetSourceHeight() { return RGB32Video->GetVideoInfo().height; };
|
||||
|
||||
void OverrideFrameTimeList(wxArrayInt list);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -55,9 +55,10 @@ DEFINE_GUID(CLSID_VideoSink, 0xf13d3732, 0x96bd, 0x4108, 0xaf, 0xeb, 0xe8, 0x5f,
|
|||
///////////////
|
||||
// Constructor
|
||||
// Based on Haali's code for DirectShowSource2
|
||||
DirectShowVideoProvider::DirectShowVideoProvider(wxString _filename, wxString _subfilename) {
|
||||
DirectShowVideoProvider::DirectShowVideoProvider(wxString _filename, wxString _subfilename,double _fps) {
|
||||
zoom = 1.0;
|
||||
dar = 4.0/3.0;
|
||||
fps = _fps;
|
||||
m_hFrameReady = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
OpenVideo(_filename);
|
||||
}
|
||||
|
@ -260,13 +261,6 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
|||
// Get video duration
|
||||
if (FAILED(hr = ms->GetDuration(&duration))) return hr;
|
||||
|
||||
// Length of each frame? (??)
|
||||
if (defd == 0) defd = 417083;
|
||||
|
||||
// No clue, either
|
||||
int avgf = 0;
|
||||
if (avgf > 0) defd = avgf;
|
||||
|
||||
// Set pixel type
|
||||
//switch (type) {
|
||||
// case IVS_RGB32: m_vi.pixel_type = VideoInfo::CS_BGR32; break;
|
||||
|
@ -275,13 +269,14 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
|||
// default: return E_FAIL;
|
||||
//}
|
||||
|
||||
// Set number of frames and fps
|
||||
// Set FPS and frame duration
|
||||
if (defd == 0) defd = 417083;
|
||||
if (fps != 0.0) defd = long long (10000000.0 / fps);
|
||||
else fps = 10000000.0 / double(defd);
|
||||
|
||||
// Set number of frames
|
||||
last_fnum = -1;
|
||||
num_frames = duration / defd;
|
||||
fps = 10000000.0 / double(defd);
|
||||
|
||||
// Set frame length
|
||||
//m_avgframe = defd;
|
||||
|
||||
// Store filters
|
||||
m_pR = sink;
|
||||
|
@ -401,34 +396,45 @@ void DirectShowVideoProvider::ReadFrame(long long timestamp, unsigned format, un
|
|||
|
||||
/////////////////////
|
||||
// Get Next DS Frame
|
||||
bool DirectShowVideoProvider::NextFrame(DF &_df,int &_fn) {
|
||||
int DirectShowVideoProvider::NextFrame(DF &_df,int &_fn) {
|
||||
// Keep reading until it gets a good frame
|
||||
while (true) {
|
||||
if (WaitForSingleObject(m_hFrameReady, INFINITE) != WAIT_OBJECT_0) return false;
|
||||
|
||||
// Set object to receive data
|
||||
// Set object and receive data
|
||||
DF df;
|
||||
if (WaitForSingleObject(m_hFrameReady, INFINITE) != WAIT_OBJECT_0) return 1;
|
||||
|
||||
// Read frame
|
||||
HRESULT hr = m_pR->ReadFrame(ReadFrame, &df);
|
||||
if (FAILED(hr)) return false;
|
||||
if (FAILED(hr)) return 2;
|
||||
|
||||
// End of file
|
||||
if (hr == S_FALSE) return false;
|
||||
if (hr == S_FALSE) return 3;
|
||||
|
||||
// Valid timestamp
|
||||
if (df.timestamp >= 0) {
|
||||
// Frame number
|
||||
int frameno = (int)((double)df.timestamp / defd + 0.5);
|
||||
// CFR frame number
|
||||
int frameno = -1;
|
||||
if (frameTime.Count() == 0) frameno = (int)((double)df.timestamp / defd + 0.5);
|
||||
|
||||
// VFR
|
||||
else {
|
||||
for (unsigned int i=0;i<frameTime.Count();i++) {
|
||||
if (df.timestamp < (long long) frameTime[i] * 10000) {
|
||||
frameno = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (frameno == -1) frameno = frameTime.Count()-1;
|
||||
}
|
||||
|
||||
// Got a good one
|
||||
if (frameno >= 0 && frameno <= (signed) num_frames) {
|
||||
if (frameno >= 0) {
|
||||
_fn = frameno;
|
||||
_df = df;
|
||||
if (zoom != 1.0 || dar != 1.0) {
|
||||
_df.frame.Rescale(height*zoom*dar,height*zoom,wxIMAGE_QUALITY_NORMAL);
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -440,6 +446,7 @@ bool DirectShowVideoProvider::NextFrame(DF &_df,int &_fn) {
|
|||
wxBitmap DirectShowVideoProvider::GetFrame(int n) {
|
||||
// Normalize frame number
|
||||
if (n >= (signed) num_frames) n = num_frames-1;
|
||||
if (n < 0) n = 0;
|
||||
|
||||
// Current
|
||||
if (n == last_fnum) return wxBitmap(rdf.frame);
|
||||
|
@ -447,7 +454,11 @@ wxBitmap DirectShowVideoProvider::GetFrame(int n) {
|
|||
// Variables
|
||||
DF df;
|
||||
int fn;
|
||||
REFERENCE_TIME cur = defd * n + 10001;
|
||||
|
||||
// Time to seek to
|
||||
REFERENCE_TIME cur;
|
||||
cur = defd * n + 10001;
|
||||
if (frameTime.Count() > (unsigned) n) cur = frameTime[n] * 10000 + 10001;
|
||||
if (cur < 0) cur = 0;
|
||||
|
||||
// Is next
|
||||
|
@ -472,14 +483,14 @@ seek:
|
|||
while (true) {
|
||||
// Get frame
|
||||
DF df;
|
||||
int fn;
|
||||
NextFrame(df,fn);
|
||||
int fn = -1;
|
||||
int result = NextFrame(df,fn);
|
||||
|
||||
// Preroll
|
||||
if (fn < n) continue;
|
||||
if (result == 0 && fn < n) continue;
|
||||
|
||||
// Right frame
|
||||
if (fn == n) {
|
||||
else if (fn == n) {
|
||||
// we want this frame, compare timestamps to account for decimation
|
||||
// we see this for the first time
|
||||
if (rdf.timestamp < 0) rdf.timestamp = df.timestamp;
|
||||
|
@ -492,11 +503,15 @@ seek:
|
|||
break;
|
||||
}
|
||||
|
||||
// Passed, seek back and try again
|
||||
else {
|
||||
// Passed or end of file, seek back and try again
|
||||
else if (result == 0 || result == 3) {
|
||||
cur -= defd;
|
||||
goto seek;
|
||||
//return wxBitmap(width,height);
|
||||
}
|
||||
|
||||
// Failed
|
||||
else {
|
||||
return wxBitmap(height*zoom*dar,height*zoom);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,4 +549,12 @@ void DirectShowVideoProvider::GetFloatFrame(float* Buffer, int n) {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////
|
||||
// Override frame times
|
||||
void DirectShowVideoProvider::OverrideFrameTimeList(wxArrayInt list) {
|
||||
frameTime = list;
|
||||
num_frames = frameTime.Count();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,6 +68,7 @@ class DirectShowVideoProvider: public VideoProvider {
|
|||
|
||||
private:
|
||||
wxString subfilename;
|
||||
wxArrayInt frameTime;
|
||||
|
||||
unsigned int last_fnum;
|
||||
unsigned int width;
|
||||
|
@ -89,7 +90,7 @@ private:
|
|||
void CloseVideo();
|
||||
|
||||
static void ReadFrame(long long timestamp, unsigned format, unsigned bpp, const unsigned char *frame, unsigned width, unsigned height, unsigned stride, unsigned arx, unsigned ary, void *arg);
|
||||
bool NextFrame(DF &df,int &fn);
|
||||
int NextFrame(DF &df,int &fn);
|
||||
|
||||
void RegROT();
|
||||
void UnregROT();
|
||||
|
@ -104,7 +105,7 @@ private:
|
|||
DWORD m_rot_cookie;
|
||||
|
||||
public:
|
||||
DirectShowVideoProvider(wxString _filename, wxString _subfilename);
|
||||
DirectShowVideoProvider(wxString _filename, wxString _subfilename,double _fps=0.0);
|
||||
~DirectShowVideoProvider();
|
||||
|
||||
void RefreshSubtitles();
|
||||
|
@ -124,6 +125,8 @@ public:
|
|||
|
||||
int GetSourceWidth() { return width; };
|
||||
int GetSourceHeight() { return height; };
|
||||
|
||||
void OverrideFrameTimeList(wxArrayInt list);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue