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
|
// Check if it's CFR
|
||||||
bool isCFR = true;
|
bool isCFR = true;
|
||||||
double estimateCFR = timecodes.back() / timecodes.size()-1;
|
double estimateCFR = timecodes.back() / timecodes.size()-1;
|
||||||
double curTime = 0;
|
double t1,t2;
|
||||||
for (int i=0;i<frames;i++) {
|
for (int i=1;i<frames;i++) {
|
||||||
int delta = int(curTime - timecodes[i]);
|
t1 = timecodes[i];
|
||||||
if (abs(delta > 1)) {
|
t2 = timecodes[i-1];
|
||||||
|
int delta = int(t1 - t2 - estimateCFR);
|
||||||
|
if (abs(delta > 2)) {
|
||||||
isCFR = false;
|
isCFR = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
curTime += estimateCFR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant framerate
|
// Constant framerate
|
||||||
if (isCFR) {
|
if (isCFR) {
|
||||||
if (abs(estimateCFR - 23.976) < 0.01) estimateCFR = 23.976;
|
if (abs(estimateCFR - 23.976) < 0.01) estimateCFR = 24000.0 / 1001.0;
|
||||||
if (abs(estimateCFR - 29.97) < 0.01) estimateCFR = 29.97;
|
if (abs(estimateCFR - 29.97) < 0.01) estimateCFR = 30000.0 / 1001.0;
|
||||||
target.SetCFR(estimateCFR);
|
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
|
// Globals
|
||||||
FrameRate VFR_Output;
|
FrameRate VFR_Output;
|
||||||
|
|
|
@ -77,6 +77,7 @@ private:
|
||||||
ASS_FrameRateType FrameRateType;
|
ASS_FrameRateType FrameRateType;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
wxString vfrFile;
|
wxString vfrFile;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FrameRate();
|
FrameRate();
|
||||||
~FrameRate();
|
~FrameRate();
|
||||||
|
@ -94,6 +95,9 @@ public:
|
||||||
bool IsLoaded() { return loaded; };
|
bool IsLoaded() { return loaded; };
|
||||||
ASS_FrameRateType GetFrameRateType() { return FrameRateType; };
|
ASS_FrameRateType GetFrameRateType() { return FrameRateType; };
|
||||||
wxString GetFilename() { return vfrFile; };
|
wxString GetFilename() { return vfrFile; };
|
||||||
|
|
||||||
|
wxArrayInt GetFrameTimeList();
|
||||||
|
double GetCommonFPS();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -163,14 +163,9 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
||||||
if (!filename.IsEmpty()) {
|
if (!filename.IsEmpty()) {
|
||||||
try {
|
try {
|
||||||
grid->CommitChanges(true);
|
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
|
// Read extra data from file
|
||||||
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
||||||
wxString ext = filename.Right(4).Lower();
|
wxString ext = filename.Right(4).Lower();
|
||||||
|
@ -186,7 +181,11 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
||||||
// Ask to override timecodes
|
// Ask to override timecodes
|
||||||
int override = wxYES;
|
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 (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
|
// Close mkv
|
||||||
MatroskaWrapper::wrapper.Close();
|
MatroskaWrapper::wrapper.Close();
|
||||||
|
@ -198,6 +197,13 @@ void VideoDisplay::SetVideo(const wxString &filename) {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// Update size
|
||||||
UpdateSize();
|
UpdateSize();
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// Get provider
|
// Get provider
|
||||||
VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles,double fps) {
|
||||||
// Check if avisynth is available
|
// Check if avisynth is available
|
||||||
bool avisynthAvailable = false;
|
bool avisynthAvailable = false;
|
||||||
bool dshowAvailable = false;
|
bool dshowAvailable = false;
|
||||||
|
@ -106,7 +106,7 @@ VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
||||||
// Use DirectShow provider
|
// Use DirectShow provider
|
||||||
if (!provider && (preffered == _T("dshow") || !avisynthAvailable)) {
|
if (!provider && (preffered == _T("dshow") || !avisynthAvailable)) {
|
||||||
try {
|
try {
|
||||||
provider = new DirectShowVideoProvider(video,subtitles);
|
provider = new DirectShowVideoProvider(video,subtitles,fps);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
delete provider;
|
delete provider;
|
||||||
|
@ -119,7 +119,7 @@ VideoProvider *VideoProvider::GetProvider(wxString video,wxString subtitles) {
|
||||||
// Use Avisynth provider
|
// Use Avisynth provider
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
try {
|
try {
|
||||||
provider = new AvisynthVideoProvider(video,subtitles);
|
provider = new AvisynthVideoProvider(video,subtitles,fps);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
delete provider;
|
delete provider;
|
||||||
|
|
|
@ -65,5 +65,7 @@ public:
|
||||||
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
||||||
virtual int GetSourceHeight()=0; // Returns the original source height 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 "video_provider_avs.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "vfr.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
@ -46,17 +47,19 @@
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// Constructor
|
// 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));
|
AVSTRACE(wxString::Format(_T("AvisynthVideoProvider: Creating new AvisynthVideoProvider: \"%s\", \"%s\""), _filename, _subfilename));
|
||||||
bool mpeg2dec3_priority = true;
|
bool mpeg2dec3_priority = true;
|
||||||
RGB32Video = NULL;
|
RGB32Video = NULL;
|
||||||
SubtitledVideo = NULL;
|
SubtitledVideo = NULL;
|
||||||
ResizedVideo = NULL;
|
ResizedVideo = NULL;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
fps = _fps;
|
||||||
|
|
||||||
depth = 0;
|
depth = 0;
|
||||||
|
|
||||||
last_fnum = -1;
|
last_fnum = -1;
|
||||||
|
num_frames = 0;
|
||||||
|
|
||||||
subfilename = _subfilename;
|
subfilename = _subfilename;
|
||||||
zoom = 1.0;
|
zoom = 1.0;
|
||||||
|
@ -219,7 +222,12 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
dss2 = false;
|
dss2 = false;
|
||||||
if (env->FunctionExists("dss2")) {
|
if (env->FunctionExists("dss2")) {
|
||||||
AVSTRACE(_T("visynthVideoProvider::OpenVideo: Invoking 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"));
|
AVSTRACE(_T("visynthVideoProvider::OpenVideo: Successfully opened file with DSS2"));
|
||||||
dss2 = true;
|
dss2 = true;
|
||||||
}
|
}
|
||||||
|
@ -333,7 +341,18 @@ PClip AvisynthVideoProvider::ApplyDARZoom(double _zoom, double _dar, PClip video
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Actually get a frame
|
// 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"));
|
AVSTRACE(_T("AvisynthVideoProvider::GetFrame"));
|
||||||
if (n != last_fnum || force) {
|
if (n != last_fnum || force) {
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
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
|
#endif
|
||||||
|
|
|
@ -65,6 +65,7 @@ private:
|
||||||
wxString subfilename;
|
wxString subfilename;
|
||||||
|
|
||||||
int last_fnum;
|
int last_fnum;
|
||||||
|
int num_frames;
|
||||||
|
|
||||||
int depth;
|
int depth;
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ private:
|
||||||
|
|
||||||
double dar;
|
double dar;
|
||||||
double zoom;
|
double zoom;
|
||||||
|
double fps;
|
||||||
|
wxArrayInt frameTime;
|
||||||
|
|
||||||
PClip RGB32Video;
|
PClip RGB32Video;
|
||||||
PClip SubtitledVideo;
|
PClip SubtitledVideo;
|
||||||
|
@ -86,7 +89,7 @@ private:
|
||||||
void AttachOverlay(SubtitleProvider::Overlay *_overlay) {}
|
void AttachOverlay(SubtitleProvider::Overlay *_overlay) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AvisynthVideoProvider(wxString _filename, wxString _subfilename);
|
AvisynthVideoProvider(wxString _filename, wxString _subfilename, double fps=0.0);
|
||||||
~AvisynthVideoProvider();
|
~AvisynthVideoProvider();
|
||||||
|
|
||||||
void RefreshSubtitles();
|
void RefreshSubtitles();
|
||||||
|
@ -98,7 +101,7 @@ public:
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
int GetPosition() { return last_fnum; };
|
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; };
|
double GetFPS() { return (double)vi.fps_numerator/(double)vi.fps_denominator; };
|
||||||
|
|
||||||
int GetWidth() { return vi.width; };
|
int GetWidth() { return vi.width; };
|
||||||
|
@ -107,6 +110,8 @@ public:
|
||||||
|
|
||||||
int GetSourceWidth() { return RGB32Video->GetVideoInfo().width; };
|
int GetSourceWidth() { return RGB32Video->GetVideoInfo().width; };
|
||||||
int GetSourceHeight() { return RGB32Video->GetVideoInfo().height; };
|
int GetSourceHeight() { return RGB32Video->GetVideoInfo().height; };
|
||||||
|
|
||||||
|
void OverrideFrameTimeList(wxArrayInt list);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -55,9 +55,10 @@ DEFINE_GUID(CLSID_VideoSink, 0xf13d3732, 0x96bd, 0x4108, 0xaf, 0xeb, 0xe8, 0x5f,
|
||||||
///////////////
|
///////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
// Based on Haali's code for DirectShowSource2
|
// Based on Haali's code for DirectShowSource2
|
||||||
DirectShowVideoProvider::DirectShowVideoProvider(wxString _filename, wxString _subfilename) {
|
DirectShowVideoProvider::DirectShowVideoProvider(wxString _filename, wxString _subfilename,double _fps) {
|
||||||
zoom = 1.0;
|
zoom = 1.0;
|
||||||
dar = 4.0/3.0;
|
dar = 4.0/3.0;
|
||||||
|
fps = _fps;
|
||||||
m_hFrameReady = CreateEvent(NULL, FALSE, FALSE, NULL);
|
m_hFrameReady = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
OpenVideo(_filename);
|
OpenVideo(_filename);
|
||||||
}
|
}
|
||||||
|
@ -260,13 +261,6 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
||||||
// Get video duration
|
// Get video duration
|
||||||
if (FAILED(hr = ms->GetDuration(&duration))) return hr;
|
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
|
// Set pixel type
|
||||||
//switch (type) {
|
//switch (type) {
|
||||||
// case IVS_RGB32: m_vi.pixel_type = VideoInfo::CS_BGR32; break;
|
// case IVS_RGB32: m_vi.pixel_type = VideoInfo::CS_BGR32; break;
|
||||||
|
@ -275,13 +269,14 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
||||||
// default: return E_FAIL;
|
// 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;
|
last_fnum = -1;
|
||||||
num_frames = duration / defd;
|
num_frames = duration / defd;
|
||||||
fps = 10000000.0 / double(defd);
|
|
||||||
|
|
||||||
// Set frame length
|
|
||||||
//m_avgframe = defd;
|
|
||||||
|
|
||||||
// Store filters
|
// Store filters
|
||||||
m_pR = sink;
|
m_pR = sink;
|
||||||
|
@ -401,34 +396,45 @@ void DirectShowVideoProvider::ReadFrame(long long timestamp, unsigned format, un
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// Get Next DS Frame
|
// 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
|
// Keep reading until it gets a good frame
|
||||||
while (true) {
|
while (true) {
|
||||||
if (WaitForSingleObject(m_hFrameReady, INFINITE) != WAIT_OBJECT_0) return false;
|
// Set object and receive data
|
||||||
|
|
||||||
// Set object to receive data
|
|
||||||
DF df;
|
DF df;
|
||||||
|
if (WaitForSingleObject(m_hFrameReady, INFINITE) != WAIT_OBJECT_0) return 1;
|
||||||
|
|
||||||
// Read frame
|
// Read frame
|
||||||
HRESULT hr = m_pR->ReadFrame(ReadFrame, &df);
|
HRESULT hr = m_pR->ReadFrame(ReadFrame, &df);
|
||||||
if (FAILED(hr)) return false;
|
if (FAILED(hr)) return 2;
|
||||||
|
|
||||||
// End of file
|
// End of file
|
||||||
if (hr == S_FALSE) return false;
|
if (hr == S_FALSE) return 3;
|
||||||
|
|
||||||
// Valid timestamp
|
// Valid timestamp
|
||||||
if (df.timestamp >= 0) {
|
if (df.timestamp >= 0) {
|
||||||
// Frame number
|
// CFR frame number
|
||||||
int frameno = (int)((double)df.timestamp / defd + 0.5);
|
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
|
// Got a good one
|
||||||
if (frameno >= 0 && frameno <= (signed) num_frames) {
|
if (frameno >= 0) {
|
||||||
_fn = frameno;
|
_fn = frameno;
|
||||||
_df = df;
|
_df = df;
|
||||||
if (zoom != 1.0 || dar != 1.0) {
|
if (zoom != 1.0 || dar != 1.0) {
|
||||||
_df.frame.Rescale(height*zoom*dar,height*zoom,wxIMAGE_QUALITY_NORMAL);
|
_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) {
|
wxBitmap DirectShowVideoProvider::GetFrame(int n) {
|
||||||
// Normalize frame number
|
// Normalize frame number
|
||||||
if (n >= (signed) num_frames) n = num_frames-1;
|
if (n >= (signed) num_frames) n = num_frames-1;
|
||||||
|
if (n < 0) n = 0;
|
||||||
|
|
||||||
// Current
|
// Current
|
||||||
if (n == last_fnum) return wxBitmap(rdf.frame);
|
if (n == last_fnum) return wxBitmap(rdf.frame);
|
||||||
|
@ -447,7 +454,11 @@ wxBitmap DirectShowVideoProvider::GetFrame(int n) {
|
||||||
// Variables
|
// Variables
|
||||||
DF df;
|
DF df;
|
||||||
int fn;
|
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;
|
if (cur < 0) cur = 0;
|
||||||
|
|
||||||
// Is next
|
// Is next
|
||||||
|
@ -472,14 +483,14 @@ seek:
|
||||||
while (true) {
|
while (true) {
|
||||||
// Get frame
|
// Get frame
|
||||||
DF df;
|
DF df;
|
||||||
int fn;
|
int fn = -1;
|
||||||
NextFrame(df,fn);
|
int result = NextFrame(df,fn);
|
||||||
|
|
||||||
// Preroll
|
// Preroll
|
||||||
if (fn < n) continue;
|
if (result == 0 && fn < n) continue;
|
||||||
|
|
||||||
// Right frame
|
// Right frame
|
||||||
if (fn == n) {
|
else if (fn == n) {
|
||||||
// we want this frame, compare timestamps to account for decimation
|
// we want this frame, compare timestamps to account for decimation
|
||||||
// we see this for the first time
|
// we see this for the first time
|
||||||
if (rdf.timestamp < 0) rdf.timestamp = df.timestamp;
|
if (rdf.timestamp < 0) rdf.timestamp = df.timestamp;
|
||||||
|
@ -492,11 +503,15 @@ seek:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Passed, seek back and try again
|
// Passed or end of file, seek back and try again
|
||||||
else {
|
else if (result == 0 || result == 3) {
|
||||||
cur -= defd;
|
cur -= defd;
|
||||||
goto seek;
|
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
|
#endif
|
||||||
|
|
|
@ -68,6 +68,7 @@ class DirectShowVideoProvider: public VideoProvider {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxString subfilename;
|
wxString subfilename;
|
||||||
|
wxArrayInt frameTime;
|
||||||
|
|
||||||
unsigned int last_fnum;
|
unsigned int last_fnum;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
@ -89,7 +90,7 @@ private:
|
||||||
void CloseVideo();
|
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);
|
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 RegROT();
|
||||||
void UnregROT();
|
void UnregROT();
|
||||||
|
@ -104,7 +105,7 @@ private:
|
||||||
DWORD m_rot_cookie;
|
DWORD m_rot_cookie;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DirectShowVideoProvider(wxString _filename, wxString _subfilename);
|
DirectShowVideoProvider(wxString _filename, wxString _subfilename,double _fps=0.0);
|
||||||
~DirectShowVideoProvider();
|
~DirectShowVideoProvider();
|
||||||
|
|
||||||
void RefreshSubtitles();
|
void RefreshSubtitles();
|
||||||
|
@ -124,6 +125,8 @@ public:
|
||||||
|
|
||||||
int GetSourceWidth() { return width; };
|
int GetSourceWidth() { return width; };
|
||||||
int GetSourceHeight() { return height; };
|
int GetSourceHeight() { return height; };
|
||||||
|
|
||||||
|
void OverrideFrameTimeList(wxArrayInt list);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue